[PATCH] [sanitizer] Support padding with spaces in Printf.

Sergey Matveev earthdok at google.com
Thu Jun 27 08:19:51 PDT 2013


    - addressed samsonov's comments

Hi glider, samsonov,

http://llvm-reviews.chandlerc.com/D1057

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D1057?vs=2596&id=2598#toc

Files:
  lib/sanitizer_common/sanitizer_printf.cc
  lib/sanitizer_common/tests/sanitizer_printf_test.cc

Index: lib/sanitizer_common/sanitizer_printf.cc
===================================================================
--- lib/sanitizer_common/sanitizer_printf.cc
+++ lib/sanitizer_common/sanitizer_printf.cc
@@ -38,45 +38,62 @@
 }
 
 // Appends number in a given base to buffer. If its length is less than
-// "minimal_num_length", it is padded with leading zeroes.
-static int AppendUnsigned(char **buff, const char *buff_end, u64 num,
-                          u8 base, u8 minimal_num_length) {
+// |minimal_num_length|, it is padded with leading zeroes or spaces, depending
+// on the value of |pad_with_zero|.
+static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
+                        u8 base, u8 minimal_num_length, bool pad_with_zero,
+                        bool negative) {
   uptr const kMaxLen = 30;
   RAW_CHECK(base == 10 || base == 16);
+  RAW_CHECK(base == 10 || !negative);
+  RAW_CHECK(absolute_value || !negative);
   RAW_CHECK(minimal_num_length < kMaxLen);
+  int result = 0;
+  if (negative && minimal_num_length)
+    --minimal_num_length;
+  if (negative && pad_with_zero)
+    result += AppendChar(buff, buff_end, '-');
   uptr num_buffer[kMaxLen];
-  uptr pos = 0;
+  int pos = 0;
   do {
-    RAW_CHECK_MSG(pos < kMaxLen, "appendNumber buffer overflow");
-    num_buffer[pos++] = num % base;
-    num /= base;
-  } while (num > 0);
+    RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
+    num_buffer[pos++] = absolute_value % base;
+    absolute_value /= base;
+  } while (absolute_value > 0);
   if (pos < minimal_num_length) {
     // Make sure compiler doesn't insert call to memset here.
     internal_memset(&num_buffer[pos], 0,
                     sizeof(num_buffer[0]) * (minimal_num_length - pos));
     pos = minimal_num_length;
   }
-  int result = 0;
-  while (pos-- > 0) {
+  RAW_CHECK(pos > 0);
+  pos--;
+  while (pos >= 0 && num_buffer[pos] == 0) {
+    char c = (pad_with_zero || pos == 0) ? '0' : ' ';
+    result += AppendChar(buff, buff_end, c);
+    pos--;
+  }
+  if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
+  while (pos >= 0) {
     char digit = static_cast<char>(num_buffer[pos]);
     result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
                                                       : 'a' + digit - 10);
+    pos--;
   }
   return result;
 }
 
+static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
+                          u8 minimal_num_length, bool pad_with_zero) {
+  return AppendNumber(buff, buff_end, num, base, minimal_num_length,
+                      pad_with_zero, false /* negative */);
+}
+
 static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
-                               u8 minimal_num_length) {
-  int result = 0;
-  if (num < 0) {
-    result += AppendChar(buff, buff_end, '-');
-    num = -num;
-    if (minimal_num_length)
-      --minimal_num_length;
-  }
-  result += AppendUnsigned(buff, buff_end, (u64)num, 10, minimal_num_length);
-  return result;
+                               u8 minimal_num_length, bool pad_with_zero) {
+  bool negative = (num < 0);
+  return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
+                      minimal_num_length, pad_with_zero, negative);
 }
 
 static int AppendString(char **buff, const char *buff_end, const char *s) {
@@ -93,14 +110,14 @@
   int result = 0;
   result += AppendString(buff, buff_end, "0x");
   result += AppendUnsigned(buff, buff_end, ptr_value, 16,
-                           (SANITIZER_WORDSIZE == 64) ? 12 : 8);
+                           (SANITIZER_WORDSIZE == 64) ? 12 : 8, true);
   return result;
 }
 
 int VSNPrintf(char *buff, int buff_length,
               const char *format, va_list args) {
   static const char *kPrintfFormatsHelp =
-    "Supported Printf formats: %(0[0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n";
+    "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %s; %c\n";
   RAW_CHECK(format);
   RAW_CHECK(buff_length > 0);
   const char *buff_end = &buff[buff_length - 1];
@@ -112,11 +129,11 @@
       continue;
     }
     cur++;
