From cf34c17b6383b371d66e1bfca7f0e82bb29fb9ff Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 19 Apr 2023 19:54:12 -0700 Subject: [PATCH] treewide: Fix memory leaks from calls to relocate(). These were all avoidable, and I got tired of seeing message from Address Sanitizer about them. --- src/language/commands/set.c | 6 +++++- src/language/lexer/include-path.c | 2 +- src/libpspp/message.c | 6 +++++- src/libpspp/str.c | 23 +++++++++++++++++++++++ src/libpspp/str.h | 4 +++- src/ui/gui/builder-wrapper.c | 14 +++++++++++++- src/ui/gui/builder-wrapper.h | 4 +--- src/ui/gui/help-menu.c | 20 +++++++++----------- src/ui/gui/main.c | 8 +++----- src/ui/gui/psppire-syntax-window.c | 4 +++- src/ui/gui/psppire-window.c | 4 +++- 11 files changed, 69 insertions(+), 26 deletions(-) diff --git a/src/language/commands/set.c b/src/language/commands/set.c index 7998850127..5994228c7c 100644 --- a/src/language/commands/set.c +++ b/src/language/commands/set.c @@ -1253,7 +1253,11 @@ show_system (const struct dataset *ds UNUSED) add_row (table, N_("Version"), version); add_row (table, N_("Host System"), host_system); add_row (table, N_("Build System"), build_system); - add_row (table, N_("Locale Directory"), relocate (locale_dir)); + + char *allocated; + add_row (table, N_("Locale Directory"), relocate2 (locale_dir, &allocated)); + free (allocated); + add_row (table, N_("Compiler Version"), #ifdef __VERSION__ __VERSION__ diff --git a/src/language/lexer/include-path.c b/src/language/lexer/include-path.c index 96870a5a9a..0c640917b2 100644 --- a/src/language/lexer/include-path.c +++ b/src/language/lexer/include-path.c @@ -83,7 +83,7 @@ include_path_init__ (void) if (home != NULL) string_array_append_nocopy (&the_include_path, xasprintf ("%s/.pspp", home)); - string_array_append (&the_include_path, relocate (PKGDATADIR)); + string_array_append_nocopy (&the_include_path, relocate_clone (PKGDATADIR)); string_array_clone (&default_include_path, &the_include_path); } diff --git a/src/libpspp/message.c b/src/libpspp/message.c index 07cc270787..9b20a2350d 100644 --- a/src/libpspp/message.c +++ b/src/libpspp/message.c @@ -638,10 +638,12 @@ prepare_fatal_error_message (void) const char * prepare_diagnostic_information (void) { + char *allocated; + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "version: %s\n", version); diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "host_system: %s\n", host_system); diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "build_system: %s\n", build_system); - diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "locale_dir: %s\n", relocate (locale_dir)); + diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "locale_dir: %s\n", relocate2 (locale_dir, &allocated)); diagnostic_information_bytes += append_message (diagnostic_information, diagnostic_information_bytes, "compiler version: %s\n", #ifdef __VERSION__ __VERSION__ @@ -650,6 +652,8 @@ prepare_diagnostic_information (void) #endif ); + free (allocated); + return diagnostic_information; } diff --git a/src/libpspp/str.c b/src/libpspp/str.c index 9cd6351e8d..f85844076b 100644 --- a/src/libpspp/str.c +++ b/src/libpspp/str.c @@ -1749,7 +1749,30 @@ ds_relocate (struct string *st) } } +/* Returns a relocated version of S as a malloc()'d string that the caller must + eventually free(). */ +char * +relocate_clone (const char *s) +{ + char *r = CONST_CAST (char *, relocate (s)); + return r != s ? r : xstrdup (s); +} +/* Formats FORMAT in a printf()-like manner and returns a relocated version of + it. The caller must eventually free() the returned string. */ +char * PRINTF_FORMAT (1, 2) MALLOC_LIKE +relocate_format (const char *format, ...) +{ + va_list args; + va_start (args, format); + char *s = xvasprintf (format, args); + va_end (args); + + char *r = CONST_CAST (char *, relocate (s)); + if (r != s) + free (s); + return r; +} /* Operations on uint8_t "strings" */ diff --git a/src/libpspp/str.h b/src/libpspp/str.h index 17584f8920..77ba625dec 100644 --- a/src/libpspp/str.h +++ b/src/libpspp/str.h @@ -262,7 +262,9 @@ char *ds_splice_uninit (struct string *, size_t ofs, size_t old_len, /* Other */ /* calls relocate from gnulib on ST */ void ds_relocate (struct string *st); - +char *relocate_clone (const char *); +char *relocate_format (const char *, ...) + PRINTF_FORMAT (1, 2) MALLOC_LIKE; void u8_buf_copy_rpad (uint8_t *dst, size_t dst_size, const uint8_t *src, size_t src_size, diff --git a/src/ui/gui/builder-wrapper.c b/src/ui/gui/builder-wrapper.c index f856b3e87a..2f3cbdf9cf 100644 --- a/src/ui/gui/builder-wrapper.c +++ b/src/ui/gui/builder-wrapper.c @@ -20,8 +20,10 @@ #include "builder-wrapper.h" +#include "libpspp/str.h" -GtkBuilder * + +static GtkBuilder * builder_new_real (const gchar *name) { GtkBuilder *builder = gtk_builder_new (); @@ -36,6 +38,16 @@ builder_new_real (const gchar *name) return builder; } +GtkBuilder * +builder_new (const gchar *name) +{ + char *full_name = relocate_format ("%s/%s", PKGDATADIR, name); + GtkBuilder *builder = builder_new_real (full_name); + free (full_name); + + return builder; +} + GObject * get_object_assert (GtkBuilder *builder, const gchar *name, GType type) { diff --git a/src/ui/gui/builder-wrapper.h b/src/ui/gui/builder-wrapper.h index db45168f32..755ddcd9cf 100644 --- a/src/ui/gui/builder-wrapper.h +++ b/src/ui/gui/builder-wrapper.h @@ -23,9 +23,7 @@ #include "relocatable.h" #include "gl/configmake.h" -GtkBuilder *builder_new_real (const gchar *name); - -#define builder_new(NAME) (builder_new_real (relocate (PKGDATADIR "/" NAME))) +GtkBuilder *builder_new (const gchar *name); GObject *get_object_assert (GtkBuilder *builder, const gchar *name, GType type); GtkWidget * get_widget_assert (GtkBuilder *builder, const gchar *name); diff --git a/src/ui/gui/help-menu.c b/src/ui/gui/help-menu.c index 403e595058..646c47a383 100644 --- a/src/ui/gui/help-menu.c +++ b/src/ui/gui/help-menu.c @@ -194,14 +194,11 @@ void online_help (const char *page) { GError *htmlerr = NULL; - gchar *htmlfilename = NULL; - gchar *htmlfullname = NULL; gchar *htmluri = NULL; + char *htmlfilename; if (page == NULL) - { - htmlfilename = g_strdup ("index.html"); - } + htmlfilename = xstrdup ("index.html"); else { gchar **tokens = NULL; @@ -215,13 +212,13 @@ online_help (const char *page) tokens = g_strsplit (page, "#", maxtokens); for (idx = 0; idx < maxtokens && tokens[idx]; idx++) ; - htmlfilename = g_strdup_printf ("%s.html", tokens[idx-1]); + htmlfilename = xasprintf ("%s.html", tokens[idx-1]); g_strfreev (tokens); } /* Hint: pspp.html is a directory...*/ - htmlfullname = g_strdup_printf ("%s/%s", relocate (DOCDIR "/pspp.html"), - htmlfilename); - if (g_file_test (relocate (DOCDIR "/pspp.html"), G_FILE_TEST_IS_DIR)) + char *htmldir = relocate_clone (DOCDIR "/pspp.html"); + char *htmlfullname = xasprintf ("%s/%s", htmldir, htmlfilename); + if (g_file_test (htmldir, G_FILE_TEST_IS_DIR)) { GError *urierr = NULL; htmluri = g_filename_to_uri (htmlfullname,NULL, &urierr); @@ -235,8 +232,9 @@ online_help (const char *page) else htmluri = g_strdup_printf (PACKAGE_URL "manual/html_node/%s", htmlfilename); - g_free (htmlfullname); - g_free (htmlfilename); + free (htmlfullname); + free (htmldir); + free (htmlfilename); #ifdef _WIN32 bool ok = open_windows_help (htmluri, &htmlerr); diff --git a/src/ui/gui/main.c b/src/ui/gui/main.c index 3241877d85..e7c917ad41 100644 --- a/src/ui/gui/main.c +++ b/src/ui/gui/main.c @@ -107,11 +107,9 @@ create_splash_window (void) { GtkWidget *sp = gtk_window_new (GTK_WINDOW_TOPLEVEL); - const gchar *filename = PKGDATADIR "/splash.png"; - const char *relocated_filename = relocate (filename); - GtkWidget *l = gtk_image_new_from_file (relocated_filename); - if (filename != relocated_filename) - free (CONST_CAST (char *, relocated_filename)); + char *splash = relocate_clone (PKGDATADIR"/splash.png"); + GtkWidget *l = gtk_image_new_from_file (splash); + free (splash); gtk_container_add (GTK_CONTAINER (sp), l); gtk_window_set_type_hint (GTK_WINDOW (sp), diff --git a/src/ui/gui/psppire-syntax-window.c b/src/ui/gui/psppire-syntax-window.c index 393c2afb5a..3da9bf58f7 100644 --- a/src/ui/gui/psppire-syntax-window.c +++ b/src/ui/gui/psppire-syntax-window.c @@ -157,9 +157,11 @@ psppire_syntax_window_class_init (PsppireSyntaxWindowClass *class) gchar **new_paths = g_strdupv ((gchar **)existing_paths); int n = g_strv_length ((gchar **) existing_paths); + char *pkg_data_dir = relocate_clone (PKGDATADIR); new_paths = g_realloc (new_paths, (n + 2) * sizeof (*new_paths)); - new_paths[n] = g_strdup (relocate (PKGDATADIR)); + new_paths[n] = g_strdup (pkg_data_dir); new_paths[n+1] = NULL; + free (pkg_data_dir); lm = gtk_source_language_manager_new (); gtk_source_language_manager_set_search_path (lm, new_paths); diff --git a/src/ui/gui/psppire-window.c b/src/ui/gui/psppire-window.c index 60f265e443..b636aa18e4 100644 --- a/src/ui/gui/psppire-window.c +++ b/src/ui/gui/psppire-window.c @@ -718,7 +718,9 @@ psppire_window_open (PsppireWindow *de) { GtkWidget *dialog = psppire_window_file_chooser_dialog (de); - gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), relocate (examples_dir), NULL); + char *dir = relocate_clone (examples_dir); + gtk_file_chooser_add_shortcut_folder (GTK_FILE_CHOOSER (dialog), dir, NULL); + free (dir); switch (gtk_dialog_run (GTK_DIALOG (dialog))) { -- 2.30.2