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