diff --git a/gio/glocalfile.c b/gio/glocalfile.c index 72ef947d4..5d01a4baf 100644 --- a/gio/glocalfile.c +++ b/gio/glocalfile.c @@ -1511,7 +1511,7 @@ g_local_file_delete (GFile *file, { int errsv = errno; - /* Posix allows EEXIST too, but the more sane error + /* Posix allows EEXIST too, but the clearer error is G_IO_ERROR_NOT_FOUND, and it's what nautilus expects */ if (errsv == EEXIST) diff --git a/gio/gmenumodel.c b/gio/gmenumodel.c index 8ca45e098..b3f3fb7d9 100644 --- a/gio/gmenumodel.c +++ b/gio/gmenumodel.c @@ -309,7 +309,7 @@ g_menu_model_real_iterate_item_attributes (GMenuModel *model, else { g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_attributes() " - "and fails to return sane values from get_item_attributes()", + "and fails to return valid values from get_item_attributes()", G_OBJECT_TYPE_NAME (model)); result = NULL; } @@ -373,7 +373,7 @@ g_menu_model_real_iterate_item_links (GMenuModel *model, else { g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_links() " - "and fails to return sane values from get_item_links()", + "and fails to return valid values from get_item_links()", G_OBJECT_TYPE_NAME (model)); result = NULL; } diff --git a/glib/gcharset.c b/glib/gcharset.c index 9db56f732..bb775bda4 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -315,7 +315,7 @@ g_get_console_charset (const char **charset) g_free (emsg); } } - /* fall-back to UTF-8 if the rest failed (it's a sane and universal default) */ + /* fall-back to UTF-8 if the rest failed (it's a universal default) */ if (raw == NULL) raw = "UTF-8"; diff --git a/glib/gconstructor.h b/glib/gconstructor.h index 603c2dde6..9509e595f 100644 --- a/glib/gconstructor.h +++ b/glib/gconstructor.h @@ -1,6 +1,6 @@ /* If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and - destructors, in a sane way, including e.g. on library unload. If not you're on + destructors, in a usable way, including e.g. on library unload. If not you're on your own. Some compilers need #pragma to handle this, which does not work with macros, diff --git a/glib/gdate.c b/glib/gdate.c index b867ba9db..ec7b95bef 100644 --- a/glib/gdate.c +++ b/glib/gdate.c @@ -83,8 +83,8 @@ * * #GDate is simple to use. First you need a "blank" date; you can get a * dynamically allocated date from g_date_new(), or you can declare an - * automatic variable or array and initialize it to a sane state by - * calling g_date_clear(). A cleared date is sane; it's safe to call + * automatic variable or array and initialize it by + * calling g_date_clear(). A cleared date is safe; it's safe to call * g_date_set_dmy() and the other mutator functions to initialize the * value of a cleared date. However, a cleared date is initially * invalid, meaning that it doesn't represent a day that exists. @@ -146,7 +146,7 @@ * * If it's declared on the stack, it will contain garbage so must be * initialized with g_date_clear(). g_date_clear() makes the date invalid - * but sane. An invalid date doesn't represent a day, it's "empty." A date + * but safe. An invalid date doesn't represent a day, it's "empty." A date * becomes valid after you set it to a Julian day or you set a day, month, * and year. */ @@ -259,7 +259,7 @@ * g_date_new: * * Allocates a #GDate and initializes - * it to a sane state. The new date will + * it to a safe state. The new date will * be cleared (as if you'd called g_date_clear()) but invalid (it won't * represent an existing day). Free the return value with g_date_free(). * @@ -862,7 +862,7 @@ g_date_days_between (const GDate *d1, * @date: pointer to one or more dates to clear * @n_dates: number of dates to clear * - * Initializes one or more #GDate structs to a sane but invalid + * Initializes one or more #GDate structs to a safe but invalid * state. The cleared dates will not represent an existing date, but will * not contain garbage. Useful to init a date declared on the stack. * Validity can be tested with g_date_valid(). @@ -2055,7 +2055,7 @@ g_date_compare (const GDate *lhs, * @tm: (not nullable): struct tm to fill * * Fills in the date-related bits of a struct tm using the @date value. - * Initializes the non-date parts with something sane but meaningless. + * Initializes the non-date parts with something safe but meaningless. */ void g_date_to_struct_tm (const GDate *d, diff --git a/glib/gdate.h b/glib/gdate.h index 3bc07bf5c..65fe811fa 100644 --- a/glib/gdate.h +++ b/glib/gdate.h @@ -178,7 +178,7 @@ GLIB_AVAILABLE_IN_ALL guint g_date_get_iso8601_week_of_year (const GDate *date); /* If you create a static date struct you need to clear it to get it - * in a sane state before use. You can clear a whole array at + * in a safe state before use. You can clear a whole array at * once with the ndates argument. */ GLIB_AVAILABLE_IN_ALL diff --git a/glib/gdatetime.c b/glib/gdatetime.c index e85a00f56..f93d7d88c 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -935,9 +935,8 @@ g_date_time_new_from_unix (GTimeZone *tz, * time zone @tz. The time is as accurate as the system allows, to a * maximum accuracy of 1 microsecond. * - * This function will always succeed unless the system clock is set to - * truly insane values (or unless GLib is still being used after the - * year 9999). + * This function will always succeed unless GLib is still being used after the + * year 9999. * * You should release the return value by calling g_date_time_unref() * when you are done with it. diff --git a/glib/gspawn.c b/glib/gspawn.c index 85813ef00..e8141ad94 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -155,12 +155,16 @@ extern char **environ; */ +static gint safe_close (gint fd); static gint g_execute (const gchar *file, - gchar **argv, - gchar **envp, - gboolean search_path, - gboolean search_path_from_envp); + gchar **argv, + gchar **argv_buffer, + gsize argv_buffer_len, + gchar **envp, + const gchar *search_path, + gchar *search_path_buffer, + gsize search_path_buffer_len); static gboolean fork_exec_with_pipes (gboolean intermediate_child, const gchar *working_directory, @@ -262,6 +266,9 @@ g_spawn_async (const gchar *working_directory, /* Avoids a danger in threaded situations (calling close() * on a file descriptor twice, and another thread has * re-opened it since the first close) + * + * This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static void close_and_invalidate (gint *fd) @@ -270,7 +277,7 @@ close_and_invalidate (gint *fd) return; else { - (void) g_close (*fd, NULL); + safe_close (*fd); *fd = -1; } } @@ -1081,6 +1088,8 @@ g_spawn_check_exit_status (gint exit_status, return ret; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gssize write_all (gint fd, gconstpointer vbuf, gsize to_write) { @@ -1104,6 +1113,8 @@ write_all (gint fd, gconstpointer vbuf, gsize to_write) return TRUE; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ G_GNUC_NORETURN static void write_err_and_exit (gint fd, gint msg) @@ -1116,6 +1127,8 @@ write_err_and_exit (gint fd, gint msg) _exit (1); } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static int set_cloexec (void *data, gint fd) { @@ -1125,8 +1138,10 @@ set_cloexec (void *data, gint fd) return 0; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gint -sane_close (gint fd) +safe_close (gint fd) { gint ret; @@ -1137,11 +1152,13 @@ sane_close (gint fd) return ret; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ G_GNUC_UNUSED static int close_func (void *data, int fd) { if (fd >= GPOINTER_TO_INT (data)) - (void) sane_close (fd); + (void) safe_close (fd); return 0; } @@ -1156,6 +1173,8 @@ struct linux_dirent64 char d_name[]; /* Filename (null-terminated) */ }; +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gint filename_to_fd (const char *p) { @@ -1169,7 +1188,7 @@ filename_to_fd (const char *p) while ((c = *p++) != '\0') { - if (!g_ascii_isdigit (c)) + if (c < '0' || c > '9') return -1; c -= '0'; @@ -1184,6 +1203,8 @@ filename_to_fd (const char *p) } #endif +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static int safe_fdwalk (int (*cb)(void *data, int fd), void *data) { @@ -1200,11 +1221,11 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) * may be slow on non-Linux operating systems, especially on systems allowing * very high number of open file descriptors. */ - gint open_max; + gint open_max = -1; gint fd; gint res = 0; -#ifdef HAVE_SYS_RESOURCE_H +#if 0 && defined(HAVE_SYS_RESOURCE_H) struct rlimit rl; #endif @@ -1232,22 +1253,41 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) } } - sane_close (dir_fd); + safe_close (dir_fd); return res; } /* If /proc is not mounted or not accessible we fall back to the old - * rlimit trick */ + * rlimit trick. */ #endif -#ifdef HAVE_SYS_RESOURCE_H - - if (getrlimit(RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) - open_max = rl.rlim_max; - else +#if 0 && defined(HAVE_SYS_RESOURCE_H) + /* Use getrlimit() function provided by the system if it is known to be + * async-signal safe. + * + * Currently there are no operating systems known to provide a safe + * implementation, so this section is not used for now. + */ + if (getrlimit (RLIMIT_NOFILE, &rl) == 0 && rl.rlim_max != RLIM_INFINITY) + open_max = rl.rlim_max; #endif - open_max = sysconf (_SC_OPEN_MAX); +#if defined(__FreeBSD__) || defined(__OpenBSD__) + /* Use sysconf() function provided by the system if it is known to be + * async-signal safe. + * + * FreeBSD: sysconf() is included in the list of async-signal safe functions + * found in https://man.freebsd.org/sigaction(2). + * + * OpenBSD: sysconf() is included in the list of async-signal safe functions + * found in https://man.openbsd.org/sigaction.2. + */ + if (open_max < 0) + open_max = sysconf (_SC_OPEN_MAX); +#endif + /* Hardcoded fallback: the default process hard limit in Linux as of 2020 */ + if (open_max < 0) + open_max = 4096; for (fd = 0; fd < open_max; fd++) if ((res = cb (data, fd)) != 0) @@ -1257,6 +1297,8 @@ safe_fdwalk (int (*cb)(void *data, int fd), void *data) #endif } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static void safe_closefrom (int lowfd) { @@ -1289,8 +1331,10 @@ safe_closefrom (int lowfd) #endif } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gint -sane_dup2 (gint fd1, gint fd2) +safe_dup2 (gint fd1, gint fd2) { gint ret; @@ -1301,8 +1345,10 @@ sane_dup2 (gint fd1, gint fd2) return ret; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gint -sane_open (const char *path, gint mode) +safe_open (const char *path, gint mode) { gint ret; @@ -1321,6 +1367,8 @@ enum CHILD_FORK_FAILED }; +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)) until it calls exec(). */ static void do_exec (gint child_err_report_fd, gint stdin_fd, @@ -1328,10 +1376,13 @@ do_exec (gint child_err_report_fd, gint stderr_fd, const gchar *working_directory, gchar **argv, + gchar **argv_buffer, + gsize argv_buffer_len, gchar **envp, gboolean close_descriptors, - gboolean search_path, - gboolean search_path_from_envp, + const gchar *search_path, + gchar *search_path_buffer, + gsize search_path_buffer_len, gboolean stdout_to_null, gboolean stderr_to_null, gboolean child_inherits_stdin, @@ -1349,7 +1400,7 @@ do_exec (gint child_err_report_fd, { /* dup2 can't actually fail here I don't think */ - if (sane_dup2 (stdin_fd, 0) < 0) + if (safe_dup2 (stdin_fd, 0) < 0) write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); @@ -1358,9 +1409,11 @@ do_exec (gint child_err_report_fd, else if (!child_inherits_stdin) { /* Keep process from blocking on a read of stdin */ - gint read_null = sane_open ("/dev/null", O_RDONLY); - g_assert (read_null != -1); - sane_dup2 (read_null, 0); + gint read_null = safe_open ("/dev/null", O_RDONLY); + if (read_null < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); + safe_dup2 (read_null, 0); close_and_invalidate (&read_null); } @@ -1368,7 +1421,7 @@ do_exec (gint child_err_report_fd, { /* dup2 can't actually fail here I don't think */ - if (sane_dup2 (stdout_fd, 1) < 0) + if (safe_dup2 (stdout_fd, 1) < 0) write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); @@ -1376,9 +1429,11 @@ do_exec (gint child_err_report_fd, } else if (stdout_to_null) { - gint write_null = sane_open ("/dev/null", O_WRONLY); - g_assert (write_null != -1); - sane_dup2 (write_null, 1); + gint write_null = safe_open ("/dev/null", O_WRONLY); + if (write_null < 0) + write_err_and_exit (child_err_report_fd, + CHILD_DUP2_FAILED); + safe_dup2 (write_null, 1); close_and_invalidate (&write_null); } @@ -1386,7 +1441,7 @@ do_exec (gint child_err_report_fd, { /* dup2 can't actually fail here I don't think */ - if (sane_dup2 (stderr_fd, 2) < 0) + if (safe_dup2 (stderr_fd, 2) < 0) write_err_and_exit (child_err_report_fd, CHILD_DUP2_FAILED); @@ -1394,8 +1449,8 @@ do_exec (gint child_err_report_fd, } else if (stderr_to_null) { - gint write_null = sane_open ("/dev/null", O_WRONLY); - sane_dup2 (write_null, 2); + gint write_null = safe_open ("/dev/null", O_WRONLY); + safe_dup2 (write_null, 2); close_and_invalidate (&write_null); } @@ -1408,7 +1463,7 @@ do_exec (gint child_err_report_fd, { if (child_setup == NULL) { - sane_dup2 (child_err_report_fd, 3); + safe_dup2 (child_err_report_fd, 3); set_cloexec (GINT_TO_POINTER (0), 3); safe_closefrom (4); child_err_report_fd = 3; @@ -1432,7 +1487,8 @@ do_exec (gint child_err_report_fd, g_execute (argv[0], file_and_argv_zero ? argv + 1 : argv, - envp, search_path, search_path_from_envp); + argv_buffer, argv_buffer_len, + envp, search_path, search_path_buffer, search_path_buffer_len); /* Exec failed */ write_err_and_exit (child_err_report_fd, @@ -1565,7 +1621,7 @@ do_posix_spawn (gchar **argv, else if (!child_inherits_stdin) { /* Keep process from blocking on a read of stdin */ - gint read_null = sane_open ("/dev/null", O_RDONLY | O_CLOEXEC); + gint read_null = safe_open ("/dev/null", O_RDONLY | O_CLOEXEC); g_assert (read_null != -1); parent_close_fds[num_parent_close_fds++] = read_null; @@ -1589,7 +1645,7 @@ do_posix_spawn (gchar **argv, } else if (stdout_to_null) { - gint write_null = sane_open ("/dev/null", O_WRONLY | O_CLOEXEC); + gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC); g_assert (write_null != -1); parent_close_fds[num_parent_close_fds++] = write_null; @@ -1613,7 +1669,7 @@ do_posix_spawn (gchar **argv, } else if (stderr_to_null) { - gint write_null = sane_open ("/dev/null", O_WRONLY | O_CLOEXEC); + gint write_null = safe_open ("/dev/null", O_WRONLY | O_CLOEXEC); g_assert (write_null != -1); parent_close_fds[num_parent_close_fds++] = write_null; @@ -1694,6 +1750,11 @@ fork_exec_with_fds (gboolean intermediate_child, gint child_pid_report_pipe[2] = { -1, -1 }; guint pipe_flags = cloexec_pipes ? FD_CLOEXEC : 0; gint status; + const gchar *chosen_search_path; + gchar *search_path_buffer = NULL; + gsize search_path_buffer_len = 0; + gchar **argv_buffer = NULL; + gsize argv_buffer_len = 0; #ifdef POSIX_SPAWN_AVAILABLE if (!intermediate_child && working_directory == NULL && !close_descriptors && @@ -1744,8 +1805,50 @@ fork_exec_with_fds (gboolean intermediate_child, } #endif /* POSIX_SPAWN_AVAILABLE */ + /* Choose a search path. This has to be done before calling fork() + * as getenv() isn’t async-signal-safe (see `man 7 signal-safety`). */ + chosen_search_path = NULL; + if (search_path_from_envp) + chosen_search_path = g_environ_getenv (envp, "PATH"); + if (search_path && chosen_search_path == NULL) + chosen_search_path = g_getenv ("PATH"); + + if (chosen_search_path == NULL) + { + /* There is no 'PATH' in the environment. The default + * * search path in libc is the current directory followed by + * * the path 'confstr' returns for '_CS_PATH'. + * */ + + /* In GLib we put . last, for security, and don't use the + * * unportable confstr(); UNIX98 does not actually specify + * * what to search if PATH is unset. POSIX may, dunno. + * */ + + chosen_search_path = "/bin:/usr/bin:."; + } + + /* Allocate a buffer which the fork()ed child can use to assemble potential + * paths for the binary to exec(), combining the argv[0] and elements from + * the chosen_search_path. This can’t be done in the child because malloc() + * (or alloca()) are not async-signal-safe (see `man 7 signal-safety`). + * + * Add 2 for the nul terminator and a leading `/`. */ + search_path_buffer_len = strlen (chosen_search_path) + strlen (argv[0]) + 2; + search_path_buffer = g_malloc (search_path_buffer_len); + + /* And allocate a buffer which is 2 elements longer than @argv, so that if + * script_execute() has to be called later on, it can build a wrapper argv + * array in this buffer. */ + argv_buffer_len = g_strv_length (argv) + 2; + argv_buffer = g_new (gchar *, argv_buffer_len); + if (!g_unix_open_pipe (child_err_report_pipe, pipe_flags, error)) - return FALSE; + { + g_free (search_path_buffer); + g_free (argv_buffer); + return FALSE; + } if (intermediate_child && !g_unix_open_pipe (child_pid_report_pipe, pipe_flags, error)) goto cleanup_and_fail; @@ -1823,10 +1926,13 @@ fork_exec_with_fds (gboolean intermediate_child, stderr_fd, working_directory, argv, + argv_buffer, + argv_buffer_len, envp, close_descriptors, - search_path, - search_path_from_envp, + chosen_search_path, + search_path_buffer, + search_path_buffer_len, stdout_to_null, stderr_to_null, child_inherits_stdin, @@ -1853,10 +1959,13 @@ fork_exec_with_fds (gboolean intermediate_child, stderr_fd, working_directory, argv, + argv_buffer, + argv_buffer_len, envp, close_descriptors, - search_path, - search_path_from_envp, + chosen_search_path, + search_path_buffer, + search_path_buffer_len, stdout_to_null, stderr_to_null, child_inherits_stdin, @@ -1983,7 +2092,10 @@ fork_exec_with_fds (gboolean intermediate_child, /* Success against all odds! return the information */ close_and_invalidate (&child_err_report_pipe[0]); close_and_invalidate (&child_pid_report_pipe[0]); - + + g_free (search_path_buffer); + g_free (argv_buffer); + if (child_pid) *child_pid = pid; @@ -2016,6 +2128,9 @@ fork_exec_with_fds (gboolean intermediate_child, close_and_invalidate (&child_pid_report_pipe[0]); close_and_invalidate (&child_pid_report_pipe[1]); + g_free (search_path_buffer); + g_free (argv_buffer); + return FALSE; } @@ -2113,40 +2228,43 @@ cleanup_and_fail: /* Based on execvp from GNU C Library */ -static void +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)) until it calls exec(). */ +static gboolean script_execute (const gchar *file, gchar **argv, + gchar **argv_buffer, + gsize argv_buffer_len, gchar **envp) { /* Count the arguments. */ int argc = 0; while (argv[argc]) ++argc; - - /* Construct an argument list for the shell. */ - { - gchar **new_argv; - new_argv = g_new0 (gchar*, argc + 2); /* /bin/sh and NULL */ - - new_argv[0] = (char *) "/bin/sh"; - new_argv[1] = (char *) file; - while (argc > 0) - { - new_argv[argc + 1] = argv[argc]; - --argc; - } + /* Construct an argument list for the shell. */ + if (argc + 2 > argv_buffer_len) + return FALSE; - /* Execute the shell. */ - if (envp) - execve (new_argv[0], new_argv, envp); - else - execv (new_argv[0], new_argv); - - g_free (new_argv); - } + argv_buffer[0] = (char *) "/bin/sh"; + argv_buffer[1] = (char *) file; + while (argc > 0) + { + argv_buffer[argc + 1] = argv[argc]; + --argc; + } + + /* Execute the shell. */ + if (envp) + execve (argv_buffer[0], argv_buffer, envp); + else + execv (argv_buffer[0], argv_buffer); + + return TRUE; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)). */ static gchar* my_strchrnul (const gchar *str, gchar c) { @@ -2157,12 +2275,17 @@ my_strchrnul (const gchar *str, gchar c) return p; } +/* This function is called between fork() and exec() and hence must be + * async-signal-safe (see signal-safety(7)) until it calls exec(). */ static gint -g_execute (const gchar *file, - gchar **argv, - gchar **envp, - gboolean search_path, - gboolean search_path_from_envp) +g_execute (const gchar *file, + gchar **argv, + gchar **argv_buffer, + gsize argv_buffer_len, + gchar **envp, + const gchar *search_path, + gchar *search_path_buffer, + gsize search_path_buffer_len) { if (*file == '\0') { @@ -2171,7 +2294,7 @@ g_execute (const gchar *file, return -1; } - if (!(search_path || search_path_from_envp) || strchr (file, '/') != NULL) + if (search_path == NULL || strchr (file, '/') != NULL) { /* Don't search when it contains a slash. */ if (envp) @@ -2179,42 +2302,32 @@ g_execute (const gchar *file, else execv (file, argv); - if (errno == ENOEXEC) - script_execute (file, argv, envp); + if (errno == ENOEXEC && + !script_execute (file, argv, argv_buffer, argv_buffer_len, envp)) + { + errno = ENOMEM; + return -1; + } } else { gboolean got_eacces = 0; const gchar *path, *p; - gchar *name, *freeme; + gchar *name; gsize len; gsize pathlen; - path = NULL; - if (search_path_from_envp) - path = g_environ_getenv (envp, "PATH"); - if (search_path && path == NULL) - path = g_getenv ("PATH"); - - if (path == NULL) - { - /* There is no 'PATH' in the environment. The default - * search path in libc is the current directory followed by - * the path 'confstr' returns for '_CS_PATH'. - */ - - /* In GLib we put . last, for security, and don't use the - * unportable confstr(); UNIX98 does not actually specify - * what to search if PATH is unset. POSIX may, dunno. - */ - - path = "/bin:/usr/bin:."; - } - + path = search_path; len = strlen (file) + 1; pathlen = strlen (path); - freeme = name = g_malloc (pathlen + len + 1); - + name = search_path_buffer; + + if (search_path_buffer_len < pathlen + len + 1) + { + errno = ENOMEM; + return -1; + } + /* Copy the file name at the top, including '\0' */ memcpy (name + pathlen + 1, file, len); name = name + pathlen; @@ -2243,8 +2356,12 @@ g_execute (const gchar *file, else execv (startp, argv); - if (errno == ENOEXEC) - script_execute (startp, argv, envp); + if (errno == ENOEXEC && + !script_execute (startp, argv, argv_buffer, argv_buffer_len, envp)) + { + errno = ENOMEM; + return -1; + } switch (errno) { @@ -2283,7 +2400,6 @@ g_execute (const gchar *file, * something went wrong executing it; return the error to our * caller. */ - g_free (freeme); return -1; } } @@ -2295,8 +2411,6 @@ g_execute (const gchar *file, * error. */ errno = EACCES; - - g_free (freeme); } /* Return the error from the last attempt (probably ENOENT). */ diff --git a/glib/gtestutils.c b/glib/gtestutils.c index 1010dcc1b..18b117285 100644 --- a/glib/gtestutils.c +++ b/glib/gtestutils.c @@ -3067,7 +3067,7 @@ test_trap_clear (void) #ifdef G_OS_UNIX static int -sane_dup2 (int fd1, +safe_dup2 (int fd1, int fd2) { int ret; @@ -3319,7 +3319,7 @@ g_test_trap_fork (guint64 usec_timeout, if (fd0 < 0) g_error ("failed to open /dev/null for stdin redirection"); } - if (sane_dup2 (stdout_pipe[1], 1) < 0 || sane_dup2 (stderr_pipe[1], 2) < 0 || (fd0 >= 0 && sane_dup2 (fd0, 0) < 0)) + if (safe_dup2 (stdout_pipe[1], 1) < 0 || safe_dup2 (stderr_pipe[1], 2) < 0 || (fd0 >= 0 && safe_dup2 (fd0, 0) < 0)) { errsv = errno; g_error ("failed to dup2() in forked test program: %s", g_strerror (errsv)); diff --git a/glib/gutils.c b/glib/gutils.c index 572c06ce6..c5aef47fa 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -3102,7 +3102,7 @@ g_abort (void) { /* One call to break the debugger */ DebugBreak (); - /* One call in case CRT does get saner about abort() behaviour */ + /* One call in case CRT changes its abort() behaviour */ abort (); /* And one call to bind them all and terminate the program for sure */ ExitProcess (127); diff --git a/glib/gvarianttype.c b/glib/gvarianttype.c index 1a228f73b..c46f1a2c6 100644 --- a/glib/gvarianttype.c +++ b/glib/gvarianttype.c @@ -1120,7 +1120,7 @@ g_variant_type_new_tuple_slow (const GVariantType * const *items, { /* the "slow" version is needed in case the static buffer of 1024 * bytes is exceeded when running the normal version. this will - * happen only in truly insane code, so it can be slow. + * happen only with very unusually large types, so it can be slow. */ GString *string; gint i; diff --git a/glib/tests/regex.c b/glib/tests/regex.c index 56bd2d5eb..ee9cd21ca 100644 --- a/glib/tests/regex.c +++ b/glib/tests/regex.c @@ -2321,7 +2321,7 @@ main (int argc, char *argv[]) TEST_NEW_FAIL ("(*:0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEFG)XX", 0, G_REGEX_ERROR_NAME_TOO_LONG); TEST_NEW_FAIL ("\\u0100", G_REGEX_RAW | G_REGEX_JAVASCRIPT_COMPAT, G_REGEX_ERROR_CHARACTER_VALUE_TOO_LARGE); - /* These errors can't really be tested sanely: + /* These errors can't really be tested easily: * G_REGEX_ERROR_EXPRESSION_TOO_LARGE * G_REGEX_ERROR_MEMORY_ERROR * G_REGEX_ERROR_SUBPATTERN_NAME_TOO_LONG diff --git a/glib/tests/spawn-singlethread.c b/glib/tests/spawn-singlethread.c index 15f03a0c7..ab449eb95 100644 --- a/glib/tests/spawn-singlethread.c +++ b/glib/tests/spawn-singlethread.c @@ -166,7 +166,7 @@ test_spawn_async (void) * Routine if the file descriptor does not exist. */ static void -sane_close (int fd) +safe_close (int fd) { if (fd >= 0) close (fd); @@ -252,10 +252,10 @@ test_spawn_async_with_fds (void) test_pipe[0][0], test_pipe[1][1], test_pipe[2][1], &error); g_assert_no_error (error); - sane_close (test_pipe[0][0]); - sane_close (test_pipe[1][1]); + safe_close (test_pipe[0][0]); + safe_close (test_pipe[1][1]); if (fd_info[2] != STDOUT_PIPE) - sane_close (test_pipe[2][1]); + safe_close (test_pipe[2][1]); data.loop = loop; data.stdout_done = FALSE; @@ -297,10 +297,10 @@ test_spawn_async_with_fds (void) g_main_context_unref (context); g_main_loop_unref (loop); - sane_close (test_pipe[0][1]); - sane_close (test_pipe[1][0]); + safe_close (test_pipe[0][1]); + safe_close (test_pipe[1][0]); if (fd_info[2] != STDOUT_PIPE) - sane_close (test_pipe[2][0]); + safe_close (test_pipe[2][0]); } g_ptr_array_free (argv, TRUE); diff --git a/gobject/gobject.c b/gobject/gobject.c index eea40b3ae..07752cf25 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -1617,7 +1617,7 @@ object_interface_check_properties (gpointer check_data, /* We do a number of checks on the properties of an interface to * make sure that all classes implementing the interface are - * overriding the properties in a sane way. + * overriding the properties correctly. * * We do the checks in order of importance so that we can give * more useful error messages first. diff --git a/gobject/gsignal.c b/gobject/gsignal.c index 2b6b0d05b..45effa92d 100644 --- a/gobject/gsignal.c +++ b/gobject/gsignal.c @@ -2291,7 +2291,7 @@ g_signal_chain_from_overridden_handler (gpointer instance, g_free (error); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ while (i--) g_value_unset (param_values + i); @@ -2347,7 +2347,7 @@ g_signal_chain_from_overridden_handler (gpointer instance, g_free (error); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ } } @@ -3446,7 +3446,7 @@ g_signal_emit_valist (gpointer instance, g_warning ("%s: %s", G_STRLOC, error); g_free (error); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ } } @@ -3483,7 +3483,7 @@ g_signal_emit_valist (gpointer instance, g_free (error); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ while (i--) g_value_unset (param_values + i); @@ -3519,7 +3519,7 @@ g_signal_emit_valist (gpointer instance, g_free (error); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ } } diff --git a/gobject/gvalue.c b/gobject/gvalue.c index c30501a6b..468da2e7d 100644 --- a/gobject/gvalue.c +++ b/gobject/gvalue.c @@ -376,7 +376,7 @@ g_value_set_instance (GValue *value, g_free (error_msg); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ value_meminit (value, g_type); value_table->value_init (value); @@ -440,7 +440,7 @@ g_value_init_from_instance (GValue *value, g_free (error_msg); /* we purposely leak the value here, it might not be - * in a sane state if an error condition occurred + * in a correct state if an error condition occurred */ value_meminit (value, g_type); value_table->value_init (value);