xref: /aosp_15_r20/external/libchrome/base/strings/safe_sprintf.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef BASE_STRINGS_SAFE_SPRINTF_H_
6*635a8641SAndroid Build Coastguard Worker #define BASE_STRINGS_SAFE_SPRINTF_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
9*635a8641SAndroid Build Coastguard Worker 
10*635a8641SAndroid Build Coastguard Worker #include <stddef.h>
11*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
12*635a8641SAndroid Build Coastguard Worker #include <stdlib.h>
13*635a8641SAndroid Build Coastguard Worker 
14*635a8641SAndroid Build Coastguard Worker #if defined(OS_POSIX) || defined(OS_FUCHSIA)
15*635a8641SAndroid Build Coastguard Worker // For ssize_t
16*635a8641SAndroid Build Coastguard Worker #include <unistd.h>
17*635a8641SAndroid Build Coastguard Worker #endif
18*635a8641SAndroid Build Coastguard Worker 
19*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h"
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker namespace base {
22*635a8641SAndroid Build Coastguard Worker namespace strings {
23*635a8641SAndroid Build Coastguard Worker 
24*635a8641SAndroid Build Coastguard Worker #if defined(COMPILER_MSVC)
25*635a8641SAndroid Build Coastguard Worker // Define ssize_t inside of our namespace.
26*635a8641SAndroid Build Coastguard Worker #if defined(_WIN64)
27*635a8641SAndroid Build Coastguard Worker typedef __int64 ssize_t;
28*635a8641SAndroid Build Coastguard Worker #else
29*635a8641SAndroid Build Coastguard Worker typedef long ssize_t;
30*635a8641SAndroid Build Coastguard Worker #endif
31*635a8641SAndroid Build Coastguard Worker #endif
32*635a8641SAndroid Build Coastguard Worker 
33*635a8641SAndroid Build Coastguard Worker // SafeSPrintf() is a type-safe and completely self-contained version of
34*635a8641SAndroid Build Coastguard Worker // snprintf().
35*635a8641SAndroid Build Coastguard Worker //
36*635a8641SAndroid Build Coastguard Worker // SafeSNPrintf() is an alternative function signature that can be used when
37*635a8641SAndroid Build Coastguard Worker // not dealing with fixed-sized buffers. When possible, SafeSPrintf() should
38*635a8641SAndroid Build Coastguard Worker // always be used instead of SafeSNPrintf()
39*635a8641SAndroid Build Coastguard Worker //
40*635a8641SAndroid Build Coastguard Worker // These functions allow for formatting complicated messages from contexts that
41*635a8641SAndroid Build Coastguard Worker // require strict async-signal-safety. In fact, it is safe to call them from
42*635a8641SAndroid Build Coastguard Worker // any low-level execution context, as they are guaranteed to make no library
43*635a8641SAndroid Build Coastguard Worker // or system calls. It deliberately never touches "errno", either.
44*635a8641SAndroid Build Coastguard Worker //
45*635a8641SAndroid Build Coastguard Worker // The only exception to this rule is that in debug builds the code calls
46*635a8641SAndroid Build Coastguard Worker // RAW_CHECK() to help diagnose problems when the format string does not
47*635a8641SAndroid Build Coastguard Worker // match the rest of the arguments. In release builds, no CHECK()s are used,
48*635a8641SAndroid Build Coastguard Worker // and SafeSPrintf() instead returns an output string that expands only
49*635a8641SAndroid Build Coastguard Worker // those arguments that match their format characters. Mismatched arguments
50*635a8641SAndroid Build Coastguard Worker // are ignored.
51*635a8641SAndroid Build Coastguard Worker //
52*635a8641SAndroid Build Coastguard Worker // The code currently only supports a subset of format characters:
53*635a8641SAndroid Build Coastguard Worker //   %c, %o, %d, %x, %X, %p, and %s.
54*635a8641SAndroid Build Coastguard Worker //
55*635a8641SAndroid Build Coastguard Worker // SafeSPrintf() aims to be as liberal as reasonably possible. Integer-like
56*635a8641SAndroid Build Coastguard Worker // values of arbitrary width can be passed to all of the format characters
57*635a8641SAndroid Build Coastguard Worker // that expect integers. Thus, it is explicitly legal to pass an "int" to
58*635a8641SAndroid Build Coastguard Worker // "%c", and output will automatically look at the LSB only. It is also
59*635a8641SAndroid Build Coastguard Worker // explicitly legal to pass either signed or unsigned values, and the format
60*635a8641SAndroid Build Coastguard Worker // characters will automatically interpret the arguments accordingly.
61*635a8641SAndroid Build Coastguard Worker //
62*635a8641SAndroid Build Coastguard Worker // It is still not legal to mix-and-match integer-like values with pointer
63*635a8641SAndroid Build Coastguard Worker // values. For instance, you cannot pass a pointer to %x, nor can you pass an
64*635a8641SAndroid Build Coastguard Worker // integer to %p.
65*635a8641SAndroid Build Coastguard Worker //
66*635a8641SAndroid Build Coastguard Worker // The one exception is "0" zero being accepted by "%p". This works-around
67*635a8641SAndroid Build Coastguard Worker // the problem of C++ defining NULL as an integer-like value.
68*635a8641SAndroid Build Coastguard Worker //
69*635a8641SAndroid Build Coastguard Worker // All format characters take an optional width parameter. This must be a
70*635a8641SAndroid Build Coastguard Worker // positive integer. For %d, %o, %x, %X and %p, if the width starts with
71*635a8641SAndroid Build Coastguard Worker // a leading '0', padding is done with '0' instead of ' ' characters.
72*635a8641SAndroid Build Coastguard Worker //
73*635a8641SAndroid Build Coastguard Worker // There are a few features of snprintf()-style format strings, that
74*635a8641SAndroid Build Coastguard Worker // SafeSPrintf() does not support at this time.
75*635a8641SAndroid Build Coastguard Worker //
76*635a8641SAndroid Build Coastguard Worker // If an actual user showed up, there is no particularly strong reason they
77*635a8641SAndroid Build Coastguard Worker // couldn't be added. But that assumes that the trade-offs between complexity
78*635a8641SAndroid Build Coastguard Worker // and utility are favorable.
79*635a8641SAndroid Build Coastguard Worker //
80*635a8641SAndroid Build Coastguard Worker // For example, adding support for negative padding widths, and for %n are all
81*635a8641SAndroid Build Coastguard Worker // likely to be viewed positively. They are all clearly useful, low-risk, easy
82*635a8641SAndroid Build Coastguard Worker // to test, don't jeopardize the async-signal-safety of the code, and overall
83*635a8641SAndroid Build Coastguard Worker // have little impact on other parts of SafeSPrintf() function.
84*635a8641SAndroid Build Coastguard Worker //
85*635a8641SAndroid Build Coastguard Worker // On the other hands, adding support for alternate forms, positional
86*635a8641SAndroid Build Coastguard Worker // arguments, grouping, wide characters, localization or floating point numbers
87*635a8641SAndroid Build Coastguard Worker // are all unlikely to ever be added.
88*635a8641SAndroid Build Coastguard Worker //
89*635a8641SAndroid Build Coastguard Worker // SafeSPrintf() and SafeSNPrintf() mimic the behavior of snprintf() and they
90*635a8641SAndroid Build Coastguard Worker // return the number of bytes needed to store the untruncated output. This
91*635a8641SAndroid Build Coastguard Worker // does *not* include the terminating NUL byte.
92*635a8641SAndroid Build Coastguard Worker //
93*635a8641SAndroid Build Coastguard Worker // They return -1, iff a fatal error happened. This typically can only happen,
94*635a8641SAndroid Build Coastguard Worker // if the buffer size is a) negative, or b) zero (i.e. not even the NUL byte
95*635a8641SAndroid Build Coastguard Worker // can be written). The return value can never be larger than SSIZE_MAX-1.
96*635a8641SAndroid Build Coastguard Worker // This ensures that the caller can always add one to the signed return code
97*635a8641SAndroid Build Coastguard Worker // in order to determine the amount of storage that needs to be allocated.
98*635a8641SAndroid Build Coastguard Worker //
99*635a8641SAndroid Build Coastguard Worker // While the code supports type checking and while it is generally very careful
100*635a8641SAndroid Build Coastguard Worker // to avoid printing incorrect values, it tends to be conservative in printing
101*635a8641SAndroid Build Coastguard Worker // as much as possible, even when given incorrect parameters. Typically, in
102*635a8641SAndroid Build Coastguard Worker // case of an error, the format string will not be expanded. (i.e. something
103*635a8641SAndroid Build Coastguard Worker // like SafeSPrintf(buf, "%p %d", 1, 2) results in "%p 2"). See above for
104*635a8641SAndroid Build Coastguard Worker // the use of RAW_CHECK() in debug builds, though.
105*635a8641SAndroid Build Coastguard Worker //
106*635a8641SAndroid Build Coastguard Worker // Basic example:
107*635a8641SAndroid Build Coastguard Worker //   char buf[20];
108*635a8641SAndroid Build Coastguard Worker //   base::strings::SafeSPrintf(buf, "The answer: %2d", 42);
109*635a8641SAndroid Build Coastguard Worker //
110*635a8641SAndroid Build Coastguard Worker // Example with dynamically sized buffer (async-signal-safe). This code won't
111*635a8641SAndroid Build Coastguard Worker // work on Visual studio, as it requires dynamically allocating arrays on the
112*635a8641SAndroid Build Coastguard Worker // stack. Consider picking a smaller value for |kMaxSize| if stack size is
113*635a8641SAndroid Build Coastguard Worker // limited and known. On the other hand, if the parameters to SafeSNPrintf()
114*635a8641SAndroid Build Coastguard Worker // are trusted and not controllable by the user, you can consider eliminating
115*635a8641SAndroid Build Coastguard Worker // the check for |kMaxSize| altogether. The current value of SSIZE_MAX is
116*635a8641SAndroid Build Coastguard Worker // essentially a no-op that just illustrates how to implement an upper bound:
117*635a8641SAndroid Build Coastguard Worker //   const size_t kInitialSize = 128;
118*635a8641SAndroid Build Coastguard Worker //   const size_t kMaxSize = std::numeric_limits<ssize_t>::max();
119*635a8641SAndroid Build Coastguard Worker //   size_t size = kInitialSize;
120*635a8641SAndroid Build Coastguard Worker //   for (;;) {
121*635a8641SAndroid Build Coastguard Worker //     char buf[size];
122*635a8641SAndroid Build Coastguard Worker //     size = SafeSNPrintf(buf, size, "Error message \"%s\"\n", err) + 1;
123*635a8641SAndroid Build Coastguard Worker //     if (sizeof(buf) < kMaxSize && size > kMaxSize) {
124*635a8641SAndroid Build Coastguard Worker //       size = kMaxSize;
125*635a8641SAndroid Build Coastguard Worker //       continue;
126*635a8641SAndroid Build Coastguard Worker //     } else if (size > sizeof(buf))
127*635a8641SAndroid Build Coastguard Worker //       continue;
128*635a8641SAndroid Build Coastguard Worker //     write(2, buf, size-1);
129*635a8641SAndroid Build Coastguard Worker //     break;
130*635a8641SAndroid Build Coastguard Worker //   }
131*635a8641SAndroid Build Coastguard Worker 
132*635a8641SAndroid Build Coastguard Worker namespace internal {
133*635a8641SAndroid Build Coastguard Worker // Helpers that use C++ overloading, templates, and specializations to deduce
134*635a8641SAndroid Build Coastguard Worker // and record type information from function arguments. This allows us to
135*635a8641SAndroid Build Coastguard Worker // later write a type-safe version of snprintf().
136*635a8641SAndroid Build Coastguard Worker 
137*635a8641SAndroid Build Coastguard Worker struct Arg {
138*635a8641SAndroid Build Coastguard Worker   enum Type { INT, UINT, STRING, POINTER };
139*635a8641SAndroid Build Coastguard Worker 
140*635a8641SAndroid Build Coastguard Worker   // Any integer-like value.
ArgArg141*635a8641SAndroid Build Coastguard Worker   Arg(signed char c) : type(INT) {
142*635a8641SAndroid Build Coastguard Worker     integer.i = c;
143*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(char);
144*635a8641SAndroid Build Coastguard Worker   }
ArgArg145*635a8641SAndroid Build Coastguard Worker   Arg(unsigned char c) : type(UINT) {
146*635a8641SAndroid Build Coastguard Worker     integer.i = c;
147*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(char);
148*635a8641SAndroid Build Coastguard Worker   }
ArgArg149*635a8641SAndroid Build Coastguard Worker   Arg(signed short j) : type(INT) {
150*635a8641SAndroid Build Coastguard Worker     integer.i = j;
151*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(short);
152*635a8641SAndroid Build Coastguard Worker   }
ArgArg153*635a8641SAndroid Build Coastguard Worker   Arg(unsigned short j) : type(UINT) {
154*635a8641SAndroid Build Coastguard Worker     integer.i = j;
155*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(short);
156*635a8641SAndroid Build Coastguard Worker   }
ArgArg157*635a8641SAndroid Build Coastguard Worker   Arg(signed int j) : type(INT) {
158*635a8641SAndroid Build Coastguard Worker     integer.i = j;
159*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(int);
160*635a8641SAndroid Build Coastguard Worker   }
ArgArg161*635a8641SAndroid Build Coastguard Worker   Arg(unsigned int j) : type(UINT) {
162*635a8641SAndroid Build Coastguard Worker     integer.i = j;
163*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(int);
164*635a8641SAndroid Build Coastguard Worker   }
ArgArg165*635a8641SAndroid Build Coastguard Worker   Arg(signed long j) : type(INT) {
166*635a8641SAndroid Build Coastguard Worker     integer.i = j;
167*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(long);
168*635a8641SAndroid Build Coastguard Worker   }
ArgArg169*635a8641SAndroid Build Coastguard Worker   Arg(unsigned long j) : type(UINT) {
170*635a8641SAndroid Build Coastguard Worker     integer.i = j;
171*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(long);
172*635a8641SAndroid Build Coastguard Worker   }
ArgArg173*635a8641SAndroid Build Coastguard Worker   Arg(signed long long j) : type(INT) {
174*635a8641SAndroid Build Coastguard Worker     integer.i = j;
175*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(long long);
176*635a8641SAndroid Build Coastguard Worker   }
ArgArg177*635a8641SAndroid Build Coastguard Worker   Arg(unsigned long long j) : type(UINT) {
178*635a8641SAndroid Build Coastguard Worker     integer.i = j;
179*635a8641SAndroid Build Coastguard Worker     integer.width = sizeof(long long);
180*635a8641SAndroid Build Coastguard Worker   }
181*635a8641SAndroid Build Coastguard Worker 
182*635a8641SAndroid Build Coastguard Worker   // A C-style text string.
ArgArg183*635a8641SAndroid Build Coastguard Worker   Arg(const char* s) : str(s), type(STRING) { }
ArgArg184*635a8641SAndroid Build Coastguard Worker   Arg(char* s)       : str(s), type(STRING) { }
185*635a8641SAndroid Build Coastguard Worker 
186*635a8641SAndroid Build Coastguard Worker   // Any pointer value that can be cast to a "void*".
ArgArg187*635a8641SAndroid Build Coastguard Worker   template<class T> Arg(T* p) : ptr((void*)p), type(POINTER) { }
188*635a8641SAndroid Build Coastguard Worker 
189*635a8641SAndroid Build Coastguard Worker   union {
190*635a8641SAndroid Build Coastguard Worker     // An integer-like value.
191*635a8641SAndroid Build Coastguard Worker     struct {
192*635a8641SAndroid Build Coastguard Worker       int64_t       i;
193*635a8641SAndroid Build Coastguard Worker       unsigned char width;
194*635a8641SAndroid Build Coastguard Worker     } integer;
195*635a8641SAndroid Build Coastguard Worker 
196*635a8641SAndroid Build Coastguard Worker     // A C-style text string.
197*635a8641SAndroid Build Coastguard Worker     const char* str;
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker     // A pointer to an arbitrary object.
200*635a8641SAndroid Build Coastguard Worker     const void* ptr;
201*635a8641SAndroid Build Coastguard Worker   };
202*635a8641SAndroid Build Coastguard Worker   const enum Type type;
203*635a8641SAndroid Build Coastguard Worker };
204*635a8641SAndroid Build Coastguard Worker 
205*635a8641SAndroid Build Coastguard Worker // This is the internal function that performs the actual formatting of
206*635a8641SAndroid Build Coastguard Worker // an snprintf()-style format string.
207*635a8641SAndroid Build Coastguard Worker BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t sz, const char* fmt,
208*635a8641SAndroid Build Coastguard Worker                                  const Arg* args, size_t max_args);
209*635a8641SAndroid Build Coastguard Worker 
210*635a8641SAndroid Build Coastguard Worker #if !defined(NDEBUG)
211*635a8641SAndroid Build Coastguard Worker // In debug builds, allow unit tests to artificially lower the kSSizeMax
212*635a8641SAndroid Build Coastguard Worker // constant that is used as a hard upper-bound for all buffers. In normal
213*635a8641SAndroid Build Coastguard Worker // use, this constant should always be std::numeric_limits<ssize_t>::max().
214*635a8641SAndroid Build Coastguard Worker BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max);
215*635a8641SAndroid Build Coastguard Worker BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest();
216*635a8641SAndroid Build Coastguard Worker #endif
217*635a8641SAndroid Build Coastguard Worker 
218*635a8641SAndroid Build Coastguard Worker }  // namespace internal
219*635a8641SAndroid Build Coastguard Worker 
220*635a8641SAndroid Build Coastguard Worker template<typename... Args>
SafeSNPrintf(char * buf,size_t N,const char * fmt,Args...args)221*635a8641SAndroid Build Coastguard Worker ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args... args) {
222*635a8641SAndroid Build Coastguard Worker   // Use Arg() object to record type information and then copy arguments to an
223*635a8641SAndroid Build Coastguard Worker   // array to make it easier to iterate over them.
224*635a8641SAndroid Build Coastguard Worker   const internal::Arg arg_array[] = { args... };
225*635a8641SAndroid Build Coastguard Worker   return internal::SafeSNPrintf(buf, N, fmt, arg_array, sizeof...(args));
226*635a8641SAndroid Build Coastguard Worker }
227*635a8641SAndroid Build Coastguard Worker 
228*635a8641SAndroid Build Coastguard Worker template<size_t N, typename... Args>
SafeSPrintf(char (& buf)[N],const char * fmt,Args...args)229*635a8641SAndroid Build Coastguard Worker ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, Args... args) {
230*635a8641SAndroid Build Coastguard Worker   // Use Arg() object to record type information and then copy arguments to an
231*635a8641SAndroid Build Coastguard Worker   // array to make it easier to iterate over them.
232*635a8641SAndroid Build Coastguard Worker   const internal::Arg arg_array[] = { args... };
233*635a8641SAndroid Build Coastguard Worker   return internal::SafeSNPrintf(buf, N, fmt, arg_array, sizeof...(args));
234*635a8641SAndroid Build Coastguard Worker }
235*635a8641SAndroid Build Coastguard Worker 
236*635a8641SAndroid Build Coastguard Worker // Fast-path when we don't actually need to substitute any arguments.
237*635a8641SAndroid Build Coastguard Worker BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt);
238*635a8641SAndroid Build Coastguard Worker template<size_t N>
SafeSPrintf(char (& buf)[N],const char * fmt)239*635a8641SAndroid Build Coastguard Worker inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) {
240*635a8641SAndroid Build Coastguard Worker   return SafeSNPrintf(buf, N, fmt);
241*635a8641SAndroid Build Coastguard Worker }
242*635a8641SAndroid Build Coastguard Worker 
243*635a8641SAndroid Build Coastguard Worker }  // namespace strings
244*635a8641SAndroid Build Coastguard Worker }  // namespace base
245*635a8641SAndroid Build Coastguard Worker 
246*635a8641SAndroid Build Coastguard Worker #endif  // BASE_STRINGS_SAFE_SPRINTF_H_
247