summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRami Ylimäki <ext-rami.ylimaki@nokia.com>2010-06-22 14:57:20 +0300
committerKeith Packard <keithp@keithp.com>2010-06-22 11:43:36 -0700
commit8b65f2edb407521e0ac0e207e5d5358986bd46da (patch)
tree483bef618539953c863427968b9725a80cd85f7d
parent660f6ab5494a728c3ca7ba00c305e9ff06c8ecb2 (diff)
record: Prevent a crash on recording client disconnect.
Execute the following steps to reproduce the issue. 1. Run at least two recording clients simultaneously. $ cnee --record --request-range 1-127 & $ cnee --record --request-range 1-127 & 2. Kill the recording clients. $ killall cnee 3. Give X server something to do so that the clients are closed. $ xinput list $ xinput list As a result RecordUninstallHooks accesses NullClient, because RecordAClientStateChange doesn't clean the recording clients up properly. Fix RecordUninstallHooks to fail locally on an assertion instead of much later in privates code, if NullClient is still accessed because of some other bug. Fix RecordAClientStateChange to iterate through all contexts so that modifications of the iterated array during iteration don't cause contexts to be skipped. Signed-off-by: Rami Ylimäki <ext-rami.ylimaki@nokia.com> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--record/record.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/record/record.c b/record/record.c
index 06006f76d..6a93d7a5c 100644
--- a/record/record.c
+++ b/record/record.c
@@ -997,10 +997,11 @@ RecordUninstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient)
ClientPtr pClient = clients[CLIENT_ID(client)];
int c;
Bool otherRCAPwantsProcVector = FALSE;
- RecordClientPrivatePtr pClientPriv =
- RecordClientPrivate(pClient);
+ RecordClientPrivatePtr pClientPriv = NULL;
- assert (pClient && RecordClientPrivate(pClient));
+ assert (pClient);
+ pClientPriv = RecordClientPrivate(pClient);
+ assert (pClientPriv);
memcpy(pClientPriv->recordVector, pClientPriv->originalVector,
sizeof (pClientPriv->recordVector));
@@ -2813,6 +2814,8 @@ RecordAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer callda
NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
int i;
ClientPtr pClient = pci->client;
+ RecordContextPtr *ppAllContextsCopy = NULL;
+ int numContextsCopy = 0;
switch (pClient->clientState)
{
@@ -2834,10 +2837,17 @@ RecordAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer callda
case ClientStateGone:
case ClientStateRetained: /* client disconnected */
- for (i = 0; i < numContexts; i++)
+
+ /* RecordDisableContext modifies contents of ppAllContexts. */
+ numContextsCopy = numContexts;
+ ppAllContextsCopy = malloc(numContextsCopy * sizeof(RecordContextPtr));
+ assert(ppAllContextsCopy);
+ memcpy(ppAllContextsCopy, ppAllContexts, numContextsCopy * sizeof(RecordContextPtr));
+
+ for (i = 0; i < numContextsCopy; i++)
{
RecordClientsAndProtocolPtr pRCAP;
- RecordContextPtr pContext = ppAllContexts[i];
+ RecordContextPtr pContext = ppAllContextsCopy[i];
int pos;
if (pContext->pRecordingClient == pClient)
@@ -2851,6 +2861,8 @@ RecordAClientStateChange(CallbackListPtr *pcbl, pointer nulldata, pointer callda
RecordDeleteClientFromRCAP(pRCAP, pos);
}
}
+
+ free(ppAllContextsCopy);
break;
default: