1
0
mirror of https://github.com/gryf/wmaker.git synced 2026-07-07 19:26:39 +02:00

Compare commits

...

2 Commits

Author SHA1 Message Date
David Maciejak aa7287efbf wmaker: check RCreateImage() result for _NET_WM_ICON
makeRImageFromARGBData() dereferences image->data immediately after
RCreateImage() without checking for NULL. A client that advertises a
20000x20000 icon makes RCreateImage() try a 1.6 GB malloc, on failure
wmaker segfaults.
2026-05-11 10:09:42 +01:00
David Maciejak 5eb3287535 wmaker: fix integer overflow in _NET_WM_ICON parser
findBestIcon() multiplies two attacker-controlled 32-bit ints (icon
width * height) without overflow checking. A client setting
_NET_WM_ICON = {2, 0x7FFFFFFF} makes "size" wrap to 0 so "i += size"
never advances and wmaker spins forever at 100% CPU.

The same loop also never verifies that the claimed icon actually fits
inside the property buffer, allowing a 2-element property to drive a
multi-KB OOB read in makeRImageFromARGBData().

Validate dimensions against a 4096-pixel cap (safe from unsigned long
overflow) and reject icons whose pixel data would extend past the end
of the property.
2026-05-11 10:09:42 +01:00
+12 -4
View File
@@ -408,6 +408,8 @@ static RImage *makeRImageFromARGBData(unsigned long *data)
return NULL;
image = RCreateImage(width, height, True);
if (!image)
return NULL;
for (imgdata = image->data, i = 2; i < size + 2; i++, imgdata += 4) {
pixel = data[i];
@@ -458,9 +460,11 @@ static RImage *findBestIcon(unsigned long *data, unsigned long items)
/* get the current icon's size */
sx = (int)data[i];
sy = (int)data[i + 1];
if ((sx < 1) || (sy < 1))
if (sx < 1 || sy < 1 || sx > 4096 || sy > 4096)
break;
size = (unsigned long)sx * (unsigned long)sy + 2;
if ((unsigned long)size > items - i)
break;
size = sx * sy + 2;
/* check the size difference if it's not too large */
if ((sx <= wanted) && (sy <= wanted)) {
@@ -485,8 +489,12 @@ static RImage *findBestIcon(unsigned long *data, unsigned long items)
* small image by a small scale. */
largest = 0;
for (i = 0L; i < items - 1;) {
size = (int)data[i] * (int)data[i + 1];
if (size == 0)
sx = (int)data[i];
sy = (int)data[i + 1];
if (sx < 1 || sy < 1 || sx > 4096 || sy > 4096)
break;
size = (unsigned long)sx * (unsigned long)sy;
if ((unsigned long)size + 2 > items - i)
break;
if (size > largest) {
icon = &data[i];