Fix unsafe buffer usage in xfa_basic_data.cpp Spanify, get bounds checks for free. Bug: pdfium:2155 Change-Id: If6be531ec2cd5690ac14782b32f7da6d87a0fc82 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/118955 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Thomas Sepez <tsepez@google.com> Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/parser/cxfa_color.cpp b/xfa/fxfa/parser/cxfa_color.cpp index 38ce3be..f09251e 100644 --- a/xfa/fxfa/parser/cxfa_color.cpp +++ b/xfa/fxfa/parser/cxfa_color.cpp
@@ -4,11 +4,6 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2153): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "xfa/fxfa/parser/cxfa_color.h" #include "core/fxcrt/fx_extension.h" @@ -37,43 +32,46 @@ if (view.IsEmpty()) return kDefaultValue; - const wchar_t* str = view.unterminated_c_str(); - size_t len = view.GetLength(); + pdfium::span<const wchar_t> str = view.span(); size_t cc = 0; - while (cc < len && FXSYS_iswspace(str[cc])) + while (cc < str.size() && FXSYS_iswspace(str[cc])) { cc++; + } - if (cc >= len) + if (cc >= str.size()) { return kDefaultValue; + } uint8_t r = 0; uint8_t g = 0; uint8_t b = 0; - while (cc < len) { + while (cc < str.size()) { if (str[cc] == ',' || !FXSYS_IsDecimalDigit(str[cc])) break; r = r * 10 + str[cc] - '0'; cc++; } - if (cc < len && str[cc] == ',') { + if (cc < str.size() && str[cc] == ',') { cc++; - while (cc < len && FXSYS_iswspace(str[cc])) + while (cc < str.size() && FXSYS_iswspace(str[cc])) { cc++; + } - while (cc < len) { + while (cc < str.size()) { if (str[cc] == ',' || !FXSYS_IsDecimalDigit(str[cc])) break; g = g * 10 + str[cc] - '0'; cc++; } - if (cc < len && str[cc] == ',') { + if (cc < str.size() && str[cc] == ',') { cc++; - while (cc < len && FXSYS_iswspace(str[cc])) + while (cc < str.size() && FXSYS_iswspace(str[cc])) { cc++; + } - while (cc < len) { + while (cc < str.size()) { if (str[cc] == ',' || !FXSYS_IsDecimalDigit(str[cc])) break;
diff --git a/xfa/fxfa/parser/cxfa_localemgr.cpp b/xfa/fxfa/parser/cxfa_localemgr.cpp index 459b2b9..ef4b8f4 100644 --- a/xfa/fxfa/parser/cxfa_localemgr.cpp +++ b/xfa/fxfa/parser/cxfa_localemgr.cpp
@@ -4,11 +4,6 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2153): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "xfa/fxfa/parser/cxfa_localemgr.h" #include <time.h> @@ -18,6 +13,7 @@ #include "core/fxcodec/flate/flatemodule.h" #include "core/fxcrt/check.h" +#include "core/fxcrt/compiler_specific.h" #include "core/fxcrt/fx_memory_wrappers.h" #include "fxjs/gc/container_trace.h" #include "fxjs/xfa/cjx_object.h" @@ -1081,7 +1077,9 @@ if (!output) return nullptr; - return CXFA_XMLLocale::Create(heap, pdfium::make_span(output.get(), dwSize)); + // TODO(crbug.com/pdfuim/2155): investigate safety issues. + return CXFA_XMLLocale::Create( + heap, UNSAFE_BUFFERS(pdfium::make_span(output.get(), dwSize))); } CXFA_LocaleMgr::LangID GetLanguageID(WideString wsLanguage) {
diff --git a/xfa/fxfa/parser/cxfa_localevalue.cpp b/xfa/fxfa/parser/cxfa_localevalue.cpp index b54c7d3..c938f7a 100644 --- a/xfa/fxfa/parser/cxfa_localevalue.cpp +++ b/xfa/fxfa/parser/cxfa_localevalue.cpp
@@ -4,11 +4,6 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2153): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "xfa/fxfa/parser/cxfa_localevalue.h" #include <wchar.h> @@ -391,8 +386,8 @@ bool CXFA_LocaleValue::ValidateCanonicalDate(const WideString& wsDate, CFX_DateTime* unDate) { - static const uint8_t LastDay[12] = {31, 28, 31, 30, 31, 30, - 31, 31, 30, 31, 30, 31}; + static const std::array<const uint8_t, 12> LastDay = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; static const uint16_t wCountY = 4; static const uint16_t wCountM = 2; static const uint16_t wCountD = 2;
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp index 919b245..375e024 100644 --- a/xfa/fxfa/parser/cxfa_node.cpp +++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -4,17 +4,13 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2153): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "xfa/fxfa/parser/cxfa_node.h" #include <math.h> #include <stdint.h> #include <algorithm> +#include <array> #include <map> #include <memory> #include <set> @@ -380,7 +376,7 @@ constexpr uint8_t kMaxExecuteRecursion = 2; -constexpr uint8_t kInvBase64[128] = { +constexpr std::array<const uint8_t, 128> kInvBase64 = {{ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62, 255, @@ -390,7 +386,7 @@ 25, 255, 255, 255, 255, 255, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 255, 255, 255, 255, 255, -}; +}}; inline uint8_t GetInvBase64(uint8_t x) { return (x & 128) == 0 ? kInvBase64[x] : 255;
diff --git a/xfa/fxfa/parser/xfa_basic_data.cpp b/xfa/fxfa/parser/xfa_basic_data.cpp index 4af24ed..164bddf 100644 --- a/xfa/fxfa/parser/xfa_basic_data.cpp +++ b/xfa/fxfa/parser/xfa_basic_data.cpp
@@ -4,16 +4,12 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com -#if defined(UNSAFE_BUFFERS_BUILD) -// TODO(crbug.com/pdfium/2153): resolve buffer safety issues. -#pragma allow_unsafe_buffers -#endif - #include "xfa/fxfa/parser/xfa_basic_data.h" #include <iterator> #include <utility> +#include "core/fxcrt/span.h" #include "fxjs/xfa/cjx_boolean.h" #include "fxjs/xfa/cjx_container.h" #include "fxjs/xfa/cjx_datawindow.h" @@ -62,6 +58,8 @@ #undef PCKT____ }; +constexpr pdfium::span<const PacketTableRecord> kPacketSpan{kPacketTable}; + struct ElementRecord { uint32_t hash; // Hashed as wide string. XFA_Element element; @@ -77,6 +75,8 @@ #undef ELEM____ }; +constexpr pdfium::span<const ElementRecord> kElementRecordSpan{kElementRecords}; + constexpr const char* kElementNames[] = { #undef ELEM____ #define ELEM____(a, b, c, d) b, @@ -84,6 +84,8 @@ #undef ELEM____ }; +constexpr const pdfium::span<const char* const> kElementNameSpan{kElementNames}; + static_assert(std::size(kElementRecords) == std::size(kElementNames), "Size mismatch"); @@ -102,6 +104,9 @@ #undef ATTR____ }; +constexpr pdfium::span<const AttributeRecord> kAttributeRecordSpan{ + kAttributeRecords}; + constexpr const char* kAttributeNames[] = { #undef ATTR____ #define ATTR____(a, b, c, d) b, @@ -109,6 +114,8 @@ #undef ATTR____ }; +constexpr pdfium::span<const char* const> kAttributeNameSpan{kAttributeNames}; + static_assert(std::size(kAttributeRecords) == std::size(kAttributeNames), "Size mismatch"); @@ -134,6 +141,9 @@ #undef VALUE____ }; +constexpr pdfium::span<const char* const> kAttributeValueNameSpan{ + kAttributeValueNames}; + static_assert(std::size(kAttributeValueRecords) == std::size(kAttributeValueNames), "Size mismatch"); @@ -159,6 +169,9 @@ #undef ELEM_ATTR____ }; +constexpr pdfium::span<const XFA_ATTRIBUTE_CALLBACK> + kElementAttributeCallbackSpan{kElementAttributeCallbacks}; + static_assert(std::size(kElementAttributeRecords) == std::size(kElementAttributeCallbacks), "Size mismatch"); @@ -166,7 +179,7 @@ } // namespace XFA_PACKETINFO XFA_GetPacketByIndex(XFA_PacketType ePacket) { - return kPacketTable[static_cast<uint8_t>(ePacket)].info; + return kPacketSpan[static_cast<uint8_t>(ePacket)].info; } std::optional<XFA_PACKETINFO> XFA_GetPacketByName(WideStringView wsName) { @@ -180,7 +193,7 @@ } ByteStringView XFA_ElementToName(XFA_Element elem) { - return kElementNames[static_cast<size_t>(elem)]; + return kElementNameSpan[static_cast<size_t>(elem)]; } XFA_Element XFA_GetElementByName(WideStringView name) { @@ -192,26 +205,26 @@ return XFA_Element::Unknown; size_t index = std::distance(std::begin(kElementRecords), elem); - return name.EqualsASCII(kElementNames[index]) ? elem->element - : XFA_Element::Unknown; + return name.EqualsASCII(kElementNameSpan[index]) ? elem->element + : XFA_Element::Unknown; } ByteStringView XFA_AttributeToName(XFA_Attribute attr) { - return kAttributeNames[static_cast<size_t>(attr)]; + return kAttributeNameSpan[static_cast<size_t>(attr)]; } std::optional<XFA_ATTRIBUTEINFO> XFA_GetAttributeByName(WideStringView name) { uint32_t hash = FX_HashCode_GetW(name); auto* elem = std::lower_bound( - std::begin(kAttributeRecords), std::end(kAttributeRecords), hash, + kAttributeRecordSpan.begin(), kAttributeRecordSpan.end(), hash, [](const AttributeRecord& a, uint32_t hash) { return a.hash < hash; }); - if (elem == std::end(kAttributeRecords)) + if (elem == kAttributeRecordSpan.end()) { return std::nullopt; - - size_t index = std::distance(std::begin(kAttributeRecords), elem); - if (!name.EqualsASCII(kAttributeNames[index])) + } + size_t index = std::distance(kAttributeRecordSpan.begin(), elem); + if (!name.EqualsASCII(kAttributeNameSpan[index])) { return std::nullopt; - + } XFA_ATTRIBUTEINFO result; result.attribute = elem->attribute; result.eValueType = elem->script_type; @@ -219,7 +232,7 @@ } ByteStringView XFA_AttributeValueToName(XFA_AttributeValue item) { - return kAttributeValueNames[static_cast<int32_t>(item)]; + return kAttributeValueNameSpan[static_cast<int32_t>(item)]; } std::optional<XFA_AttributeValue> XFA_GetAttributeValueByName( @@ -234,8 +247,9 @@ return std::nullopt; size_t index = std::distance(std::begin(kAttributeValueRecords), it); - if (!name.EqualsASCII(kAttributeValueNames[index])) + if (!name.EqualsASCII(kAttributeValueNameSpan[index])) { return std::nullopt; + } return it->eName; } @@ -263,10 +277,10 @@ result.attribute = attr.value().attribute; result.eValueType = attr.value().eValueType; size_t index = std::distance(std::begin(kElementAttributeRecords), it); - result.callback = kElementAttributeCallbacks[index]; + result.callback = kElementAttributeCallbackSpan[index]; return result; } - element = kElementRecords[static_cast<size_t>(element)].parent; + element = kElementRecordSpan[static_cast<size_t>(element)].parent; } return std::nullopt; }