Avoid unsafe indexing in EncodeURL()
-- use std::array<> where useful.
-- use pdfium::contains() to avoid indexing otherwise.
Change-Id: I7c2ba4c6f71ab6ae94822a711c322ee1658ac82c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/118070
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 18c2534..673b3a5 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -12,6 +12,7 @@
#include <stdlib.h>
#include <algorithm>
+#include <array>
#include <limits>
#include <memory>
#include <optional>
@@ -21,6 +22,7 @@
#include "core/fxcrt/cfx_datetime.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/code_point_view.h"
+#include "core/fxcrt/containers/contains.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_extension.h"
#include "core/fxcrt/fx_random.h"
@@ -61,7 +63,9 @@
const double kFinancialPrecision = 0.00000001;
-const wchar_t kStrCode[] = L"0123456789abcdef";
+constexpr std::array<wchar_t, 16> kStrCode = {
+ {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'a', L'b',
+ L'c', L'd', L'e', L'f'}};
struct XFA_FMHtmlReserveCode {
uint16_t m_uCode;
@@ -673,93 +677,53 @@
'^', '~', '[', ']', '`'};
static constexpr char32_t kStrReserved[] = {';', '/', '?', ':',
'@', '=', '&'};
- static constexpr char32_t kStrSpecial[] = {'$', '-', '+', '!', '*',
- '\'', '(', ')', ','};
WideString wsURL = WideString::FromUTF8(bsURL.AsStringView());
WideTextBuffer wsResultBuf;
- wchar_t encode_buffer[3];
- encode_buffer[0] = '%';
+ std::array<wchar_t, 3> encode_buffer = {L'%'}; // Starts with %.
for (char32_t ch : pdfium::CodePointView(wsURL.AsStringView())) {
- size_t i = 0;
- size_t iCount = std::size(kStrUnsafe);
- while (i < iCount) {
- if (ch == kStrUnsafe[i]) {
- int32_t iIndex = ch / 16;
- encode_buffer[1] = kStrCode[iIndex];
- encode_buffer[2] = kStrCode[ch - iIndex * 16];
- wsResultBuf << WideStringView(encode_buffer, 3);
- break;
- }
- ++i;
- }
- if (i < iCount)
- continue;
-
- i = 0;
- iCount = std::size(kStrReserved);
- while (i < iCount) {
- if (ch == kStrReserved[i]) {
- int32_t iIndex = ch / 16;
- encode_buffer[1] = kStrCode[iIndex];
- encode_buffer[2] = kStrCode[ch - iIndex * 16];
- wsResultBuf << WideStringView(encode_buffer, 3);
- break;
- }
- ++i;
- }
- if (i < iCount)
- continue;
-
- i = 0;
- iCount = std::size(kStrSpecial);
- while (i < iCount) {
- if (ch == kStrSpecial[i]) {
- wsResultBuf.AppendChar(ch);
- break;
- }
- ++i;
- }
- if (i < iCount)
- continue;
-
- if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) {
+ if (ch <= 0x1f || (ch >= 0x7f && ch <= 0xff) ||
+ pdfium::Contains(kStrUnsafe, ch) ||
+ pdfium::Contains(kStrReserved, ch)) {
int32_t iIndex = ch / 16;
encode_buffer[1] = kStrCode[iIndex];
encode_buffer[2] = kStrCode[ch - iIndex * 16];
- wsResultBuf << WideStringView(encode_buffer, 3);
- } else if (ch >= 0x20 && ch <= 0x7e) {
+ wsResultBuf << WideStringView(encode_buffer);
+ continue;
+ }
+ if (ch >= 0x20 && ch <= 0x7e) {
wsResultBuf.AppendChar(ch);
- } else {
- const wchar_t iRadix = 16;
- WideString wsBuffer;
- while (ch >= iRadix) {
- wchar_t tmp = kStrCode[ch % iRadix];
- ch /= iRadix;
- wsBuffer += tmp;
- }
- wsBuffer += kStrCode[ch];
- int32_t iLen = wsBuffer.GetLength();
- if (iLen < 2)
- break;
+ continue;
+ }
+ const wchar_t iRadix = 16;
+ WideString wsBuffer;
+ while (ch >= iRadix) {
+ wchar_t tmp = kStrCode[ch % iRadix];
+ ch /= iRadix;
+ wsBuffer += tmp;
+ }
+ wsBuffer += kStrCode[ch];
+ int32_t iLen = wsBuffer.GetLength();
+ if (iLen < 2) {
+ break;
+ }
- int32_t iIndex = 0;
- if (iLen % 2 != 0) {
- encode_buffer[1] = '0';
- encode_buffer[2] = wsBuffer[iLen - 1];
- iIndex = iLen - 2;
- } else {
- encode_buffer[1] = wsBuffer[iLen - 1];
- encode_buffer[2] = wsBuffer[iLen - 2];
- iIndex = iLen - 3;
- }
- wsResultBuf << WideStringView(encode_buffer, 3);
- while (iIndex > 0) {
- encode_buffer[1] = wsBuffer[iIndex];
- encode_buffer[2] = wsBuffer[iIndex - 1];
- iIndex -= 2;
- wsResultBuf << WideStringView(encode_buffer, 3);
- }
+ int32_t iIndex = 0;
+ if (iLen % 2 != 0) {
+ encode_buffer[1] = '0';
+ encode_buffer[2] = wsBuffer[iLen - 1];
+ iIndex = iLen - 2;
+ } else {
+ encode_buffer[1] = wsBuffer[iLen - 1];
+ encode_buffer[2] = wsBuffer[iLen - 2];
+ iIndex = iLen - 3;
+ }
+ wsResultBuf << WideStringView(encode_buffer);
+ while (iIndex > 0) {
+ encode_buffer[1] = wsBuffer[iIndex];
+ encode_buffer[2] = wsBuffer[iIndex - 1];
+ iIndex -= 2;
+ wsResultBuf << WideStringView(encode_buffer);
}
}
return wsResultBuf.MakeString();