Compare commits

...

11 Commits

Author SHA1 Message Date
Enrico Weigelt, metux IT consult 2957bf04fc randr: add BUG_* checks for possible NULL pointer issue
The ‘RRCrtcNotify() and RRCrtcSet() functions are exported, so there's chance
that a buggy driver could call them with NULL parameter, leading to segfault.
Those are hard to trace, so it's better having a BUG_* check here.

| ../randr/rrcrtc.c: In function ‘RRCrtcNotify’:
| ../randr/rrcrtc.c:187:5: warning: use of NULL ‘outputs’ where non-null expected [CWE-476] [-Wanalyzer-null-argument]
|   187 |     memcpy(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr));
|       |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

| ../randr/rrcrtc.c: In function ‘RRCrtcSet’:
| ../randr/rrcrtc.c:742:20: warning: dereference of NULL ‘outputs’ [CWE-476] [-Wanalyzer-null-dereference]
|   742 |         if (outputs[o]) {
|       |             ~~~~~~~^~~

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:19:54 +02:00
Enrico Weigelt, metux IT consult 6b4894aa07 randr: skip payload assembly in ProcRRGetScreenInfo() no data to send
If there's no data to send, the whole reply payload can be skipped entirely.
This can also ease the whole code flow, and we don't need to rely on the
individual copy loops never trying to dereference a NULL pointer.
(what the analyzer can't proof). Also scoping several some variables that
are only used when there actually is data to send.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:19:48 +02:00
Enrico Weigelt, metux IT consult d93d9af35a randr: skip payload assembly in rrGetScreenResources() no data to send
If there's no data to send, the whole reply payload can be skipped entirely.
This can also ease the whole code flow, and we don't need to rely on the
individual copy loops never trying to dereference a NULL pointer.
(what the analyzer can't proof). Also scoping several some variables that
are only used when there actually is data to send.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:19:24 +02:00
Enrico Weigelt, metux IT consult df85b516c4 randr: simplify reply assembly in ProcRRListProviderProperties()
Moving payload buffer assembly right into the same branch where the buffer is
allocated, so making the whole code flow easier to understand. Also moving the
byteswap there (when the fields should still be in CPU cache), instead of having
some callback doing it much later, so even more simplication.

As a nice by-product, that's also reducing some analyzer noise.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:19:18 +02:00
Enrico Weigelt, metux IT consult e4270e8bcf randr: no need to for local temp buffer in ProcRRQueryProviderProperty()
The code can be much simpler by just using CopySwap32Write().
And we also don't need the callback in WriteSwappedDataToClient(),
just call the corresponding write function directly.

This also makes some analyzer warnings go away.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:49 +02:00
Enrico Weigelt, metux IT consult d0802de141 randr: ProcRRGetOutputInfo() skip payload assembly when nothing to do
If there's no extra payload to send, we can skip the whole payload
assembly chain.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:18 +02:00
Enrico Weigelt, metux IT consult ca9e23c263 randr: simplify extra payload copying in ProcRRGetOutputInfo()
Make it a bit easier to understand how exactly the name string is copied into
the reply payload: just do the little memcpy() right where the target position
is decided any the rest of the payload is filled.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:13 +02:00
Enrico Weigelt, metux IT consult caed2ae6fc randr: RROutputSetCrtcs(): simplify buffer allocation / copying
Instead of relying on memcpy() coping with NULL buffer when size == 0,
move the call to the branch where we actually have things to copy.

This also silences yet another analyzer warning.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:09 +02:00
Enrico Weigelt, metux IT consult 1e47daf592 randr: RROutputSetModes(): simplify buffer allocation / copying
Instead of relying on memcpy() coping with NULL buffer when size == 0,
move the call to the branch where we actually have things to copy.

This also silences yet another analyzer warning.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:04 +02:00
Enrico Weigelt, metux IT consult 6dd0b813ad randr: RROutputSetClones(): simplify buffer allocation / copying
Instead of relying on memcpy() coping with NULL buffer when size == 0,
move the call to the branch where we actually have things to copy.

This also silences yet another analyzer warning.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:18:00 +02:00
Enrico Weigelt, metux IT consult c7a1827541 randr: refine allocation and copying of optional buffers
Simplifying the code flow allocating/checking/copying some buffers in
RRConfigureOutputProperty() and RRConfigureProviderProperty() so it's
easier to understand for both the human reader as well as the analyzer.

Depending on whether we have elements to process, a temporary buffer needs
to be allocated, checked for successful allocation and copy over data. The
way it's currently done is technically correct, but unnecessarily complex to
understand: instead of just branching on whether there are elements and doing
all the buffer-related things only then, the branching is done just somewhere
in the middle, only on checking for allocation failure, and relying on both
calloc() and memcpy() not doing weird things when size is zero.

It's easy to simplify by putting it all behind one if statement and so make
things easier for both human reader as well as the analyzer (so it's not
spilling out false alarms here anymore) and also drops unnecessary calls
in the zero-size case.

Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-05-13 17:17:53 +02:00
5 changed files with 112 additions and 109 deletions

View File

@ -20,12 +20,16 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE. * OF THIS SOFTWARE.
*/ */
#include <dix-config.h>
#include <X11/Xatom.h>
#include "os/bug_priv.h"
#include "randrstr_priv.h" #include "randrstr_priv.h"
#include "swaprep.h" #include "swaprep.h"
#include "mipointer.h" #include "mipointer.h"
#include <X11/Xatom.h>
RESTYPE RRCrtcType = 0; RESTYPE RRCrtcType = 0;
@ -181,10 +185,13 @@ RRCrtcNotify(RRCrtcPtr crtc,
crtc->outputs = newoutputs; crtc->outputs = newoutputs;
crtc->numOutputs = numOutputs; crtc->numOutputs = numOutputs;
} }
/* /*
* Copy the new list of outputs into the crtc * Copy the new list of outputs into the crtc
*/ */
BUG_RETURN_VAL(outputs == NULL, FALSE);
memcpy(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr)); memcpy(crtc->outputs, outputs, numOutputs * sizeof(RROutputPtr));
/* /*
* Update remaining crtc fields * Update remaining crtc fields
*/ */
@ -735,6 +742,8 @@ RRCrtcSet(RRCrtcPtr crtc,
Bool crtcChanged; Bool crtcChanged;
int o; int o;
BUG_RETURN_VAL(outputs == NULL, FALSE);
rrScrPriv(pScreen); rrScrPriv(pScreen);
crtcChanged = FALSE; crtcChanged = FALSE;

View File

@ -119,7 +119,6 @@ RROutputCreate(ScreenPtr pScreen,
Bool Bool
RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones) RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
{ {
RROutputPtr *newClones;
int i; int i;
if (numClones == output->numClones) { if (numClones == output->numClones) {
@ -129,15 +128,16 @@ RROutputSetClones(RROutputPtr output, RROutputPtr * clones, int numClones)
if (i == numClones) if (i == numClones)
return TRUE; return TRUE;
} }
RROutputPtr *newClones = NULL;
if (numClones) { if (numClones) {
newClones = xallocarray(numClones, sizeof(RROutputPtr)); newClones = xallocarray(numClones, sizeof(RROutputPtr));
if (!newClones) if (!newClones)
return FALSE; return FALSE;
memcpy(newClones, clones, numClones * sizeof(RROutputPtr));
} }
else
newClones = NULL;
free(output->clones); free(output->clones);
memcpy(newClones, clones, numClones * sizeof(RROutputPtr));
output->clones = newClones; output->clones = newClones;
output->numClones = numClones; output->numClones = numClones;
RROutputChanged(output, TRUE); RROutputChanged(output, TRUE);
@ -148,7 +148,6 @@ Bool
RROutputSetModes(RROutputPtr output, RROutputSetModes(RROutputPtr output,
RRModePtr * modes, int numModes, int numPreferred) RRModePtr * modes, int numModes, int numPreferred)
{ {
RRModePtr *newModes;
int i; int i;
if (numModes == output->numModes && numPreferred == output->numPreferred) { if (numModes == output->numModes && numPreferred == output->numPreferred) {
@ -162,19 +161,19 @@ RROutputSetModes(RROutputPtr output,
} }
} }
RRModePtr *newModes = NULL;
if (numModes) { if (numModes) {
newModes = xallocarray(numModes, sizeof(RRModePtr)); newModes = xallocarray(numModes, sizeof(RRModePtr));
if (!newModes) if (!newModes)
return FALSE; return FALSE;
memcpy(newModes, modes, numModes * sizeof(RRModePtr));
} }
else
newModes = NULL;
if (output->modes) { if (output->modes) {
for (i = 0; i < output->numModes; i++) for (i = 0; i < output->numModes; i++)
RRModeDestroy(output->modes[i]); RRModeDestroy(output->modes[i]);
free(output->modes); free(output->modes);
} }
memcpy(newModes, modes, numModes * sizeof(RRModePtr));
output->modes = newModes; output->modes = newModes;
output->numModes = numModes; output->numModes = numModes;
output->numPreferred = numPreferred; output->numPreferred = numPreferred;
@ -251,7 +250,6 @@ RROutputDeleteUserMode(RROutputPtr output, RRModePtr mode)
Bool Bool
RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs) RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
{ {
RRCrtcPtr *newCrtcs;
int i; int i;
if (numCrtcs == output->numCrtcs) { if (numCrtcs == output->numCrtcs) {
@ -261,15 +259,16 @@ RROutputSetCrtcs(RROutputPtr output, RRCrtcPtr * crtcs, int numCrtcs)
if (i == numCrtcs) if (i == numCrtcs)
return TRUE; return TRUE;
} }
RRCrtcPtr *newCrtcs = NULL;
if (numCrtcs) { if (numCrtcs) {
newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr)); newCrtcs = xallocarray(numCrtcs, sizeof(RRCrtcPtr));
if (!newCrtcs) if (!newCrtcs)
return FALSE; return FALSE;
memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr));
} }
else
newCrtcs = NULL;
free(output->crtcs); free(output->crtcs);
memcpy(newCrtcs, crtcs, numCrtcs * sizeof(RRCrtcPtr));
output->crtcs = newCrtcs; output->crtcs = newCrtcs;
output->numCrtcs = numCrtcs; output->numCrtcs = numCrtcs;
RROutputChanged(output, TRUE); RROutputChanged(output, TRUE);
@ -439,14 +438,12 @@ ProcRRGetOutputInfo(ClientPtr client)
REQUEST(xRRGetOutputInfoReq); REQUEST(xRRGetOutputInfoReq);
xRRGetOutputInfoReply rep; xRRGetOutputInfoReply rep;
RROutputPtr output; RROutputPtr output;
CARD8 *extra;
unsigned long extraLen; unsigned long extraLen;
ScreenPtr pScreen; ScreenPtr pScreen;
rrScrPrivPtr pScrPriv; rrScrPrivPtr pScrPriv;
RRCrtc *crtcs; RRCrtc *crtcs;
RRMode *modes; RRMode *modes;
RROutput *clones; RROutput *clones;
char *name;
int i; int i;
Bool leased; Bool leased;
@ -458,6 +455,8 @@ ProcRRGetOutputInfo(ClientPtr client)
pScreen = output->pScreen; pScreen = output->pScreen;
pScrPriv = rrGetScrPriv(pScreen); pScrPriv = rrGetScrPriv(pScreen);
CARD8 *extra = NULL;
if (leased) { if (leased) {
rep = (xRRGetOutputInfoReply) { rep = (xRRGetOutputInfoReply) {
.type = X_Reply, .type = X_Reply,
@ -470,16 +469,14 @@ ProcRRGetOutputInfo(ClientPtr client)
.nameLength = output->nameLength .nameLength = output->nameLength
}; };
extraLen = bytes_to_int32(rep.nameLength) << 2; extraLen = bytes_to_int32(rep.nameLength) << 2;
if (extraLen) { if (!extraLen)
rep.length += bytes_to_int32(extraLen); goto sendout;
extra = calloc(1, extraLen);
if (!extra)
return BadAlloc;
}
else
extra = NULL;
name = (char *) extra; rep.length += bytes_to_int32(extraLen);
extra = calloc(1, extraLen);
if (!extra)
return BadAlloc;
memcpy(extra, output->name, output->nameLength);
} else { } else {
rep = (xRRGetOutputInfoReply) { rep = (xRRGetOutputInfoReply) {
.type = X_Reply, .type = X_Reply,
@ -502,25 +499,26 @@ ProcRRGetOutputInfo(ClientPtr client)
output->numModes + output->numUserModes + output->numModes + output->numUserModes +
output->numClones + bytes_to_int32(rep.nameLength)) << 2); output->numClones + bytes_to_int32(rep.nameLength)) << 2);
if (extraLen) { if (!extraLen)
rep.length += bytes_to_int32(extraLen); goto sendout;
extra = calloc(1, extraLen);
if (!extra) rep.length += bytes_to_int32(extraLen);
return BadAlloc; extra = calloc(1, extraLen);
} if (!extra)
else return BadAlloc;
extra = NULL;
crtcs = (RRCrtc *) extra; crtcs = (RRCrtc *) extra;
modes = (RRMode *) (crtcs + output->numCrtcs); modes = (RRMode *) (crtcs + output->numCrtcs);
clones = (RROutput *) (modes + output->numModes + output->numUserModes); clones = (RROutput *) (modes + output->numModes + output->numUserModes);
name = (char *) (clones + output->numClones);
memcpy((clones + output->numClones), output->name, output->nameLength);
for (i = 0; i < output->numCrtcs; i++) { for (i = 0; i < output->numCrtcs; i++) {
crtcs[i] = output->crtcs[i]->id; crtcs[i] = output->crtcs[i]->id;
if (client->swapped) if (client->swapped)
swapl(&crtcs[i]); swapl(&crtcs[i]);
} }
for (i = 0; i < output->numModes + output->numUserModes; i++) { for (i = 0; i < output->numModes + output->numUserModes; i++) {
if (i < output->numModes) if (i < output->numModes)
modes[i] = output->modes[i]->mode.id; modes[i] = output->modes[i]->mode.id;
@ -535,7 +533,8 @@ ProcRRGetOutputInfo(ClientPtr client)
swapl(&clones[i]); swapl(&clones[i]);
} }
} }
memcpy(name, output->name, output->nameLength);
sendout:
if (client->swapped) { if (client->swapped) {
swaps(&rep.sequenceNumber); swaps(&rep.sequenceNumber);
swapl(&rep.length); swapl(&rep.length);
@ -549,11 +548,10 @@ ProcRRGetOutputInfo(ClientPtr client)
swaps(&rep.nClones); swaps(&rep.nClones);
swaps(&rep.nameLength); swaps(&rep.nameLength);
} }
WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep); WriteToClient(client, sizeof(xRRGetOutputInfoReply), &rep);
if (extraLen) { WriteToClient(client, extraLen, extra);
WriteToClient(client, extraLen, extra); free(extra);
free(extra);
}
return Success; return Success;
} }

