/src/mozilla-central/security/sandbox/chromium/base/strings/stringprintf.cc
Line | Count | Source (jump to first uncovered line) |
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 | | #include "base/strings/stringprintf.h" |
6 | | |
7 | | #include <errno.h> |
8 | | #include <stddef.h> |
9 | | |
10 | | #include <vector> |
11 | | |
12 | | #include "base/macros.h" |
13 | | #include "base/scoped_clear_errno.h" |
14 | | #include "base/strings/string_util.h" |
15 | | #include "base/strings/utf_string_conversions.h" |
16 | | #include "build/build_config.h" |
17 | | |
18 | | namespace base { |
19 | | |
20 | | namespace { |
21 | | |
22 | | // Overloaded wrappers around vsnprintf and vswprintf. The buf_size parameter |
23 | | // is the size of the buffer. These return the number of characters in the |
24 | | // formatted string excluding the NUL terminator. If the buffer is not |
25 | | // large enough to accommodate the formatted string without truncation, they |
26 | | // return the number of characters that would be in the fully-formatted string |
27 | | // (vsnprintf, and vswprintf on Windows), or -1 (vswprintf on POSIX platforms). |
28 | | inline int vsnprintfT(char* buffer, |
29 | | size_t buf_size, |
30 | | const char* format, |
31 | 0 | va_list argptr) { |
32 | 0 | return base::vsnprintf(buffer, buf_size, format, argptr); |
33 | 0 | } |
34 | | |
35 | | #if defined(OS_WIN) |
36 | | inline int vsnprintfT(wchar_t* buffer, |
37 | | size_t buf_size, |
38 | | const wchar_t* format, |
39 | | va_list argptr) { |
40 | | return base::vswprintf(buffer, buf_size, format, argptr); |
41 | | } |
42 | | #endif |
43 | | |
44 | | // Templatized backend for StringPrintF/StringAppendF. This does not finalize |
45 | | // the va_list, the caller is expected to do that. |
46 | | template <class StringType> |
47 | | static void StringAppendVT(StringType* dst, |
48 | | const typename StringType::value_type* format, |
49 | 0 | va_list ap) { |
50 | 0 | // First try with a small fixed size buffer. |
51 | 0 | // This buffer size should be kept in sync with StringUtilTest.GrowBoundary |
52 | 0 | // and StringUtilTest.StringPrintfBounds. |
53 | 0 | typename StringType::value_type stack_buf[1024]; |
54 | 0 |
|
55 | 0 | va_list ap_copy; |
56 | 0 | va_copy(ap_copy, ap); |
57 | 0 |
|
58 | 0 | #if !defined(OS_WIN) |
59 | 0 | ScopedClearErrno clear_errno; |
60 | 0 | #endif |
61 | 0 | int result = vsnprintfT(stack_buf, arraysize(stack_buf), format, ap_copy); |
62 | 0 | va_end(ap_copy); |
63 | 0 |
|
64 | 0 | if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) { |
65 | 0 | // It fit. |
66 | 0 | dst->append(stack_buf, result); |
67 | 0 | return; |
68 | 0 | } |
69 | 0 | |
70 | 0 | // Repeatedly increase buffer size until it fits. |
71 | 0 | int mem_length = arraysize(stack_buf); |
72 | 0 | while (true) { |
73 | 0 | if (result < 0) { |
74 | | #if defined(OS_WIN) |
75 | | // On Windows, vsnprintfT always returns the number of characters in a |
76 | | // fully-formatted string, so if we reach this point, something else is |
77 | | // wrong and no amount of buffer-doubling is going to fix it. |
78 | | return; |
79 | | #else |
80 | 0 | if (errno != 0 && errno != EOVERFLOW) |
81 | 0 | return; |
82 | 0 | // Try doubling the buffer size. |
83 | 0 | mem_length *= 2; |
84 | 0 | #endif |
85 | 0 | } else { |
86 | 0 | // We need exactly "result + 1" characters. |
87 | 0 | mem_length = result + 1; |
88 | 0 | } |
89 | 0 |
|
90 | 0 | if (mem_length > 32 * 1024 * 1024) { |
91 | 0 | // That should be plenty, don't try anything larger. This protects |
92 | 0 | // against huge allocations when using vsnprintfT implementations that |
93 | 0 | // return -1 for reasons other than overflow without setting errno. |
94 | 0 | DLOG(WARNING) << "Unable to printf the requested string due to size."; |
95 | 0 | return; |
96 | 0 | } |
97 | 0 |
|
98 | 0 | std::vector<typename StringType::value_type> mem_buf(mem_length); |
99 | 0 |
|
100 | 0 | // NOTE: You can only use a va_list once. Since we're in a while loop, we |
101 | 0 | // need to make a new copy each time so we don't use up the original. |
102 | 0 | va_copy(ap_copy, ap); |
103 | 0 | result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy); |
104 | 0 | va_end(ap_copy); |
105 | 0 |
|
106 | 0 | if ((result >= 0) && (result < mem_length)) { |
107 | 0 | // It fit. |
108 | 0 | dst->append(&mem_buf[0], result); |
109 | 0 | return; |
110 | 0 | } |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | } // namespace |
115 | | |
116 | 0 | std::string StringPrintf(const char* format, ...) { |
117 | 0 | va_list ap; |
118 | 0 | va_start(ap, format); |
119 | 0 | std::string result; |
120 | 0 | StringAppendV(&result, format, ap); |
121 | 0 | va_end(ap); |
122 | 0 | return result; |
123 | 0 | } |
124 | | |
125 | | #if defined(OS_WIN) |
126 | | std::wstring StringPrintf(const wchar_t* format, ...) { |
127 | | va_list ap; |
128 | | va_start(ap, format); |
129 | | std::wstring result; |
130 | | StringAppendV(&result, format, ap); |
131 | | va_end(ap); |
132 | | return result; |
133 | | } |
134 | | #endif |
135 | | |
136 | 0 | std::string StringPrintV(const char* format, va_list ap) { |
137 | 0 | std::string result; |
138 | 0 | StringAppendV(&result, format, ap); |
139 | 0 | return result; |
140 | 0 | } |
141 | | |
142 | 0 | const std::string& SStringPrintf(std::string* dst, const char* format, ...) { |
143 | 0 | va_list ap; |
144 | 0 | va_start(ap, format); |
145 | 0 | dst->clear(); |
146 | 0 | StringAppendV(dst, format, ap); |
147 | 0 | va_end(ap); |
148 | 0 | return *dst; |
149 | 0 | } |
150 | | |
151 | | #if defined(OS_WIN) |
152 | | const std::wstring& SStringPrintf(std::wstring* dst, |
153 | | const wchar_t* format, ...) { |
154 | | va_list ap; |
155 | | va_start(ap, format); |
156 | | dst->clear(); |
157 | | StringAppendV(dst, format, ap); |
158 | | va_end(ap); |
159 | | return *dst; |
160 | | } |
161 | | #endif |
162 | | |
163 | 0 | void StringAppendF(std::string* dst, const char* format, ...) { |
164 | 0 | va_list ap; |
165 | 0 | va_start(ap, format); |
166 | 0 | StringAppendV(dst, format, ap); |
167 | 0 | va_end(ap); |
168 | 0 | } |
169 | | |
170 | | #if defined(OS_WIN) |
171 | | void StringAppendF(std::wstring* dst, const wchar_t* format, ...) { |
172 | | va_list ap; |
173 | | va_start(ap, format); |
174 | | StringAppendV(dst, format, ap); |
175 | | va_end(ap); |
176 | | } |
177 | | #endif |
178 | | |
179 | 0 | void StringAppendV(std::string* dst, const char* format, va_list ap) { |
180 | 0 | StringAppendVT(dst, format, ap); |
181 | 0 | } |
182 | | |
183 | | #if defined(OS_WIN) |
184 | | void StringAppendV(std::wstring* dst, const wchar_t* format, va_list ap) { |
185 | | StringAppendVT(dst, format, ap); |
186 | | } |
187 | | #endif |
188 | | |
189 | | } // namespace base |