Compare commits

..
9 Commits
Author SHA1 Message Date
Hiltjo Posthuma bfb071698a getline: add check for len > 0
This condition cannot happen here though.
2026-10-27 21:10:35 +01:00
Hiltjo Posthuma 7c0334de3d check integer overflow for multiplication before realloc 2026-10-27 21:09:38 +01:00
Hiltjo Posthuma 8627d0c659 check return value of XCreateIC() 2026-10-16 13:05:13 +02:00
Hiltjo Posthuma 61e0072c3e keypress, check if len > 0 just in case before reading buf
I'm not sure if this can happen, but check it just in case:

Maybe possible when:

len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
len == 0 and case XLookupChars would be executed on a keypress.

Reported by: jb19357 <jb19357@protonmail.com>
Who used Claude to write a report.

I cannot reproduce this issue, but it seems logical.
2026-09-13 20:48:49 +02:00
Hiltjo Posthuma 0785a28f1d fix out-of-bounds read of the Xinerama screen array with no screens
This can happen if dmenu is run with Xinerama enabled and no screens are
detected.

Also fallback to the first screen if there is no intersection of the root
pointer to the screens found.

Reported by: jb19357 <jb19357@protonmail.com>
Who used Claude to write a report.

I cannot reproduce this issue, but it seems logical.
2026-09-13 20:39:14 +02:00
Hiltjo Posthuma 5453bb65d9 fix crash with long prompt and pressing the end key in horizontal mode
Reproducable with:

printf 'a\nb\n' | ./dmenu -p "$(printf 'x%.0s' $(seq 1 400))"

and then pressing the end key.

Reported by: jb19357 <jb19357@protonmail.com>
Who used Claude to write a report.
2026-09-13 20:31:37 +02:00
Julien Addé 7175c4880b add -of and -ob arguments for outline colors options for multi-selection 2026-01-30 11:09:51 +01:00
Hiltjo Posthuma 8b48986f4c drw.c: drw_scm_free: call free inside
Because drw_scm_create() allocates it.
2025-09-29 18:47:16 +02:00
Hiltjo Posthuma 77f96d704b cleanup schemes and colors 2025-09-27 12:10:37 +02:00
4 changed files with 57 additions and 9 deletions

No files matched your search

+10
View File
@@ -20,6 +20,10 @@ dmenu \- dynamic menu
.IR color ]
.RB [ \-sf
.IR color ]
.RB [ \-ob
.IR color ]
.RB [ \-of
.IR color ]
.RB [ \-w
.IR windowid ]
.P
@@ -75,6 +79,12 @@ defines the selected background color.
.BI \-sf " color"
defines the selected foreground color.
.TP
.BI \-ob " color"
defines the outline background color (for multiple selection).
.TP
.BI \-of " color"
defines the outline foreground color (for multiple selection).
.TP
.B \-v
prints version information to stdout, then exits.
.TP
+19 -6
View File
@@ -1,6 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include <ctype.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -102,7 +103,7 @@ cleanup(void)
XUngrabKeyboard(dpy, CurrentTime);
for (i = 0; i < SchemeLast; i++)
free(scheme[i]);
drw_scm_free(drw, scheme[i], 2);
for (i = 0; items && items[i].text; ++i)
free(items[i].text);
free(items);
@@ -171,7 +172,7 @@ drawmenu(void)
/* draw vertical list */
for (item = curr; item != next; item = item->right)
drawitem(item, x, y += bh, mw - x);
} else if (matches) {
} else if (matches && curr) {
/* draw horizontal list */
x += inputw;
w = TEXTW("<");
@@ -414,7 +415,7 @@ keypress(XKeyEvent *ev)
switch(ksym) {
default:
insert:
if (!iscntrl((unsigned char)*buf))
if (len > 0 && !iscntrl((unsigned char)*buf))
insert(buf, len);
break;
case XK_Delete:
@@ -556,10 +557,12 @@ readstdin(void)
for (i = 0; (len = getline(&line, &linesiz, stdin)) != -1; i++) {
if (i + 1 >= itemsiz) {
itemsiz += 256;
if (itemsiz > SIZE_MAX / sizeof(*items))
die("too many items");
if (!(items = realloc(items, itemsiz * sizeof(*items))))
die("cannot realloc %zu bytes:", itemsiz * sizeof(*items));
}
if (line[len - 1] == '\n')
if (len > 0 && line[len - 1] == '\n')
line[len - 1] = '\0';
if (!(items[i].text = strdup(line)))
die("strdup:");
@@ -639,6 +642,8 @@ setup(void)
#ifdef XINERAMA
i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
if (n < 1)
die("Xinerama reported no screens");
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n)
i = mon;
@@ -661,6 +666,9 @@ setup(void)
for (i = 0; i < n; i++)
if (INTERSECT(x, y, 1, 1, info[i]) != 0)
break;
/* fallback to the first screen if there is no intersection */
if (i >= n)
i = 0;
x = info[i].x_org;
y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
@@ -693,8 +701,9 @@ setup(void)
if ((xim = XOpenIM(dpy, NULL, NULL, NULL)) == NULL)
die("XOpenIM failed: could not open input device");
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win, XNFocusWindow, win, NULL);
if ((xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
XNClientWindow, win, XNFocusWindow, win, NULL)) == NULL)
die("XCreateIC failed: could not obtain input context");
XMapRaised(dpy, win);
if (embed) {
@@ -755,6 +764,10 @@ main(int argc, char *argv[])
colors[SchemeSel][ColBg] = argv[++i];
else if (!strcmp(argv[i], "-sf")) /* selected foreground color */
colors[SchemeSel][ColFg] = argv[++i];
else if (!strcmp(argv[i], "-ob")) /* outline background color */
colors[SchemeOut][ColBg] = argv[++i];
else if (!strcmp(argv[i], "-of")) /* outline foreground color */
colors[SchemeOut][ColFg] = argv[++i];
else if (!strcmp(argv[i], "-w")) /* embedding window id */
embed = argv[++i];
else
+26 -3
View File
@@ -178,8 +178,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
die("error, cannot allocate color '%s'", clrname);
}
/* Wrapper to create color schemes. The caller has to call free(3) on the
* returned color scheme when done using it. */
/* Create color schemes. */
Clr *
drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
{
@@ -187,7 +186,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
Clr *ret;
/* need at least two colors for a scheme */
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(Clr))))
return NULL;
for (i = 0; i < clrcount; i++)
@@ -195,6 +194,30 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
return ret;
}
void
drw_clr_free(Drw *drw, Clr *c)
{
if (!drw || !c)
return;
/* c is typedef XftColor Clr */
XftColorFree(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
DefaultColormap(drw->dpy, drw->screen), c);
}
void
drw_scm_free(Drw *drw, Clr *scm, size_t clrcount)
{
size_t i;
if (!drw || !scm)
return;
for (i = 0; i < clrcount; i++)
drw_clr_free(drw, &scm[i]);
free(scm);
}
void
drw_setfontset(Drw *drw, Fnt *set)
{
+2
View File
@@ -40,7 +40,9 @@ void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned in
/* Colorscheme abstraction */
void drw_clr_create(Drw *drw, Clr *dest, const char *clrname);
void drw_clr_free(Drw *drw, Clr *c);
Clr *drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount);
void drw_scm_free(Drw *drw, Clr *scm, size_t clrcount);
/* Cursor abstraction */
Cur *drw_cur_create(Drw *drw, int shape);