Skip to content

Commit 75c2305

Browse files
authored
Merge pull request #1413 from bynect/fix-gradient
Fix memory corruption when reloading
2 parents edad0e1 + 5642325 commit 75c2305

15 files changed

+152
-89
lines changed

src/dbus.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,9 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
873873
gradient_pattern(grad);
874874

875875
notification_keep_original(n);
876-
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = n->colors.highlight;
877-
n->colors.highlight = grad;
876+
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = gradient_acquire(n->colors.highlight);
877+
gradient_release(n->colors.highlight);
878+
n->colors.highlight = gradient_acquire(grad);
878879

879880
end:
880881
g_variant_unref(dict_value);
@@ -886,8 +887,9 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
886887
gradient_pattern(grad);
887888

888889
notification_keep_original(n);
889-
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = n->colors.highlight;
890-
n->colors.highlight = grad;
890+
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = gradient_acquire(n->colors.highlight);
891+
gradient_release(n->colors.highlight);
892+
n->colors.highlight = gradient_acquire(grad);
891893
}
892894
g_variant_unref(dict_value);
893895
}

src/draw.c

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,29 @@ struct gradient *gradient_alloc(size_t length)
7676
if (length == 0)
7777
return NULL;
7878

79-
struct gradient *grad = g_malloc(sizeof(struct gradient) + length * sizeof(struct color));
79+
struct gradient *grad = g_rc_box_alloc(sizeof(struct gradient) + length * sizeof(struct color));
8080

8181
grad->length = length;
8282
grad->pattern = NULL;
8383

8484
return grad;
8585
}
8686

87-
void gradient_free(struct gradient *grad)
87+
struct gradient *gradient_acquire(struct gradient *grad)
8888
{
89-
if (grad == NULL) return;
89+
return grad != NULL ? g_rc_box_acquire(grad) : NULL;
90+
}
9091

92+
static void gradient_free(struct gradient *grad)
93+
{
9194
if (grad->pattern)
9295
cairo_pattern_destroy(grad->pattern);
96+
}
9397

94-
g_free(grad);
98+
void gradient_release(struct gradient *grad)
99+
{
100+
if (grad != NULL)
101+
g_rc_box_release_full(grad, (GDestroyNotify)gradient_free);
95102
}
96103

