security/sandbox/chromium/base/strings/stringprintf.cc

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial