1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "raw_data_parser.h"
17
18 #include <chrono>
19
20 #include "multi_platform_endian.h"
21
22 namespace OHOS::NativeRdb {
ParserRawData(const uint8_t * data,size_t length,Asset & asset)23 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, Asset &asset)
24 {
25 size_t used = 0;
26 uint16_t size = 0;
27
28 if (sizeof(ASSET_MAGIC) > length - used) {
29 return 0;
30 }
31 std::vector<uint8_t> alignData;
32 alignData.assign(data, data + sizeof(ASSET_MAGIC));
33 used += sizeof(ASSET_MAGIC);
34 auto hostMagicWord = Endian::LeToH(*(reinterpret_cast<decltype(&ASSET_MAGIC)>(alignData.data())));
35 if (hostMagicWord != ASSET_MAGIC) {
36 return 0;
37 }
38
39 if (sizeof(size) > length - used) {
40 return 0;
41 }
42 alignData.assign(data + used, data + used + sizeof(size));
43 used += sizeof(size);
44 size = Endian::LeToH(*(reinterpret_cast<decltype(&size)>(alignData.data())));
45 if (size > length - used) {
46 return 0;
47 }
48 auto rawData = std::string(reinterpret_cast<const char *>(&data[used]), size);
49 InnerAsset innerAsset = InnerAsset(asset);
50 if (!innerAsset.Unmarshall(rawData)) {
51 return 0;
52 }
53 used += size;
54 return used;
55 }
56
ParserRawData(const uint8_t * data,size_t length,Assets & assets)57 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, Assets &assets)
58 {
59 size_t used = 0;
60 uint16_t num = 0;
61
62 if (sizeof(ASSETS_MAGIC) > length - used) {
63 return 0;
64 }
65 std::vector<uint8_t> alignData;
66 alignData.assign(data, data + sizeof (ASSETS_MAGIC));
67 used += sizeof (ASSETS_MAGIC);
68 auto hostMagicWord = Endian::LeToH(*(reinterpret_cast<decltype(&ASSETS_MAGIC)>(alignData.data())));
69 if (hostMagicWord != ASSETS_MAGIC) {
70 return 0;
71 }
72
73 if (sizeof(num) > length - used) {
74 return 0;
75 }
76 alignData.assign(data, data + sizeof(num));
77 num = Endian::LeToH(*(reinterpret_cast<decltype(&num)>(alignData.data())));
78 used += sizeof(num);
79 uint16_t count = 0;
80 while (used < length && count < num) {
81 Asset asset;
82 auto dataLen = ParserRawData(&data[used], length - used, asset);
83 if (dataLen == 0) {
84 break;
85 }
86 used += dataLen;
87 assets.push_back(std::move(asset));
88 count++;
89 }
90 return used;
91 }
92
PackageRawData(const Asset & asset)93 std::vector<uint8_t> RawDataParser::PackageRawData(const Asset &asset)
94 {
95 std::vector<uint8_t> rawData;
96 InnerAsset innerAsset(const_cast<Asset &>(asset));
97 auto data = Serializable::Marshall(innerAsset);
98 uint16_t size = Endian::HToLe((uint16_t)data.length());
99 auto leMagic = Endian::HToLe(ASSET_MAGIC);
100 auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
101 rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSET_MAGIC));
102 rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&size),
103 reinterpret_cast<uint8_t *>(&size) + sizeof(size));
104 rawData.insert(rawData.end(), data.begin(), data.end());
105 return rawData;
106 }
107
PackageRawData(const Assets & assets)108 std::vector<uint8_t> RawDataParser::PackageRawData(const Assets &assets)
109 {
110 std::vector<uint8_t> rawData;
111 uint16_t num = uint16_t(assets.size());
112 auto leMagic = Endian::HToLe(ASSETS_MAGIC);
113 auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
114 rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSETS_MAGIC));
115 rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&num), reinterpret_cast<uint8_t *>(&num) + sizeof(num));
116 for (auto &asset : assets) {
117 auto data = PackageRawData(asset);
118 rawData.insert(rawData.end(), data.begin(), data.end());
119 }
120 return rawData;
121 }
122
ParserRawData(const uint8_t * data,size_t length,std::map<std::string,Asset> & assets)123 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, std::map<std::string, Asset> &assets)
124 {
125 Assets res;
126 auto used = ParserRawData(data, length, res);
127 auto it = res.begin();
128 while (it != res.end()) {
129 assets.insert({ it->name, *it });
130 it++;
131 }
132 return used;
133 }
134
ParserRawData(const uint8_t * data,size_t length,BigInteger & bigint)135 size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, BigInteger& bigint)
136 {
137 size_t used = 0;
138 if (sizeof(BIG_INT) > length - used) {
139 return 0;
140 }
141 std::vector<uint8_t> copiedData;
142 const uint8_t *alignData = data;
143 if ((reinterpret_cast<uintptr_t>(data) & (sizeof(uintptr_t) - 1)) != 0) {
144 copiedData.assign(data, data + length);
145 alignData = copiedData.data();
146 }
147 auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&BIG_INT)>(alignData)));
148 used += sizeof(BIG_INT);
149 if (magic != BIG_INT) {
150 return 0;
151 }
152
153 if (sizeof(uint32_t) > length - used) {
154 return 0;
155 }
156
157 uint32_t sign = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(alignData + used)));
158 used += sizeof(uint32_t);
159
160 if (sizeof(uint64_t) > length - used) {
161 return 0;
162 }
163 uint64_t count = Endian::LeToH(*(reinterpret_cast<const uint64_t *>(alignData + used)));
164 used += sizeof(uint64_t);
165
166 if (count > (length - used) / sizeof(uint64_t)) {
167 return 0;
168 }
169 const uint64_t *temp = (reinterpret_cast<const uint64_t *>(alignData + used));
170 std::vector<uint64_t> trueFrom(temp, temp + count);
171 used += sizeof(uint64_t) * count;
172 for (size_t i = 0; i < trueFrom.size(); ++i) {
173 trueFrom[i] = Endian::LeToH(trueFrom[i]);
174 }
175 bigint = BigInteger(static_cast<int32_t>(sign), std::move(trueFrom));
176 return used;
177 }
178
ParserRawData(const uint8_t * data,size_t length,RawDataParser::Floats & floats)179 size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, RawDataParser::Floats& floats)
180 {
181 size_t used = 0;
182 if (sizeof(FLOUT32_ARRAY) > length - used) {
183 return 0;
184 }
185 std::vector<uint8_t> copiedData;
186 const uint8_t *alignData = data;
187 if ((reinterpret_cast<uintptr_t>(data) & (sizeof(uintptr_t) - 1)) != 0) {
188 copiedData.assign(data, data + length);
189 alignData = copiedData.data();
190 }
191 auto magic = Endian::LeToH(*(reinterpret_cast<decltype(&FLOUT32_ARRAY)>(alignData)));
192 used += sizeof(FLOUT32_ARRAY);
193 if (magic != FLOUT32_ARRAY) {
194 return 0;
195 }
196
197 if (sizeof(uint32_t) > length - used) {
198 return 0;
199 }
200
201 uint32_t count = Endian::LeToH(*(reinterpret_cast<const uint32_t *>(alignData + used)));
202 used += sizeof(uint32_t);
203
204 if (count > (length - used) / sizeof(float)) {
205 return 0;
206 }
207 auto values = reinterpret_cast<const float *>(alignData + used);
208 floats.assign(values, values + count);
209 used += sizeof(float) * count;
210 return used;
211 }
212
PackageRawData(const std::map<std::string,Asset> & assets)213 std::vector<uint8_t> RawDataParser::PackageRawData(const std::map<std::string, Asset> &assets)
214 {
215 Assets res;
216 for (auto asset : assets) {
217 res.push_back(asset.second);
218 }
219 return PackageRawData(res);
220 }
221
PackageRawData(const BigInteger & bigint)222 std::vector<uint8_t> RawDataParser::PackageRawData(const BigInteger& bigint)
223 {
224 size_t offset = 0;
225 auto size = sizeof(BIG_INT) + sizeof(uint32_t) + sizeof(uint64_t) * (bigint.Size() + 1);
226 std::vector<uint8_t> rawData(size, 0);
227 uint8_t* data = rawData.data();
228 *(reinterpret_cast<uint32_t *>(&data[offset])) = Endian::HToLe(BIG_INT);
229 offset += sizeof(BIG_INT);
230 *(reinterpret_cast<uint32_t *>(&data[offset])) = Endian::HToLe(uint32_t(bigint.Sign()));
231 offset += sizeof(uint32_t);
232 *(reinterpret_cast<uint64_t *>(&data[offset])) = Endian::HToLe(uint64_t(bigint.Size()));
233 offset += sizeof(uint64_t);
234 auto trueForm = bigint.TrueForm();
235 if (trueForm == nullptr) {
236 return {};
237 }
238 for (size_t i = 0; i < bigint.Size(); ++i) {
239 *(reinterpret_cast<uint64_t *>(&data[offset])) = Endian::HToLe(trueForm[i]);
240 offset += sizeof(uint64_t);
241 }
242 return rawData;
243 }
244
PackageRawData(const RawDataParser::Floats & floats)245 std::vector<uint8_t> RawDataParser::PackageRawData(const RawDataParser::Floats& floats)
246 {
247 size_t offset = 0;
248 auto size = sizeof(FLOUT32_ARRAY) + sizeof(uint32_t) + sizeof(float) * floats.size();
249 std::vector<uint8_t> rawData(size, 0);
250 uint8_t* data = rawData.data();
251 *(reinterpret_cast<uint32_t *>(&data[offset])) = Endian::HToLe(FLOUT32_ARRAY);
252 offset += sizeof(FLOUT32_ARRAY);
253 *(reinterpret_cast<uint32_t *>(&data[offset])) = Endian::HToLe(uint32_t(floats.size()));
254 offset += sizeof(uint32_t);
255 for (size_t i = 0; i < floats.size(); ++i) {
256 *(reinterpret_cast<float *>(&data[offset])) = floats[i];
257 offset += sizeof(float);
258 }
259 return rawData;
260 }
261
Marshal(Serializable::json & node) const262 bool RawDataParser::InnerAsset::Marshal(Serializable::json &node) const
263 {
264 SetValue(node[GET_NAME(version)], asset_.version);
265 SetValue(node[GET_NAME(expiresTime)], asset_.expiresTime);
266 SetValue(node[GET_NAME(id)], asset_.id);
267 SetValue(node[GET_NAME(name)], asset_.name);
268 SetValue(node[GET_NAME(uri)], asset_.uri);
269 SetValue(node[GET_NAME(createTime)], asset_.createTime);
270 SetValue(node[GET_NAME(modifyTime)], asset_.modifyTime);
271 SetValue(node[GET_NAME(size)], asset_.size);
272 SetValue(node[GET_NAME(hash)], asset_.hash);
273 SetValue(node[GET_NAME(path)], asset_.path);
274 SetValue(node[GET_NAME(status)], asset_.status);
275 return true;
276 }
Unmarshal(const Serializable::json & node)277 bool RawDataParser::InnerAsset::Unmarshal(const Serializable::json &node)
278 {
279 bool ret = true;
280 ret = GetValue(node, GET_NAME(version), asset_.version) && ret;
281 ret = GetValue(node, GET_NAME(expiresTime), asset_.expiresTime) && ret;
282 ret = GetValue(node, GET_NAME(id), asset_.id) && ret;
283 ret = GetValue(node, GET_NAME(name), asset_.name) && ret;
284 ret = GetValue(node, GET_NAME(uri), asset_.uri) && ret;
285 ret = GetValue(node, GET_NAME(createTime), asset_.createTime) && ret;
286 ret = GetValue(node, GET_NAME(modifyTime), asset_.modifyTime) && ret;
287 ret = GetValue(node, GET_NAME(size), asset_.size) && ret;
288 ret = GetValue(node, GET_NAME(hash), asset_.hash) && ret;
289 ret = GetValue(node, GET_NAME(path), asset_.path) && ret;
290 ret = GetValue(node, GET_NAME(status), asset_.status) && ret;
291 if (asset_.status == AssetValue::STATUS_DOWNLOADING &&
292 asset_.expiresTime < static_cast<uint64_t>(std::chrono::system_clock::now().time_since_epoch().count())) {
293 asset_.status = AssetValue::STATUS_ABNORMAL;
294 }
295 return ret;
296 }
297 } // namespace OHOS::NativeRdb