Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix memory corruption when reloading #1413

Merged
merged 4 commits into from
Dec 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/dbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,8 +873,9 @@ static struct notification *dbus_message_to_notification(const gchar *sender, GV
gradient_pattern(grad);

notification_keep_original(n);
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = n->colors.highlight;
n->colors.highlight = grad;
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = gradient_acquire(n->colors.highlight);
gradient_release(n->colors.highlight);
n->colors.highlight = gradient_acquire(grad);

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

notification_keep_original(n);
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = n->colors.highlight;
n->colors.highlight = grad;
if (!GRADIENT_VALID(n->original->highlight)) n->original->highlight = gradient_acquire(n->colors.highlight);
gradient_release(n->colors.highlight);
n->colors.highlight = gradient_acquire(grad);
}
g_variant_unref(dict_value);
}
Expand Down
28 changes: 19 additions & 9 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,29 @@ struct gradient *gradient_alloc(size_t length)
if (length == 0)
return NULL;

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

grad->length = length;
grad->pattern = NULL;

return grad;
}

void gradient_free(struct gradient *grad)
struct gradient *gradient_acquire(struct gradient *grad)
{
if (grad == NULL) return;
return grad != NULL ? g_rc_box_acquire(grad) : NULL;
}

static void gradient_free(struct gradient *grad)
{
if (grad->pattern)
cairo_pattern_destroy(grad->pattern);
}

g_free(grad);
void gradient_release(struct gradient *grad)
{
if (grad != NULL)
g_rc_box_release_full(grad, (GDestroyNotify)gradient_free);
}

