egl/x11: Free memory allocated for reply structures on error
authorAndrey Vostrikov <av.linux.dev@gmail.com>
Thu, 27 Aug 2020 06:32:48 +0000 (09:32 +0300)
committerVivek Pandya <vivekvpandya@gmail.com>
Mon, 7 Sep 2020 15:55:15 +0000 (21:25 +0530)
This patch fixes memory leaks when reply is allocated and is not freed
on error execution path.

Found by enabling address sanitizer on simple EGL app.

```c

int main()
{
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    EGLint major;
    EGLint minor;

    if (!eglInitialize(display, &major, &minor))
    {
        return 1;
    }
    eglTerminate(display);
    return 0;
}
```

Compiled with: `gcc testme.c -o testme -fsanitize=address -lasan -lEGL`

Execution environment:
- Windows 10, VMWare Player 15.5.2 build-15785246 without 3D accelaration
- Guest OS: OpenSUSE Leap 15.2
- Mesa 19.3.4

Program output:

```sh
ASAN_OPTIONS=fast_unwind_on_malloc=0 ./testme

libEGL warning: DRI2: failed to authenticate
==52510==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0x7fa62315f500 in malloc (/usr/lib64/libasan.so.4+0xdc500)
    #1 0x7fa61e12d86b  (/usr/lib64/libxcb.so.1+0xf86b)
    #2 0x7fa61e12b5c7  (/usr/lib64/libxcb.so.1+0xd5c7)
    #3 0x7fa61e12cc3e  (/usr/lib64/libxcb.so.1+0xec3e)
    #4 0x7fa61e12cd4f in xcb_wait_for_reply (/usr/lib64/libxcb.so.1+0xed4f)
    #5 0x7fa61ebe02a5  (/usr/lib64/libEGL_mesa.so.0+0x202a5)
    #6 0x7fa61ebdb5ca  (/usr/lib64/libEGL_mesa.so.0+0x1b5ca)
    #7 0x7fa61ebd750c  (/usr/lib64/libEGL_mesa.so.0+0x1750c)
    #8 0x7fa61ebd7554  (/usr/lib64/libEGL_mesa.so.0+0x17554)
    #9 0x7fa61ebd1107  (/usr/lib64/libEGL_mesa.so.0+0x11107)
    #10 0x400856 in main (/home/user/testme+0x400856)
    #11 0x7fa622ad8349 in __libc_start_main (/lib64/libc.so.6+0x24349)
    #12 0x4006e9 in _start (/home/user/testme+0x4006e9)

SUMMARY: AddressSanitizer: 32 byte(s) leaked in 1 allocation(s).
```

Signed-off-by: Andrey Vostrikov <av.linux.dev@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Reviewed-by: Eric Engestrom <eric@engestrom.ch>
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6611>

src/egl/drivers/dri2/platform_x11.c

index b8011866234428725b928d6199a7e5222b32ccef..af79eb1df6dcff949bf96f5e9c2c147c92576eba 100644 (file)
@@ -300,6 +300,7 @@ dri2_x11_create_surface(_EGLDisplay *disp, EGLint type, _EGLConfig *conf,
          else
             _eglError(EGL_BAD_NATIVE_PIXMAP, "xcb_get_geometry");
          free(error);
+         free(reply);
          goto cleanup_dri_drawable;
       } else if (reply == NULL) {
          _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
@@ -519,8 +520,10 @@ dri2_x11_get_buffers(__DRIdrawable * driDrawable,
    if (reply == NULL)
       return NULL;
    buffers = xcb_dri2_get_buffers_buffers (reply);
-   if (buffers == NULL)
+   if (buffers == NULL) {
+      free(reply);
       return NULL;
+   }
 
    *out_count = reply->count;
    dri2_surf->base.Width = *width = reply->width;
@@ -677,6 +680,7 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
    if (dri2_query == NULL || error != NULL) {
       _eglLog(_EGL_WARNING, "DRI2: failed to query version");
       free(error);
+      free(dri2_query);
       return EGL_FALSE;
    }
    dri2_dpy->dri2_major = dri2_query->major_version;
@@ -687,6 +691,7 @@ dri2_x11_connect(struct dri2_egl_display *dri2_dpy)
    if (connect == NULL ||
        connect->driver_name_length + connect->device_name_length == 0) {
       _eglLog(_EGL_WARNING, "DRI2: failed to authenticate");
+      free(connect);
       return EGL_FALSE;
    }
 
@@ -1072,6 +1077,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
 
    buffers = xcb_dri2_get_buffers_buffers (buffers_reply);
    if (buffers == NULL) {
+      free(buffers_reply);
       return NULL;
    }
 
@@ -1081,6 +1087,7 @@ dri2_create_image_khr_pixmap(_EGLDisplay *disp, _EGLContext *ctx,
       _eglError(EGL_BAD_ALLOC, "xcb_get_geometry");
       free(error);
       free(buffers_reply);
+      free(geometry_reply);
       return NULL;
    }