Use string view internally in GuessSizeForVSWPrintf()
Inside core/fxcrt/widestring.cpp, change GuessSizeForVSWPrintf() to stop
dealing with pointers. Instead, immediately take the pointer input and
convert it to a string view and then do the equivalent work using string
view APIs.
Bug: 42271176
Change-Id: Ia6f679cb10c79fcc28a866ae0320bbb93f9f51eb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/126015
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/widestring.cpp b/core/fxcrt/widestring.cpp
index a4bdde4..745303b 100644
--- a/core/fxcrt/widestring.cpp
+++ b/core/fxcrt/widestring.cpp
@@ -15,11 +15,11 @@
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
-#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_codepage.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/fx_safe_types.h"
+#include "core/fxcrt/fx_string.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/numerics/safe_math.h"
#include "core/fxcrt/span_util.h"
@@ -59,198 +59,199 @@
std::optional<size_t> GuessSizeForVSWPrintf(const wchar_t* pFormat,
va_list argList) {
size_t nMaxLen = 0;
- UNSAFE_TODO({
- for (const wchar_t* pStr = pFormat; *pStr != 0; pStr++) {
- if (*pStr != '%' || *(pStr = pStr + 1) == '%') {
- ++nMaxLen;
- continue;
- }
- int iWidth = 0;
- for (; *pStr != 0; pStr++) {
- if (*pStr == '#') {
- nMaxLen += 2;
- } else if (*pStr == '*') {
- iWidth = va_arg(argList, int);
- } else if (*pStr != '-' && *pStr != '+' && *pStr != '0' &&
- *pStr != ' ') {
- break;
- }
- }
- if (iWidth == 0) {
- iWidth = FXSYS_wtoi(pStr);
- while (FXSYS_IsDecimalDigit(*pStr))
- ++pStr;
- }
- if (iWidth < 0 || iWidth > 128 * 1024) {
- return std::nullopt;
- }
- uint32_t nWidth = static_cast<uint32_t>(iWidth);
- int iPrecision = 0;
- if (*pStr == '.') {
- pStr++;
- if (*pStr == '*') {
- iPrecision = va_arg(argList, int);
- pStr++;
- } else {
- iPrecision = FXSYS_wtoi(pStr);
- while (FXSYS_IsDecimalDigit(*pStr)) {
- ++pStr;
- }
- }
- }
- if (iPrecision < 0 || iPrecision > 128 * 1024) {
- return std::nullopt;
- }
- uint32_t nPrecision = static_cast<uint32_t>(iPrecision);
- int nModifier = 0;
- if (*pStr == L'I' && *(pStr + 1) == L'6' && *(pStr + 2) == L'4') {
- pStr += 3;
- nModifier = FORCE_INT64;
- } else {
- switch (*pStr) {
- case 'h':
- nModifier = FORCE_ANSI;
- pStr++;
- break;
- case 'l':
- nModifier = FORCE_UNICODE;
- pStr++;
- break;
- case 'F':
- case 'N':
- case 'L':
- pStr++;
- break;
- }
- }
- size_t nItemLen = 0;
- switch (*pStr | nModifier) {
- case 'c':
- case 'C':
- nItemLen = 2;
- va_arg(argList, int);
- break;
- case 'c' | FORCE_ANSI:
- case 'C' | FORCE_ANSI:
- nItemLen = 2;
- va_arg(argList, int);
- break;
- case 'c' | FORCE_UNICODE:
- case 'C' | FORCE_UNICODE:
- nItemLen = 2;
- va_arg(argList, int);
- break;
- case 's': {
- const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*);
- if (pstrNextArg) {
- nItemLen = wcslen(pstrNextArg);
- if (nItemLen < 1) {
- nItemLen = 1;
- }
- } else {
- nItemLen = 6;
- }
- } break;
- case 'S': {
- const char* pstrNextArg = va_arg(argList, const char*);
- if (pstrNextArg) {
- nItemLen = strlen(pstrNextArg);
- if (nItemLen < 1) {
- nItemLen = 1;
- }
- } else {
- nItemLen = 6;
- }
- } break;
- case 's' | FORCE_ANSI:
- case 'S' | FORCE_ANSI: {
- const char* pstrNextArg = va_arg(argList, const char*);
- if (pstrNextArg) {
- nItemLen = strlen(pstrNextArg);
- if (nItemLen < 1) {
- nItemLen = 1;
- }
- } else {
- nItemLen = 6;
- }
- } break;
- case 's' | FORCE_UNICODE:
- case 'S' | FORCE_UNICODE: {
- const wchar_t* pstrNextArg = va_arg(argList, wchar_t*);
- if (pstrNextArg) {
- nItemLen = wcslen(pstrNextArg);
- if (nItemLen < 1) {
- nItemLen = 1;
- }
- } else {
- nItemLen = 6;
- }
- } break;
- }
- if (nItemLen != 0) {
- if (nPrecision != 0 && nItemLen > nPrecision) {
- nItemLen = nPrecision;
- }
- if (nItemLen < nWidth) {
- nItemLen = nWidth;
- }
- } else {
- switch (*pStr) {
- case 'd':
- case 'i':
- case 'u':
- case 'x':
- case 'X':
- case 'o':
- if (nModifier & FORCE_INT64) {
- va_arg(argList, int64_t);
- } else {
- va_arg(argList, int);
- }
- nItemLen = 32;
- if (nItemLen < nWidth + nPrecision) {
- nItemLen = nWidth + nPrecision;
- }
- break;
- case 'a':
- case 'A':
- case 'e':
- case 'E':
- case 'g':
- case 'G':
- va_arg(argList, double);
- nItemLen = 128;
- if (nItemLen < nWidth + nPrecision) {
- nItemLen = nWidth + nPrecision;
- }
- break;
- case 'f':
- if (nWidth + nPrecision > 100) {
- nItemLen = nPrecision + nWidth + 128;
- } else {
- double f;
- char pszTemp[256];
- f = va_arg(argList, double);
- FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth,
- nPrecision + 6, f);
- nItemLen = strlen(pszTemp);
- }
- break;
- case 'p':
- va_arg(argList, void*);
- nItemLen = 32;
- if (nItemLen < nWidth + nPrecision) {
- nItemLen = nWidth + nPrecision;
- }
- break;
- case 'n':
- va_arg(argList, int*);
- break;
- }
- }
- nMaxLen += nItemLen;
+ for (WideStringView view(pFormat); !view.IsEmpty(); view = view.Substr(1u)) {
+ if (view.Front() != '%' ||
+ (view.GetLength() > 1 && view.CharAt(1u) == '%')) {
+ ++nMaxLen;
+ continue;
}
- });
+ int iWidth = 0;
+ for (; !view.IsEmpty(); view = view.Substr(1u)) {
+ const wchar_t c = view.Front();
+ if (c == '#') {
+ nMaxLen += 2;
+ } else if (c == '*') {
+ iWidth = va_arg(argList, int);
+ } else if (c != '-' && c != '+' && c != '0' && c != ' ') {
+ break;
+ }
+ view = view.Substr(1u);
+ }
+ if (iWidth == 0) {
+ iWidth = StringToInt(view);
+ while (FXSYS_IsDecimalDigit(static_cast<wchar_t>(view.Front()))) {
+ view = view.Substr(1u);
+ }
+ }
+ if (iWidth < 0 || iWidth > 128 * 1024) {
+ return std::nullopt;
+ }
+ uint32_t nWidth = static_cast<uint32_t>(iWidth);
+ int iPrecision = 0;
+ if (view.Front() == '.') {
+ view = view.Substr(1u);
+ if (view.Front() == '*') {
+ iPrecision = va_arg(argList, int);
+ view = view.Substr(1u);
+ } else {
+ iPrecision = StringToInt(view);
+ while (FXSYS_IsDecimalDigit(static_cast<wchar_t>(view.Front()))) {
+ view = view.Substr(1u);
+ }
+ }
+ }
+ if (iPrecision < 0 || iPrecision > 128 * 1024) {
+ return std::nullopt;
+ }
+ uint32_t nPrecision = static_cast<uint32_t>(iPrecision);
+ int nModifier = 0;
+ if (view.First(3u) == L"I64") {
+ view = view.Substr(3u);
+ nModifier = FORCE_INT64;
+ } else {
+ switch (view.Front()) {
+ case 'h':
+ nModifier = FORCE_ANSI;
+ view = view.Substr(1u);
+ break;
+ case 'l':
+ nModifier = FORCE_UNICODE;
+ view = view.Substr(1u);
+ break;
+ case 'F':
+ case 'N':
+ case 'L':
+ view = view.Substr(1u);
+ break;
+ }
+ }
+ size_t nItemLen = 0;
+ switch (view.Front() | nModifier) {
+ case 'c':
+ case 'C':
+ nItemLen = 2;
+ va_arg(argList, int);
+ break;
+ case 'c' | FORCE_ANSI:
+ case 'C' | FORCE_ANSI:
+ nItemLen = 2;
+ va_arg(argList, int);
+ break;
+ case 'c' | FORCE_UNICODE:
+ case 'C' | FORCE_UNICODE:
+ nItemLen = 2;
+ va_arg(argList, int);
+ break;
+ case 's': {
+ const wchar_t* pstrNextArg = va_arg(argList, const wchar_t*);
+ if (pstrNextArg) {
+ nItemLen = wcslen(pstrNextArg);
+ if (nItemLen < 1) {
+ nItemLen = 1;
+ }
+ } else {
+ nItemLen = 6;
+ }
+ } break;
+ case 'S': {
+ const char* pstrNextArg = va_arg(argList, const char*);
+ if (pstrNextArg) {
+ nItemLen = strlen(pstrNextArg);
+ if (nItemLen < 1) {
+ nItemLen = 1;
+ }
+ } else {
+ nItemLen = 6;
+ }
+ } break;
+ case 's' | FORCE_ANSI:
+ case 'S' | FORCE_ANSI: {
+ const char* pstrNextArg = va_arg(argList, const char*);
+ if (pstrNextArg) {
+ nItemLen = strlen(pstrNextArg);
+ if (nItemLen < 1) {
+ nItemLen = 1;
+ }
+ } else {
+ nItemLen = 6;
+ }
+ } break;
+ case 's' | FORCE_UNICODE:
+ case 'S' | FORCE_UNICODE: {
+ const wchar_t* pstrNextArg = va_arg(argList, wchar_t*);
+ if (pstrNextArg) {
+ nItemLen = wcslen(pstrNextArg);
+ if (nItemLen < 1) {
+ nItemLen = 1;
+ }
+ } else {
+ nItemLen = 6;
+ }
+ } break;
+ }
+ if (nItemLen != 0) {
+ if (nPrecision != 0 && nItemLen > nPrecision) {
+ nItemLen = nPrecision;
+ }
+ if (nItemLen < nWidth) {
+ nItemLen = nWidth;
+ }
+ } else {
+ switch (view.Front()) {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'o':
+ if (nModifier & FORCE_INT64) {
+ va_arg(argList, int64_t);
+ } else {
+ va_arg(argList, int);
+ }
+ nItemLen = 32;
+ if (nItemLen < nWidth + nPrecision) {
+ nItemLen = nWidth + nPrecision;
+ }
+ break;
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ va_arg(argList, double);
+ nItemLen = 128;
+ if (nItemLen < nWidth + nPrecision) {
+ nItemLen = nWidth + nPrecision;
+ }
+ break;
+ case 'f':
+ if (nWidth + nPrecision > 100) {
+ nItemLen = nPrecision + nWidth + 128;
+ } else {
+ double f;
+ char pszTemp[256];
+ f = va_arg(argList, double);
+ FXSYS_snprintf(pszTemp, sizeof(pszTemp), "%*.*f", nWidth,
+ nPrecision + 6, f);
+ nItemLen = strlen(pszTemp);
+ }
+ break;
+ case 'p':
+ va_arg(argList, void*);
+ nItemLen = 32;
+ if (nItemLen < nWidth + nPrecision) {
+ nItemLen = nWidth + nPrecision;
+ }
+ break;
+ case 'n':
+ va_arg(argList, int*);
+ break;
+ }
+ }
+ nMaxLen += nItemLen;
+ }
nMaxLen += 32; // Fudge factor.
return nMaxLen;
}