void gradient_pattern(struct gradient *grad)
Expand Down Expand Up @@ -119,16 +126,19 @@ char *gradient_to_string(const struct gradient *grad)
{
if (!GRADIENT_VALID(grad)) return NULL;

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

for (int i = 1; i < grad->length; i++) {
ptr += g_snprintf(ptr, 11, ", #%02x%02x%02x%02x",
for (int i = 0, j = 0; i < grad->length; i++) {
j += g_snprintf(buf + j, max - j, "#%02x%02x%02x%02x",
(int)(grad->colors[i].r * 255),
(int)(grad->colors[i].g * 255),
(int)(grad->colors[i].b * 255),
(int)(grad->colors[i].a * 255));

if (i != grad->length - 1) {
j += g_snprintf(buf + j, max - j, ", ");
}
}

return buf;
Expand Down
4 changes: 3 additions & 1 deletion src/draw.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ struct gradient {

struct gradient *gradient_alloc(size_t length);

void gradient_free(struct gradient *grad);
struct gradient *gradient_acquire(struct gradient *grad);

void gradient_release(struct gradient *grad);

void gradient_pattern(struct gradient *grad);

Expand Down
13 changes: 8 additions & 5 deletions src/dunst.c
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,12 @@ void reload(char **const configs)
setup_done = false;
draw_deinit();

g_slist_free_full(rules, (GDestroyNotify)rule_free);
rules = NULL;

settings_free(&settings);
load_settings(configs);

draw_setup();
setup_done = true;

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

settings_init();

queues_init();

cmdline_load(argc, argv);
Expand Down Expand Up @@ -269,9 +272,9 @@ int dunst_main(int argc, char *argv[])
config_paths[count++] = path;
} while (path != NULL);

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

settings.startup_notification = cmdline_get_bool("-startup_notification/--startup_notification",
bool startup_notification = cmdline_get_bool("-startup_notification/--startup_notification",
false, "Display a notification on startup.");

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

if (settings.startup_notification) {
if (startup_notification) {
struct notification *n = notification_create();
n->id = 0;
n->appname = g_strdup("dunst");
Expand Down
44 changes: 27 additions & 17 deletions src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ void notification_run_script(struct notification *n)
safe_setenv("DUNST_URLS", n->urls);
safe_setenv("DUNST_TIMEOUT", n_timeout_str);
safe_setenv("DUNST_TIMESTAMP", n_timestamp_str);
safe_setenv("DUNST_STACK_TAG", n->stack_tag);
safe_setenv("DUNST_DESKTOP_ENTRY", n->desktop_entry);

execlp(script,
Expand Down Expand Up @@ -298,35 +297,38 @@ void notification_unref(struct notification *n)
if (!g_atomic_int_dec_and_test(&n->priv->refcount))
return;

if (n->original) {
if (n->original)
rule_free(n->original);
g_free(n->original);
}

g_free(n->dbus_client);
g_free(n->appname);
g_free(n->summary);
g_free(n->body);
g_free(n->iconname);
g_free(n->default_icon_name);
g_free(n->icon_path);
g_free(n->msg);
g_free(n->dbus_client);
g_free(n->category);
g_free(n->text_to_render);
g_free(n->urls);
g_free(n->stack_tag);
g_free(n->desktop_entry);

g_free(n->icon_id);
g_free(n->iconname);
g_free(n->icon_path);
g_free(n->default_icon_name);

g_hash_table_unref(n->actions);
g_free(n->default_action_name);

if (n->icon)
cairo_surface_destroy(n->icon);
g_free(n->icon_id);

notification_private_free(n->priv);

gradient_release(n->colors.highlight);

g_free(n->format);
g_strfreev(n->scripts);
g_free(n->stack_tag);

g_free(n->msg);
g_free(n->text_to_render);
g_free(n->urls);

g_free(n);
}
Expand Down Expand Up @@ -392,6 +394,12 @@ void notification_icon_replace_data(struct notification *n, GVariant *new_icon)
g_object_unref(icon);
}

void notification_replace_format(struct notification *n, const char *format)
{
g_free(n->format);
n->format = g_strdup(format);
}

/* see notification.h */
void notification_replace_single_field(char **haystack,
char **needle,
Expand Down Expand Up @@ -434,7 +442,7 @@ struct notification *notification_create(void)
/* Unparameterized default values */
n->first_render = true;
n->markup = MARKUP_FULL;
n->format = settings.format;
n->format = g_strdup(settings.format);

n->timestamp = time_monotonic_now();

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

if (!GRADIENT_VALID(n->colors.highlight)) n->colors.highlight = defcolors.highlight;
if (!GRADIENT_VALID(n->colors.highlight)) {
gradient_release(n->colors.highlight);
n->colors.highlight = gradient_acquire(defcolors.highlight);
}

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

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


/* UPDATE derived fields */
notification_extract_urls(n);
notification_format_message(n);
Expand Down
4 changes: 3 additions & 1 deletion src/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ struct notification {
char *default_action_name; /**< The name of the action to be invoked on do_action */

enum markup_mode markup;
const char *format;
char *format;
char **scripts;
int script_count;
struct notification_colors colors;
Expand Down Expand Up @@ -202,6 +202,8 @@ void notification_icon_replace_path(struct notification *n, const char *new_icon
*/
void notification_icon_replace_data(struct notification *n, GVariant *new_icon);

void notification_replace_format(struct notification *n, const char *format);

/**
* Run the script associated with the
* given notification.
Expand Down
7 changes: 4 additions & 3 deletions src/option_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,13 @@ bool set_rule(struct setting setting, char* value, char* section) {
r = rule_new(section);
LOG_D("Creating new rule '%s'", section);
}

return set_rule_value(r, setting, value);
}

void set_defaults(void) {
LOG_D("Initializing settings");
settings = (struct settings) {0};

for (int i = 0; i < G_N_ELEMENTS(allowed_settings); i++) {
// FIXME Rule settings can only have a default if they have an
// working entry in the settings struct as well. Make an
Expand Down Expand Up @@ -689,8 +691,7 @@ void cmdline_usage_append(const char *key, const char *type, const char *descrip
}

char *tmp;
tmp =
g_strdup_printf("%s%-50s - %s\n", usage_str, key_type, description);
tmp = g_strdup_printf("%s%-50s - %s\n", usage_str, key_type, description);
g_free(key_type);

g_free(usage_str);
Expand Down
2 changes: 1 addition & 1 deletion src/queues.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ int queues_notification_insert(struct notification *n)
notification_icon_replace_path(n, n->iconname);
}

if (settings.print_notifications)
if (print_notifications)
notification_print(n);

return n->id;
Expand Down
Loading
Loading