[ASan] Try to use a small (512 bytes) stack-local buffer in Report() for short messag...
authorAlexander Potapenko <glider@google.com>
Mon, 11 Mar 2013 11:47:43 +0000 (11:47 +0000)
committerAlexander Potapenko <glider@google.com>
Mon, 11 Mar 2013 11:47:43 +0000 (11:47 +0000)
This shall eliminate most of the cryptic "ERROR: failed to mmap" messages caused by recursively calling MmapOrDie() from MmapOrDie().

llvm-svn: 176802

compiler-rt/lib/sanitizer_common/sanitizer_printf.cc

index 2393e8f..8fb2778 100644 (file)
@@ -201,19 +201,48 @@ int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
 // Like Printf, but prints the current PID before the output string.
 void Report(const char *format, ...) {
   const int kLen = 16 * 1024;
-  InternalScopedBuffer<char> buffer(kLen);
-  int needed_length = internal_snprintf(buffer.data(),
-                                        kLen, "==%d== ", GetPid());
-  RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
-  va_list args;
-  va_start(args, format);
-  needed_length += VSNPrintf(buffer.data() + needed_length,
-                             kLen - needed_length, format, args);
-  va_end(args);
-  RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
-  RawWrite(buffer.data());
-  if (PrintfAndReportCallback)
-    PrintfAndReportCallback(buffer.data());
+  // |local_buffer| is small enough not to overflow the stack.
+  char local_buffer[512];
+  int needed_length;
+  int pid = GetPid();
+  char *buffer = local_buffer;
+  int cur_size = sizeof(local_buffer) / sizeof(char);
+  for (int use_mmap = 0; use_mmap < 2; use_mmap++) {
+    needed_length = internal_snprintf(buffer, cur_size,
+                                      "==%d==", pid);
+    if (needed_length >= cur_size) {
+      if (use_mmap) {
+        RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
+      } else {
+        // The pid doesn't fit into the local buffer.
+        continue;
+      }
+    }
+    va_list args;
+    va_start(args, format);
+    needed_length += VSNPrintf(buffer + needed_length,
+                               cur_size - needed_length, format, args);
+    va_end(args);
+    if (needed_length >= cur_size) {
+      if (use_mmap) {
+        RAW_CHECK_MSG(needed_length < kLen, "Buffer in Report is too short!\n");
+      } else {
+        // The error message doesn't fit into the local buffer - allocate a bigger one.
+        buffer = (char*)MmapOrDie(kLen, "Report");
+        cur_size = kLen;
+        continue;
+      }
+    } else {
+      RawWrite(buffer);
+      if (PrintfAndReportCallback)
+        PrintfAndReportCallback(buffer);
+      // Don't do anything for the second time if the first iteration
+      // succeeded.
+      break;
+    }
+  }
+  // If we had mapped any memory, clean up.
+  if (buffer != local_buffer) UnmapOrDie((void*)buffer, cur_size);
 }
 
 }  // namespace __sanitizer