[PATCH v2 0/1] MR9956: wined3d: Check invalid addresses when copying buffer objects.
When a thread that created windows is being closed, the destination buffer address might be NULL. For example: 1. context_gl->internal_format_set is set to 1 in wined3d_context_gl_set_pixel_format(). 2. A thread gets destroyed, all the windows in the thread get destroyed. 3. wined3d_context_gl_set_pixel_format() fails because WindowFromDC() returns NULL. 4. get_dc_pixel_format() fails in win32u_wglMakeContextCurrentARB(). 5. wined3d_buffer_gl_create_buffer_object() fails to create a buffer object. 6. wined3d_buffer_get_memory() returns a struct wined3d_bo_address with addr being NULL. Adding a NULL check in wined3d_context_gl_copy_bo_address() avoids triggering write segfaults when terminating a thread. This could happen for React Native applications. -- v2: wined3d: Check invalid addresses when copying buffer objects. https://gitlab.winehq.org/wine/wine/-/merge_requests/9956
From: Zhiyi Zhang <zzhang@codeweavers.com> When a thread that created windows is being closed, the destination buffer address might be NULL. For example: 1. context_gl->internal_format_set is set to 1 in wined3d_context_gl_set_pixel_format(). 2. A thread gets destroyed, all the windows in the thread get destroyed. 3. wined3d_context_gl_set_pixel_format() fails because WindowFromDC() returns NULL. 4. get_dc_pixel_format() fails in win32u_wglMakeContextCurrentARB(). 5. wined3d_buffer_gl_create_buffer_object() fails to create a buffer object. 6. wined3d_buffer_get_memory() returns a struct wined3d_bo_address with addr being NULL. Adding a NULL check in wined3d_context_gl_copy_bo_address() avoids triggering write segfaults when terminating a thread. This could happen for React Native applications. --- dlls/wined3d/context_gl.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index fc480f5a440..4042e329bba 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -3048,6 +3048,12 @@ void wined3d_context_gl_copy_bo_address(struct wined3d_context_gl *context_gl, } else { + if (!dst->addr || !src->addr) + { + ERR("Invalid addresses.\n"); + return; + } + for (i = 0; i < range_count; ++i) memcpy(dst->addr + ranges[i].offset, src->addr + ranges[i].offset, ranges[i].size); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9956
I'm not opposed to this, but why aren't we falling back to the backup DC? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9956#note_128031
On Tue Jan 27 03:23:26 2026 +0000, Elizabeth Figura wrote:
I'm not opposed to this, but why aren't we falling back to the backup DC? We are falling back to the backup DC in this case. It's just that using the backup DC failed as well.
01ec:err:d3d:wined3d_context_gl_set_gl_context Fallback to backup window (dc 000000001701004A) failed too, last error 0x7d0.
The reason why this happens with the backup DC is that in the following if condition in wined3d_context_gl_set_pixel_format(), current is 0, and context_gl->internal_format_set is 1 due to step 1. The check was introduced by 8da023fe. ``` current = gl_info->gl_ops.wgl.p_wglGetPixelFormat(dc); if ((current == format) || (!current && context_gl->internal_format_set)) goto success; ``` Another way to avoid the crash is to reset internal_format_set to FALSE when using backup DC in wined3d_context_gl_set_gl_context(). Is the following change better? ``` TRACE("Using backup DC %p.\n", context_gl->dc); context_gl->dc_is_private = TRUE; context_gl->dc_has_format = FALSE; + context_gl->internal_format_set = FALSE; ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9956#note_128080
participants (3)
-
Elizabeth Figura (@zfigura) -
Zhiyi Zhang -
Zhiyi Zhang (@zhiyi)