[gimp] libgimpbase: do not assume PATH_MAX to be the actual max size of paths.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] libgimpbase: do not assume PATH_MAX to be the actual max size of paths.
- Date: Sat, 20 Mar 2021 17:54:32 +0000 (UTC)
commit 47fbfc2f0e9bf8c210e7dc4ecf7a02afbc827c82
Author: Jehan <jehan girinstud io>
Date: Sat Mar 20 18:40:32 2021 +0100
libgimpbase: do not assume PATH_MAX to be the actual max size of paths.
Even though it is set by Linux's limits.h and apparently by other OSes
too, it seems this macro is mostly bogus. On many systems, the actual
allowed max size of paths is much higher.
On Hurd, they don't even define the macro as there is no upper limit.
See MR !424.
This commit replaces two usages of PATH_MAX:
- readlink() by g_file_read_link(). I checked the GLib implementation
and could confirm it will do the proper thing, which is progressively
incrementing their buffer allocation in a loop until the buffer is big
enough to contain the symbolic link contents. Hence no need to rely on
a bogus macro which is not the actual max.
- fgets() by g_data_input_stream_read_line() which also dynamically
allocates the returned buffer, and also properly removes the newline
and adds a NUL byte (hence simpler code).
Additionally I loop through the lines of /proc/self/maps until I find
the first "r-xp" pathname. Indeed the current code was assuming that the
first line was always right. Yet on my OS at least, the first line was
GIMP executable with "r--p" permission, hence the test would fail. The
second line had the right permission. So let's assume that we want the
first executable path, looping through each line.
libgimpbase/gimpreloc.c | 166 ++++++++++++++++++++++--------------------------
1 file changed, 75 insertions(+), 91 deletions(-)
---
diff --git a/libgimpbase/gimpreloc.c b/libgimpbase/gimpreloc.c
index 7ed1783b3c..48f3b5048d 100644
--- a/libgimpbase/gimpreloc.c
+++ b/libgimpbase/gimpreloc.c
@@ -22,6 +22,7 @@
#include <unistd.h>
#endif /* ENABLE_RELOCATABLE_RESOURCES && ! G_OS_WIN32 */
+#include <gio/gio.h>
#include <glib.h>
#include <glib/gstdio.h>
@@ -41,139 +42,122 @@ _br_find_exe (GimpBinrelocInitError *error)
*error = GIMP_RELOC_INIT_ERROR_DISABLED;
return NULL;
#else
- char *path, *path2, *line, *result;
- size_t buf_size;
- ssize_t size;
- struct stat stat_buf;
- FILE *f;
-
- /* Read from /proc/self/exe (symlink) */
- if (sizeof (path) > SSIZE_MAX)
- buf_size = SSIZE_MAX - 1;
- else
- buf_size = PATH_MAX - 1;
- path = g_try_new (char, buf_size);
- if (path == NULL)
- {
- /* Cannot allocate memory. */
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_NOMEM;
- return NULL;
- }
- path2 = g_try_new (char, buf_size);
- if (path2 == NULL)
- {
- /* Cannot allocate memory. */
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_NOMEM;
- g_free (path);
- return NULL;
- }
+ GDataInputStream *data_input;
+ GInputStream *input;
+ GFile *file;
+ GError *gerror = NULL;
+ gchar *path;
+ gchar *sym_path;
+ gchar *maps_line;
- g_strlcpy (path2, "/proc/self/exe", buf_size);
+ sym_path = g_strdup ("/proc/self/exe");
while (1)
{
- int i;
-
- size = readlink (path2, path, buf_size - 1);
- if (size == -1)
+ struct stat stat_buf;
+ int i;
+
+ /* Do not use readlink() with a buffer of size PATH_MAX because
+ * some systems actually allow paths of bigger size. Thus this
+ * macro is kind of bogus. Some systems like Hurd will not even
+ * define it (see MR !424).
+ * g_file_read_link() on the other hand will return a size of
+ * appropriate size, with newline removed and NUL terminator
+ * added.
+ */
+ path = g_file_read_link (sym_path, &gerror);
+ g_free (sym_path);
+ if (! path)
{
- /* Error. */
- g_free (path2);
+ /* Read link fails but we can try reading /proc/self/maps as
+ * an alternate method.
+ */
+ g_printerr ("%s: %s\n", G_STRFUNC, gerror->message);
+ g_error_free (gerror);
+
break;
}
- /* readlink() success. */
- path[size] = '\0';
-
/* Check whether the symlink's target is also a symlink.
* We want to get the final target. */
i = stat (path, &stat_buf);
if (i == -1)
{
/* Error. */
- g_free (path2);
break;
}
/* stat() success. */
- if (!S_ISLNK (stat_buf.st_mode))
+ if (! S_ISLNK (stat_buf.st_mode))
{
/* path is not a symlink. Done. */
- g_free (path2);
return path;
}
/* path is a symlink. Continue loop and resolve this. */
- g_strlcpy (path, path2, buf_size);
+ sym_path = path;
}
-
/* readlink() or stat() failed; this can happen when the program is
* running in Valgrind 2.2. Read from /proc/self/maps as fallback. */
- buf_size = PATH_MAX + 128;
- line = (char *) g_try_realloc (path, buf_size);
- if (line == NULL)
+ file = g_file_new_for_path ("/proc/self/maps");
+ input = G_INPUT_STREAM (g_file_read (file, NULL, &gerror));
+ g_object_unref (file);
+ if (! input)
{
- /* Cannot allocate memory. */
- g_free (path);
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_NOMEM;
- return NULL;
- }
+ g_printerr ("%s: %s", G_STRFUNC, gerror->message);
+ g_error_free (gerror);
- f = g_fopen ("/proc/self/maps", "r");
- if (f == NULL)
- {
- g_free (line);
if (error)
*error = GIMP_RELOC_INIT_ERROR_OPEN_MAPS;
- return NULL;
- }
- /* The first entry should be the executable name. */
- result = fgets (line, (int) buf_size, f);
- if (result == NULL)
- {
- fclose (f);
- g_free (line);
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_READ_MAPS;
return NULL;
}
- /* Get rid of newline character. */
- buf_size = strlen (line);
- if (buf_size == 0)
+ data_input = g_data_input_stream_new (input);
+ g_object_unref (input);
+
+ /* The first entry with r-xp permission should be the executable name. */
+ while ((maps_line = g_data_input_stream_read_line (data_input, NULL, NULL, &gerror)))
{
- /* Huh? An empty string? */
- fclose (f);
- g_free (line);
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_INVALID_MAPS;
- return NULL;
- }
- if (line[buf_size - 1] == 10)
- line[buf_size - 1] = 0;
+ if (maps_line == NULL)
+ {
+ if (gerror)
+ {
+ g_printerr ("%s: %s\n", G_STRFUNC, gerror->message);
+ g_error_free (gerror);
+ }
+ g_object_unref (data_input);
- /* Extract the filename; it is always an absolute path. */
- path = strchr (line, '/');
+ if (error)
+ *error = GIMP_RELOC_INIT_ERROR_READ_MAPS;
- /* Sanity check. */
- if (strstr (line, " r-xp ") == NULL || path == NULL)
- {
- fclose (f);
- g_free (line);
- if (error)
- *error = GIMP_RELOC_INIT_ERROR_INVALID_MAPS;
- return NULL;
+ return NULL;
+ }
+
+ /* Extract the filename; it is always an absolute path. */
+ path = strchr (maps_line, '/');
+
+ /* Sanity check. */
+ if (path && strstr (maps_line, " r-xp "))
+ {
+ /* We found the executable name. */
+ path = g_strdup (path);
+ break;
+ }
+
+ g_free (maps_line);
+ maps_line = NULL;
+ path = NULL;
}
- path = g_strdup (path);
- g_free (line);
- fclose (f);
+ if (path == NULL && error)
+ *error = GIMP_RELOC_INIT_ERROR_INVALID_MAPS;
+
+ g_object_unref (data_input);
+ g_free (maps_line);
+
return path;
#endif /* ! ENABLE_RELOCATABLE_RESOURCES || G_OS_WIN32 */
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]