From: Twaik Yont <9674930+twaik@users.noreply.github.com> `dequeueBuffer()` may return success without initializing the `ANativeWindowBuffer` pointer. In that case the caller would observe either a `NULL` pointer or uninitialized stack garbage and proceed to dereference it, leading to crashes or undefined behavior in the rendering path. Initialize buffer variables to `NULL` and explicitly validate the returned pointer. If `dequeueBuffer` reports success but does not provide a valid buffer, treat it as a failure (`STATUS_UNSUCCESSFUL` / `-EWOULDBLOCK`) and abort processing. This avoids dereferencing uninitialized or stale pointers when the backend fails to populate the output buffer while still reporting success. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 51afb279579..71cb45be0f4 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -804,7 +804,7 @@ static NTSTATUS dequeueBuffer_ioctl( void *data, DWORD in_size, DWORD out_size, struct ANativeWindow *parent; struct ioctl_android_dequeueBuffer *res = data; struct native_win_data *win_data; - struct ANativeWindowBuffer *buffer; + struct ANativeWindowBuffer *buffer = NULL; int fence, ret, is_new; if (out_size < sizeof( *res )) return STATUS_BUFFER_OVERFLOW; @@ -823,6 +823,11 @@ static NTSTATUS dequeueBuffer_ioctl( void *data, DWORD in_size, DWORD out_size, { HANDLE mapping = 0; + if (!buffer) { + TRACE( "got invalid buffer\n" ); + return STATUS_UNSUCCESSFUL; + } + TRACE( "%08x got buffer %p fence %d\n", res->hdr.hwnd, buffer, fence ); res->width = buffer->width; res->height = buffer->height; @@ -1254,7 +1259,7 @@ static void buffer_decRef( struct android_native_base_t *base ) static int dequeueBuffer( struct ANativeWindow *window, struct ANativeWindowBuffer **buffer, int *fence ) { struct native_win_wrapper *win = (struct native_win_wrapper *)window; - struct ioctl_android_dequeueBuffer res; + struct ioctl_android_dequeueBuffer res = {0}; DWORD size = sizeof(res); int ret, use_win32 = !gralloc_module && !gralloc1_device; @@ -1468,10 +1473,14 @@ static int perform( ANativeWindow *window, int operation, ... ) } case NATIVE_WINDOW_LOCK: { - struct ANativeWindowBuffer *buffer; + struct ANativeWindowBuffer *buffer = NULL; struct ANativeWindow_Buffer *buffer_ret = va_arg( args, ANativeWindow_Buffer * ); ARect *bounds = va_arg( args, ARect * ); int ret = window->dequeueBuffer_DEPRECATED( window, &buffer ); + if (!ret && !buffer) { + ret = -EWOULDBLOCK; + TRACE( "got invalid buffer\n" ); + } if (!ret) { if ((ret = gralloc_lock( buffer, &buffer_ret->bits ))) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9874