Skip to content

Free memory allocated for reply structures on error

Andrey Vostrikov requested to merge av.linux.dev/mesa:master into master

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.


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:

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).

Translates under debugger to:

#0  __interceptor_malloc (size=32) at ../../../../libsanitizer/asan/asan_malloc_linux.cc:59
#1  0x00007ffff48a986c in read_packet (c=0x62a000006200) at xcb_in.c:259
#2  _xcb_in_read (c=c@entry=0x62a000006200) at xcb_in.c:1030
#3  0x00007ffff48a75c8 in _xcb_conn_wait (c=c@entry=0x62a000006200, cond=cond@entry=0x7fffffffb8d0, vector=vector@entry=0x0, count=count@entry=0x0) at xcb_conn.c:515
#4  0x00007ffff48a8c3f in wait_for_reply (c=c@entry=0x62a000006200, request=3, e=e@entry=0x7fffffffb990) at xcb_in.c:516
#5  0x00007ffff48a8d50 in xcb_wait_for_reply (c=0x62a000006200, request=3, e=e@entry=0x7fffffffb990) at xcb_in.c:546
#6  0x00007ffff0b3d085 in xcb_xfixes_query_version_reply (c=<optimized out>, cookie=..., cookie@entry=..., e=e@entry=0x7fffffffb990) at xfixes.c:84
#7  0x00007ffff17e02a6 in dri2_x11_connect (dri2_dpy=0x614000000240) at ../src/egl/drivers/dri2/platform_x11.c:673
#8  dri2_initialize_x11_dri2 (drv=0x614000000240, disp=0x61b000000080) at ../src/egl/drivers/dri2/platform_x11.c:1489
#9  dri2_initialize_x11 (drv=drv@entry=0x613000000580, disp=disp@entry=0x61b000000080) at ../src/egl/drivers/dri2/platform_x11.c:1558
#10 0x00007ffff17db5cb in dri2_initialize (drv=0x613000000580, disp=0x61b000000080) at ../src/egl/drivers/dri2/egl_dri2.c:990
#11 0x00007ffff17d750d in _eglMatchAndInitialize (disp=disp@entry=0x61b000000080) at ../src/egl/main/egldriver.c:75
#12 0x00007ffff17d7555 in _eglMatchDriver (disp=disp@entry=0x61b000000080) at ../src/egl/main/egldriver.c:96
#13 0x00007ffff17d1108 in eglInitialize (dpy=0x61b000000080, major=0x7fffffffbab0, minor=0x7fffffffbaf0) at ../src/egl/main/eglapi.c:617

Root cause:

reply structure is not freed in case of error branch makes early exit.

Looking up through the file, it is a common pattern. Made changes to each similar case in this file to free reply struct if control leaves on error.

Signed-off-by: Andrey Vostrikov av.linux.dev@gmail.com

Merge request reports