瀏覽代碼

snprintf wrapper with consistant (though not C99) overflow behavior

svn:r2606
Nick Mathewson 19 年之前
父節點
當前提交
22dc19b590
共有 2 個文件被更改,包括 48 次插入1 次删除
  1. 36 1
      src/common/util.c
  2. 12 0
      src/common/util.h

+ 36 - 1
src/common/util.c

@@ -2185,7 +2185,7 @@ parse_addr_and_port_range(const char *s, uint32_t *addr_out,
    *     "mask" is the Mask|Maskbits part...
    * and "port" is the *|port|min-max part.
    */
-  
+
   if (strcmp(address,"*")==0) {
     *addr_out = 0;
   } else if (tor_inet_aton(address, &in) != 0) {
@@ -2318,6 +2318,41 @@ tor_parse_ulong(const char *s, int base, unsigned long min,
   return 0;
 }
 
+/** Replacement for snprintf.  Differs from platform snprintf in two
+ * ways: First, always NUL-terminates its output.  Second, always
+ * returns -1 if the result is truncated.  (Note that this return
+ * behavior does <i>not</i> conform to C99; it just happens to be the
+ * easiest to emulate "return -1" with conformant implementations than
+ * it is to emulate "return number that would be written" with
+ * non-conformant implementations.) */
+int tor_snprintf(char *str, size_t size, const char *format, ...)
+{
+  va_list ap;
+  int r;
+  va_start(ap,format);
+  r = tor_vsnprintf(str,size,format,ap);
+  va_end(ap);
+  return r;
+}
+
+/** Replacement for vsnpritnf; behavior differs as tor_snprintf differs from
+ * snprintf.
+ */
+int tor_vsnprintf(char *str, size_t size, const char *format, va_list args)
+{
+  int r;
+#ifdef MS_WINDOWS
+  r = _vsnprintf(str, size, format, args);
+#else
+  r = vsnprintf(str, size, format, args);
+#endif
+  str[size-1] = '\0';
+  if (r < 0 || r >= size)
+    return -1;
+  return r;
+}
+
+
 #ifndef MS_WINDOWS
 struct tor_mutex_t {
 };

+ 12 - 0
src/common/util.h

@@ -13,6 +13,7 @@
 #include "orconfig.h"
 #include "torint.h"
 #include <stdio.h>
+#include <stdarg.h>
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
 #endif
@@ -106,7 +107,18 @@ long tor_parse_long(const char *s, int base, long min,
 unsigned long tor_parse_ulong(const char *s, int base, unsigned long min,
                               unsigned long max, int *ok, char **next);
 
+/* XXXX duplicated from log.h */
+#ifdef __GNUC__
+#define CHECK_PRINTF(formatIdx, firstArg) \
+   __attribute__ ((format (printf, formatIdx, firstArg)))
+#else
+#define CHECK_PRINTF(formatIdx, firstArg)
+#endif
 
+int tor_snprintf(char *str, size_t size, const char *format, ...)
+     CHECK_PRINTF(3,4);
+int tor_vsnprintf(char *str, size_t size, const char *format, va_list args);
+     
 /* Some platforms segfault when you try to access a multi-byte type
  * that isn't aligned to a word boundary.  The macros and/or functions
  * below can be used to access unaligned data on any platform.