Make core/fxcrt/css compile under nounsafe_buffer_usage.
Change-Id: Ib7bc494cc688b077de12e2d6056cc51162c73c05
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117030
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
diff --git a/core/fxcrt/css/BUILD.gn b/core/fxcrt/css/BUILD.gn
index cd138b6..3482f71 100644
--- a/core/fxcrt/css/BUILD.gn
+++ b/core/fxcrt/css/BUILD.gn
@@ -54,6 +54,7 @@
configs += [
"../../../:pdfium_strict_config",
"../../../:pdfium_noshorten_config",
+ "../../../:pdfium_nounsafe_buffer_usage_config",
]
deps = [
"../",
diff --git a/core/fxcrt/css/cfx_cssdata.cpp b/core/fxcrt/css/cfx_cssdata.cpp
index 40aacf3..99c3e60 100644
--- a/core/fxcrt/css/cfx_cssdata.cpp
+++ b/core/fxcrt/css/cfx_cssdata.cpp
@@ -9,6 +9,8 @@
#include <algorithm>
#include <utility>
+#include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/css/cfx_cssstyleselector.h"
#include "core/fxcrt/css/cfx_cssvaluelistparser.h"
#include "core/fxcrt/fx_codepage.h"
@@ -73,7 +75,10 @@
const CFX_CSSData::Property* CFX_CSSData::GetPropertyByEnum(
CFX_CSSProperty property) {
- return &kPropertyTable[static_cast<uint8_t>(property)];
+ auto index = static_cast<size_t>(property);
+ CHECK_LT(index, std::size(kPropertyTable));
+ // SAFETY: CHECK() on previous line ensures index is in bounds.
+ return UNSAFE_BUFFERS(&kPropertyTable[index]);
}
const CFX_CSSData::PropertyValue* CFX_CSSData::GetPropertyValueByName(
@@ -102,13 +107,12 @@
WideString lowerName = WideString(wsName);
lowerName.MakeLower();
- for (auto* iter = std::begin(kLengthUnitTable);
- iter != std::end(kLengthUnitTable); ++iter) {
- if (lowerName == iter->value)
- return iter;
- }
-
- return nullptr;
+ auto* iter =
+ std::find_if(std::begin(kLengthUnitTable), std::end(kLengthUnitTable),
+ [lowerName](const CFX_CSSData::LengthUnit& unit) {
+ return lowerName == unit.value;
+ });
+ return iter != std::end(kLengthUnitTable) ? iter : nullptr;
}
const CFX_CSSData::Color* CFX_CSSData::GetColorByName(WideStringView wsName) {
@@ -118,10 +122,9 @@
WideString lowerName = WideString(wsName);
lowerName.MakeLower();
- for (auto* iter = std::begin(kColorTable); iter != std::end(kColorTable);
- ++iter) {
- if (lowerName == iter->name)
- return iter;
- }
- return nullptr;
+ auto* iter = std::find_if(std::begin(kColorTable), std::end(kColorTable),
+ [lowerName](const CFX_CSSData::Color& color) {
+ return lowerName == color.name;
+ });
+ return iter != std::end(kColorTable) ? iter : nullptr;
}
diff --git a/core/fxcrt/css/cfx_cssdeclaration.cpp b/core/fxcrt/css/cfx_cssdeclaration.cpp
index 87aee28..3e4f67a 100644
--- a/core/fxcrt/css/cfx_cssdeclaration.cpp
+++ b/core/fxcrt/css/cfx_cssdeclaration.cpp
@@ -8,6 +8,7 @@
#include <math.h>
+#include <array>
#include <utility>
#include "core/fxcrt/check.h"
@@ -96,9 +97,9 @@
if (!value.First(4).EqualsASCIINoCase("rgb(") || value.Back() != ')') {
return std::nullopt;
}
- uint8_t rgb[3] = {0};
+ std::array<uint8_t, 3> rgb = {};
CFX_CSSValueListParser list(value.Substr(4, value.GetLength() - 5), ',');
- for (int32_t i = 0; i < 3; ++i) {
+ for (auto& component : rgb) {
auto maybe_value = list.NextValue();
if (!maybe_value.has_value() ||
maybe_value.value().type != CFX_CSSValue::PrimitiveType::kNumber) {
@@ -108,9 +109,9 @@
if (!maybe_number.has_value()) {
return std::nullopt;
}
- rgb[i] = maybe_number.value().unit == CFX_CSSNumber::Unit::kPercent
- ? FXSYS_roundf(maybe_number.value().value * 2.55f)
- : FXSYS_roundf(maybe_number.value().value);
+ component = maybe_number.value().unit == CFX_CSSNumber::Unit::kPercent
+ ? FXSYS_roundf(maybe_number.value().value * 2.55f)
+ : FXSYS_roundf(maybe_number.value().value);
}
return ArgbEncode(255, rgb[0], rgb[1], rgb[2]);
}
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.cpp b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
index ac5471e..4fcd7be 100644
--- a/core/fxcrt/css/cfx_cssvaluelistparser.cpp
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.cpp
@@ -8,29 +8,31 @@
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
+#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_system.h"
CFX_CSSValueListParser::CFX_CSSValueListParser(WideStringView list,
wchar_t separator)
- : m_Separator(separator),
- m_pCur(list.unterminated_c_str()),
- m_pEnd(list.unterminated_c_str() + list.GetLength()) {
- DCHECK_NE(m_pCur, m_pEnd);
+ : m_Cur(list), m_Separator(separator) {
+ DCHECK(CharsRemain());
}
+CFX_CSSValueListParser::~CFX_CSSValueListParser() = default;
+
std::optional<CFX_CSSValueListParser::Result>
CFX_CSSValueListParser::NextValue() {
- while (m_pCur < m_pEnd && (*m_pCur <= ' ' || *m_pCur == m_Separator)) {
- ++m_pCur;
+ while (CharsRemain() &&
+ (CurrentChar() <= ' ' || CurrentChar() == m_Separator)) {
+ Advance();
}
- if (m_pCur >= m_pEnd) {
+ if (!CharsRemain()) {
return std::nullopt;
}
auto eType = CFX_CSSValue::PrimitiveType::kUnknown;
- const wchar_t* pStart = m_pCur;
+ WideStringView start = m_Cur;
size_t nLength = 0;
- wchar_t wch = *m_pCur;
+ wchar_t wch = CurrentChar();
if (wch == '#') {
nLength = SkipToChar(' ');
if (nLength == 4 || nLength == 7) {
@@ -38,57 +40,63 @@
}
} else if (FXSYS_IsDecimalDigit(wch) || wch == '.' || wch == '-' ||
wch == '+') {
- while (m_pCur < m_pEnd && (*m_pCur > ' ' && *m_pCur != m_Separator)) {
- ++m_pCur;
+ while (CharsRemain() &&
+ (CurrentChar() > ' ' && CurrentChar() != m_Separator)) {
+ ++nLength;
+ Advance();
}
- nLength = m_pCur - pStart;
eType = CFX_CSSValue::PrimitiveType::kNumber;
} else if (wch == '\"' || wch == '\'') {
- ++pStart;
- ++m_pCur;
+ start = start.Substr(1);
+ Advance();
nLength = SkipToChar(wch);
- ++m_pCur;
+ Advance();
eType = CFX_CSSValue::PrimitiveType::kString;
- } else if (m_pEnd - m_pCur > 5 && m_pCur[3] == '(') {
- if (FXSYS_wcsnicmp(L"rgb", m_pCur, 3) == 0) {
- nLength = SkipToChar(')') + 1;
- ++m_pCur;
- eType = CFX_CSSValue::PrimitiveType::kRGB;
- }
+ } else if (m_Cur.First(4).EqualsASCIINoCase(
+ "rgb(")) { // First() always safe.
+ nLength = SkipToChar(')') + 1;
+ Advance();
+ eType = CFX_CSSValue::PrimitiveType::kRGB;
} else {
nLength = SkipToCharMatchingParens(m_Separator);
eType = CFX_CSSValue::PrimitiveType::kString;
}
- if (m_pCur <= m_pEnd && nLength > 0) {
- return Result{eType, WideStringView(pStart, nLength)};
+ if (nLength == 0) {
+ return std::nullopt;
}
- return std::nullopt;
+ return Result{eType, start.First(nLength)};
}
size_t CFX_CSSValueListParser::SkipToChar(wchar_t wch) {
- const wchar_t* pStart = m_pCur;
- while (m_pCur < m_pEnd && *m_pCur != wch) {
- m_pCur++;
+ size_t count = 0;
+ while (CharsRemain() && CurrentChar() != wch) {
+ Advance();
+ ++count;
}
- return m_pCur - pStart;
+ return count;
}
size_t CFX_CSSValueListParser::SkipToCharMatchingParens(wchar_t wch) {
- const wchar_t* pStart = m_pCur;
+ size_t nLength = 0;
int64_t bracketCount = 0;
- while (m_pCur < m_pEnd && *m_pCur != wch) {
- if (*m_pCur <= ' ')
+ while (CharsRemain() && CurrentChar() != wch) {
+ if (CurrentChar() <= ' ') {
break;
- if (*m_pCur == '(')
+ }
+ if (CurrentChar() == '(') {
bracketCount++;
- else if (*m_pCur == ')')
+ } else if (CurrentChar() == ')') {
bracketCount--;
- m_pCur++;
+ }
+ ++nLength;
+ Advance();
}
- while (bracketCount > 0 && m_pCur < m_pEnd) {
- if (*m_pCur == ')')
+ while (bracketCount > 0 && CharsRemain()) {
+ if (CurrentChar() == ')') {
bracketCount--;
- m_pCur++;
+ }
+ ++nLength;
+ Advance();
}
- return m_pCur - pStart;
+ return nLength;
}
diff --git a/core/fxcrt/css/cfx_cssvaluelistparser.h b/core/fxcrt/css/cfx_cssvaluelistparser.h
index e6deb88..2673520 100644
--- a/core/fxcrt/css/cfx_cssvaluelistparser.h
+++ b/core/fxcrt/css/cfx_cssvaluelistparser.h
@@ -22,17 +22,25 @@
};
CFX_CSSValueListParser(WideStringView list, wchar_t separator);
+ ~CFX_CSSValueListParser();
std::optional<Result> NextValue();
void UseCommaSeparator() { m_Separator = ','; }
private:
+ bool CharsRemain() const { return !m_Cur.IsEmpty(); }
+
+ // Safe to call even when input exhausted, stays unchanged.
+ void Advance() { m_Cur = m_Cur.Substr(1); }
+
+ // Safe to call even when input exhausted, returns NUL.
+ wchar_t CurrentChar() const { return static_cast<wchar_t>(m_Cur.Front()); }
+
size_t SkipToChar(wchar_t wch);
size_t SkipToCharMatchingParens(wchar_t wch);
+ WideStringView m_Cur;
wchar_t m_Separator;
- const wchar_t* m_pCur;
- const wchar_t* m_pEnd;
};
#endif // CORE_FXCRT_CSS_CFX_CSSVALUELISTPARSER_H_