blob: 59b43c1d64b032bc1953de0fc4a82bdeb47c800d [file] [log] [blame]
K. Moon832a6942022-10-31 20:11:31 +00001// Copyright 2014 The PDFium Authors
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Tom Sepez41d04e12018-10-30 22:07:36 +00007#include "fxjs/cfx_globaldata.h"
Tom Sepez37458412015-10-06 11:33:46 -07008
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <utility>
10
Lei Zhangd145e4b2018-10-12 18:54:31 +000011#include "core/fdrm/fx_crypt.h"
Lei Zhang549fe5d2021-06-18 23:46:09 +000012#include "core/fxcrt/stl_util.h"
Tom Sepeza0de6da2021-11-11 01:40:23 +000013#include "third_party/base/numerics/safe_conversions.h"
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070014
weili47228ac2016-07-20 10:35:31 -070015namespace {
16
Tom Sepezeccfe0e2018-11-01 16:34:52 +000017constexpr size_t kMinGlobalDataBytes = 12;
Tom Sepez9964a4a2018-10-30 23:12:31 +000018constexpr size_t kMaxGlobalDataBytes = 4 * 1024 - 8;
Tom Sepezeccfe0e2018-11-01 16:34:52 +000019constexpr uint16_t kMagic = ('X' << 8) | 'F';
20constexpr uint16_t kMaxVersion = 2;
Tom Sepez9964a4a2018-10-30 23:12:31 +000021
22const uint8_t kRC4KEY[] = {
Nico Weber9d8ec5a2015-08-04 13:00:21 -070023 0x19, 0xa8, 0xe8, 0x01, 0xf6, 0xa8, 0xb6, 0x4d, 0x82, 0x04, 0x45, 0x6d,
24 0xb4, 0xcf, 0xd7, 0x77, 0x67, 0xf9, 0x75, 0x9f, 0xf0, 0xe0, 0x1e, 0x51,
25 0xee, 0x46, 0xfd, 0x0b, 0xc9, 0x93, 0x25, 0x55, 0x4a, 0xee, 0xe0, 0x16,
26 0xd0, 0xdf, 0x8c, 0xfa, 0x2a, 0xa9, 0x49, 0xfd, 0x97, 0x1c, 0x0e, 0x22,
27 0x13, 0x28, 0x7c, 0xaf, 0xc4, 0xfc, 0x9c, 0x12, 0x65, 0x8c, 0x4e, 0x5b,
28 0x04, 0x75, 0x89, 0xc9, 0xb1, 0xed, 0x50, 0xca, 0x96, 0x6f, 0x1a, 0x7a,
29 0xfe, 0x58, 0x5d, 0xec, 0x19, 0x4a, 0xf6, 0x35, 0x6a, 0x97, 0x14, 0x00,
30 0x0e, 0xd0, 0x6b, 0xbb, 0xd5, 0x75, 0x55, 0x8b, 0x6e, 0x6b, 0x19, 0xa0,
31 0xf8, 0x77, 0xd5, 0xa3};
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070032
Tom Sepezbf2ef782018-11-07 20:03:30 +000033CFX_GlobalData* g_pInstance = nullptr;
34
tsepez41a53ad2016-03-28 16:59:30 -070035// Returns true if non-empty, setting sPropName
Ryan Harrison275e2602017-09-18 14:23:18 -040036bool TrimPropName(ByteString* sPropName) {
Lei Zhang135c6602017-11-21 18:07:00 +000037 sPropName->Trim();
tsepez41a53ad2016-03-28 16:59:30 -070038 return sPropName->GetLength() != 0;
39}
40
Tom Sepezbf2ef782018-11-07 20:03:30 +000041void MakeNameTypeString(const ByteString& name,
Tom Sepez4a463d52018-11-07 22:32:41 +000042 CFX_Value::DataType eType,
Tom Sepez44a3bf32022-08-02 20:21:39 +000043 BinaryBuffer* result) {
Tom Sepez5c18e872022-11-17 20:41:38 +000044 uint32_t dwNameLen = pdfium::base::checked_cast<uint32_t>(name.GetLength());
45 result->AppendUint32(dwNameLen);
Tom Sepezbf2ef782018-11-07 20:03:30 +000046 result->AppendString(name);
Tom Sepez5c18e872022-11-17 20:41:38 +000047 result->AppendUint16(static_cast<uint16_t>(eType));
Tom Sepezbf2ef782018-11-07 20:03:30 +000048}
49
50bool MakeByteString(const ByteString& name,
51 const CFX_KeyValue& pData,
Tom Sepez44a3bf32022-08-02 20:21:39 +000052 BinaryBuffer* result) {
Tom Sepezbf2ef782018-11-07 20:03:30 +000053 switch (pData.nType) {
Lei Zhang4709fa22020-06-02 20:02:26 +000054 case CFX_Value::DataType::kNumber: {
Tom Sepezbf2ef782018-11-07 20:03:30 +000055 MakeNameTypeString(name, pData.nType, result);
Tom Sepez5c18e872022-11-17 20:41:38 +000056 result->AppendDouble(pData.dData);
Tom Sepezbf2ef782018-11-07 20:03:30 +000057 return true;
58 }
Lei Zhang4709fa22020-06-02 20:02:26 +000059 case CFX_Value::DataType::kBoolean: {
Tom Sepezbf2ef782018-11-07 20:03:30 +000060 MakeNameTypeString(name, pData.nType, result);
Tom Sepez5c18e872022-11-17 20:41:38 +000061 result->AppendUint16(static_cast<uint16_t>(pData.bData));
Tom Sepezbf2ef782018-11-07 20:03:30 +000062 return true;
63 }
Lei Zhang4709fa22020-06-02 20:02:26 +000064 case CFX_Value::DataType::kString: {
Tom Sepezbf2ef782018-11-07 20:03:30 +000065 MakeNameTypeString(name, pData.nType, result);
Tom Sepez5c18e872022-11-17 20:41:38 +000066 uint32_t dwDataLen =
67 pdfium::base::checked_cast<uint32_t>(pData.sData.GetLength());
68 result->AppendUint32(dwDataLen);
Tom Sepezbf2ef782018-11-07 20:03:30 +000069 result->AppendString(pData.sData);
70 return true;
71 }
Lei Zhang4709fa22020-06-02 20:02:26 +000072 case CFX_Value::DataType::kNull: {
Tom Sepezbf2ef782018-11-07 20:03:30 +000073 MakeNameTypeString(name, pData.nType, result);
74 return true;
75 }
Tom Sepez3eaad182018-11-07 21:52:21 +000076 // Arrays don't get persisted per JS spec page 484.
Lei Zhang4709fa22020-06-02 20:02:26 +000077 case CFX_Value::DataType::kObject:
Tom Sepezbf2ef782018-11-07 20:03:30 +000078 default:
79 break;
80 }
81 return false;
82}
weili47228ac2016-07-20 10:35:31 -070083
84} // namespace
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070085
Tom Sepezf4583622015-09-14 15:06:53 -070086// static
Tom Sepezeccfe0e2018-11-01 16:34:52 +000087CFX_GlobalData* CFX_GlobalData::GetRetainedInstance(Delegate* pDelegate) {
weili47228ac2016-07-20 10:35:31 -070088 if (!g_pInstance) {
Tom Sepezeccfe0e2018-11-01 16:34:52 +000089 g_pInstance = new CFX_GlobalData(pDelegate);
Tom Sepezf4583622015-09-14 15:06:53 -070090 }
weili47228ac2016-07-20 10:35:31 -070091 ++g_pInstance->m_RefCount;
92 return g_pInstance;
Tom Sepezf4583622015-09-14 15:06:53 -070093}
94
Tom Sepezeccfe0e2018-11-01 16:34:52 +000095bool CFX_GlobalData::Release() {
96 if (--m_RefCount)
97 return false;
98
99 delete g_pInstance;
100 g_pInstance = nullptr;
101 return true;
Tom Sepezf4583622015-09-14 15:06:53 -0700102}
103
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000104CFX_GlobalData::CFX_GlobalData(Delegate* pDelegate) : m_pDelegate(pDelegate) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700105 LoadGlobalPersistentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700106}
107
Tom Sepez41d04e12018-10-30 22:07:36 +0000108CFX_GlobalData::~CFX_GlobalData() {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700109 SaveGlobalPersisitentVariables();
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700110}
111
Tom Sepez41d04e12018-10-30 22:07:36 +0000112CFX_GlobalData::iterator CFX_GlobalData::FindGlobalVariable(
Ryan Harrison275e2602017-09-18 14:23:18 -0400113 const ByteString& propname) {
tsepez41a53ad2016-03-28 16:59:30 -0700114 for (auto it = m_arrayGlobalData.begin(); it != m_arrayGlobalData.end();
115 ++it) {
116 if ((*it)->data.sKey == propname)
117 return it;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118 }
tsepez41a53ad2016-03-28 16:59:30 -0700119 return m_arrayGlobalData.end();
120}
121
Tom Sepez41d04e12018-10-30 22:07:36 +0000122CFX_GlobalData::Element* CFX_GlobalData::GetGlobalVariable(
Ryan Harrison275e2602017-09-18 14:23:18 -0400123 const ByteString& propname) {
tsepez41a53ad2016-03-28 16:59:30 -0700124 auto iter = FindGlobalVariable(propname);
125 return iter != m_arrayGlobalData.end() ? iter->get() : nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700126}
127
Tom Sepez41d04e12018-10-30 22:07:36 +0000128void CFX_GlobalData::SetGlobalVariableNumber(ByteString sPropName,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700129 double dData) {
tsepez24a48882016-04-11 15:18:40 -0700130 if (!TrimPropName(&sPropName))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700131 return;
132
Tom Sepez41d04e12018-10-30 22:07:36 +0000133 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
Tom Sepeza8a69e72018-10-17 21:53:43 +0000134 if (pData) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000135 pData->data.nType = CFX_Value::DataType::kNumber;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 pData->data.dData = dData;
tsepez41a53ad2016-03-28 16:59:30 -0700137 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700138 }
Tom Sepez31d722d2020-05-15 22:03:46 +0000139 auto pNewData = std::make_unique<CFX_GlobalData::Element>();
Tom Sepeze005dc32018-06-19 17:33:32 +0000140 pNewData->data.sKey = std::move(sPropName);
Lei Zhang4709fa22020-06-02 20:02:26 +0000141 pNewData->data.nType = CFX_Value::DataType::kNumber;
tsepez41a53ad2016-03-28 16:59:30 -0700142 pNewData->data.dData = dData;
143 m_arrayGlobalData.push_back(std::move(pNewData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144}
145
Tom Sepez41d04e12018-10-30 22:07:36 +0000146void CFX_GlobalData::SetGlobalVariableBoolean(ByteString sPropName,
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700147 bool bData) {
tsepez24a48882016-04-11 15:18:40 -0700148 if (!TrimPropName(&sPropName))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149 return;
150
Tom Sepez41d04e12018-10-30 22:07:36 +0000151 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
Tom Sepeza8a69e72018-10-17 21:53:43 +0000152 if (pData) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000153 pData->data.nType = CFX_Value::DataType::kBoolean;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 pData->data.bData = bData;
tsepez41a53ad2016-03-28 16:59:30 -0700155 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700156 }
Tom Sepez31d722d2020-05-15 22:03:46 +0000157 auto pNewData = std::make_unique<CFX_GlobalData::Element>();
Tom Sepeze005dc32018-06-19 17:33:32 +0000158 pNewData->data.sKey = std::move(sPropName);
Lei Zhang4709fa22020-06-02 20:02:26 +0000159 pNewData->data.nType = CFX_Value::DataType::kBoolean;
tsepez41a53ad2016-03-28 16:59:30 -0700160 pNewData->data.bData = bData;
161 m_arrayGlobalData.push_back(std::move(pNewData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700162}
163
Tom Sepez41d04e12018-10-30 22:07:36 +0000164void CFX_GlobalData::SetGlobalVariableString(ByteString sPropName,
Ryan Harrison275e2602017-09-18 14:23:18 -0400165 const ByteString& sData) {
tsepez24a48882016-04-11 15:18:40 -0700166 if (!TrimPropName(&sPropName))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700167 return;
168
Tom Sepez41d04e12018-10-30 22:07:36 +0000169 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
Tom Sepeza8a69e72018-10-17 21:53:43 +0000170 if (pData) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000171 pData->data.nType = CFX_Value::DataType::kString;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700172 pData->data.sData = sData;
tsepez41a53ad2016-03-28 16:59:30 -0700173 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 }
Tom Sepez31d722d2020-05-15 22:03:46 +0000175 auto pNewData = std::make_unique<CFX_GlobalData::Element>();
Tom Sepeze005dc32018-06-19 17:33:32 +0000176 pNewData->data.sKey = std::move(sPropName);
Lei Zhang4709fa22020-06-02 20:02:26 +0000177 pNewData->data.nType = CFX_Value::DataType::kString;
tsepez41a53ad2016-03-28 16:59:30 -0700178 pNewData->data.sData = sData;
179 m_arrayGlobalData.push_back(std::move(pNewData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700180}
181
Tom Sepez574ee372020-01-29 17:25:43 +0000182void CFX_GlobalData::SetGlobalVariableObject(
183 ByteString sPropName,
184 std::vector<std::unique_ptr<CFX_KeyValue>> array) {
tsepez24a48882016-04-11 15:18:40 -0700185 if (!TrimPropName(&sPropName))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700186 return;
187
Tom Sepez41d04e12018-10-30 22:07:36 +0000188 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
Tom Sepeza8a69e72018-10-17 21:53:43 +0000189 if (pData) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000190 pData->data.nType = CFX_Value::DataType::kObject;
Tom Sepez436c9f12018-11-05 18:20:23 +0000191 pData->data.objData = std::move(array);
tsepez41a53ad2016-03-28 16:59:30 -0700192 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700193 }
Tom Sepez31d722d2020-05-15 22:03:46 +0000194 auto pNewData = std::make_unique<CFX_GlobalData::Element>();
Tom Sepeze005dc32018-06-19 17:33:32 +0000195 pNewData->data.sKey = std::move(sPropName);
Lei Zhang4709fa22020-06-02 20:02:26 +0000196 pNewData->data.nType = CFX_Value::DataType::kObject;
Tom Sepez436c9f12018-11-05 18:20:23 +0000197 pNewData->data.objData = std::move(array);
tsepez41a53ad2016-03-28 16:59:30 -0700198 m_arrayGlobalData.push_back(std::move(pNewData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700199}
200
Tom Sepez41d04e12018-10-30 22:07:36 +0000201void CFX_GlobalData::SetGlobalVariableNull(ByteString sPropName) {
tsepez24a48882016-04-11 15:18:40 -0700202 if (!TrimPropName(&sPropName))
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700203 return;
204
Tom Sepez41d04e12018-10-30 22:07:36 +0000205 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
Tom Sepeza8a69e72018-10-17 21:53:43 +0000206 if (pData) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000207 pData->data.nType = CFX_Value::DataType::kNull;
tsepez41a53ad2016-03-28 16:59:30 -0700208 return;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700209 }
Tom Sepez31d722d2020-05-15 22:03:46 +0000210 auto pNewData = std::make_unique<CFX_GlobalData::Element>();
Tom Sepeze005dc32018-06-19 17:33:32 +0000211 pNewData->data.sKey = std::move(sPropName);
Lei Zhang4709fa22020-06-02 20:02:26 +0000212 pNewData->data.nType = CFX_Value::DataType::kNull;
tsepez41a53ad2016-03-28 16:59:30 -0700213 m_arrayGlobalData.push_back(std::move(pNewData));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700214}
215
Tom Sepez41d04e12018-10-30 22:07:36 +0000216bool CFX_GlobalData::SetGlobalVariablePersistent(ByteString sPropName,
tsepez4cf55152016-11-02 14:37:54 -0700217 bool bPersistent) {
tsepez24a48882016-04-11 15:18:40 -0700218 if (!TrimPropName(&sPropName))
tsepez4cf55152016-11-02 14:37:54 -0700219 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700220
Tom Sepez41d04e12018-10-30 22:07:36 +0000221 CFX_GlobalData::Element* pData = GetGlobalVariable(sPropName);
tsepez41a53ad2016-03-28 16:59:30 -0700222 if (!pData)
tsepez4cf55152016-11-02 14:37:54 -0700223 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700224
tsepez41a53ad2016-03-28 16:59:30 -0700225 pData->bPersistent = bPersistent;
tsepez4cf55152016-11-02 14:37:54 -0700226 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700227}
228
Tom Sepez41d04e12018-10-30 22:07:36 +0000229bool CFX_GlobalData::DeleteGlobalVariable(ByteString sPropName) {
tsepez24a48882016-04-11 15:18:40 -0700230 if (!TrimPropName(&sPropName))
tsepez4cf55152016-11-02 14:37:54 -0700231 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700232
tsepez41a53ad2016-03-28 16:59:30 -0700233 auto iter = FindGlobalVariable(sPropName);
234 if (iter == m_arrayGlobalData.end())
tsepez4cf55152016-11-02 14:37:54 -0700235 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700236
tsepez41a53ad2016-03-28 16:59:30 -0700237 m_arrayGlobalData.erase(iter);
tsepez4cf55152016-11-02 14:37:54 -0700238 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700239}
240
Tom Sepez41d04e12018-10-30 22:07:36 +0000241int32_t CFX_GlobalData::GetSize() const {
Lei Zhang549fe5d2021-06-18 23:46:09 +0000242 return fxcrt::CollectionSize<int32_t>(m_arrayGlobalData);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700243}
244
Tom Sepezbf2ef782018-11-07 20:03:30 +0000245CFX_GlobalData::Element* CFX_GlobalData::GetAt(int index) {
tsepez41a53ad2016-03-28 16:59:30 -0700246 if (index < 0 || index >= GetSize())
247 return nullptr;
248 return m_arrayGlobalData[index].get();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700249}
250
Tom Sepez3eaad182018-11-07 21:52:21 +0000251bool CFX_GlobalData::LoadGlobalPersistentVariables() {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000252 if (!m_pDelegate)
Tom Sepez3eaad182018-11-07 21:52:21 +0000253 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700254
Tom Sepez3eaad182018-11-07 21:52:21 +0000255 bool ret;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000256 {
257 // Span can't outlive call to BufferDone().
Lei Zhang2c495302021-10-07 23:13:30 +0000258 absl::optional<pdfium::span<uint8_t>> buffer = m_pDelegate->LoadBuffer();
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000259 if (!buffer.has_value() || buffer.value().empty())
Tom Sepez3eaad182018-11-07 21:52:21 +0000260 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261
Tom Sepez3eaad182018-11-07 21:52:21 +0000262 ret = LoadGlobalPersistentVariablesFromBuffer(buffer.value());
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000263 }
264 m_pDelegate->BufferDone();
Tom Sepez3eaad182018-11-07 21:52:21 +0000265 return ret;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000266}
267
Tom Sepez3eaad182018-11-07 21:52:21 +0000268bool CFX_GlobalData::LoadGlobalPersistentVariablesFromBuffer(
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000269 pdfium::span<uint8_t> buffer) {
270 if (buffer.size() < kMinGlobalDataBytes)
Tom Sepez3eaad182018-11-07 21:52:21 +0000271 return false;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000272
Lei Zhang2e0549b2019-12-05 21:59:34 +0000273 CRYPT_ArcFourCryptBlock(buffer, kRC4KEY);
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000274
275 uint8_t* p = buffer.data();
276 uint16_t wType = *((uint16_t*)p);
277 p += sizeof(uint16_t);
278 if (wType != kMagic)
Tom Sepez3eaad182018-11-07 21:52:21 +0000279 return false;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000280
281 uint16_t wVersion = *((uint16_t*)p);
282 p += sizeof(uint16_t);
283 if (wVersion > kMaxVersion)
Tom Sepez3eaad182018-11-07 21:52:21 +0000284 return false;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000285
286 uint32_t dwCount = *((uint32_t*)p);
287 p += sizeof(uint32_t);
288
289 uint32_t dwSize = *((uint32_t*)p);
290 p += sizeof(uint32_t);
291
292 if (dwSize != buffer.size() - sizeof(uint16_t) * 2 - sizeof(uint32_t) * 2)
Tom Sepez3eaad182018-11-07 21:52:21 +0000293 return false;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000294
295 for (int32_t i = 0, sz = dwCount; i < sz; i++) {
296 if (p > buffer.end())
297 break;
298
299 uint32_t dwNameLen = *((uint32_t*)p);
300 p += sizeof(uint32_t);
301 if (p + dwNameLen > buffer.end())
302 break;
303
304 ByteString sEntry = ByteString(p, dwNameLen);
305 p += sizeof(char) * dwNameLen;
306
Tom Sepez4a463d52018-11-07 22:32:41 +0000307 CFX_Value::DataType wDataType =
308 static_cast<CFX_Value::DataType>(*((uint16_t*)p));
Tom Sepez62a70f92016-03-21 15:00:20 -0700309 p += sizeof(uint16_t);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700310
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000311 switch (wDataType) {
Lei Zhang4709fa22020-06-02 20:02:26 +0000312 case CFX_Value::DataType::kNumber: {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000313 double dData = 0;
314 switch (wVersion) {
315 case 1: {
316 uint32_t dwData = *((uint32_t*)p);
317 p += sizeof(uint32_t);
318 dData = dwData;
319 } break;
320 case 2: {
321 dData = *((double*)p);
322 p += sizeof(double);
323 } break;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700324 }
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000325 SetGlobalVariableNumber(sEntry, dData);
326 SetGlobalVariablePersistent(sEntry, true);
327 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000328 case CFX_Value::DataType::kBoolean: {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000329 uint16_t wData = *((uint16_t*)p);
330 p += sizeof(uint16_t);
331 SetGlobalVariableBoolean(sEntry, (bool)(wData == 1));
332 SetGlobalVariablePersistent(sEntry, true);
333 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000334 case CFX_Value::DataType::kString: {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000335 uint32_t dwLength = *((uint32_t*)p);
336 p += sizeof(uint32_t);
337 if (p + dwLength > buffer.end())
338 break;
339
340 SetGlobalVariableString(sEntry, ByteString(p, dwLength));
341 SetGlobalVariablePersistent(sEntry, true);
342 p += sizeof(char) * dwLength;
343 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000344 case CFX_Value::DataType::kNull: {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000345 SetGlobalVariableNull(sEntry);
346 SetGlobalVariablePersistent(sEntry, true);
347 } break;
Lei Zhang4709fa22020-06-02 20:02:26 +0000348 case CFX_Value::DataType::kObject:
Tom Sepez3eaad182018-11-07 21:52:21 +0000349 default:
350 // Arrays aren't allowed in these buffers, nor are unrecoginzed tags.
351 return false;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700352 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700353 }
Tom Sepez3eaad182018-11-07 21:52:21 +0000354 return true;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700355}
356
Tom Sepez3eaad182018-11-07 21:52:21 +0000357bool CFX_GlobalData::SaveGlobalPersisitentVariables() {
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000358 if (!m_pDelegate)
Tom Sepez3eaad182018-11-07 21:52:21 +0000359 return false;
Tom Sepezeccfe0e2018-11-01 16:34:52 +0000360
tsepezc3255f52016-03-25 14:52:27 -0700361 uint32_t nCount = 0;
Tom Sepez44a3bf32022-08-02 20:21:39 +0000362 BinaryBuffer sData;
tsepez41a53ad2016-03-28 16:59:30 -0700363 for (const auto& pElement : m_arrayGlobalData) {
Tom Sepezbf2ef782018-11-07 20:03:30 +0000364 if (!pElement->bPersistent)
365 continue;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700366
Tom Sepez44a3bf32022-08-02 20:21:39 +0000367 BinaryBuffer sElement;
Tom Sepezbf2ef782018-11-07 20:03:30 +0000368 if (!MakeByteString(pElement->data.sKey, pElement->data, &sElement))
369 continue;
370
371 if (sData.GetSize() + sElement.GetSize() > kMaxGlobalDataBytes)
372 break;
373
Lei Zhang2e0549b2019-12-05 21:59:34 +0000374 sData.AppendSpan(sElement.GetSpan());
Tom Sepezbf2ef782018-11-07 20:03:30 +0000375 nCount++;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700376 }
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700377
Tom Sepez44a3bf32022-08-02 20:21:39 +0000378 BinaryBuffer sFile;
Tom Sepez5c18e872022-11-17 20:41:38 +0000379 sFile.AppendUint16(kMagic);
380 sFile.AppendUint16(kMaxVersion);
381 sFile.AppendUint32(nCount);
Tom Sepez3eaad182018-11-07 21:52:21 +0000382
Tom Sepeza0de6da2021-11-11 01:40:23 +0000383 uint32_t dwSize = pdfium::base::checked_cast<uint32_t>(sData.GetSize());
Tom Sepez5c18e872022-11-17 20:41:38 +0000384 sFile.AppendUint32(dwSize);
Lei Zhang2e0549b2019-12-05 21:59:34 +0000385 sFile.AppendSpan(sData.GetSpan());
Tom Sepez3eaad182018-11-07 21:52:21 +0000386
Tom Sepezbd177612022-09-16 21:04:42 +0000387 CRYPT_ArcFourCryptBlock(sFile.GetMutableSpan(), kRC4KEY);
Tom Sepez5adae6d2021-12-16 23:16:35 +0000388 return m_pDelegate->StoreBuffer(sFile.GetSpan());
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700389}
390
Tom Sepez41d04e12018-10-30 22:07:36 +0000391CFX_GlobalData::Element::Element() = default;
Tom Sepeza8a69e72018-10-17 21:53:43 +0000392
Tom Sepez41d04e12018-10-30 22:07:36 +0000393CFX_GlobalData::Element::~Element() = default;