diff options
author | Brian Salomon <bsalomon@google.com> | 2018-04-25 12:58:23 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-04-25 20:58:09 +0000 |
commit | 43227522e494d02011eb541789bb652065349658 (patch) | |
tree | 4410cdec6c02538c8d12edd96e375d7b97d80121 /src/core/SkString.cpp | |
parent | abc1976c12e7fdcc59df578712d3ad9cf74f8f48 (diff) |
Make SkString::appendf safe for long strings.
Bug: skia:7841
Change-Id: I5bc77f5230b63da74e42d756ab4a1fefcfab9926
Reviewed-on: https://skia-review.googlesource.com/123634
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/core/SkString.cpp')
-rw-r--r-- | src/core/SkString.cpp | 96 |
1 files changed, 55 insertions, 41 deletions
diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp index 554cde8f9f..707e8befb8 100644 --- a/src/core/SkString.cpp +++ b/src/core/SkString.cpp @@ -5,48 +5,60 @@ * found in the LICENSE file. */ +#include "SkString.h" +#include <stdarg.h> +#include <cstdio> #include "SkAtomics.h" #include "SkSafeMath.h" -#include "SkString.h" #include "SkUtils.h" -#include <stdarg.h> -#include <stdio.h> // number of bytes (on the stack) to receive the printf result static const size_t kBufferSize = 1024; -#define ARGS_TO_BUFFER(format, buffer, size, written) \ - do { \ - va_list args; \ - va_start(args, format); \ - written = vsnprintf(buffer, size, format, args); \ - SkASSERT(written >= 0 && written < SkToInt(size)); \ - va_end(args); \ +static const char* apply_format_string(const char* format, va_list args, char* stackBuffer, + size_t stackBufferSize, int* length, SkString* heapBuffer) { + va_list argsCopy; + va_copy(argsCopy, args); + *length = std::vsnprintf(stackBuffer, stackBufferSize, format, args); + if (*length < 0) { + SkDebugf("SkString: vsnprintf reported error."); + va_end(argsCopy); + *length = 0; + return stackBuffer; + } + if (*length < SkToInt(stackBufferSize)) { + va_end(argsCopy); + return stackBuffer; + } + heapBuffer->resize(*length); + SkDEBUGCODE(int check =) + std::vsnprintf(heapBuffer->writable_str(), *length + 1, format, argsCopy); + SkASSERT(check == *length); + va_end(argsCopy); + return heapBuffer->c_str(); +} + +#define ARGS_TO_BUFFER(format, buffer, size, written, result) \ + SkString overflow; \ + do { \ + va_list args; \ + va_start(args, format); \ + result = apply_format_string(format, args, buffer, size, &written, &overflow); \ + va_end(args); \ } while (0) -#define V_SKSTRING_PRINTF(output, format) \ - do { \ - va_list args; \ - va_start(args, format); \ - char buffer[kBufferSize]; \ - int length = vsnprintf(buffer, sizeof(buffer), format, args); \ - va_end(args); \ - if (length < 0) { \ - break; \ - } \ - if (length < (int)sizeof(buffer)) { \ - output.set(buffer, length); \ - break; \ - } \ - SkString tmp((size_t)length); \ - va_start(args, format); \ - SkDEBUGCODE(int check = ) vsnprintf(tmp.writable_str(), \ - length + 1, format, args); \ - va_end(args); \ - SkASSERT(check == length); \ - output = std::move(tmp); \ - SkASSERT(output[length] == '\0'); \ - } while (false) +#define V_SKSTRING_PRINTF(output, format) \ + do { \ + char buffer[kBufferSize]; \ + va_list args; \ + va_start(args, format); \ + int length; \ + auto result = apply_format_string(format, args, buffer, kBufferSize, &length, &output); \ + SkASSERT(result == output.c_str() || result == buffer); \ + if (result == buffer) { \ + output.set(buffer, length); \ + } \ + } while (0) /////////////////////////////////////////////////////////////////////////////// @@ -491,15 +503,16 @@ void SkString::printf(const char format[], ...) { } void SkString::appendf(const char format[], ...) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length; - ARGS_TO_BUFFER(format, buffer, kBufferSize, length); + const char* result; + ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result); - this->append(buffer, length); + this->append(result, length); } void SkString::appendVAList(const char format[], va_list args) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length = vsnprintf(buffer, kBufferSize, format, args); SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); @@ -507,15 +520,16 @@ void SkString::appendVAList(const char format[], va_list args) { } void SkString::prependf(const char format[], ...) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length; - ARGS_TO_BUFFER(format, buffer, kBufferSize, length); + const char* result; + ARGS_TO_BUFFER(format, buffer, kBufferSize, length, result); - this->prepend(buffer, length); + this->prepend(result, length); } void SkString::prependVAList(const char format[], va_list args) { - char buffer[kBufferSize]; + char buffer[kBufferSize]; int length = vsnprintf(buffer, kBufferSize, format, args); SkASSERT(length >= 0 && length < SkToInt(kBufferSize)); |