Home | History | Annotate | Download | only in sanitizer_common
      1 //===-- sanitizer_printf.cc -----------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is shared between AddressSanitizer and ThreadSanitizer.
     11 //
     12 // Internal printf function, used inside run-time libraries.
     13 // We can't use libc printf because we intercept some of the functions used
     14 // inside it.
     15 //===----------------------------------------------------------------------===//
     16 
     17 #include "sanitizer_common.h"
     18 #include "sanitizer_flags.h"
     19 #include "sanitizer_libc.h"
     20 
     21 #include <stdio.h>
     22 #include <stdarg.h>
     23 
     24 #if SANITIZER_WINDOWS && defined(_MSC_VER) && _MSC_VER < 1800 &&               \
     25       !defined(va_copy)
     26 # define va_copy(dst, src) ((dst) = (src))
     27 #endif
     28 
     29 namespace __sanitizer {
     30 
     31 StaticSpinMutex CommonSanitizerReportMutex;
     32 
     33 static int AppendChar(char **buff, const char *buff_end, char c) {
     34   if (*buff < buff_end) {
     35     **buff = c;
     36     (*buff)++;
     37   }
     38   return 1;
     39 }
     40 
     41 // Appends number in a given base to buffer. If its length is less than
     42 // |minimal_num_length|, it is padded with leading zeroes or spaces, depending
     43 // on the value of |pad_with_zero|.
     44 static int AppendNumber(char **buff, const char *buff_end, u64 absolute_value,
     45                         u8 base, u8 minimal_num_length, bool pad_with_zero,
     46                         bool negative) {
     47   uptr const kMaxLen = 30;
     48   RAW_CHECK(base == 10 || base == 16);
     49   RAW_CHECK(base == 10 || !negative);
     50   RAW_CHECK(absolute_value || !negative);
     51   RAW_CHECK(minimal_num_length < kMaxLen);
     52   int result = 0;
     53   if (negative && minimal_num_length)
     54     --minimal_num_length;
     55   if (negative && pad_with_zero)
     56     result += AppendChar(buff, buff_end, '-');
     57   uptr num_buffer[kMaxLen];
     58   int pos = 0;
     59   do {
     60     RAW_CHECK_MSG((uptr)pos < kMaxLen, "AppendNumber buffer overflow");
     61     num_buffer[pos++] = absolute_value % base;
     62     absolute_value /= base;
     63   } while (absolute_value > 0);
     64   if (pos < minimal_num_length) {
     65     // Make sure compiler doesn't insert call to memset here.
     66     internal_memset(&num_buffer[pos], 0,
     67                     sizeof(num_buffer[0]) * (minimal_num_length - pos));
     68     pos = minimal_num_length;
     69   }
     70   RAW_CHECK(pos > 0);
     71   pos--;
     72   for (; pos >= 0 && num_buffer[pos] == 0; pos--) {
     73     char c = (pad_with_zero || pos == 0) ? '0' : ' ';
     74     result += AppendChar(buff, buff_end, c);
     75   }
     76   if (negative && !pad_with_zero) result += AppendChar(buff, buff_end, '-');
     77   for (; pos >= 0; pos--) {
     78     char digit = static_cast<char>(num_buffer[pos]);
     79     result += AppendChar(buff, buff_end, (digit < 10) ? '0' + digit
     80                                                       : 'a' + digit - 10);
     81   }
     82   return result;
     83 }
     84 
     85 static int AppendUnsigned(char **buff, const char *buff_end, u64 num, u8 base,
     86                           u8 minimal_num_length, bool pad_with_zero) {
     87   return AppendNumber(buff, buff_end, num, base, minimal_num_length,
     88                       pad_with_zero, false /* negative */);
     89 }
     90 
     91 static int AppendSignedDecimal(char **buff, const char *buff_end, s64 num,
     92                                u8 minimal_num_length, bool pad_with_zero) {
     93   bool negative = (num < 0);
     94   return AppendNumber(buff, buff_end, (u64)(negative ? -num : num), 10,
     95                       minimal_num_length, pad_with_zero, negative);
     96 }
     97 
     98 static int AppendString(char **buff, const char *buff_end, int precision,
     99                         const char *s) {
    100   if (!s)
    101     s = "<null>";
    102   int result = 0;
    103   for (; *s; s++) {
    104     if (precision >= 0 && result >= precision)
    105       break;
    106     result += AppendChar(buff, buff_end, *s);
    107   }
    108   return result;
    109 }
    110 
    111 static int AppendPointer(char **buff, const char *buff_end, u64 ptr_value) {
    112   int result = 0;
    113   result += AppendString(buff, buff_end, -1, "0x");
    114   result += AppendUnsigned(buff, buff_end, ptr_value, 16,
    115                            SANITIZER_POINTER_FORMAT_LENGTH, true);
    116   return result;
    117 }
    118 
    119 int VSNPrintf(char *buff, int buff_length,
    120               const char *format, va_list args) {
    121   static const char *kPrintfFormatsHelp =
    122     "Supported Printf formats: %([0-9]*)?(z|ll)?{d,u,x}; %p; %(\\.\\*)?s; %c\n";
    123   RAW_CHECK(format);
    124   RAW_CHECK(buff_length > 0);
    125   const char *buff_end = &buff[buff_length - 1];
    126   const char *cur = format;
    127   int result = 0;
    128   for (; *cur; cur++) {
    129     if (*cur != '%') {
    130       result += AppendChar(&buff, buff_end, *cur);
    131       continue;
    132     }
    133     cur++;
    134     bool have_width = (*cur >= '0' && *cur <= '9');
    135     bool pad_with_zero = (*cur == '0');
    136     int width = 0;
    137     if (have_width) {
    138       while (*cur >= '0' && *cur <= '9') {
    139         width = width * 10 + *cur++ - '0';
    140       }
    141     }
    142     bool have_precision = (cur[0] == '.' && cur[1] == '*');
    143     int precision = -1;
    144     if (have_precision) {
    145       cur += 2;
    146       precision = va_arg(args, int);
    147     }
    148     bool have_z = (*cur == 'z');
    149     cur += have_z;
    150     bool have_ll = !have_z && (cur[0] == 'l' && cur[1] == 'l');
    151     cur += have_ll * 2;
    152     s64 dval;
    153     u64 uval;
    154     bool have_flags = have_width | have_z | have_ll;
    155     // Only %s supports precision for now
    156     CHECK(!(precision >= 0 && *cur != 's'));
    157     switch (*cur) {
    158       case 'd': {
    159         dval = have_ll ? va_arg(args, s64)
    160              : have_z ? va_arg(args, sptr)
    161              : va_arg(args, int);
    162         result += AppendSignedDecimal(&buff, buff_end, dval, width,
    163                                       pad_with_zero);
    164         break;
    165       }
    166       case 'u':
    167       case 'x': {
    168         uval = have_ll ? va_arg(args, u64)
    169              : have_z ? va_arg(args, uptr)
    170              : va_arg(args, unsigned);
    171         result += AppendUnsigned(&buff, buff_end, uval,
    172                                  (*cur == 'u') ? 10 : 16, width, pad_with_zero);
    173         break;
    174       }
    175       case 'p': {
    176         RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
    177         result += AppendPointer(&buff, buff_end, va_arg(args, uptr));
    178         break;
    179       }
    180       case 's': {
    181         RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
    182         result += AppendString(&buff, buff_end, precision, va_arg(args, char*));
    183         break;
    184       }
    185       case 'c': {
    186         RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
    187         result += AppendChar(&buff, buff_end, va_arg(args, int));
    188         break;
    189       }
    190       case '%' : {
    191         RAW_CHECK_MSG(!have_flags, kPrintfFormatsHelp);
    192         result += AppendChar(&buff, buff_end, '%');
    193         break;
    194       }
    195       default: {
    196         RAW_CHECK_MSG(false, kPrintfFormatsHelp);
    197       }
    198     }
    199   }
    200   RAW_CHECK(buff <= buff_end);
    201   AppendChar(&buff, buff_end + 1, '\0');
    202   return result;
    203 }
    204 
    205 static void (*PrintfAndReportCallback)(const char *);
    206 void SetPrintfAndReportCallback(void (*callback)(const char *)) {
    207   PrintfAndReportCallback = callback;
    208 }
    209 
    210 // Can be overriden in frontend.
    211 #if SANITIZER_SUPPORTS_WEAK_HOOKS
    212 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
    213 void OnPrint(const char *str) {
    214   (void)str;
    215 }
    216 #elif defined(SANITIZER_GO) && defined(TSAN_EXTERNAL_HOOKS)
    217 void OnPrint(const char *str);
    218 #else
    219 void OnPrint(const char *str) {
    220   (void)str;
    221 }
    222 #endif
    223 
    224 static void CallPrintfAndReportCallback(const char *str) {
    225   OnPrint(str);
    226   if (PrintfAndReportCallback)
    227     PrintfAndReportCallback(str);
    228 }
    229 
    230 static void SharedPrintfCode(bool append_pid, const char *format,
    231                              va_list args) {
    232   va_list args2;
    233   va_copy(args2, args);
    234   const int kLen = 16 * 1024;
    235   // |local_buffer| is small enough not to overflow the stack and/or violate
    236   // the stack limit enforced by TSan (-Wframe-larger-than=512). On the other
    237   // hand, the bigger the buffer is, the more the chance the error report will
    238   // fit into it.
    239   char local_buffer[400];
    240   int needed_length;
    241   char *buffer = local_buffer;
    242   int buffer_size = ARRAY_SIZE(local_buffer);
    243   // First try to print a message using a local buffer, and then fall back to
    244   // mmaped buffer.
    245   for (int use_mmap = 0; use_mmap < 2; use_mmap++) {
    246     if (use_mmap) {
    247       va_end(args);
    248       va_copy(args, args2);
    249       buffer = (char*)MmapOrDie(kLen, "Report");
    250       buffer_size = kLen;
    251     }
    252     needed_length = 0;
    253     // Check that data fits into the current buffer.
    254 #   define CHECK_NEEDED_LENGTH \
    255       if (needed_length >= buffer_size) { \
    256         if (!use_mmap) continue; \
    257         RAW_CHECK_MSG(needed_length < kLen, \
    258                       "Buffer in Report is too short!\n"); \
    259       }
    260     if (append_pid) {
    261       int pid = internal_getpid();
    262       const char *exe_name = GetProcessName();
    263       if (common_flags()->log_exe_name && exe_name) {
    264         needed_length += internal_snprintf(buffer, buffer_size,
    265                                            "==%s", exe_name);
    266         CHECK_NEEDED_LENGTH
    267       }
    268       needed_length += internal_snprintf(buffer + needed_length,
    269                                          buffer_size - needed_length,
    270                                          "==%d==", pid);
    271       CHECK_NEEDED_LENGTH
    272     }
    273     needed_length += VSNPrintf(buffer + needed_length,
    274                                buffer_size - needed_length, format, args);
    275     CHECK_NEEDED_LENGTH
    276     // If the message fit into the buffer, print it and exit.
    277     break;
    278 #   undef CHECK_NEEDED_LENGTH
    279   }
    280   RawWrite(buffer);
    281 
    282   // Remove color sequences from the message.
    283   RemoveANSIEscapeSequencesFromString(buffer);
    284   CallPrintfAndReportCallback(buffer);
    285   LogMessageOnPrintf(buffer);
    286 
    287   // If we had mapped any memory, clean up.
    288   if (buffer != local_buffer)
    289     UnmapOrDie((void *)buffer, buffer_size);
    290   va_end(args2);
    291 }
    292 
    293 FORMAT(1, 2)
    294 void Printf(const char *format, ...) {
    295   va_list args;
    296   va_start(args, format);
    297   SharedPrintfCode(false, format, args);
    298   va_end(args);
    299 }
    300 
    301 // Like Printf, but prints the current PID before the output string.
    302 FORMAT(1, 2)
    303 void Report(const char *format, ...) {
    304   va_list args;
    305   va_start(args, format);
    306   SharedPrintfCode(true, format, args);
    307   va_end(args);
    308 }
    309 
    310 // Writes at most "length" symbols to "buffer" (including trailing '\0').
    311 // Returns the number of symbols that should have been written to buffer
    312 // (not including trailing '\0'). Thus, the string is truncated
    313 // iff return value is not less than "length".
    314 FORMAT(3, 4)
    315 int internal_snprintf(char *buffer, uptr length, const char *format, ...) {
    316   va_list args;
    317   va_start(args, format);
    318   int needed_length = VSNPrintf(buffer, length, format, args);
    319   va_end(args);
    320   return needed_length;
    321 }
    322 
    323 FORMAT(2, 3)
    324 void InternalScopedString::append(const char *format, ...) {
    325   CHECK_LT(length_, size());
    326   va_list args;
    327   va_start(args, format);
    328   VSNPrintf(data() + length_, size() - length_, format, args);
    329   va_end(args);
    330   length_ += internal_strlen(data() + length_);
    331   CHECK_LT(length_, size());
    332 }
    333 
    334 } // namespace __sanitizer
    335