Use vector of uint8_t in XFA_Base64Decode().
Preferable to malloc() and pointer arithmetic.
Pass const-ref bytestring rather than pointer while at it.
Change-Id: Ic19d0f9fb3a66724ff1e64573887d7f7d1234b02
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/52656
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 7a1d1fe..bbf340e 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -381,60 +381,58 @@
49, 50, 51, 255, 255, 255, 255, 255,
};
-uint8_t* XFA_RemoveBase64Whitespace(pdfium::span<const uint8_t> spStr) {
- uint8_t* pCP = FX_Alloc(uint8_t, spStr.size() + 1);
- size_t j = 0;
- for (size_t i = 0; i < spStr.size(); ++i) {
- if ((spStr[i] & 128) == 0 &&
- (g_inv_base64[spStr[i]] != 0xFF || spStr[i] == '=')) {
- pCP[j++] = spStr[i];
- }
- }
- pCP[j] = '\0';
- return pCP;
+inline uint8_t GetInvBase64(uint8_t x) {
+ return (x & 128) == 0 ? g_inv_base64[x] : 255;
}
-int32_t XFA_Base64Decode(const char* pStr, uint8_t* pOutBuffer) {
- if (!pStr)
- return 0;
+std::vector<uint8_t> XFA_RemoveBase64Whitespace(
+ pdfium::span<const uint8_t> spStr) {
+ std::vector<uint8_t> result;
+ result.reserve(spStr.size());
+ for (uint8_t ch : spStr) {
+ if (GetInvBase64(ch) != 255 || ch == '=')
+ result.push_back(ch);
+ }
+ return result;
+}
- uint8_t* pBuffer = XFA_RemoveBase64Whitespace(
- {reinterpret_cast<const uint8_t*>(pStr), strlen(pStr)});
- int32_t iLen = strlen((char*)pBuffer);
- int32_t i = 0, j = 0;
+std::vector<uint8_t> XFA_Base64Decode(const ByteString& bsStr) {
+ std::vector<uint8_t> result;
+ if (bsStr.IsEmpty())
+ return result;
+
+ std::vector<uint8_t> buffer = XFA_RemoveBase64Whitespace(bsStr.AsRawSpan());
+ result.reserve(3 * (buffer.size() / 4));
+
uint32_t dwLimb = 0;
- for (; i + 3 < iLen; i += 4) {
- if (pBuffer[i] == '=' || pBuffer[i + 1] == '=' || pBuffer[i + 2] == '=' ||
- pBuffer[i + 3] == '=') {
- if (pBuffer[i] == '=' || pBuffer[i + 1] == '=') {
+ for (size_t i = 0; i + 3 < buffer.size(); i += 4) {
+ if (buffer[i] == '=' || buffer[i + 1] == '=' || buffer[i + 2] == '=' ||
+ buffer[i + 3] == '=') {
+ if (buffer[i] == '=' || buffer[i + 1] == '=') {
break;
}
- if (pBuffer[i + 2] == '=') {
- dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 6) |
- ((uint32_t)g_inv_base64[pBuffer[i + 1]]);
- pOutBuffer[j] = (uint8_t)(dwLimb >> 4) & 0xFF;
- j++;
+ if (buffer[i + 2] == '=') {
+ dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 6) |
+ ((uint32_t)g_inv_base64[buffer[i + 1]]);
+ result.push_back((uint8_t)(dwLimb >> 4) & 0xFF);
} else {
- dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 12) |
- ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 6) |
- ((uint32_t)g_inv_base64[pBuffer[i + 2]]);
- pOutBuffer[j] = (uint8_t)(dwLimb >> 10) & 0xFF;
- pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 2) & 0xFF;
- j += 2;
+ dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 12) |
+ ((uint32_t)g_inv_base64[buffer[i + 1]] << 6) |
+ ((uint32_t)g_inv_base64[buffer[i + 2]]);
+ result.push_back((uint8_t)(dwLimb >> 10) & 0xFF);
+ result.push_back((uint8_t)(dwLimb >> 2) & 0xFF);
}
} else {
- dwLimb = ((uint32_t)g_inv_base64[pBuffer[i]] << 18) |
- ((uint32_t)g_inv_base64[pBuffer[i + 1]] << 12) |
- ((uint32_t)g_inv_base64[pBuffer[i + 2]] << 6) |
- ((uint32_t)g_inv_base64[pBuffer[i + 3]]);
- pOutBuffer[j] = (uint8_t)(dwLimb >> 16) & 0xff;
- pOutBuffer[j + 1] = (uint8_t)(dwLimb >> 8) & 0xff;
- pOutBuffer[j + 2] = (uint8_t)(dwLimb)&0xff;
- j += 3;
+ dwLimb = ((uint32_t)g_inv_base64[buffer[i]] << 18) |
+ ((uint32_t)g_inv_base64[buffer[i + 1]] << 12) |
+ ((uint32_t)g_inv_base64[buffer[i + 2]] << 6) |
+ ((uint32_t)g_inv_base64[buffer[i + 3]]);
+ result.push_back((uint8_t)(dwLimb >> 16) & 0xff);
+ result.push_back((uint8_t)(dwLimb >> 8) & 0xff);
+ result.push_back((uint8_t)(dwLimb)&0xff);
}
}
- FX_Free(pBuffer);
- return j;
+ return result;
}
FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) {
@@ -477,18 +475,15 @@
FXCODEC_IMAGE_TYPE type = XFA_GetImageType(pImage->GetContentType());
ByteString bsData; // Must outlive |pImageFileRead|.
- std::vector<uint8_t> buffer;
+ std::vector<uint8_t> buffer; // Must outlive |pImageFileRead|.
RetainPtr<IFX_SeekableReadStream> pImageFileRead;
if (wsImage.GetLength() > 0) {
XFA_AttributeValue iEncoding = pImage->GetTransferEncoding();
if (iEncoding == XFA_AttributeValue::Base64) {
bsData = wsImage.ToUTF8();
- buffer.resize(bsData.GetLength());
- int32_t iRead = XFA_Base64Decode(bsData.c_str(), buffer.data());
- if (iRead > 0) {
- pImageFileRead = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(
- pdfium::make_span(buffer.data(), iRead));
- }
+ buffer = XFA_Base64Decode(bsData);
+ if (!buffer.empty())
+ pImageFileRead = pdfium::MakeRetain<CFX_ReadOnlyMemoryStream>(buffer);
} else {
bsData = wsImage.ToDefANSI();
pImageFileRead =