[glib: 1/6] gbacktrace: Ensure return values of write, dup and fgets are used




commit 0e4d8c2478f37757574fae24d232a7975d48c911
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Wed Jul 6 16:02:13 2022 +0200

    gbacktrace: Ensure return values of write, dup and fgets are used
    
    Make sure that we did not error when doing write or read operations, and
    in such case, just exit reporting the error.

 glib/gbacktrace.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 76 insertions(+), 13 deletions(-)
---
diff --git a/glib/gbacktrace.c b/glib/gbacktrace.c
index cb02c8a1b6..ae4bdec0c7 100644
--- a/glib/gbacktrace.c
+++ b/glib/gbacktrace.c
@@ -45,6 +45,7 @@
 #include <time.h>
 
 #ifdef G_OS_UNIX
+#include <errno.h>
 #include <unistd.h>
 #include <sys/wait.h>
 #ifdef HAVE_SYS_SELECT_H
@@ -175,9 +176,14 @@ g_on_error_query (const gchar *prg_name)
   fflush (stdout);
 
   if (isatty(0) && isatty(1))
-    fgets (buf, 8, stdin);
+    {
+      if (fgets (buf, 8, stdin) == NULL)
+        _exit (0);
+    }
   else
-    strcpy (buf, "E\n");
+    {
+      strcpy (buf, "E\n");
+    }
 
   if ((buf[0] == 'E' || buf[0] == 'e')
       && buf[1] == '\n')
@@ -314,6 +320,59 @@ stack_trace_sigchld (int signum)
 
 #define BUFSIZE 1024
 
+static inline const char *
+get_strerror (char *buffer, gsize n)
+{
+#ifdef HAVE_STRERROR_R
+  return strerror_r (errno, buffer, n);
+#else
+  const char *error_str = strerror (errno);
+  if (!error_str)
+    return NULL;
+
+  strncpy (buffer, error_str, n);
+  return buffer;
+#endif
+}
+
+static gssize
+checked_write (int fd, gconstpointer buf, gsize n)
+{
+  gssize written = write (fd, buf, n);
+
+  if (written == -1)
+    {
+      char msg[BUFSIZE] = {0};
+      char error_str[BUFSIZE / 2] = {0};
+
+      get_strerror (error_str, sizeof (error_str) - 1);
+      snprintf (msg, sizeof (msg) - 1, "Unable to write to fd %d: %s", fd, error_str);
+      perror (msg);
+      _exit (0);
+    }
+
+  return written;
+}
+
+static int
+checked_dup (int fd)
+{
+  int new_fd = dup (fd);
+
+  if (new_fd == -1)
+    {
+      char msg[BUFSIZE] = {0};
+      char error_str[BUFSIZE / 2] = {0};
+
+      get_strerror (error_str, sizeof (error_str) - 1);
+      snprintf (msg, sizeof (msg) - 1, "Unable to duplicate fd %d: %s", fd, error_str);
+      perror (msg);
+      _exit (0);
+    }
+
+  return new_fd;
+}
+
 static void
 stack_trace (const char * const *args)
 {
@@ -351,9 +410,12 @@ stack_trace (const char * const *args)
            (void) fcntl (old_err, F_SETFD, getfd | FD_CLOEXEC);
        }
 
-      close (0); dup (in_fd[0]);   /* set the stdin to the in pipe */
-      close (1); dup (out_fd[1]);  /* set the stdout to the out pipe */
-      close (2); dup (out_fd[1]);  /* set the stderr to the out pipe */
+      close (0);
+      checked_dup (in_fd[0]);   /* set the stdin to the in pipe */
+      close (1);
+      checked_dup (out_fd[1]);  /* set the stdout to the out pipe */
+      close (2);
+      checked_dup (out_fd[1]);  /* set the stderr to the out pipe */
 
       execvp (args[0], (char **) args);      /* exec gdb */
 
@@ -361,7 +423,8 @@ stack_trace (const char * const *args)
       if (old_err != -1)
         {
           close (2);
-          dup (old_err);
+          /* We can ignore the return value here as we're failing anyways */
+          (void) !dup (old_err);
         }
       perror ("exec " DEBUGGER " failed");
       _exit (0);
@@ -376,14 +439,14 @@ stack_trace (const char * const *args)
   FD_SET (out_fd[0], &fdset);
 
 #ifdef USE_LLDB
-  write (in_fd[1], "bt\n", 3);
-  write (in_fd[1], "p x = 0\n", 8);
-  write (in_fd[1], "process detach\n", 15);
-  write (in_fd[1], "quit\n", 5);
+  checked_write (in_fd[1], "bt\n", 3);
+  checked_write (in_fd[1], "p x = 0\n", 8);
+  checked_write (in_fd[1], "process detach\n", 15);
+  checked_write (in_fd[1], "quit\n", 5);
 #else
-  write (in_fd[1], "backtrace\n", 10);
-  write (in_fd[1], "p x = 0\n", 8);
-  write (in_fd[1], "quit\n", 5);
+  checked_write (in_fd[1], "backtrace\n", 10);
+  checked_write (in_fd[1], "p x = 0\n", 8);
+  checked_write (in_fd[1], "quit\n", 5);
 #endif
 
   idx = 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]