View File

@ -359,7 +359,6 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property,
{ {
RRPropertyPtr prop = RRQueryOutputProperty(output, property); RRPropertyPtr prop = RRQueryOutputProperty(output, property);
Bool add = FALSE; Bool add = FALSE;
INT32 *new_values;
if (!prop) { if (!prop) {
prop = RRCreateOutputProperty(property); prop = RRCreateOutputProperty(property);
@ -379,14 +378,17 @@ RRConfigureOutputProperty(RROutputPtr output, Atom property,
return BadMatch; return BadMatch;
} }
new_values = xallocarray(num_values, sizeof(INT32)); INT32 *new_values = NULL;
if (!new_values && num_values) {
if (add) if (num_values) {
RRDestroyOutputProperty(prop); new_values = calloc(num_values, sizeof(INT32));
return BadAlloc; if (!new_values) {
} if (add)
if (num_values) RRDestroyOutputProperty(prop);
return BadAlloc;
}
memcpy(new_values, values, num_values * sizeof(INT32)); memcpy(new_values, values, num_values * sizeof(INT32));
}
/* /*
* Property moving from pending to non-pending * Property moving from pending to non-pending

View File

@ -327,7 +327,6 @@ RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
{ {
RRPropertyPtr prop = RRQueryProviderProperty(provider, property); RRPropertyPtr prop = RRQueryProviderProperty(provider, property);
Bool add = FALSE; Bool add = FALSE;
INT32 *new_values;
if (!prop) { if (!prop) {
prop = RRCreateProviderProperty(property); prop = RRCreateProviderProperty(property);
@ -347,14 +346,16 @@ RRConfigureProviderProperty(RRProviderPtr provider, Atom property,
return BadMatch; return BadMatch;
} }
new_values = xallocarray(num_values, sizeof(INT32)); INT32 *new_values = NULL;
if (!new_values && num_values) { if (num_values) {
if (add) new_values = calloc(num_values, sizeof(INT32));
RRDestroyProviderProperty(prop); if (!new_values) {
return BadAlloc; if (add)
} RRDestroyProviderProperty(prop);
if (num_values) return BadAlloc;
}
memcpy(new_values, values, num_values * sizeof(INT32)); memcpy(new_values, values, num_values * sizeof(INT32));
}
/* /*
* Property moving from pending to non-pending * Property moving from pending to non-pending
@ -384,7 +385,7 @@ int
ProcRRListProviderProperties(ClientPtr client) ProcRRListProviderProperties(ClientPtr client)
{ {
REQUEST(xRRListProviderPropertiesReq); REQUEST(xRRListProviderPropertiesReq);
Atom *pAtoms = NULL, *temppAtoms; Atom *pAtoms = NULL;
int numProps = 0; int numProps = 0;
RRProviderPtr provider; RRProviderPtr provider;
RRPropertyPtr prop; RRPropertyPtr prop;
@ -395,9 +396,20 @@ ProcRRListProviderProperties(ClientPtr client)
for (prop = provider->properties; prop; prop = prop->next) for (prop = provider->properties; prop; prop = prop->next)
numProps++; numProps++;
if (numProps)
if (!(pAtoms = xallocarray(numProps, sizeof(Atom)))) const Bool swapped = client->swapped;
if (numProps) {
if (!(pAtoms = calloc(numProps, sizeof(Atom))))
return BadAlloc; return BadAlloc;
Atom *temppAtoms = pAtoms;
for (prop = provider->properties; prop; prop = prop->next) {
*temppAtoms = prop->propertyName;
if (swapped)
swapl(temppAtoms);
temppAtoms++;
}
}
xRRListProviderPropertiesReply rep = { xRRListProviderPropertiesReply rep = {
.type = X_Reply, .type = X_Reply,
@ -405,21 +417,16 @@ ProcRRListProviderProperties(ClientPtr client)
.length = bytes_to_int32(numProps * sizeof(Atom)), .length = bytes_to_int32(numProps * sizeof(Atom)),
.nAtoms = numProps .nAtoms = numProps
}; };
if (client->swapped) { if (swapped) {
swaps(&rep.sequenceNumber); swaps(&rep.sequenceNumber);
swapl(&rep.length); swapl(&rep.length);
swaps(&rep.nAtoms); swaps(&rep.nAtoms);
} }
temppAtoms = pAtoms;
for (prop = provider->properties; prop; prop = prop->next)
*temppAtoms++ = prop->propertyName;
WriteToClient(client, sizeof(xRRListProviderPropertiesReply), (char *) &rep); WriteToClient(client, sizeof(xRRListProviderPropertiesReply), (char *) &rep);
if (numProps) { WriteToClient(client, numProps * sizeof(Atom), pAtoms);
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); free(pAtoms);
free(pAtoms);
}
return Success; return Success;
} }
@ -429,7 +436,6 @@ ProcRRQueryProviderProperty(ClientPtr client)
REQUEST(xRRQueryProviderPropertyReq); REQUEST(xRRQueryProviderPropertyReq);
RRProviderPtr provider; RRProviderPtr provider;
RRPropertyPtr prop; RRPropertyPtr prop;
char *extra = NULL;
REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq); REQUEST_SIZE_MATCH(xRRQueryProviderPropertyReq);
@ -439,12 +445,6 @@ ProcRRQueryProviderProperty(ClientPtr client)
if (!prop) if (!prop)
return BadName; return BadName;
if (prop->num_valid) {
extra = xallocarray(prop->num_valid, sizeof(INT32));
if (!extra)
return BadAlloc;
}
xRRQueryProviderPropertyReply rep = { xRRQueryProviderPropertyReply rep = {
.type = X_Reply, .type = X_Reply,
.sequenceNumber = client->sequence, .sequenceNumber = client->sequence,
@ -459,11 +459,10 @@ ProcRRQueryProviderProperty(ClientPtr client)
} }
WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep); WriteToClient(client, sizeof(xRRQueryProviderPropertyReply), (char *) &rep);
if (prop->num_valid) { if (prop->num_valid) {
memcpy(extra, prop->valid_values, prop->num_valid * sizeof(INT32)); if (client->swapped)
client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; CopySwap32Write(client, prop->num_valid * sizeof(INT32), (CARD32*)prop->valid_values);
WriteSwappedDataToClient(client, prop->num_valid * sizeof(INT32), else
extra); WriteToClient(client, prop->num_valid * sizeof(INT32), prop->valid_values);
free(extra);
} }
return Success; return Success;
} }

View File

@ -488,10 +488,6 @@ rrGetScreenResources(ClientPtr client, Bool query)
CARD8 *extra = NULL; CARD8 *extra = NULL;
unsigned long extraLen = 0; unsigned long extraLen = 0;
int i, rc, has_primary = 0; int i, rc, has_primary = 0;
RRCrtc *crtcs;
RROutput *outputs;
xRRModeInfo *modeinfos;
CARD8 *names;
REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq); REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
@ -543,20 +539,19 @@ rrGetScreenResources(ClientPtr client, Bool query)
bytes_to_int32(rep.nbytesNames)); bytes_to_int32(rep.nbytesNames));
extraLen = rep.length << 2; extraLen = rep.length << 2;
if (extraLen) { if (!extraLen)
extra = calloc(1, extraLen); goto finish;
if (!extra) {
free(modes);
return BadAlloc;
}
}
else
extra = NULL;
crtcs = (RRCrtc *) extra; extra = calloc(1, extraLen);
outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs); if (!extra) {
modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs); free(modes);
names = (CARD8 *) (modeinfos + num_modes); return BadAlloc;
}
RRCrtc *crtcs = (RRCrtc *) extra;
RROutput *outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
xRRModeInfo *modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
CARD8* names = (CARD8 *) (modeinfos + num_modes);
if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) { if (pScrPriv->primaryOutput && pScrPriv->primaryOutput->crtc) {
has_primary = 1; has_primary = 1;
@ -604,8 +599,9 @@ rrGetScreenResources(ClientPtr client, Bool query)
memcpy(names, mode->name, mode->mode.nameLength); memcpy(names, mode->name, mode->mode.nameLength);
names += mode->mode.nameLength; names += mode->mode.nameLength;
} }
free(modes);
assert(bytes_to_int32((char *) names - (char *) extra) == rep.length); assert(bytes_to_int32((char *) names - (char *) extra) == rep.length);
finish:
free(modes);
} }
if (client->swapped) { if (client->swapped) {
@ -777,8 +773,6 @@ ProcRRGetScreenInfo(ClientPtr client)
} }
else { else {
int i, j; int i, j;
xScreenSizes *size;
CARD16 *rates;
CARD8 *data8; CARD8 *data8;
Bool has_rate = RRClientKnowsRates(client); Bool has_rate = RRClientKnowsRates(client);
RR10DataPtr pData; RR10DataPtr pData;
@ -806,21 +800,20 @@ ProcRRGetScreenInfo(ClientPtr client)
if (has_rate) if (has_rate)
extraLen += rep.nrateEnts * sizeof(CARD16); extraLen += rep.nrateEnts * sizeof(CARD16);
if (extraLen) { if (!extraLen)
extra = (CARD8 *) malloc(extraLen); goto finish; // no extra payload
if (!extra) {
free(pData); extra = calloc(1, extraLen);
return BadAlloc; if (!extra) {
} free(pData);
return BadAlloc;
} }
else
extra = NULL;
/* /*
* First comes the size information * First comes the size information
*/ */
size = (xScreenSizes *) extra; xScreenSizes *size = (xScreenSizes *) extra;
rates = (CARD16 *) (size + rep.nSizes); CARD16 *rates = (CARD16 *) (size + rep.nSizes);
for (i = 0; i < pData->nsize; i++) { for (i = 0; i < pData->nsize; i++) {
pSize = &pData->sizes[i]; pSize = &pData->sizes[i];
size->widthInPixels = pSize->width; size->widthInPixels = pSize->width;
@ -849,7 +842,6 @@ ProcRRGetScreenInfo(ClientPtr client)
} }
} }
} }
free(pData);
data8 = (CARD8 *) rates; data8 = (CARD8 *) rates;
@ -857,6 +849,9 @@ ProcRRGetScreenInfo(ClientPtr client)
FatalError("RRGetScreenInfo bad extra len %ld != %ld\n", FatalError("RRGetScreenInfo bad extra len %ld != %ld\n",
(unsigned long) (data8 - (CARD8 *) extra), extraLen); (unsigned long) (data8 - (CARD8 *) extra), extraLen);
rep.length = bytes_to_int32(extraLen); rep.length = bytes_to_int32(extraLen);
finish:
free(pData);
} }
if (client->swapped) { if (client->swapped) {
swaps(&rep.sequenceNumber); swaps(&rep.sequenceNumber);