Use spans in CFGAS_FormatString, part 2
This introduces some mixed signed/unsigned operations that are
handled by CollectionSize<>(), but which will be removed in a
subsequent CL.
- Tidy FX_TimeFromCanonical(), input before output args.
- Don't trust caller bounds in GetLiteralText().
- Write wcscmp() == 0 instead of !wcscmp() in a few places because
I still can't read !wcscmp() as "matched".
Change-Id: I84c8ba50e1ebf969218b5989f4d74d14e051bf35
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/51650
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/xfa/fgas/crt/cfgas_formatstring.cpp b/xfa/fgas/crt/cfgas_formatstring.cpp
index b9b0ea0..46594dd 100644
--- a/xfa/fgas/crt/cfgas_formatstring.cpp
+++ b/xfa/fgas/crt/cfgas_formatstring.cpp
@@ -107,7 +107,7 @@
WideString GetLiteralText(pdfium::span<const wchar_t> pStrPattern,
size_t* iPattern) {
WideString wsOutput;
- if (pStrPattern[*iPattern] != '\'')
+ if (*iPattern >= pStrPattern.size() || pStrPattern[*iPattern] != '\'')
return wsOutput;
(*iPattern)++;
@@ -199,13 +199,12 @@
return result.has_value();
}
-bool ExtractCountDigits(const wchar_t* str,
- int len,
+bool ExtractCountDigits(pdfium::span<const wchar_t> str,
int count,
int* cc,
uint32_t* value) {
for (int i = count; i > 0; --i) {
- if (*cc >= len)
+ if (*cc >= pdfium::CollectionSize<int32_t>(str))
return false;
if (!FXSYS_IsDecimalDigit(str[*cc]))
return false;
@@ -214,14 +213,13 @@
return true;
}
-bool ExtractCountDigitsWithOptional(const wchar_t* str,
- int len,
+bool ExtractCountDigitsWithOptional(pdfium::span<const wchar_t> str,
int count,
int* cc,
uint32_t* value) {
- if (!ExtractCountDigits(str, len, count, cc, value))
+ if (!ExtractCountDigits(str, count, cc, value))
return false;
- ExtractCountDigits(str, len, 1, cc, value);
+ ExtractCountDigits(str, 1, cc, value);
return true;
}
@@ -234,7 +232,7 @@
uint32_t month = 1;
uint32_t day = 1;
size_t ccf = 0;
- const wchar_t* str = wsDate.c_str();
+ pdfium::span<const wchar_t> spDate = wsDate.AsSpan();
int32_t len = wsDate.GetLength();
pdfium::span<const wchar_t> spDatePattern = wsDatePattern.AsSpan();
WideStringView wsDateSymbols(gs_wsDateSymbols);
@@ -243,7 +241,7 @@
WideString wsLiteral = GetLiteralText(spDatePattern, &ccf);
int32_t iLiteralLen = wsLiteral.GetLength();
if (*cc + iLiteralLen > len ||
- wcsncmp(str + *cc, wsLiteral.c_str(), iLiteralLen)) {
+ wcsncmp(spDate.data() + *cc, wsLiteral.c_str(), iLiteralLen) != 0) {
return false;
}
*cc += iLiteralLen;
@@ -251,7 +249,7 @@
continue;
}
if (!wsDateSymbols.Contains(spDatePattern[ccf])) {
- if (spDatePattern[ccf] != str[*cc])
+ if (spDatePattern[ccf] != spDate[*cc])
return false;
(*cc)++;
ccf++;
@@ -266,14 +264,14 @@
}
if (symbol.EqualsASCII("D") || symbol.EqualsASCII("DD")) {
day = 0;
- if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &day))
+ if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &day))
return false;
} else if (symbol.EqualsASCII("J")) {
uint32_t val = 0;
- ExtractCountDigits(str, len, 3, cc, &val);
+ ExtractCountDigits(spDate, 3, cc, &val);
} else if (symbol.EqualsASCII("M") || symbol.EqualsASCII("MM")) {
month = 0;
- if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &month))
+ if (!ExtractCountDigitsWithOptional(spDate, 1, cc, &month))
return false;
} else if (symbol.EqualsASCII("MMM") || symbol.EqualsASCII("MMMM")) {
for (uint16_t i = 0; i < 12; i++) {
@@ -281,7 +279,8 @@
pLocale->GetMonthName(i, symbol.EqualsASCII("MMM"));
if (wsMonthName.IsEmpty())
continue;
- if (!wcsncmp(wsMonthName.c_str(), str + *cc, wsMonthName.GetLength())) {
+ if (wcsncmp(wsMonthName.c_str(), spDate.data() + *cc,
+ wsMonthName.GetLength()) == 0) {
*cc += wsMonthName.GetLength();
month = i + 1;
break;
@@ -293,7 +292,8 @@
pLocale->GetDayName(i, symbol.EqualsASCII("EEE"));
if (wsDayName.IsEmpty())
continue;
- if (!wcsncmp(wsDayName.c_str(), str + *cc, wsDayName.GetLength())) {
+ if (wcsncmp(wsDayName.c_str(), spDate.data() + *cc,
+ wsDayName.GetLength()) == 0) {
*cc += wsDayName.GetLength();
break;
}
@@ -303,7 +303,7 @@
return false;
year = 0;
- if (!ExtractCountDigits(str, len, symbol.GetLength(), cc, &year))
+ if (!ExtractCountDigits(spDate, symbol.GetLength(), cc, &year))
return false;
if (symbol.EqualsASCII("YY")) {
if (year <= 29)
@@ -326,7 +326,7 @@
}
void ResolveZone(FX_TIMEZONE tzDiff,
- LocaleIface* pLocale,
+ const LocaleIface* pLocale,
uint32_t* wHour,
uint32_t* wMinute) {
int32_t iMinuteDiff = *wHour * 60 + *wMinute;
@@ -354,18 +354,18 @@
uint32_t second = 0;
uint32_t millisecond = 0;
size_t ccf = 0;
- const wchar_t* str = wsTime.c_str();
- int len = wsTime.GetLength();
+ pdfium::span<const wchar_t> spTime = wsTime.AsSpan();
pdfium::span<const wchar_t> spTimePattern = wsTimePattern.AsSpan();
bool bHasA = false;
bool bPM = false;
WideStringView wsTimeSymbols(gs_wsTimeSymbols);
- while (*cc < len && ccf < spTimePattern.size()) {
+ while (*cc < pdfium::CollectionSize<int32_t>(spTime) &&
+ ccf < spTimePattern.size()) {
if (spTimePattern[ccf] == '\'') {
WideString wsLiteral = GetLiteralText(spTimePattern, &ccf);
int32_t iLiteralLen = wsLiteral.GetLength();
- if (*cc + iLiteralLen > len ||
- wcsncmp(str + *cc, wsLiteral.c_str(), iLiteralLen)) {
+ if (*cc + iLiteralLen > pdfium::CollectionSize<int32_t>(spTime) ||
+ wcsncmp(spTime.data() + *cc, wsLiteral.c_str(), iLiteralLen)) {
return false;
}
*cc += iLiteralLen;
@@ -373,7 +373,7 @@
continue;
}
if (!wsTimeSymbols.Contains(spTimePattern[ccf])) {
- if (spTimePattern[ccf] != str[*cc])
+ if (spTimePattern[ccf] != spTime[*cc])
return false;
(*cc)++;
ccf++;
@@ -388,66 +388,65 @@
if (symbol.EqualsASCIINoCase("k") || symbol.EqualsASCIINoCase("h")) {
hour = 0;
- if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &hour))
+ if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &hour))
return false;
if (symbol.EqualsASCII("K") && hour == 24)
hour = 0;
} else if (symbol.EqualsASCIINoCase("kk") ||
symbol.EqualsASCIINoCase("hh")) {
hour = 0;
- if (!ExtractCountDigits(str, len, 2, cc, &hour))
+ if (!ExtractCountDigits(spTime, 2, cc, &hour))
return false;
if (symbol.EqualsASCII("KK") && hour == 24)
hour = 0;
} else if (symbol.EqualsASCII("M")) {
minute = 0;
- if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &minute))
+ if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &minute))
return false;
} else if (symbol.EqualsASCII("MM")) {
minute = 0;
- if (!ExtractCountDigits(str, len, 2, cc, &minute))
+ if (!ExtractCountDigits(spTime, 2, cc, &minute))
return false;
} else if (symbol.EqualsASCII("S")) {
second = 0;
- if (!ExtractCountDigitsWithOptional(str, len, 1, cc, &second))
+ if (!ExtractCountDigitsWithOptional(spTime, 1, cc, &second))
return false;
} else if (symbol.EqualsASCII("SS")) {
second = 0;
- if (!ExtractCountDigits(str, len, 2, cc, &second))
+ if (!ExtractCountDigits(spTime, 2, cc, &second))
return false;
} else if (symbol.EqualsASCII("FFF")) {
millisecond = 0;
- if (!ExtractCountDigits(str, len, 3, cc, &millisecond))
+ if (!ExtractCountDigits(spTime, 3, cc, &millisecond))
return false;
} else if (symbol.EqualsASCII("A")) {
WideString wsAM = pLocale->GetMeridiemName(true);
WideString wsPM = pLocale->GetMeridiemName(false);
- if ((*cc + pdfium::base::checked_cast<int32_t>(wsAM.GetLength()) <=
- len) &&
- (WideStringView(str + *cc, wsAM.GetLength()) == wsAM)) {
+ if (*cc + wsAM.GetLength() <= spTime.size() &&
+ WideStringView(spTime.data() + *cc, wsAM.GetLength()) == wsAM) {
*cc += wsAM.GetLength();
bHasA = true;
- } else if ((*cc + pdfium::base::checked_cast<int32_t>(wsPM.GetLength()) <=
- len) &&
- (WideStringView(str + *cc, wsPM.GetLength()) == wsPM)) {
+ } else if (*cc + wsPM.GetLength() <= spTime.size() &&
+ WideStringView(spTime.data() + *cc, wsPM.GetLength()) ==
+ wsPM) {
*cc += wsPM.GetLength();
bHasA = true;
bPM = true;
}
} else if (symbol.EqualsASCII("Z")) {
- if (*cc + 3 > len)
+ if (*cc + 3 > pdfium::CollectionSize<int32_t>(spTime))
continue;
- WideString tz(str[(*cc)++]);
- tz += str[(*cc)++];
- tz += str[(*cc)++];
+ WideString tz(spTime[(*cc)++]);
+ tz += spTime[(*cc)++];
+ tz += spTime[(*cc)++];
if (tz.EqualsASCII("GMT")) {
FX_TIMEZONE tzDiff;
tzDiff.tzHour = 0;
tzDiff.tzMinute = 0;
- if (*cc < len && (str[*cc] == '-' || str[*cc] == '+')) {
- *cc += ParseTimeZone({str + *cc, static_cast<size_t>(len - *cc)},
- &tzDiff);
+ if (*cc < pdfium::CollectionSize<int32_t>(spTime) &&
+ (spTime[*cc] == '-' || spTime[*cc] == '+')) {
+ *cc += ParseTimeZone(spTime.subspan(*cc), &tzDiff);
}
ResolveZone(tzDiff, pLocale, &hour, &minute);
} else {
@@ -463,10 +462,9 @@
}
}
} else if (symbol.EqualsASCII("z")) {
- if (str[*cc] != 'Z') {
+ if (spTime[*cc] != 'Z') {
FX_TIMEZONE tzDiff;
- *cc +=
- ParseTimeZone({str + *cc, static_cast<size_t>(len - *cc)}, &tzDiff);
+ *cc += ParseTimeZone(spTime.subspan(*cc), &tzDiff);
ResolveZone(tzDiff, pLocale, &hour, &minute);
} else {
(*cc)++;
@@ -714,41 +712,40 @@
} // namespace
-bool FX_DateFromCanonical(const WideString& wsDate, CFX_DateTime* datetime) {
- const wchar_t* str = wsDate.c_str();
- int len = wsDate.GetLength();
- if (len > 10)
+bool FX_DateFromCanonical(pdfium::span<const wchar_t> spDate,
+ CFX_DateTime* datetime) {
+ if (spDate.size() > 10)
return false;
int cc = 0;
uint32_t year = 0;
- if (!ExtractCountDigits(str, len, 4, &cc, &year))
+ if (!ExtractCountDigits(spDate, 4, &cc, &year))
return false;
if (year < 1900)
return false;
- if (cc >= len) {
+ if (cc >= pdfium::CollectionSize<int32_t>(spDate)) {
datetime->SetDate(year, 1, 1);
return true;
}
- if (str[cc] == '-')
+ if (spDate[cc] == '-')
cc++;
uint32_t month = 0;
- if (!ExtractCountDigits(str, len, 2, &cc, &month))
+ if (!ExtractCountDigits(spDate, 2, &cc, &month))
return false;
if (month > 12 || month < 1)
return false;
- if (cc >= len) {
+ if (cc >= pdfium::CollectionSize<int32_t>(spDate)) {
datetime->SetDate(year, month, 1);
return true;
}
- if (str[cc] == '-')
+ if (spDate[cc] == '-')
cc++;
uint32_t day = 0;
- if (!ExtractCountDigits(str, len, 2, &cc, &day))
+ if (!ExtractCountDigits(spDate, 2, &cc, &day))
return false;
if (day < 1)
return false;
@@ -763,70 +760,65 @@
return true;
}
-bool FX_TimeFromCanonical(WideStringView wsTime,
- CFX_DateTime* datetime,
- LocaleIface* pLocale) {
- if (wsTime.GetLength() == 0)
+bool FX_TimeFromCanonical(const LocaleIface* pLocale,
+ pdfium::span<const wchar_t> spTime,
+ CFX_DateTime* datetime) {
+ if (spTime.empty())
return false;
- const wchar_t* str = wsTime.unterminated_c_str();
- int len = wsTime.GetLength();
-
int cc = 0;
uint32_t hour = 0;
- if (!ExtractCountDigits(str, len, 2, &cc, &hour))
+ if (!ExtractCountDigits(spTime, 2, &cc, &hour) || hour >= 24)
return false;
- if (hour >= 24)
- return false;
- if (cc >= len) {
+
+ if (cc >= pdfium::CollectionSize<int32_t>(spTime)) {
datetime->SetTime(hour, 0, 0, 0);
return true;
}
- if (str[cc] == ':')
+ if (spTime[cc] == ':')
cc++;
uint32_t minute = 0;
- if (!ExtractCountDigits(str, len, 2, &cc, &minute))
+ if (!ExtractCountDigits(spTime, 2, &cc, &minute))
return false;
if (minute >= 60)
return false;
- if (cc >= len) {
+ if (cc >= pdfium::CollectionSize<int32_t>(spTime)) {
datetime->SetTime(hour, minute, 0, 0);
return true;
}
- if (str[cc] == ':')
+ if (spTime[cc] == ':')
cc++;
uint32_t second = 0;
uint32_t millisecond = 0;
- if (str[cc] != 'Z') {
- if (!ExtractCountDigits(str, len, 2, &cc, &second))
+ if (spTime[cc] != 'Z') {
+ if (!ExtractCountDigits(spTime, 2, &cc, &second) || second >= 60)
return false;
- if (second >= 60)
- return false;
- if (cc < len && str[cc] == '.') {
+
+ if (cc < pdfium::CollectionSize<int32_t>(spTime) && spTime[cc] == '.') {
cc++;
- if (!ExtractCountDigits(str, len, 3, &cc, &millisecond))
+ if (!ExtractCountDigits(spTime, 3, &cc, &millisecond))
return false;
}
}
// Skip until we find a + or - for the time zone.
- while (cc < len) {
- if (str[cc] == '+' || str[cc] == '-')
+ while (cc < pdfium::CollectionSize<int32_t>(spTime)) {
+ if (spTime[cc] == '+' || spTime[cc] == '-')
break;
++cc;
}
- if (cc < len) {
+ if (cc < pdfium::CollectionSize<int32_t>(spTime)) {
FX_TIMEZONE tzDiff;
tzDiff.tzHour = 0;
tzDiff.tzMinute = 0;
- if (str[cc] != 'Z')
- cc += ParseTimeZone({str + cc, static_cast<size_t>(len - cc)}, &tzDiff);
+ if (spTime[cc] != 'Z')
+ cc += ParseTimeZone(spTime.subspan(cc), &tzDiff);
ResolveZone(tzDiff, pLocale, &hour, &minute);
}
@@ -2232,25 +2224,27 @@
auto iT = wsSrcDateTime.Find(L"T");
if (!iT.has_value()) {
if (eCategory == FX_DATETIMETYPE_Date &&
- FX_DateFromCanonical(wsSrcDateTime, &dt)) {
+ FX_DateFromCanonical(wsSrcDateTime.AsSpan(), &dt)) {
*wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true,
pLocale);
return true;
}
if (eCategory == FX_DATETIMETYPE_Time &&
- FX_TimeFromCanonical(wsSrcDateTime.AsStringView(), &dt, pLocale)) {
+ FX_TimeFromCanonical(pLocale, wsSrcDateTime.AsSpan(), &dt)) {
*wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern, true,
pLocale);
return true;
}
} else {
- WideString wsSrcDate(wsSrcDateTime.c_str(), iT.value());
- WideStringView wsSrcTime(wsSrcDateTime.c_str() + iT.value() + 1,
- wsSrcDateTime.GetLength() - iT.value() - 1);
- if (wsSrcDate.IsEmpty() || wsSrcTime.IsEmpty())
+ pdfium::span<const wchar_t> wsSrcDate =
+ wsSrcDateTime.AsSpan().first(iT.value());
+ pdfium::span<const wchar_t> wsSrcTime =
+ wsSrcDateTime.AsSpan().subspan(iT.value() + 1);
+ if (wsSrcDate.empty() || wsSrcTime.empty())
return false;
+
if (FX_DateFromCanonical(wsSrcDate, &dt) &&
- FX_TimeFromCanonical(wsSrcTime, &dt, pLocale)) {
+ FX_TimeFromCanonical(pLocale, wsSrcTime, &dt)) {
*wsOutput = FormatDateTimeInternal(dt, wsDatePattern, wsTimePattern,
eCategory != FX_DATETIMETYPE_TimeDate,
pLocale);
diff --git a/xfa/fgas/crt/cfgas_formatstring.h b/xfa/fgas/crt/cfgas_formatstring.h
index fab32e1..f2a3253 100644
--- a/xfa/fgas/crt/cfgas_formatstring.h
+++ b/xfa/fgas/crt/cfgas_formatstring.h
@@ -10,13 +10,15 @@
#include <vector>
#include "core/fxcrt/unowned_ptr.h"
+#include "third_party/base/span.h"
#include "xfa/fgas/crt/locale_iface.h"
#include "xfa/fgas/crt/locale_mgr_iface.h"
-bool FX_DateFromCanonical(const WideString& wsDate, CFX_DateTime* datetime);
-bool FX_TimeFromCanonical(WideStringView wsTime,
- CFX_DateTime* datetime,
- LocaleIface* pLocale);
+bool FX_DateFromCanonical(pdfium::span<const wchar_t> wsTime,
+ CFX_DateTime* datetime);
+bool FX_TimeFromCanonical(const LocaleIface* pLocale,
+ pdfium::span<const wchar_t> wsTime,
+ CFX_DateTime* datetime);
class CFGAS_FormatString {
public:
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp
index cc9b205..23b9a9a 100644
--- a/xfa/fxfa/parser/cxfa_localevalue.cpp
+++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -219,7 +219,7 @@
return CFX_DateTime();
CFX_DateTime dt;
- FX_DateFromCanonical(m_wsValue, &dt);
+ FX_DateFromCanonical(m_wsValue.AsSpan(), &dt);
return dt;
}
@@ -228,8 +228,7 @@
return CFX_DateTime();
CFX_DateTime dt;
- FX_TimeFromCanonical(m_wsValue.AsStringView(), &dt,
- m_pLocaleMgr->GetDefLocale());
+ FX_TimeFromCanonical(m_pLocaleMgr->GetDefLocale(), m_wsValue.AsSpan(), &dt);
return dt;
}