st/dri: Fix dangling pointer to a destroyed dri_drawable
authorJohan Klokkhammer Helsing <johan.helsing@qt.io>
Fri, 20 Apr 2018 10:29:16 +0000 (12:29 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 23 Apr 2018 08:25:40 +0000 (04:25 -0400)
If an EGLSurface is created, made current and destroyed, and then a second
EGLSurface is created. Then the second malloc in driCreateNewDrawable may
return the same pointer address the first surface's drawable had.
Consequently, when dri_make_current later tries to determine if it should
update the texture_stamp it compares the surface's drawable pointer against
the drawable in the last call to dri_make_current and assumes it's the same
surface (which it isn't).

When texture_stamp is left unset, then dri_st_framebuffer_validate thinks
it has already called update_drawable_info for that drawable, leaving it
unvalidated and this is when bad things starts to happen. In my case it
manifested itself by the width and height of the surface being unset.

This is fixed this by setting the pointer to NULL before freeing the
surface.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=106126
Signed-off-by: Johan Klokkhammer Helsing <johan.helsing@qt.io>
Signed-off-by: Marek Olšák <marek.olsak@amd.com>
Cc: 18.0 18.1 <mesa-stable@lists.freedesktop.org>
src/gallium/state_trackers/dri/dri_drawable.c

index e5a7537e4731184920ab86ab2a46b00fcac20739..02328acd98d3aebc673ba590db99cf1ee94329c5 100644 (file)
@@ -185,6 +185,7 @@ fail:
 void
 dri_destroy_buffer(__DRIdrawable * dPriv)
 {
+   struct dri_context *ctx = dri_context(dPriv->driContextPriv);
    struct dri_drawable *drawable = dri_drawable(dPriv);
    struct dri_screen *screen = drawable->screen;
    struct st_api *stapi = screen->st_api;
@@ -202,6 +203,9 @@ dri_destroy_buffer(__DRIdrawable * dPriv)
    /* Notify the st manager that this drawable is no longer valid */
    stapi->destroy_drawable(stapi, &drawable->base);
 
+   if (ctx && ctx->dPriv == dPriv)
+      ctx->dPriv = NULL;
+
    FREE(drawable);
 }