From 1bc6ca30a924e36893b0a604051762821163b66a Mon Sep 17 00:00:00 2001 From: "Enrico Weigelt, metux IT consult" Date: Mon, 29 Jul 2024 18:23:15 +0200 Subject: [PATCH] randr: ProcRRGetMonitors(): collect reply payload in temporary buffer Instead of arbitrary count of individual WriteToClient() calls on small chunks, collect the whole payload in a buffer and write it out all at once. This also makes possible to use generic macros for reply sending, as well as further simplifications in the write-out path. Signed-off-by: Enrico Weigelt, metux IT consult Part-of: --- randr/rrmonitor.c | 44 ++++++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/randr/rrmonitor.c b/randr/rrmonitor.c index db33d117c..661dee32e 100644 --- a/randr/rrmonitor.c +++ b/randr/rrmonitor.c @@ -604,11 +604,13 @@ ProcRRGetMonitors(ClientPtr client) noutputs += monitors[m].numOutputs; } + int payload_len = noutputs * sizeof(CARD32) + nmonitors * sizeof(xRRMonitorInfo); + xRRGetMonitorsReply rep = { .type = X_Reply, .sequenceNumber = client->sequence, .timestamp = RRMonitorTimestamp(screen), - .length = noutputs + nmonitors * bytes_to_int32(sizeof(xRRMonitorInfo)), + .length = bytes_to_int32(payload_len), .nmonitors = nmonitors, .noutputs = noutputs, }; @@ -622,9 +624,18 @@ ProcRRGetMonitors(ClientPtr client) } WriteToClient(client, sizeof(xRRGetMonitorsReply), &rep); + char *payload_buf = calloc(1, payload_len); + if (!payload_buf) { + RRMonitorFreeList(monitors, nmonitors); + return BadAlloc; + } + + char *walk = payload_buf; + for (m = 0; m < nmonitors; m++) { RRMonitorPtr monitor = &monitors[m]; - xRRMonitorInfo info = { + xRRMonitorInfo *info = (xRRMonitorInfo*) walk; + *info = (xRRMonitorInfo) { .name = monitor->name, .primary = monitor->primary, .automatic = monitor->automatic, @@ -637,26 +648,27 @@ ProcRRGetMonitors(ClientPtr client) .heightInMillimeters = monitor->geometry.mmHeight, }; if (client->swapped) { - swapl(&info.name); - swaps(&info.noutput); - swaps(&info.x); - swaps(&info.y); - swaps(&info.width); - swaps(&info.height); - swapl(&info.widthInMillimeters); - swapl(&info.heightInMillimeters); + swapl(&info->name); + swaps(&info->noutput); + swaps(&info->x); + swaps(&info->y); + swaps(&info->width); + swaps(&info->height); + swapl(&info->widthInMillimeters); + swapl(&info->heightInMillimeters); } - RROutput outputs[monitor->numOutputs]; - memcpy(outputs, monitor->outputs, monitor->numOutputs * sizeof (RROutput)); - + walk += sizeof(xRRMonitorInfo); + memcpy(walk, monitor->outputs, monitor->numOutputs * sizeof (RROutput)); if (client->swapped) - SwapLongs(outputs, monitor->numOutputs); + SwapLongs((CARD32*)walk, monitor->numOutputs); - WriteToClient(client, sizeof(xRRMonitorInfo), &info); - WriteToClient(client, sizeof(outputs), outputs); + walk += monitor->numOutputs * sizeof (RROutput); } + WriteToClient(client, payload_len, payload_buf); + + free(payload_buf); RRMonitorFreeList(monitors, nmonitors); return Success;