Introduction
Introduction Statistics Contact Development Disclaimer Help
fix dwm-appicons - sites - public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log
Files
Refs
---
commit 53a3bc9dec3cca309fb4a77d068e4281dcb15a61
parent 8242cafbdac3078762d860c0b75d439bf3331cff
Author: Rumen <[email protected]>
Date: Sun, 1 Jun 2025 14:33:49 +0200
fix dwm-appicons
fixed segfault in dwm-appicons due to a double free
Diffstat:
A dwm.suckless.org/patches/appicons/… | 280 +++++++++++++++++++++++++++…
M dwm.suckless.org/patches/appicons/… | 3 ++-
2 files changed, 282 insertions(+), 1 deletion(-)
---
diff --git a/dwm.suckless.org/patches/appicons/dwm-appicons-20250601-c05f117.di…
@@ -0,0 +1,280 @@
+From c0fcc16b38f41a0ae7638c5ed5718f5aa9747913 Mon Sep 17 00:00:00 2001
+From: Rumen <[email protected]>
+Date: Sun, 1 Jun 2025 12:23:04 +0200
+Subject: [PATCH] fix: segfault when rendering icons
+
+fixed a segfault due to a double free when copying appicons between
+strings
+---
+ config.def.h | 14 ++++--
+ dwm.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ 2 files changed, 147 insertions(+), 7 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 9efa774..3045af6 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -21,14 +21,22 @@ static const char *colors[][3] = {
+ /* tagging */
+ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
++/* appicons */
++/* NOTE: set to 0 to set to default (whitespace) */
++static char outer_separator_beg = '[';
++static char outer_separator_end = ']';
++static char inner_separator = ' ';
++static unsigned truncate_icons_after = 2; /* will default to 1, that is the m…
++static char truncate_symbol[] = "...";
++
+ static const Rule rules[] = {
+ /* xprop(1):
+ * WM_CLASS(STRING) = instance, class
+ * WM_NAME(STRING) = title
+ */
+- /* class instance title tags mask isfloating moni…
+- { "Gimp", NULL, NULL, 0, 1, -1 },
+- { "Firefox", NULL, NULL, 1 << 8, 0, -1 },
++ /* class instance title tags mask isfloating moni…
++ { "Gimp", NULL, NULL, 0, 1, -1, …
++ { "Firefox", NULL, NULL, 1 << 8, 0, -1, …
+ };
+
+ /* layout(s) */
+diff --git a/dwm.c b/dwm.c
+index 1443802..4fe7a6d 100644
+--- a/dwm.c
++++ b/dwm.c
+@@ -85,6 +85,7 @@ typedef struct Monitor Monitor;
+ typedef struct Client Client;
+ struct Client {
+ char name[256];
++ char *appicon;
+ float mina, maxa;
+ int x, y, w, h;
+ int oldx, oldy, oldw, oldh;
+@@ -121,6 +122,7 @@ struct Monitor {
+ unsigned int seltags;
+ unsigned int sellt;
+ unsigned int tagset[2];
++ char **tag_icons;
+ int showbar;
+ int topbar;
+ Client *clients;
+@@ -138,6 +140,7 @@ typedef struct {
+ unsigned int tags;
+ int isfloating;
+ int monitor;
++ const char *appicon;
+ } Rule;
+
+ /* function declarations */
+@@ -160,6 +163,9 @@ static void destroynotify(XEvent *e);
+ static void detach(Client *c);
+ static void detachstack(Client *c);
+ static Monitor *dirtomon(int dir);
++static void remove_outer_separators(char **str);
++static void appiconsappend(char **str, const char *appicon, size_t new_size);
++static void applyappicon(char *tag_icons[], int *icons_per_tag, const Client …
+ static void drawbar(Monitor *m);
+ static void drawbars(void);
+ static void enternotify(XEvent *e);
+@@ -283,7 +289,13 @@ applyrules(Client *c)
+ Monitor *m;
+ XClassHint ch = { NULL, NULL };
+
++ outer_separator_beg = outer_separator_beg ? outer_separator_beg : ' ';
++ outer_separator_end = outer_separator_end ? outer_separator_end : ' ';
++ inner_separator = inner_separator ? inner_separator : ' ';
++ truncate_icons_after = truncate_icons_after > 0 ? truncate_icons_after : …
++
+ /* rule matching */
++ c->appicon = NULL;
+ c->isfloating = 0;
+ c->tags = 0;
+ XGetClassHint(dpy, c->win, &ch);
+@@ -296,6 +308,8 @@ applyrules(Client *c)
+ && (!r->class || strstr(class, r->class))
+ && (!r->instance || strstr(instance, r->instance)))
+ {
++ /* r->appicon is static, so lifetime is sufficient */
++ c->appicon = (char*) r->appicon;
+ c->isfloating = r->isfloating;
+ c->tags |= r->tags;
+ for (m = mons; m && m->num != r->monitor; m = m->next…
+@@ -433,7 +447,7 @@ buttonpress(XEvent *e)
+ if (ev->window == selmon->barwin) {
+ i = x = 0;
+ do
+- x += TEXTW(tags[i]);
++ x += TEXTW(m->tag_icons[i]);
+ while (ev->x >= x && ++i < LENGTH(tags));
+ if (i < LENGTH(tags)) {
+ click = ClkTagBar;
+@@ -508,6 +522,14 @@ cleanupmon(Monitor *mon)
+ }
+ XUnmapWindow(dpy, mon->barwin);
+ XDestroyWindow(dpy, mon->barwin);
++
++ for (int i = 0; i < LENGTH(tags); i++) {
++ if (mon->tag_icons[i]) free(mon->tag_icons[i]);
++ mon->tag_icons[i] = NULL;
++ }
++
++ if (mon->tag_icons) free(mon->tag_icons);
++
+ free(mon);
+ }
+
+@@ -643,6 +665,13 @@ createmon(void)
+ m->lt[0] = &layouts[0];
+ m->lt[1] = &layouts[1 % LENGTH(layouts)];
+ strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
++
++ m->tag_icons = (char**) malloc(LENGTH(tags) * sizeof(char*));
++ if (m->tag_icons == NULL) perror("dwm: malloc()");
++ for (int i = 0; i < LENGTH(tags); i++) {
++ m->tag_icons[i] = NULL;
++ }
++
+ return m;
+ }
+
+@@ -694,6 +723,96 @@ dirtomon(int dir)
+ return m;
+ }
+
++void
++remove_outer_separators(char **str)
++{
++ size_t clean_tag_name_len = strlen(*str) - 2;
++
++ char *temp_tag_name = (char*)
++ malloc(clean_tag_name_len + 1);
++
++ if (temp_tag_name == NULL) perror("dwm: malloc()");
++
++ memset(temp_tag_name, 0, clean_tag_name_len + 1);
++
++ char *clean_tag_name_beg = *str + 1;
++ strncpy(temp_tag_name,
++ clean_tag_name_beg,
++ clean_tag_name_len);
++
++ if (*str) free(*str);
++ *str = temp_tag_name;
++}
++
++void
++appiconsappend(char **str, const char *appicon, size_t new_size)
++{
++ char *temp_tag_name = (char*) malloc(new_size);
++ if (temp_tag_name == NULL) perror("dwm: malloc()");
++
++ /* NOTE: Example format of temp_tag_name (with two appicons):
++ * <outer_sep_beg><appicon><inner_sep><appicon><outer_sep_end>
++ */
++ temp_tag_name = memset(temp_tag_name, 0, new_size);
++
++ temp_tag_name[0] = outer_separator_beg;
++ temp_tag_name[new_size - 2] = outer_separator_end;
++
++ strncpy(temp_tag_name + 1, *str, strlen(*str));
++ temp_tag_name[strlen(temp_tag_name)] = inner_separator;
++
++ strncpy(temp_tag_name + strlen(temp_tag_name),
++ appicon, strlen(appicon));
++
++ if (*str) free(*str);
++ *str = temp_tag_name;
++}
++
++void
++applyappicon(char *tag_icons[], int *icons_per_tag, const Client *c)
++{
++ for (unsigned t = 1, i = 0;
++ i < LENGTH(tags);
++ t <<= 1, i++)
++ {
++ if (c->tags & t) {
++ if (icons_per_tag[i] == 0) {
++ if (tag_icons[i]) free(tag_icons[i]);
++ tag_icons[i] = strndup(c->appicon, strlen(c->appicon));
++ } else {
++ char *icon = NULL;
++ if (icons_per_tag[i] < truncate_icons_after)
++ icon = c->appicon;
++ else if (icons_per_tag[i] == truncate_icons_after)
++ icon = truncate_symbol;
++ else {
++ icons_per_tag[i]++;
++ continue;
++ }
++
++ /* remove outer separators from previous iterations
++ * otherwise they get applied recursively */
++ if (icons_per_tag[i] > 1) {
++ remove_outer_separators(&tag_icons[i]);
++ }
++
++ size_t outer_separators_size = 2;
++ size_t inner_separator_size = 1;
++
++ size_t new_size = strlen(tag_icons[i])
++ + outer_separators_size
++ + inner_separator_size
++ + strlen(icon)
++ + 1;
++
++ appiconsappend(&tag_icons[i], icon, new_size);
++ }
++
++ icons_per_tag[i]++;
++ }
++ }
++}
++
+ void
+ drawbar(Monitor *m)
+ {
+@@ -713,22 +832,35 @@ drawbar(Monitor *m)
+ drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
+ }
+
++ int icons_per_tag[LENGTH(tags)];
++ memset(icons_per_tag, 0, LENGTH(tags) * sizeof(int));
++
++ for (int i = 0; i < LENGTH(tags); i++) {
++ /* set each tag to default value */
++ m->tag_icons[i] = strndup(tags[i], strlen(tags[i]));
++ }
++
+ for (c = m->clients; c; c = c->next) {
++ if (c->appicon && strlen(c->appicon) > 0) {
++ applyappicon(m->tag_icons, icons_per_tag, c);
++ }
++
+ occ |= c->tags;
+ if (c->isurgent)
+ urg |= c->tags;
+ }
+ x = 0;
+ for (i = 0; i < LENGTH(tags); i++) {
+- w = TEXTW(tags[i]);
++ w = TEXTW(m->tag_icons[i]);
+ drw_setscheme(drw, scheme[m->tagset[m->seltags] & 1 << i ? Sc…
+- drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
+- if (occ & 1 << i)
++ drw_text(drw, x, 0, w, bh, lrpad / 2, m->tag_icons[i], urg & …
++ if (occ & 1 << i && icons_per_tag[i] == 0)
+ drw_rect(drw, x + boxs, boxs, boxw, boxw,
+ m == selmon && selmon->sel && selmon->sel->ta…
+ urg & 1 << i);
+ x += w;
+ }
++
+ w = TEXTW(m->ltsymbol);
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
+--
+2.49.0
+
diff --git a/dwm.suckless.org/patches/appicons/index.md b/dwm.suckless.org/patc…
@@ -22,7 +22,8 @@ Each tag can display a maximum of `truncate_icons_after` icon…
Download
--------
-* [dwm-appicons-6.5.diff](dwm-appicons-6.5.diff) (2025-01-04)
+* [dwm-appicons-6.5.diff](dwm-appicons-6.5.diff) (2025-01-04), *deprecated*
+* [dwm-appicons-20250601-c05f117.diff](dwm-appicons-20250601-c05f117.diff) (20…
Author
------
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.