dix: Convert selection list to a linked list.

Fixes a bug where pointers were being invalidated after a realloc.
This commit is contained in:
Eamon Walsh 2008-03-04 02:02:54 -05:00 committed by Eamon Walsh
parent 0bd0f90d7c
commit 72f2197545

View File

@ -66,24 +66,22 @@ SOFTWARE.
*****************************************************************/ *****************************************************************/
_X_EXPORT Selection *CurrentSelections; _X_EXPORT Selection *CurrentSelections;
static int NumCurrentSelections;
CallbackListPtr SelectionCallback; CallbackListPtr SelectionCallback;
_X_EXPORT int _X_EXPORT int
dixLookupSelection(Selection **result, Atom selectionName, dixLookupSelection(Selection **result, Atom selectionName,
ClientPtr client, Mask access_mode) ClientPtr client, Mask access_mode)
{ {
Selection *pSel = NULL; Selection *pSel;
int i, rc = BadMatch; int rc = BadMatch;
client->errorValue = selectionName; client->errorValue = selectionName;
for (i = 0; i < NumCurrentSelections; i++) for (pSel = CurrentSelections; pSel; pSel = pSel->next)
if (CurrentSelections[i].selection == selectionName) { if (pSel->selection == selectionName)
pSel = CurrentSelections + i;
rc = XaceHookSelectionAccess(client, &pSel, access_mode);
break; break;
}
if (pSel)
rc = XaceHookSelectionAccess(client, &pSel, access_mode);
*result = pSel; *result = pSel;
return rc; return rc;
} }
@ -91,14 +89,17 @@ dixLookupSelection(Selection **result, Atom selectionName,
void void
InitSelections(void) InitSelections(void)
{ {
Selection *pSel = CurrentSelections; Selection *pSel, *pNextSel;
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++) pSel = CurrentSelections;
while (pSel) {
pNextSel = pSel->next;
dixFreePrivates(pSel->devPrivates); dixFreePrivates(pSel->devPrivates);
xfree(pSel);
pSel = pNextSel;
}
xfree(CurrentSelections);
CurrentSelections = NULL; CurrentSelections = NULL;
NumCurrentSelections = 0;
} }
static _X_INLINE void static _X_INLINE void
@ -112,9 +113,9 @@ CallSelectionCallback(Selection *pSel, ClientPtr client,
void void
DeleteWindowFromAnySelections(WindowPtr pWin) DeleteWindowFromAnySelections(WindowPtr pWin)
{ {
Selection *pSel = CurrentSelections; Selection *pSel;
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++) for (pSel = CurrentSelections; pSel; pSel = pSel->next)
if (pSel->pWin == pWin) { if (pSel->pWin == pWin) {
CallSelectionCallback(pSel, NULL, SelectionWindowDestroy); CallSelectionCallback(pSel, NULL, SelectionWindowDestroy);
@ -127,9 +128,9 @@ DeleteWindowFromAnySelections(WindowPtr pWin)
void void
DeleteClientFromAnySelections(ClientPtr client) DeleteClientFromAnySelections(ClientPtr client)
{ {
Selection *pSel = CurrentSelections; Selection *pSel;
for (; pSel - CurrentSelections < NumCurrentSelections; pSel++) for (pSel = CurrentSelections; pSel; pSel = pSel->next)
if (pSel->client == client) { if (pSel->client == client) {
CallSelectionCallback(pSel, NULL, SelectionClientClose); CallSelectionCallback(pSel, NULL, SelectionClientClose);
@ -197,23 +198,18 @@ ProcSetSelectionOwner(ClientPtr client)
/* /*
* It doesn't exist, so add it... * It doesn't exist, so add it...
*/ */
int size = (NumCurrentSelections + 1) * sizeof(Selection); pSel = xalloc(sizeof(Selection));
CurrentSelections = xrealloc(CurrentSelections, size); if (!pSel)
if (!CurrentSelections) {
NumCurrentSelections = 0;
return BadAlloc; return BadAlloc;
}
pSel = CurrentSelections + NumCurrentSelections;
pSel->selection = stuff->selection; pSel->selection = stuff->selection;
pSel->devPrivates = NULL; pSel->devPrivates = NULL;
/* security creation/labeling check */ /* security creation/labeling check */
(void)XaceHookSelectionAccess(client, &pSel, DixCreateAccess); (void)XaceHookSelectionAccess(client, &pSel, DixCreateAccess);
pSel->next = NULL; pSel->next = CurrentSelections;
if (NumCurrentSelections > 0) CurrentSelections = pSel;
CurrentSelections[NumCurrentSelections - 1].next = pSel;
NumCurrentSelections++;
} }
else else
return rc; return rc;