URI:
       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;