[tor-commits] [tor/master] Refactor unsigned int hex formatting out of format_helper_exit_status() in util.c

nickm at torproject.org nickm at torproject.org
Sat Jun 23 02:18:26 UTC 2012


commit c21af69f29ca5a55385a926fdac4a8e6c8fb6d37
Author: Andrea Shepard <andrea at persephoneslair.org>
Date:   Wed Jun 20 14:43:50 2012 -0700

    Refactor unsigned int hex formatting out of format_helper_exit_status() in util.c
---
 src/common/util.c |  154 +++++++++++++++++++++++++++++++++--------------------
 src/common/util.h |    2 +
 2 files changed, 99 insertions(+), 57 deletions(-)

diff --git a/src/common/util.c b/src/common/util.c
index 63a8aff..79e7a70 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -3191,6 +3191,61 @@ tor_join_win_cmdline(const char *argv[])
   return joined_argv;
 }
 
+/**
+ * Helper function to output hex numbers, called by
+ * format_helper_exit_status().  This writes the hexadecimal digits of x into
+ * buf, up to max_len digits, and returns the actual number of digits written.
+ * If there is insufficient space, it will write nothing and return 0.
+ *
+ * This accepts an unsigned int because format_helper_exit_status() needs to
+ * call it with a signed int and an unsigned char, and since the C standard
+ * does not guarantee that an int is wider than a char (an int must be at
+ * least 16 bits but it is permitted for a char to be that wide as well), we
+ * can't assume a signed int is sufficient to accomodate an unsigned char.
+ * Thus, format_helper_exit_status() will still need to emit any require '-'
+ * on its own.
+ */
+
+int
+format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
+                                         int max_len)
+{
+  int len;
+  unsigned int tmp;
+  char *cur;
+
+  /* Sanity check */
+  if (!buf || max_len <= 0)
+    return 0;
+
+  /* How many chars do we need for x? */
+  if (x > 0) {
+    len = 0;
+    tmp = x;
+    while (tmp > 0) {
+      tmp >>= 4;
+      ++len;
+    }
+  }
+  else len = 1;
+
+  /* Bail if we would go past the end of the buffer */
+  if (len > max_len)
+    return 0;
+
+  /* Point to last one */
+  cur = buf + len - 1;
+
+  /* Convert x to hex */
+  do {
+    *cur-- = "0123456789ABCDEF"[x & 0xf];
+    x >>= 4;
+  } while (x != 0 && cur >= buf);
+
+  /* Return len */
+  return len;
+}
+
 /** Format <b>child_state</b> and <b>saved_errno</b> as a hex string placed in
  * <b>hex_errno</b>.  Called between fork and _exit, so must be signal-handler
  * safe.
@@ -3208,9 +3263,9 @@ void
 format_helper_exit_status(unsigned char child_state, int saved_errno,
                           char *hex_errno)
 {
-  unsigned int unsigned_errno, len, tmp_uint;
-  char *cur, *tmp;
-  unsigned char tmp_uchar;
+  unsigned int unsigned_errno;
+  int written, left;
+  char *cur;
   size_t i;
 
   /* Fill hex_errno with spaces, and a trailing newline (memset may
@@ -3226,87 +3281,72 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
     unsigned_errno = (unsigned int) saved_errno;
   }
 
-  /* How many chars do we need for child_state ? */
-  if ( child_state > 0 ) {
-    len = 0;
-    tmp_uchar = child_state;
-    while (tmp_uchar > 0) {
-      tmp_uchar >>= 4;
-      ++len;
-    }
-  }
-  else len = 1;
+  /*
+   * Count how many chars of space we have left, and keep a pointer into the
+   * current point in the buffer.
+   */
+  left = HEX_ERRNO_SIZE;
+  cur = hex_errno;
 
-  /* Bail if we would go past the end (on this or the '/') */
-  if ( len + 2 > HEX_ERRNO_SIZE)
+  /* Emit child_state */
+  written = format_hex_number_for_helper_exit_status(child_state,
+                                                     cur, left);
+  if (written <= 0)
     goto err;
 
-  /* Point to last one */
-  cur = hex_errno + len - 1;
-
-  /* Convert child_state to hex */
-  do {
-    *cur-- = "0123456789ABCDEF"[child_state & 0xf];
-    child_state >>= 4;
-  } while (child_state != 0 && cur >= hex_errno);
-
-  /* Check for overflow on first iteration of the loop */
-  if (cur + 1 < hex_errno)
+  /* Adjust left and cur */
+  left -= written;
+  cur += written;
+  if (left <= 0)
     goto err;
 
   /* Now the '/' */
-  hex_errno[len] = '/';
-
-  /* Save a pointer to the start of second number */
-  tmp = hex_errno + len;
+  *cur = '/';
 
-  /* How many chars do we need for unsigned_errno? */
-  if ( unsigned_errno > 0 ) {
-    len = 0;
-    tmp_uint = unsigned_errno;
-    while (tmp_uint > 0) {
-      tmp_uint >>= 4;
-      ++len;
-    }
-  }
-  else len = 1;
+  /* Adjust left and cur */
+  ++cur;
+  --left;
+  if (left <= 0)
+    goto err;
 
   /* Need minus? */
   if (saved_errno < 0) {
-    if ( tmp + 1 - hex_errno > (ptrdiff_t)(HEX_ERRNO_SIZE) )
+    *cur = '-';
+    ++cur;
+    --left;
+    if (left <= 0)
       goto err;
-
-    *(++tmp) = '-';
   }
 
-  /* Last check for space */
-  if ( tmp + len + 2 - hex_errno > (ptrdiff_t)(HEX_ERRNO_SIZE) )
+  /* Emit unsigned_errno */
+  written = format_hex_number_for_helper_exit_status(unsigned_errno,
+                                                     cur, left);
+
+  if (written <= 0)
     goto err;
 
-  /* Point to last one */
-  cur = tmp + len;
+  /* Adjust left and cur */
+  left -= written;
+  cur += written;
 
-  /* Convert unsigned_errno to hex */
-  do {
-    *cur-- = "0123456789ABCDEF"[unsigned_errno & 0xf];
-    unsigned_errno >>= 4;
-  } while (unsigned_errno != 0 && cur >= tmp);
+  /* Check that we have enough space left for a newline */
+  if (left <= 0)
+    goto err;
 
   /* Emit the newline and NUL */
-  cur = tmp + len;
-  *(++cur) = '\n';
-  *(++cur) = '\0';
+  *cur++ = '\n';
+  *cur++ = '\0';
 
   goto done;
 
-err:
+ err:
   /*
    * In error exit, just write a '\0' in the first char so whatever called
    * this at least won't fall off the end.
    */
   *hex_errno = '\0';
 
-done:
+ done:
   return;
 }
 
diff --git a/src/common/util.h b/src/common/util.h
index a2b196c..6b7c6fb 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -471,6 +471,8 @@ void tor_process_handle_destroy(process_handle_t *process_handle,
 #ifdef UTIL_PRIVATE
 /* Prototypes for private functions only used by util.c (and unit tests) */
 
+int format_hex_number_for_helper_exit_status(unsigned int x, char *buf,
+                                             int max_len);
 void format_helper_exit_status(unsigned char child_state,
                                int saved_errno, char *hex_errno);
 





More information about the tor-commits mailing list