-    bool have_width = (*cur == '0');
+    bool have_width = (*cur >= '0' && *cur <= '9');
+    bool pad_with_zero = (*cur == '0');
     int width = 0;
     if (have_width) {
       while (*cur >= '0' && *cur <= '9') {
-        have_width = true;
         width = width * 10 + *cur++ - '0';
       }
     }
@@ -132,16 +149,17 @@
         dval = have_ll ? va_arg(args, s64)
              : have_z ? va_arg(args, sptr)
              : va_arg(args, int);
-        result += AppendSignedDecimal(&buff, buff_end, dval, width);
+        result += AppendSignedDecimal(&buff, buff_end, dval, width,
+                                      pad_with_zero);
         break;
       }
       case 'u':
       case 'x': {
         uval = have_ll ? va_arg(args, u64)
              : have_z ? va_arg(args, uptr)
              : va_arg(args, unsigned);
         result += AppendUnsigned(&buff, buff_end, uval,
-                                 (*cur == 'u') ? 10 : 16, width);
+                                 (*cur == 'u') ? 10 : 16, width, pad_with_zero);
         break;
       }
       case 'p': {
Index: lib/sanitizer_common/tests/sanitizer_printf_test.cc
===================================================================
--- lib/sanitizer_common/tests/sanitizer_printf_test.cc
+++ lib/sanitizer_common/tests/sanitizer_printf_test.cc
@@ -104,22 +104,36 @@
 }
 
 template<typename T>
-static void TestMinMax(const char *fmt, T min, T max) {
+static void TestAgainstLibc(const char *fmt, T arg1, T arg2) {
   char buf[1024];
-  uptr len = internal_snprintf(buf, sizeof(buf), fmt, min, max);
+  uptr len = internal_snprintf(buf, sizeof(buf), fmt, arg1, arg2);
   char buf2[1024];
-  snprintf(buf2, sizeof(buf2), fmt, min, max);
+  snprintf(buf2, sizeof(buf2), fmt, arg1, arg2);
   EXPECT_EQ(len, strlen(buf));
   EXPECT_STREQ(buf2, buf);
 }
 
 TEST(Printf, MinMax) {
-  TestMinMax<int>("%d-%d", INT_MIN, INT_MAX);  // NOLINT
-  TestMinMax<long>("%zd-%zd", LONG_MIN, LONG_MAX);  // NOLINT
-  TestMinMax<unsigned>("%u-%u", 0, UINT_MAX);  // NOLINT
-  TestMinMax<unsigned long>("%zu-%zu", 0, ULONG_MAX);  // NOLINT
-  TestMinMax<unsigned>("%x-%x", 0, UINT_MAX);  // NOLINT
-  TestMinMax<unsigned long>("%zx-%zx", 0, ULONG_MAX);  // NOLINT
+  TestAgainstLibc<int>("%d-%d", INT_MIN, INT_MAX);  // NOLINT
+  TestAgainstLibc<long>("%zd-%zd", LONG_MIN, LONG_MAX);  // NOLINT
+  TestAgainstLibc<unsigned>("%u-%u", 0, UINT_MAX);  // NOLINT
+  TestAgainstLibc<unsigned long>("%zu-%zu", 0, ULONG_MAX);  // NOLINT
+  TestAgainstLibc<unsigned>("%x-%x", 0, UINT_MAX);  // NOLINT
+  TestAgainstLibc<unsigned long>("%zx-%zx", 0, ULONG_MAX);  // NOLINT
+  Report("%zd\n", LONG_MIN);
+}
+
+TEST(Printf, Padding) {
+  TestAgainstLibc<int>("%3d - %3d", 1, 0);
+  TestAgainstLibc<int>("%3d - %3d", -1, 123);
+  TestAgainstLibc<int>("%3d - %3d", -1, -123);
+  TestAgainstLibc<int>("%3d - %3d", 12, 1234);
+  TestAgainstLibc<int>("%3d - %3d", -12, -1234);
+  TestAgainstLibc<int>("%03d - %03d", 1, 0);
+  TestAgainstLibc<int>("%03d - %03d", -1, 123);
+  TestAgainstLibc<int>("%03d - %03d", -1, -123);
+  TestAgainstLibc<int>("%03d - %03d", 12, 1234);
+  TestAgainstLibc<int>("%03d - %03d", -12, -1234);
 }
 
 }  // namespace __sanitizer
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D1057.2.patch
Type: text/x-patch
Size: 7367 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20130627/8be6b215/attachment.bin>


More information about the llvm-commits mailing list