Home | History | Annotate | Download | only in strings
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef BASE_STRINGS_SAFE_SPRINTF_H_
      6 #define BASE_STRINGS_SAFE_SPRINTF_H_
      7 
      8 #include "build/build_config.h"
      9 
     10 #include <stddef.h>
     11 #include <stdint.h>
     12 #include <stdlib.h>
     13 
     14 #if defined(OS_POSIX)
     15 // For ssize_t
     16 #include <unistd.h>
     17 #endif
     18 
     19 #include "base/base_export.h"
     20 #include "base/basictypes.h"
     21 
     22 namespace base {
     23 namespace strings {
     24 
     25 #if defined(_MSC_VER)
     26 // Define ssize_t inside of our namespace.
     27 #if defined(_WIN64)
     28 typedef __int64 ssize_t;
     29 #else
     30 typedef long ssize_t;
     31 #endif
     32 #endif
     33 
     34 // SafeSPrintf() is a type-safe and completely self-contained version of
     35 // snprintf().
     36 //
     37 // SafeSNPrintf() is an alternative function signature that can be used when
     38 // not dealing with fixed-sized buffers. When possible, SafeSPrintf() should
     39 // always be used instead of SafeSNPrintf()
     40 //
     41 // These functions allow for formatting complicated messages from contexts that
     42 // require strict async-signal-safety. In fact, it is safe to call them from
     43 // any low-level execution context, as they are guaranteed to make no library
     44 // or system calls. It deliberately never touches "errno", either.
     45 //
     46 // The only exception to this rule is that in debug builds the code calls
     47 // RAW_CHECK() to help diagnose problems when the format string does not
     48 // match the rest of the arguments. In release builds, no CHECK()s are used,
     49 // and SafeSPrintf() instead returns an output string that expands only
     50 // those arguments that match their format characters. Mismatched arguments
     51 // are ignored.
     52 //
     53 // The code currently only supports a subset of format characters:
     54 //   %c, %o, %d, %x, %X, %p, and %s.
     55 //
     56 // SafeSPrintf() aims to be as liberal as reasonably possible. Integer-like
     57 // values of arbitrary width can be passed to all of the format characters
     58 // that expect integers. Thus, it is explicitly legal to pass an "int" to
     59 // "%c", and output will automatically look at the LSB only. It is also
     60 // explicitly legal to pass either signed or unsigned values, and the format
     61 // characters will automatically interpret the arguments accordingly.
     62 //
     63 // It is still not legal to mix-and-match integer-like values with pointer
     64 // values. For instance, you cannot pass a pointer to %x, nor can you pass an
     65 // integer to %p.
     66 //
     67 // The one exception is "0" zero being accepted by "%p". This works-around
     68 // the problem of C++ defining NULL as an integer-like value.
     69 //
     70 // All format characters take an optional width parameter. This must be a
     71 // positive integer. For %d, %o, %x, %X and %p, if the width starts with
     72 // a leading '0', padding is done with '0' instead of ' ' characters.
     73 //
     74 // There are a few features of snprintf()-style format strings, that
     75 // SafeSPrintf() does not support at this time.
     76 //
     77 // If an actual user showed up, there is no particularly strong reason they
     78 // couldn't be added. But that assumes that the trade-offs between complexity
     79 // and utility are favorable.
     80 //
     81 // For example, adding support for negative padding widths, and for %n are all
     82 // likely to be viewed positively. They are all clearly useful, low-risk, easy
     83 // to test, don't jeopardize the async-signal-safety of the code, and overall
     84 // have little impact on other parts of SafeSPrintf() function.
     85 //
     86 // On the other hands, adding support for alternate forms, positional
     87 // arguments, grouping, wide characters, localization or floating point numbers
     88 // are all unlikely to ever be added.
     89 //
     90 // SafeSPrintf() and SafeSNPrintf() mimic the behavior of snprintf() and they
     91 // return the number of bytes needed to store the untruncated output. This
     92 // does *not* include the terminating NUL byte.
     93 //
     94 // They return -1, iff a fatal error happened. This typically can only happen,
     95 // if the buffer size is a) negative, or b) zero (i.e. not even the NUL byte
     96 // can be written). The return value can never be larger than SSIZE_MAX-1.
     97 // This ensures that the caller can always add one to the signed return code
     98 // in order to determine the amount of storage that needs to be allocated.
     99 //
    100 // While the code supports type checking and while it is generally very careful
    101 // to avoid printing incorrect values, it tends to be conservative in printing
    102 // as much as possible, even when given incorrect parameters. Typically, in
    103 // case of an error, the format string will not be expanded. (i.e. something
    104 // like SafeSPrintf(buf, "%p %d", 1, 2) results in "%p 2"). See above for
    105 // the use of RAW_CHECK() in debug builds, though.
    106 //
    107 // Basic example:
    108 //   char buf[20];
    109 //   base::strings::SafeSPrintf(buf, "The answer: %2d", 42);
    110 //
    111 // Example with dynamically sized buffer (async-signal-safe). This code won't
    112 // work on Visual studio, as it requires dynamically allocating arrays on the
    113 // stack. Consider picking a smaller value for |kMaxSize| if stack size is
    114 // limited and known. On the other hand, if the parameters to SafeSNPrintf()
    115 // are trusted and not controllable by the user, you can consider eliminating
    116 // the check for |kMaxSize| altogether. The current value of SSIZE_MAX is
    117 // essentially a no-op that just illustrates how to implement an upper bound:
    118 //   const size_t kInitialSize = 128;
    119 //   const size_t kMaxSize = std::numeric_limits<ssize_t>::max();
    120 //   size_t size = kInitialSize;
    121 //   for (;;) {
    122 //     char buf[size];
    123 //     size = SafeSNPrintf(buf, size, "Error message \"%s\"\n", err) + 1;
    124 //     if (sizeof(buf) < kMaxSize && size > kMaxSize) {
    125 //       size = kMaxSize;
    126 //       continue;
    127 //     } else if (size > sizeof(buf))
    128 //       continue;
    129 //     write(2, buf, size-1);
    130 //     break;
    131 //   }
    132 
    133 namespace internal {
    134 // Helpers that use C++ overloading, templates, and specializations to deduce
    135 // and record type information from function arguments. This allows us to
    136 // later write a type-safe version of snprintf().
    137 
    138 struct Arg {
    139   enum Type { INT, UINT, STRING, POINTER };
    140 
    141   // Any integer-like value.
    142   Arg(signed char c)        : i(c), width(sizeof(char)),      type(INT)  { }
    143   Arg(unsigned char c)      : i(c), width(sizeof(char)),      type(UINT) { }
    144   Arg(signed short j)       : i(j), width(sizeof(short)),     type(INT)  { }
    145   Arg(unsigned short j)     : i(j), width(sizeof(short)),     type(UINT) { }
    146   Arg(signed int j)         : i(j), width(sizeof(int)),       type(INT)  { }
    147   Arg(unsigned int j)       : i(j), width(sizeof(int)),       type(UINT) { }
    148   Arg(signed long j)        : i(j), width(sizeof(long)),      type(INT)  { }
    149   Arg(unsigned long j)      : i(j), width(sizeof(long)),      type(UINT) { }
    150   Arg(signed long long j)   : i(j), width(sizeof(long long)), type(INT)  { }
    151   Arg(unsigned long long j) : i(j), width(sizeof(long long)), type(UINT) { }
    152 
    153   // A C-style text string.
    154   Arg(const char* s) : str(s), type(STRING) { }
    155   Arg(char* s)       : str(s), type(STRING) { }
    156 
    157   // Any pointer value that can be cast to a "void*".
    158   template<class T> Arg(T* p) : ptr((void*)p), type(POINTER) { }
    159 
    160   union {
    161     // An integer-like value.
    162     struct {
    163       int64_t       i;
    164       unsigned char width;
    165     };
    166 
    167     // A C-style text string.
    168     const char* str;
    169 
    170     // A pointer to an arbitrary object.
    171     const void* ptr;
    172   };
    173   const enum Type type;
    174 };
    175 
    176 // This is the internal function that performs the actual formatting of
    177 // an snprintf()-style format string.
    178 BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt,
    179                                  const Arg* args, size_t max_args);
    180 
    181 #if !defined(NDEBUG)
    182 // In debug builds, allow unit tests to artificially lower the kSSizeMax
    183 // constant that is used as a hard upper-bound for all buffers. In normal
    184 // use, this constant should always be std::numeric_limits<ssize_t>::max().
    185 BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max);
    186 BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest();
    187 #endif
    188 
    189 }  // namespace internal
    190 
    191 // TODO(markus): C++11 has a much more concise and readable solution for
    192 //   expressing what we are doing here.
    193 
    194 template<class T0, class T1, class T2, class T3, class T4,
    195          class T5, class T6, class T7, class T8, class T9>
    196 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    197                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    198                      T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
    199   // Use Arg() object to record type information and then copy arguments to an
    200   // array to make it easier to iterate over them.
    201   const internal::Arg arg_array[] = {
    202     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
    203   };
    204   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    205 }
    206 
    207 template<size_t N,
    208          class T0, class T1, class T2, class T3, class T4,
    209          class T5, class T6, class T7, class T8, class T9>
    210 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    211                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    212                     T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
    213   // Use Arg() object to record type information and then copy arguments to an
    214   // array to make it easier to iterate over them.
    215   const internal::Arg arg_array[] = {
    216     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
    217   };
    218   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    219 }
    220 
    221 template<class T0, class T1, class T2, class T3, class T4,
    222          class T5, class T6, class T7, class T8>
    223 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    224                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    225                      T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
    226   // Use Arg() object to record type information and then copy arguments to an
    227   // array to make it easier to iterate over them.
    228   const internal::Arg arg_array[] = {
    229     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
    230   };
    231   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    232 }
    233 
    234 template<size_t N,
    235          class T0, class T1, class T2, class T3, class T4, class T5,
    236          class T6, class T7, class T8>
    237 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    238                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    239                     T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
    240   // Use Arg() object to record type information and then copy arguments to an
    241   // array to make it easier to iterate over them.
    242   const internal::Arg arg_array[] = {
    243     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
    244   };
    245   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    246 }
    247 
    248 template<class T0, class T1, class T2, class T3, class T4, class T5,
    249          class T6, class T7>
    250 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    251                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    252                      T5 arg5, T6 arg6, T7 arg7) {
    253   // Use Arg() object to record type information and then copy arguments to an
    254   // array to make it easier to iterate over them.
    255   const internal::Arg arg_array[] = {
    256     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7
    257   };
    258   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    259 }
    260 
    261 template<size_t N,
    262          class T0, class T1, class T2, class T3, class T4, class T5,
    263          class T6, class T7>
    264 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    265                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    266                     T5 arg5, T6 arg6, T7 arg7) {
    267   // Use Arg() object to record type information and then copy arguments to an
    268   // array to make it easier to iterate over them.
    269   const internal::Arg arg_array[] = {
    270     arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7
    271   };
    272   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    273 }
    274 
    275 template<class T0, class T1, class T2, class T3, class T4, class T5,
    276          class T6>
    277 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    278                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
    279                      T5 arg5, T6 arg6) {
    280   // Use Arg() object to record type information and then copy arguments to an
    281   // array to make it easier to iterate over them.
    282   const internal::Arg arg_array[] = {
    283     arg0, arg1, arg2, arg3, arg4, arg5, arg6
    284   };
    285   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    286 }
    287 
    288 template<size_t N,
    289          class T0, class T1, class T2, class T3, class T4, class T5,
    290          class T6>
    291 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    292                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5,
    293                     T6 arg6) {
    294   // Use Arg() object to record type information and then copy arguments to an
    295   // array to make it easier to iterate over them.
    296   const internal::Arg arg_array[] = {
    297     arg0, arg1, arg2, arg3, arg4, arg5, arg6
    298   };
    299   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    300 }
    301 
    302 template<class T0, class T1, class T2, class T3, class T4, class T5>
    303 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    304                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
    305   // Use Arg() object to record type information and then copy arguments to an
    306   // array to make it easier to iterate over them.
    307   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 };
    308   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    309 }
    310 
    311 template<size_t N,
    312          class T0, class T1, class T2, class T3, class T4, class T5>
    313 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    314                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
    315   // Use Arg() object to record type information and then copy arguments to an
    316   // array to make it easier to iterate over them.
    317   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 };
    318   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    319 }
    320 
    321 template<class T0, class T1, class T2, class T3, class T4>
    322 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    323                      T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
    324   // Use Arg() object to record type information and then copy arguments to an
    325   // array to make it easier to iterate over them.
    326   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 };
    327   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    328 }
    329 
    330 template<size_t N, class T0, class T1, class T2, class T3, class T4>
    331 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1,
    332                     T2 arg2, T3 arg3, T4 arg4) {
    333   // Use Arg() object to record type information and then copy arguments to an
    334   // array to make it easier to iterate over them.
    335   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 };
    336   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    337 }
    338 
    339 template<class T0, class T1, class T2, class T3>
    340 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    341                      T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
    342   // Use Arg() object to record type information and then copy arguments to an
    343   // array to make it easier to iterate over them.
    344   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 };
    345   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    346 }
    347 
    348 template<size_t N, class T0, class T1, class T2, class T3>
    349 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
    350                     T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
    351   // Use Arg() object to record type information and then copy arguments to an
    352   // array to make it easier to iterate over them.
    353   const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 };
    354   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    355 }
    356 
    357 template<class T0, class T1, class T2>
    358 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
    359                      T0 arg0, T1 arg1, T2 arg2) {
    360   // Use Arg() object to record type information and then copy arguments to an
    361   // array to make it easier to iterate over them.
    362   const internal::Arg arg_array[] = { arg0, arg1, arg2 };
    363   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    364 }
    365 
    366 template<size_t N, class T0, class T1, class T2>
    367 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1,
    368                     T2 arg2) {
    369   // Use Arg() object to record type information and then copy arguments to an
    370   // array to make it easier to iterate over them.
    371   const internal::Arg arg_array[] = { arg0, arg1, arg2 };
    372   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    373 }
    374 
    375 template<class T0, class T1>
    376 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0, T1 arg1) {
    377   // Use Arg() object to record type information and then copy arguments to an
    378   // array to make it easier to iterate over them.
    379   const internal::Arg arg_array[] = { arg0, arg1 };
    380   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    381 }
    382 
    383 template<size_t N, class T0, class T1>
    384 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1) {
    385   // Use Arg() object to record type information and then copy arguments to an
    386   // array to make it easier to iterate over them.
    387   const internal::Arg arg_array[] = { arg0, arg1 };
    388   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    389 }
    390 
    391 template<class T0>
    392 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0) {
    393   // Use Arg() object to record type information and then copy arguments to an
    394   // array to make it easier to iterate over them.
    395   const internal::Arg arg_array[] = { arg0 };
    396   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    397 }
    398 
    399 template<size_t N, class T0>
    400 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0) {
    401   // Use Arg() object to record type information and then copy arguments to an
    402   // array to make it easier to iterate over them.
    403   const internal::Arg arg_array[] = { arg0 };
    404   return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
    405 }
    406 
    407 // Fast-path when we don't actually need to substitute any arguments.
    408 BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt);
    409 template<size_t N>
    410 inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) {
    411   return SafeSNPrintf(buf, N, fmt);
    412 }
    413 
    414 }  // namespace strings
    415 }  // namespace base
    416 
    417 #endif  // BASE_STRINGS_SAFE_SPRINTF_H_
    418