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
22namespace base {
23namespace strings {
24
25#if defined(_MSC_VER)
26// Define ssize_t inside of our namespace.
27#if defined(_WIN64)
28typedef __int64 ssize_t;
29#else
30typedef 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
133namespace 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
138struct Arg {
139  enum Type { INT, UINT, STRING, POINTER };
140
141  // Any integer-like value.
142  Arg(signed char c) : type(INT) {
143    integer.i = c;
144    integer.width = sizeof(char);
145  }
146  Arg(unsigned char c) : type(UINT) {
147    integer.i = c;
148    integer.width = sizeof(char);
149  }
150  Arg(signed short j) : type(INT) {
151    integer.i = j;
152    integer.width = sizeof(short);
153  }
154  Arg(unsigned short j) : type(UINT) {
155    integer.i = j;
156    integer.width = sizeof(short);
157  }
158  Arg(signed int j) : type(INT) {
159    integer.i = j;
160    integer.width = sizeof(int);
161  }
162  Arg(unsigned int j) : type(UINT) {
163    integer.i = j;
164    integer.width = sizeof(int);
165  }
166  Arg(signed long j) : type(INT) {
167    integer.i = j;
168    integer.width = sizeof(long);
169  }
170  Arg(unsigned long j) : type(UINT) {
171    integer.i = j;
172    integer.width = sizeof(long);
173  }
174  Arg(signed long long j) : type(INT) {
175    integer.i = j;
176    integer.width = sizeof(long long);
177  }
178  Arg(unsigned long long j) : type(UINT) {
179    integer.i = j;
180    integer.width = sizeof(long long);
181  }
182
183  // A C-style text string.
184  Arg(const char* s) : str(s), type(STRING) { }
185  Arg(char* s)       : str(s), type(STRING) { }
186
187  // Any pointer value that can be cast to a "void*".
188  template<class T> Arg(T* p) : ptr((void*)p), type(POINTER) { }
189
190  union {
191    // An integer-like value.
192    struct {
193      int64_t       i;
194      unsigned char width;
195    } integer;
196
197    // A C-style text string.
198    const char* str;
199
200    // A pointer to an arbitrary object.
201    const void* ptr;
202  };
203  const enum Type type;
204};
205
206// This is the internal function that performs the actual formatting of
207// an snprintf()-style format string.
208BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt,
209                                 const Arg* args, size_t max_args);
210
211#if !defined(NDEBUG)
212// In debug builds, allow unit tests to artificially lower the kSSizeMax
213// constant that is used as a hard upper-bound for all buffers. In normal
214// use, this constant should always be std::numeric_limits<ssize_t>::max().
215BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max);
216BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest();
217#endif
218
219}  // namespace internal
220
221// TODO(markus): C++11 has a much more concise and readable solution for
222//   expressing what we are doing here.
223
224template<class T0, class T1, class T2, class T3, class T4,
225         class T5, class T6, class T7, class T8, class T9>
226ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
227                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
228                     T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
229  // Use Arg() object to record type information and then copy arguments to an
230  // array to make it easier to iterate over them.
231  const internal::Arg arg_array[] = {
232    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
233  };
234  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
235}
236
237template<size_t N,
238         class T0, class T1, class T2, class T3, class T4,
239         class T5, class T6, class T7, class T8, class T9>
240ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
241                    T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
242                    T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) {
243  // Use Arg() object to record type information and then copy arguments to an
244  // array to make it easier to iterate over them.
245  const internal::Arg arg_array[] = {
246    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9
247  };
248  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
249}
250
251template<class T0, class T1, class T2, class T3, class T4,
252         class T5, class T6, class T7, class T8>
253ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
254                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
255                     T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
256  // Use Arg() object to record type information and then copy arguments to an
257  // array to make it easier to iterate over them.
258  const internal::Arg arg_array[] = {
259    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
260  };
261  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
262}
263
264template<size_t N,
265         class T0, class T1, class T2, class T3, class T4, class T5,
266         class T6, class T7, class T8>
267ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
268                    T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
269                    T5 arg5, T6 arg6, T7 arg7, T8 arg8) {
270  // Use Arg() object to record type information and then copy arguments to an
271  // array to make it easier to iterate over them.
272  const internal::Arg arg_array[] = {
273    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
274  };
275  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
276}
277
278template<class T0, class T1, class T2, class T3, class T4, class T5,
279         class T6, class T7>
280ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
281                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
282                     T5 arg5, T6 arg6, T7 arg7) {
283  // Use Arg() object to record type information and then copy arguments to an
284  // array to make it easier to iterate over them.
285  const internal::Arg arg_array[] = {
286    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7
287  };
288  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
289}
290
291template<size_t N,
292         class T0, class T1, class T2, class T3, class T4, class T5,
293         class T6, class T7>
294ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
295                    T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
296                    T5 arg5, T6 arg6, T7 arg7) {
297  // Use Arg() object to record type information and then copy arguments to an
298  // array to make it easier to iterate over them.
299  const internal::Arg arg_array[] = {
300    arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7
301  };
302  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
303}
304
305template<class T0, class T1, class T2, class T3, class T4, class T5,
306         class T6>
307ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
308                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4,
309                     T5 arg5, T6 arg6) {
310  // Use Arg() object to record type information and then copy arguments to an
311  // array to make it easier to iterate over them.
312  const internal::Arg arg_array[] = {
313    arg0, arg1, arg2, arg3, arg4, arg5, arg6
314  };
315  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
316}
317
318template<size_t N,
319         class T0, class T1, class T2, class T3, class T4, class T5,
320         class T6>
321ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
322                    T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5,
323                    T6 arg6) {
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[] = {
327    arg0, arg1, arg2, arg3, arg4, arg5, arg6
328  };
329  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
330}
331
332template<class T0, class T1, class T2, class T3, class T4, class T5>
333ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
334                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
335  // Use Arg() object to record type information and then copy arguments to an
336  // array to make it easier to iterate over them.
337  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 };
338  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
339}
340
341template<size_t N,
342         class T0, class T1, class T2, class T3, class T4, class T5>
343ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
344                    T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) {
345  // Use Arg() object to record type information and then copy arguments to an
346  // array to make it easier to iterate over them.
347  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4, arg5 };
348  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
349}
350
351template<class T0, class T1, class T2, class T3, class T4>
352ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
353                     T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4) {
354  // Use Arg() object to record type information and then copy arguments to an
355  // array to make it easier to iterate over them.
356  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 };
357  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
358}
359
360template<size_t N, class T0, class T1, class T2, class T3, class T4>
361ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1,
362                    T2 arg2, T3 arg3, T4 arg4) {
363  // Use Arg() object to record type information and then copy arguments to an
364  // array to make it easier to iterate over them.
365  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3, arg4 };
366  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
367}
368
369template<class T0, class T1, class T2, class T3>
370ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
371                     T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
372  // Use Arg() object to record type information and then copy arguments to an
373  // array to make it easier to iterate over them.
374  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 };
375  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
376}
377
378template<size_t N, class T0, class T1, class T2, class T3>
379ssize_t SafeSPrintf(char (&buf)[N], const char* fmt,
380                    T0 arg0, T1 arg1, T2 arg2, T3 arg3) {
381  // Use Arg() object to record type information and then copy arguments to an
382  // array to make it easier to iterate over them.
383  const internal::Arg arg_array[] = { arg0, arg1, arg2, arg3 };
384  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
385}
386
387template<class T0, class T1, class T2>
388ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt,
389                     T0 arg0, T1 arg1, T2 arg2) {
390  // Use Arg() object to record type information and then copy arguments to an
391  // array to make it easier to iterate over them.
392  const internal::Arg arg_array[] = { arg0, arg1, arg2 };
393  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
394}
395
396template<size_t N, class T0, class T1, class T2>
397ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1,
398                    T2 arg2) {
399  // Use Arg() object to record type information and then copy arguments to an
400  // array to make it easier to iterate over them.
401  const internal::Arg arg_array[] = { arg0, arg1, arg2 };
402  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
403}
404
405template<class T0, class T1>
406ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0, T1 arg1) {
407  // Use Arg() object to record type information and then copy arguments to an
408  // array to make it easier to iterate over them.
409  const internal::Arg arg_array[] = { arg0, arg1 };
410  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
411}
412
413template<size_t N, class T0, class T1>
414ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0, T1 arg1) {
415  // Use Arg() object to record type information and then copy arguments to an
416  // array to make it easier to iterate over them.
417  const internal::Arg arg_array[] = { arg0, arg1 };
418  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
419}
420
421template<class T0>
422ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, T0 arg0) {
423  // Use Arg() object to record type information and then copy arguments to an
424  // array to make it easier to iterate over them.
425  const internal::Arg arg_array[] = { arg0 };
426  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
427}
428
429template<size_t N, class T0>
430ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0) {
431  // Use Arg() object to record type information and then copy arguments to an
432  // array to make it easier to iterate over them.
433  const internal::Arg arg_array[] = { arg0 };
434  return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array));
435}
436
437// Fast-path when we don't actually need to substitute any arguments.
438BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt);
439template<size_t N>
440inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) {
441  return SafeSNPrintf(buf, N, fmt);
442}
443
444}  // namespace strings
445}  // namespace base
446
447#endif  // BASE_STRINGS_SAFE_SPRINTF_H_
448