OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_STRINGS_SAFE_SPRINTF_H_ | 5 #ifndef BASE_STRINGS_SAFE_SPRINTF_H_ |
6 #define BASE_STRINGS_SAFE_SPRINTF_H_ | 6 #define BASE_STRINGS_SAFE_SPRINTF_H_ |
7 | 7 |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 | 9 |
10 #include <stddef.h> | 10 #include <stddef.h> |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 // This ensures that the caller can always add one to the signed return code | 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. | 98 // in order to determine the amount of storage that needs to be allocated. |
99 // | 99 // |
100 // While the code supports type checking and while it is generally very careful | 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 | 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 | 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 | 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 | 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. | 105 // the use of RAW_CHECK() in debug builds, though. |
106 // | 106 // |
107 // The pre-C++11 version cannot handle more than ten arguments. | |
108 // | |
109 // Basic example: | 107 // Basic example: |
110 // char buf[20]; | 108 // char buf[20]; |
111 // base::strings::SafeSPrintf(buf, "The answer: %2d", 42); | 109 // base::strings::SafeSPrintf(buf, "The answer: %2d", 42); |
112 // | 110 // |
113 // Example with dynamically sized buffer (async-signal-safe). This code won't | 111 // Example with dynamically sized buffer (async-signal-safe). This code won't |
114 // work on Visual studio, as it requires dynamically allocating arrays on the | 112 // work on Visual studio, as it requires dynamically allocating arrays on the |
115 // stack. Consider picking a smaller value for |kMaxSize| if stack size is | 113 // stack. Consider picking a smaller value for |kMaxSize| if stack size is |
116 // limited and known. On the other hand, if the parameters to SafeSNPrintf() | 114 // limited and known. On the other hand, if the parameters to SafeSNPrintf() |
117 // are trusted and not controllable by the user, you can consider eliminating | 115 // are trusted and not controllable by the user, you can consider eliminating |
118 // the check for |kMaxSize| altogether. The current value of SSIZE_MAX is | 116 // the check for |kMaxSize| altogether. The current value of SSIZE_MAX is |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 #if !defined(NDEBUG) | 181 #if !defined(NDEBUG) |
184 // In debug builds, allow unit tests to artificially lower the kSSizeMax | 182 // In debug builds, allow unit tests to artificially lower the kSSizeMax |
185 // constant that is used as a hard upper-bound for all buffers. In normal | 183 // constant that is used as a hard upper-bound for all buffers. In normal |
186 // use, this constant should always be std::numeric_limits<ssize_t>::max(). | 184 // use, this constant should always be std::numeric_limits<ssize_t>::max(). |
187 BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max); | 185 BASE_EXPORT void SetSafeSPrintfSSizeMaxForTest(size_t max); |
188 BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest(); | 186 BASE_EXPORT size_t GetSafeSPrintfSSizeMaxForTest(); |
189 #endif | 187 #endif |
190 | 188 |
191 } // namespace internal | 189 } // namespace internal |
192 | 190 |
193 #if __cplusplus >= 201103 // C++11 | |
194 | |
195 template<typename... Args> | |
196 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, Args... args) { | |
197 // Use Arg() object to record type information and then copy arguments to an | |
198 // array to make it easier to iterate over them. | |
199 const internal::Arg arg_array[] = { args... }; | |
200 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); | |
201 } | |
202 | |
203 template<size_t N, typename... Args> | |
204 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, Args... args) { | |
205 // Use Arg() object to record type information and then copy arguments to an | |
206 // array to make it easier to iterate over them. | |
207 const internal::Arg arg_array[] = { args... }; | |
208 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); | |
209 } | |
210 | |
211 #else // Pre-C++11 | |
212 | |
213 // TODO(markus): C++11 has a much more concise and readable solution for | 191 // TODO(markus): C++11 has a much more concise and readable solution for |
214 // expressing what we are doing here. Delete the fall-back code for older | 192 // expressing what we are doing here. |
215 // compilers as soon as we have fully switched to C++11. | |
216 | 193 |
217 template<class T0, class T1, class T2, class T3, class T4, | 194 template<class T0, class T1, class T2, class T3, class T4, |
218 class T5, class T6, class T7, class T8, class T9> | 195 class T5, class T6, class T7, class T8, class T9> |
219 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, | 196 ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt, |
220 T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, | 197 T0 arg0, T1 arg1, T2 arg2, T3 arg3, T4 arg4, |
221 T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) { | 198 T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) { |
222 // Use Arg() object to record type information and then copy arguments to an | 199 // Use Arg() object to record type information and then copy arguments to an |
223 // array to make it easier to iterate over them. | 200 // array to make it easier to iterate over them. |
224 const internal::Arg arg_array[] = { | 201 const internal::Arg arg_array[] = { |
225 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 | 202 arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
419 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); | 396 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); |
420 } | 397 } |
421 | 398 |
422 template<size_t N, class T0> | 399 template<size_t N, class T0> |
423 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0) { | 400 ssize_t SafeSPrintf(char (&buf)[N], const char* fmt, T0 arg0) { |
424 // Use Arg() object to record type information and then copy arguments to an | 401 // Use Arg() object to record type information and then copy arguments to an |
425 // array to make it easier to iterate over them. | 402 // array to make it easier to iterate over them. |
426 const internal::Arg arg_array[] = { arg0 }; | 403 const internal::Arg arg_array[] = { arg0 }; |
427 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); | 404 return internal::SafeSNPrintf(buf, N, fmt, arg_array, arraysize(arg_array)); |
428 } | 405 } |
429 #endif | |
430 | 406 |
431 // Fast-path when we don't actually need to substitute any arguments. | 407 // Fast-path when we don't actually need to substitute any arguments. |
432 BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt); | 408 BASE_EXPORT ssize_t SafeSNPrintf(char* buf, size_t N, const char* fmt); |
433 template<size_t N> | 409 template<size_t N> |
434 inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) { | 410 inline ssize_t SafeSPrintf(char (&buf)[N], const char* fmt) { |
435 return SafeSNPrintf(buf, N, fmt); | 411 return SafeSNPrintf(buf, N, fmt); |
436 } | 412 } |
437 | 413 |
438 } // namespace strings | 414 } // namespace strings |
439 } // namespace base | 415 } // namespace base |
440 | 416 |
441 #endif // BASE_STRINGS_SAFE_SPRINTF_H_ | 417 #endif // BASE_STRINGS_SAFE_SPRINTF_H_ |
OLD | NEW |