diff --git a/Xext/saver.c b/Xext/saver.c index fd6153c31..0780e80ab 100644 --- a/Xext/saver.c +++ b/Xext/saver.c @@ -348,6 +348,9 @@ ScreenSaverFreeAttr(void *value, XID id) dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive); } CheckScreenPrivate(pScreen); + /* CheckScreenPrivate may have freed pPriv (same pattern as + * CreateSaverWindow fix for ZDI-CAN-30168). */ + pPriv = NULL; return TRUE; } @@ -479,6 +482,8 @@ CreateSaverWindow(ScreenPtr pScreen) UninstallSaverColormap(pScreen); pPriv->hasWindow = FALSE; CheckScreenPrivate(pScreen); + /* Re-fetch pPriv since CheckScreenPrivate may have freed it */ + pPriv = GetScreenPrivate(pScreen); } } diff --git a/Xext/sync.c b/Xext/sync.c index 1e250d176..ea15f3746 100644 --- a/Xext/sync.c +++ b/Xext/sync.c @@ -721,8 +721,29 @@ SyncChangeCounter(SyncCounter * pCounter, int64_t newval) /* run through triggers to see if any become true */ for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) { pnext = ptl->next; - if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) + if ((*ptl->pTrigger->CheckTrigger) (ptl->pTrigger, oldval)) { (*ptl->pTrigger->TriggerFired) (ptl->pTrigger); + /* TriggerFired may have called SyncDeleteTriggerFromSyncObject + * for sibling triggers in the same Await group, freeing their + * trigger list nodes - potentially including pnext. Verify + * pnext is still on the counter's trigger list; if not, + * restart from the list head. + * + * Unlike miSyncTriggerFence() we cannot use a do/while + * restart loop here: counter trigger lists may contain alarm + * triggers which are not removed after firing and would cause + * an infinite loop when delta is 0. + */ + if (pnext) { + SyncTriggerList *tmp; + for (tmp = pCounter->sync.pTriglist; tmp; tmp = tmp->next) { + if (tmp == pnext) + break; + } + if (!tmp) + pnext = pCounter->sync.pTriglist; + } + } } if (IsSystemCounter(pCounter)) { @@ -1163,9 +1184,12 @@ FreeCounter(void *env, XID id) SyncTriggerList *ptl, *pnext; /* tell all the counter's triggers that counter has been destroyed */ - for (ptl = pCounter->sync.pTriglist; ptl; ptl = pnext) { - (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); - pnext = ptl->next; + nt_list_for_each_entry_safe(ptl, pnext, pCounter->sync.pTriglist, next) { + /* Remove it from the list first so CounterDestroyed + * callbacks have a valid list to iterate */ + pCounter->sync.pTriglist = pnext; + if (ptl->pTrigger) + (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); free(ptl); /* destroy the trigger list as we go */ } if (IsSystemCounter(pCounter)) { @@ -1197,13 +1221,28 @@ FreeAwait(void *addr, XID id) for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; numwaits--, pAwait++) { - /* If the counter is being destroyed, FreeCounter will delete - * the trigger list itself, so don't do it here. + /* If the counter is being destroyed, FreeCounter/miSyncDestroyFence + * will delete the trigger list itself, so don't do it here. + * However, we must NULL out the pTrigger pointer in the trigger list + * node so the destroy loop knows not to dereference it - the backing + * SyncAwait memory is about to be freed below. */ SyncObject *pSync = pAwait->trigger.pSync; - if (pSync && !pSync->beingDestroyed) - SyncDeleteTriggerFromSyncObject(&pAwait->trigger); + if (pSync) { + if (!pSync->beingDestroyed) { + SyncDeleteTriggerFromSyncObject(&pAwait->trigger); + } else { + SyncTriggerList *ptl; + + nt_list_for_each_entry(ptl, pSync->pTriglist, next) { + if (ptl->pTrigger == &pAwait->trigger) { + ptl->pTrigger = NULL; + break; + } + } + } + } } free(pAwaitUnion); return Success; diff --git a/dix/dixfonts.c b/dix/dixfonts.c index 4fdb60699..b7eb09f38 100644 --- a/dix/dixfonts.c +++ b/dix/dixfonts.c @@ -670,6 +670,10 @@ doListFontsAndAliases(ClientPtr client, LFclosurePtr c) * is BadFontName, indicating the alias resolution * is complete. */ + if (resolvedlen > XLFDMAXFONTNAMELEN) { + err = BadFontName; + goto ContBadFontName; + } memcpy(tmp_pattern, resolved, resolvedlen); if (c->haveSaved) { char *tmpname; @@ -932,6 +936,10 @@ doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) memcpy(c->savedName, name, namelen + 1); aliascount = 20; } + if (namelen > XLFDMAXFONTNAMELEN) { + err = BadFontName; + goto ContBadFontName; + } memmove(c->current.pattern, name, namelen); c->current.patlen = namelen; c->current.max_names = 1; diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 1e46d0c72..8a13e34b5 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -1144,8 +1144,7 @@ __glXDisp_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc) ClientPtr client = cl->client; xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc; - /* work around mesa bug, don't use REQUEST_SIZE_MATCH */ - REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq); + REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq); return DoGetFBConfigs(cl, req->screen); } @@ -1366,9 +1365,7 @@ __glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc) ClientPtr client = cl->client; xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc; - /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set - * length to 3 instead of 2 */ - REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq); + REQUEST_SIZE_MATCH(xGLXDestroyPixmapReq); return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP); } @@ -1524,14 +1521,8 @@ __glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc) client->errorValue = req->numAttribs; return BadValue; } -#if 0 - /* mesa sends an additional 8 bytes */ + REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); -#else - if (((sizeof(xGLXChangeDrawableAttributesReq) + - (req->numAttribs << 3)) >> 2) < client->req_len) - return BadLength; -#endif return DoChangeDrawableAttributes(cl->client, req->drawable, req->numAttribs, (CARD32 *) (req + 1)); @@ -1598,8 +1589,7 @@ __glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc) ClientPtr client = cl->client; xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc; - /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */ - REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq); + REQUEST_SIZE_MATCH(xGLXDestroyWindowReq); return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW); } @@ -1960,8 +1950,7 @@ __glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc) ClientPtr client = cl->client; xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc; - /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */ - REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq); + REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq); return DoGetDrawableAttributes(cl, req->drawable); } diff --git a/glx/glxcmdsswap.c b/glx/glxcmdsswap.c index 7d6674470..96382672a 100644 --- a/glx/glxcmdsswap.c +++ b/glx/glxcmdsswap.c @@ -235,7 +235,7 @@ __glXDispSwap_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; - REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq); + REQUEST_SIZE_MATCH(xGLXGetFBConfigsSGIXReq); __GLX_SWAP_INT(&req->screen); return __glXDisp_GetFBConfigsSGIX(cl, pc); @@ -327,7 +327,7 @@ __glXDispSwap_DestroyPixmap(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; - REQUEST_AT_LEAST_SIZE(xGLXDestroyGLXPixmapReq); + REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq); __GLX_SWAP_SHORT(&req->length); __GLX_SWAP_INT(&req->glxpixmap); @@ -440,9 +440,7 @@ __glXDispSwap_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc) client->errorValue = req->numAttribs; return BadValue; } - if (((sizeof(xGLXChangeDrawableAttributesReq) + - (req->numAttribs << 3)) >> 2) < client->req_len) - return BadLength; + REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3); attribs = (CARD32 *) (req + 1); __GLX_SWAP_INT_ARRAY(attribs, req->numAttribs << 1); @@ -514,7 +512,7 @@ __glXDispSwap_DestroyWindow(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; - REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq); + REQUEST_SIZE_MATCH(xGLXDestroyWindowReq); __GLX_SWAP_INT(&req->glxwindow); @@ -723,7 +721,7 @@ __glXDispSwap_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc) __GLX_DECLARE_SWAP_VARIABLES; - REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq); + REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesReq); __GLX_SWAP_SHORT(&req->length); __GLX_SWAP_INT(&req->drawable); diff --git a/include/closestr.h b/include/closestr.h index 60e6f09bc..7567ac6ea 100644 --- a/include/closestr.h +++ b/include/closestr.h @@ -57,7 +57,12 @@ typedef struct _OFclosure { /* ListFontsWithInfo */ -#define XLFDMAXFONTNAMELEN 256 +/* libXfont2 allows font names/aliases up to MAXFONTNAMELEN (1024) bytes in + * fonts.alias files. The server's pattern buffers must be large enough to + * hold resolved alias targets returned by the font library. + * ZDI-CAN-30136 + */ +#define XLFDMAXFONTNAMELEN 1024 typedef struct _LFWIstate { char pattern[XLFDMAXFONTNAMELEN]; int patlen; diff --git a/miext/sync/misync.c b/miext/sync/misync.c index 77b4659c1..0880d1ee1 100644 --- a/miext/sync/misync.c +++ b/miext/sync/misync.c @@ -115,10 +115,14 @@ miSyncDestroyFence(SyncFence * pFence) SyncScreenPrivPtr pScreenPriv = SYNC_SCREEN_PRIV(pScreen); SyncTriggerList *ptl, *pNext; - /* tell all the fence's triggers that the counter has been destroyed */ - for (ptl = pFence->sync.pTriglist; ptl; ptl = pNext) { - (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); - pNext = ptl->next; + /* tell all the fence's triggers that the fence has been destroyed. + * Update pTriglist before each callback and free so that FreeAwait + * sees a valid list head when scanning for triggers to NULL out. + */ + nt_list_for_each_entry_safe(ptl, pNext, pFence->sync.pTriglist, next) { + pFence->sync.pTriglist = pNext; + if (ptl->pTrigger) + (*ptl->pTrigger->CounterDestroyed) (ptl->pTrigger); free(ptl); /* destroy the trigger list as we go */ } diff --git a/xkb/xkb.c b/xkb/xkb.c index c389448e4..ae6a4c09e 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -1616,6 +1616,11 @@ CheckKeyTypes(ClientPtr client, *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4); return 0; } + if (nMaps > XkbMaxLegalKeyCode + 1) { + *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, + XkbMaxLegalKeyCode + 1); + return 0; + } } else if (req->present & XkbKeyTypesMask) { nMaps = xkb->map->num_types; @@ -1647,7 +1652,7 @@ CheckKeyTypes(ClientPtr client, } n = i + req->firstType; width = wire->numLevels; - if (width < 1) { + if (width < 1 || width > XkbMaxShiftLevel) { *nMapsRtrn = _XkbErrCode3(0x04, n, width); return 0; }