97104
void gradient_pattern(struct gradient *grad)
@@ -119,16 +126,19 @@ char *gradient_to_string(const struct gradient *grad)
119126
{
120127
if (!GRADIENT_VALID(grad)) return NULL;
121128

122-
char *buf = g_malloc(grad->length * 11);
123-
color_to_string(grad->colors[0], buf);
124-
char *ptr = buf + 9;
129+
int max = grad->length * 11 + 1;
130+
char *buf = g_malloc(max);
125131

126-
for (int i = 1; i < grad->length; i++) {
127-
ptr += g_snprintf(ptr, 11, ", #%02x%02x%02x%02x",
132+
for (int i = 0, j = 0; i < grad->length; i++) {
133+
j += g_snprintf(buf + j, max - j, "#%02x%02x%02x%02x",
128134
(int)(grad->colors[i].r * 255),
129135
(int)(grad->colors[i].g * 255),
130136
(int)(grad->colors[i].b * 255),
131137
(int)(grad->colors[i].a * 255));
138+
139+
if (i != grad->length - 1) {
140+
j += g_snprintf(buf + j, max - j, ", ");
141+
}
132142
}
133143

134144
return buf;

src/draw.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ struct gradient {
6363

6464
struct gradient *gradient_alloc(size_t length);
6565

66-
void gradient_free(struct gradient *grad);
66+
struct gradient *gradient_acquire(struct gradient *grad);
67+
68+
void gradient_release(struct gradient *grad);
6769

6870
void gradient_pattern(struct gradient *grad);
6971

src/dunst.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,12 @@ void reload(char **const configs)
223223
setup_done = false;
224224
draw_deinit();
225225

226+
g_slist_free_full(rules, (GDestroyNotify)rule_free);
227+
rules = NULL;
228+
229+
settings_free(&settings);
226230
load_settings(configs);
231+
227232
draw_setup();
228233
setup_done = true;
229234

@@ -237,8 +242,6 @@ int dunst_main(int argc, char *argv[])
237242
dunst_status_int(S_PAUSE_LEVEL, 0);
238243
dunst_status(S_IDLE, false);
239244

240-
settings_init();
241-
242245
queues_init();
243246

244247
cmdline_load(argc, argv);
@@ -269,9 +272,9 @@ int dunst_main(int argc, char *argv[])
269272
config_paths[count++] = path;
270273
} while (path != NULL);
271274

272-
settings.print_notifications = cmdline_get_bool("-print/--print", false, "Print notifications to stdout");
275+
print_notifications = cmdline_get_bool("-print/--print", false, "Print notifications to stdout");
273276

274-
settings.startup_notification = cmdline_get_bool("-startup_notification/--startup_notification",
277+
bool startup_notification = cmdline_get_bool("-startup_notification/--startup_notification",
275278
false, "Display a notification on startup.");
276279

277280
/* Help should always be the last to set up as calls to cmdline_get_* (as a side effect) add entries to the usage list. */
@@ -294,7 +297,7 @@ int dunst_main(int argc, char *argv[])
294297
guint term_src = g_unix_signal_add(SIGTERM, quit_signal, NULL);
295298
guint int_src = g_unix_signal_add(SIGINT, quit_signal, NULL);
296299

297-
if (settings.startup_notification) {
300+
if (startup_notification) {
298301
struct notification *n = notification_create();
299302
n->id = 0;
300303
n->appname = g_strdup("dunst");

src/notification.c

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ void notification_run_script(struct notification *n)
162162
safe_setenv("DUNST_URLS", n->urls);
163163
safe_setenv("DUNST_TIMEOUT", n_timeout_str);
164164
safe_setenv("DUNST_TIMESTAMP", n_timestamp_str);
165-
safe_setenv("DUNST_STACK_TAG", n->stack_tag);
166165
safe_setenv("DUNST_DESKTOP_ENTRY", n->desktop_entry);
167166

168167
execlp(script,
@@ -298,35 +297,38 @@ void notification_unref(struct notification *n)
298297
if (!g_atomic_int_dec_and_test(&n->priv->refcount))
299298
return;
300299

301-
if (n->original) {
300+
if (n->original)
302301
rule_free(n->original);
303-
g_free(n->original);
304-
}
305302

303+
g_free(n->dbus_client);
306304
g_free(n->appname);
307305
g_free(n->summary);
308306
g_free(n->body);
309-
g_free(n->iconname);
310-
g_free(n->default_icon_name);
311-
g_free(n->icon_path);
312-
g_free(n->msg);
313-
g_free(n->dbus_client);
314307
g_free(n->category);
315-
g_free(n->text_to_render);
316-
g_free(n->urls);
317-
g_free(n->stack_tag);
318308
g_free(n->desktop_entry);
319309

310+
g_free(n->icon_id);
311+
g_free(n->iconname);
312+
g_free(n->icon_path);
313+
g_free(n->default_icon_name);
314+
320315
g_hash_table_unref(n->actions);
321316
g_free(n->default_action_name);
322317

323318
if (n->icon)
324319
cairo_surface_destroy(n->icon);
325-
g_free(n->icon_id);
326320

327321
notification_private_free(n->priv);
328322

323+
gradient_release(n->colors.highlight);
324+
325+
g_free(n->format);
329326
g_strfreev(n->scripts);
327+
g_free(n->stack_tag);
328+
329+
g_free(n->msg);
330+
g_free(n->text_to_render);
331+
g_free(n->urls);
330332

331333
g_free(n);
332334
}
@@ -392,6 +394,12 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon)
392394
g_object_unref(icon);
393395
}
394396

397+
void notification_replace_format(struct notification *n, const char *format)
398+
{
399+
g_free(n->format);
400+
n->format = g_strdup(format);
401+
}
402+
395403
/* see notification.h */
396404
void notification_replace_single_field(char **haystack,
397405
char **needle,
@@ -434,7 +442,7 @@ struct notification *notification_create(void)
434442
/* Unparameterized default values */
435443
n->first_render = true;
436444
n->markup = MARKUP_FULL;
437-
n->format = settings.format;
445+
n->format = g_strdup(settings.format);
438446

439447
n->timestamp = time_monotonic_now();
440448

@@ -512,7 +520,10 @@ void notification_init(struct notification *n)
512520
if (!COLOR_VALID(n->colors.bg)) n->colors.bg = defcolors.bg;
513521
if (!COLOR_VALID(n->colors.frame)) n->colors.frame = defcolors.frame;
514522

515-
if (!GRADIENT_VALID(n->colors.highlight)) n->colors.highlight = defcolors.highlight;
523+
if (!GRADIENT_VALID(n->colors.highlight)) {
524+
gradient_release(n->colors.highlight);
525+
n->colors.highlight = gradient_acquire(defcolors.highlight);
526+
}
516527

517528
/* Sanitize misc hints */
518529
if (n->progress < 0)
@@ -524,7 +535,7 @@ void notification_init(struct notification *n)
524535
rule_apply_all(n);
525536

526537
if (g_str_has_prefix(n->summary, "DUNST_COMMAND_")) {
527-
char *msg = "DUNST_COMMAND_* has been removed, please switch to dunstctl. See #830 for more details. https://github.com/dunst-project/dunst/pull/830";
538+
const char *msg = "DUNST_COMMAND_* has been removed, please switch to dunstctl. See #830 for more details. https://github.com/dunst-project/dunst/pull/830";
528539
LOG_W("%s", msg);
529540
n->body = string_append(n->body, msg, "\n");
530541
}
@@ -538,7 +549,6 @@ void notification_init(struct notification *n)
538549
if (!n->icon && !n->iconname)
539550
n->iconname = g_strdup(settings.icons[n->urgency]);
540551

541-
542552
/* UPDATE derived fields */
543553
notification_extract_urls(n);
544554
notification_format_message(n);

src/notification.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ struct notification {
8585
char *default_action_name; /**< The name of the action to be invoked on do_action */
8686

8787
enum markup_mode markup;
88-
const char *format;
88+
char *format;
8989
char **scripts;
9090
int script_count;
9191
struct notification_colors colors;
@@ -202,6 +202,8 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon
202202
*/
203203
void notification_icon_replace_data(struct notification *n, GVariant *new_icon);
204204

205+
void notification_replace_format(struct notification *n, const char *format);
206+
205207
/**
206208
* Run the script associated with the
207209
* given notification.

src/option_parser.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,11 +482,13 @@ bool set_rule(struct setting setting, char* value, char* section) {
482482
r = rule_new(section);
483483
LOG_D("Creating new rule '%s'", section);
484484
}
485-
486485
return set_rule_value(r, setting, value);
487486
}
488487

489488
void set_defaults(void) {
489+
LOG_D("Initializing settings");
490+
settings = (struct settings) {0};
491+
490492
for (int i = 0; i < G_N_ELEMENTS(allowed_settings); i++) {
491493
// FIXME Rule settings can only have a default if they have an
492494
// working entry in the settings struct as well. Make an
@@ -706,8 +708,7 @@ void cmdline_usage_append(const char *key, const char *type, const char *descrip
706708
}
707709

708710
char *tmp;
709-
tmp =
710-
g_strdup_printf("%s%-50s - %s\n", usage_str, key_type, description);
711+
tmp = g_strdup_printf("%s%-50s - %s\n", usage_str, key_type, description);
711712
g_free(key_type);
712713

713714
g_free(usage_str);

src/queues.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ int queues_notification_insert(struct notification *n)
207207
notification_icon_replace_path(n, n->iconname);
208208
}
209209

210-
if (settings.print_notifications)
210+
if (print_notifications)
211211
notification_print(n);
212212

213213
return n->id;

0 commit comments

Comments
 (0)