diff options
author | Erik Kurzinger <ekurzinger@nvidia.com> | 2020-12-10 14:24:32 -0800 |
---|---|---|
committer | Olivier Fourdan <fourdan@gmail.com> | 2021-06-07 14:53:13 +0000 |
commit | b7a85e44da91d1663d5b4eabac06327c92a80f91 (patch) | |
tree | f20a067e0ab0643795dbb235a6fdf94ddd15ce3a /glx | |
parent | 8274dd664335cd72739a1107f174e7a974a9ea24 (diff) |
glx: don't create implicit GLXWindow if one already exists
If a GLXMakeCurrent request specifies an X window as its drawable,
__glXGetDrawable will implicitly create a GLXWindow for it. However,
the client may have already explicitly created a GLXWindow for that X
window. If that happens, two __glXDrawableRes resources will be added
to the window.
If the explicitly-created GLXWindow is later destroyed by the client,
DrawableGone will call FreeResourceByType on the X window, but this
will actually free the resource for the implicitly-created GLXWindow,
since that one would be at the head of the list.
Then if the X window is destroyed after that, the resource for the
explicitly-created GLXWindow will be freed. But that GLXWindow was
already destroyed above. This crashes the server when it tries to call
the destroyed GLXWindow's destructor. It also means the
implicitly-created GLXWindow would have been leaked since the
FreeResourceByType call mentioned above skips calling the destructor.
To fix this, if __glXGetDrawable is given an X window, it should check
if there is already a GLXWindow associated with it, and only create an
implicit one if there is not.
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
Diffstat (limited to 'glx')
-rw-r--r-- | glx/glxcmds.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 368d66aa6..2f69c794a 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -487,8 +487,15 @@ __glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client, __GLXscreen *pGlxScreen; int rc; - if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY, - DixWriteAccess, &pGlxDraw, &rc)) { + rc = dixLookupResourceByType((void **)&pGlxDraw, drawId, + __glXDrawableRes, client, DixWriteAccess); + if (rc == Success && + /* If pGlxDraw->drawId == drawId, drawId is a valid GLX drawable. + * Otherwise, if pGlxDraw->type == GLX_DRAWABLE_WINDOW, drawId is + * an X window, but the client has already created a GLXWindow + * associated with it, so we don't want to create another one. */ + (pGlxDraw->drawId == drawId || + pGlxDraw->type == GLX_DRAWABLE_WINDOW)) { if (glxc != NULL && glxc->config != NULL && glxc->config != pGlxDraw->config) { |