dwm: Fix heap buffer overflow in getatomprop - dwm - dynamic window manager
HTML git clone git://git.suckless.org/dwm
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
DIR commit 244fa852fe2775cf52a3901966cd6d8700df8227
DIR parent 7c3abae4e68b6a21f05cb04f3af31217259c0aa9
HTML Author: Chris Down <chris@chrisdown.name>
Date: Wed, 7 Jan 2026 22:02:00 +0800
dwm: Fix heap buffer overflow in getatomprop
When getatomprop() is called, it invokes XGetWindowProperty() to
retrieve an Atom. If the property exists but has zero elements (length
0), Xlib returns Success and sets p to a valid, non-NULL memory address
containing a single null byte.
However, dl (that is, the number of items) is 0. dwm blindly casts p to
Atom* and dereferences it. While Xlib guarantees that p is safe to read
as a string (that is, it is null-terminated), it does _not_ guarantee it
is safe to read as an Atom (an unsigned long).
The Atom type is a typedef for unsigned long. Reading an Atom (which
thus will either likely be 4 or 8 bytes) from a 1-byte allocated buffer
results in a heap buffer overflow. Since property content is user
controlled, this allows any client to trigger an out of bounds read
simply by setting a property with format 32 and length 0.
An example client which reliably crashes dwm under ASAN:
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
Display *d;
Window root, w;
Atom net_wm_state;
d = XOpenDisplay(NULL);
if (!d) return 1;
root = DefaultRootWindow(d);
w = XCreateSimpleWindow(d, root, 10, 10, 200, 200, 1, 0, 0);
net_wm_state = XInternAtom(d, "_NET_WM_STATE", False);
if (net_wm_state == None) return 1;
XChangeProperty(d, w, net_wm_state, XA_ATOM, 32,
PropModeReplace, NULL, 0);
XMapWindow(d, w);
XSync(d, False);
sleep(1);
XCloseDisplay(d);
return 0;
}
In order to avoid this, check that the number of items returned is
greater than zero before dereferencing the pointer.
Diffstat:
M dwm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
---
DIR diff --git a/dwm.c b/dwm.c
@@ -870,7 +870,8 @@ getatomprop(Client *c, Atom prop)
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
&da, &di, &dl, &dl, &p) == Success && p) {
- atom = *(Atom *)p;
+ if (dl > 0)
+ atom = *(Atom *)p;
XFree(p);
}
return atom;