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

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial