1 /*
2 * Copyright (c) 2021 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 "parcel.h"
17
18 #include <climits>
19
20 #include "endian_convert.h"
21 #include "securec.h"
22 #include "macro_utils.h"
23 #include "log_print.h"
24 #include "db_errno.h"
25 #include "db_constant.h"
26
27 namespace DistributedDB {
Parcel(uint8_t * inBuf,uint32_t len)28 Parcel::Parcel(uint8_t *inBuf, uint32_t len)
29 : buf_(inBuf),
30 bufPtr_(inBuf),
31 totalLen_(len)
32 {
33 if (inBuf == nullptr || len == 0) {
34 isError_ = true;
35 }
36 }
37
~Parcel()38 Parcel::~Parcel()
39 {
40 buf_ = nullptr;
41 bufPtr_ = nullptr;
42 }
43
IsError() const44 bool Parcel::IsError() const
45 {
46 return isError_;
47 }
48
WriteBool(bool data)49 int Parcel::WriteBool(bool data)
50 {
51 uint8_t value = data ? 1 : 0;
52 return WriteUInt8(value);
53 }
54
ReadBool(bool & val)55 uint32_t Parcel::ReadBool(bool &val)
56 {
57 uint8_t intVal = 0;
58 uint32_t len = ReadUInt8(intVal);
59 val = intVal == 1 ? true : false;
60 return len;
61 }
62
WriteInt(int32_t data)63 int Parcel::WriteInt(int32_t data)
64 {
65 return WriteInteger(data);
66 }
67
ReadInt(int32_t & val)68 uint32_t Parcel::ReadInt(int32_t &val)
69 {
70 return ReadInteger(val);
71 }
72
WriteUInt8(uint8_t data)73 int Parcel::WriteUInt8(uint8_t data)
74 {
75 return WriteInteger(data);
76 }
77
ReadUInt8(uint8_t & val)78 uint32_t Parcel::ReadUInt8(uint8_t &val)
79 {
80 return ReadInteger(val);
81 }
82
WriteDouble(double data)83 int Parcel::WriteDouble(double data)
84 {
85 double inData = HostToNet(data);
86 if (isError_ || parcelLen_ + sizeof(double) > totalLen_) {
87 isError_ = true;
88 return -E_PARSE_FAIL;
89 }
90 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &inData, sizeof(double));
91 if (errCode != EOK) {
92 isError_ = true;
93 return -E_SECUREC_ERROR;
94 }
95 bufPtr_ += sizeof(double);
96 parcelLen_ += sizeof(double);
97 return E_OK;
98 }
99
ReadDouble(double & val)100 uint32_t Parcel::ReadDouble(double &val)
101 {
102 if (isError_ || bufPtr_ == nullptr || parcelLen_ + sizeof(double) > totalLen_) {
103 isError_ = true;
104 return 0;
105 }
106 val = *(reinterpret_cast<double *>(bufPtr_));
107 bufPtr_ += sizeof(double);
108 parcelLen_ += sizeof(double);
109 val = NetToHost(val);
110 return sizeof(double);
111 }
112
WriteInt64(int64_t data)113 int Parcel::WriteInt64(int64_t data)
114 {
115 return WriteInteger(data);
116 }
117
ReadInt64(int64_t & val)118 uint32_t Parcel::ReadInt64(int64_t &val)
119 {
120 return ReadInteger(val);
121 }
122
WriteUInt32(uint32_t data)123 int Parcel::WriteUInt32(uint32_t data)
124 {
125 return WriteInteger(data);
126 }
127
ReadUInt32(uint32_t & val)128 uint32_t Parcel::ReadUInt32(uint32_t &val)
129 {
130 return ReadInteger(val);
131 }
132
WriteUInt64(uint64_t data)133 int Parcel::WriteUInt64(uint64_t data)
134 {
135 return WriteInteger(data);
136 }
137
ReadUInt64(uint64_t & val)138 uint32_t Parcel::ReadUInt64(uint64_t &val)
139 {
140 return ReadInteger(val);
141 }
142
WriteVectorChar(const std::vector<uint8_t> & data)143 int Parcel::WriteVectorChar(const std::vector<uint8_t>& data)
144 {
145 return WriteVector<uint8_t>(data);
146 }
147
ReadVectorChar(std::vector<uint8_t> & val)148 uint32_t Parcel::ReadVectorChar(std::vector<uint8_t>& val)
149 {
150 return ReadVector<uint8_t>(val);
151 }
152
WriteString(const std::string & inVal)153 int Parcel::WriteString(const std::string &inVal)
154 {
155 if (inVal.size() > INT32_MAX) {
156 LOGE("[WriteString] Invalid string, size:%zu.", inVal.size());
157 isError_ = true;
158 return -E_PARSE_FAIL;
159 }
160 if (IsError()) {
161 return -E_PARSE_FAIL;
162 }
163 uint32_t len = inVal.size();
164 uint64_t stepLen = sizeof(uint32_t) + static_cast<uint64_t>(inVal.size());
165 len = HostToNet(len);
166 if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) {
167 LOGE("[WriteString] stepLen:%llu, totalLen:%llu, parcelLen:%llu", stepLen, totalLen_, parcelLen_);
168 isError_ = true;
169 return -E_PARSE_FAIL;
170 }
171 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &len, sizeof(uint32_t));
172 if (errCode != EOK) {
173 LOGE("[WriteString] bufPtr:%d, totalLen:%llu, parcelLen:%llu", bufPtr_ != nullptr, totalLen_, parcelLen_);
174 isError_ = true;
175 return -E_SECUREC_ERROR;
176 }
177 bufPtr_ += sizeof(uint32_t);
178 if (inVal.size() == 0) {
179 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
180 parcelLen_ += BYTE_8_ALIGN(stepLen);
181 return errCode;
182 }
183 errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_ - sizeof(uint32_t), inVal.c_str(), inVal.size());
184 if (errCode != EOK) {
185 LOGE("[WriteString] totalLen:%llu, parcelLen:%llu, inVal.size:%zu.",
186 totalLen_, parcelLen_, inVal.size());
187 isError_ = true;
188 return -E_SECUREC_ERROR;
189 }
190 bufPtr_ += inVal.size();
191 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
192 parcelLen_ += BYTE_8_ALIGN(stepLen);
193 return E_OK;
194 }
195
ReadString(std::string & outVal)196 uint32_t Parcel::ReadString(std::string &outVal)
197 {
198 if (IsError()) {
199 return 0;
200 }
201 if (bufPtr_ == nullptr || parcelLen_ + sizeof(uint32_t) > totalLen_) {
202 LOGE("[ReadString] bufPtr:%d, totalLen:%llu, parcelLen:%llu", bufPtr_ != nullptr, totalLen_, parcelLen_);
203 isError_ = true;
204 return 0;
205 }
206 uint32_t len = *(reinterpret_cast<uint32_t *>(bufPtr_));
207 len = NetToHost(len);
208 uint64_t stepLen = static_cast<uint64_t>(len) + sizeof(uint32_t);
209 if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) {
210 LOGE("[ReadString] stepLen:%llu, totalLen:%llu, parcelLen:%llu", stepLen, totalLen_, parcelLen_);
211 isError_ = true;
212 return 0;
213 }
214 outVal.resize(len);
215 outVal.assign(bufPtr_ + sizeof(uint32_t), bufPtr_ + stepLen);
216 bufPtr_ += BYTE_8_ALIGN(stepLen);
217 parcelLen_ += BYTE_8_ALIGN(stepLen);
218 stepLen = BYTE_8_ALIGN(stepLen);
219 return static_cast<uint32_t>(stepLen);
220 }
221
IsContinueRead()222 bool Parcel::IsContinueRead()
223 {
224 return (parcelLen_ < totalLen_);
225 }
226
227 #ifndef OMIT_MULTI_VER
WriteMultiVerCommit(const MultiVerCommitNode & commit)228 int Parcel::WriteMultiVerCommit(const MultiVerCommitNode &commit)
229 {
230 int errCode = WriteVectorChar(commit.commitId);
231 if (errCode != E_OK) {
232 LOGE("Parcel::WriteMultiVerCommit write commitId err!");
233 isError_ = true;
234 return errCode;
235 }
236 errCode = WriteVectorChar(commit.leftParent);
237 if (errCode != E_OK) {
238 LOGE("Parcel::WriteMultiVerCommit write leftParent err!");
239 return errCode;
240 }
241 errCode = WriteVectorChar(commit.rightParent);
242 if (errCode != E_OK) {
243 LOGE("Parcel::WriteMultiVerCommit write rightParent err!");
244 return errCode;
245 }
246 errCode = WriteUInt64(commit.timestamp);
247 if (errCode != E_OK) {
248 LOGE("Parcel::WriteMultiVerCommit write timestamp err!");
249 return errCode;
250 }
251 errCode = WriteUInt64(commit.version);
252 if (errCode != E_OK) {
253 LOGE("Parcel::WriteMultiVerCommit write version err!");
254 return errCode;
255 }
256 errCode = WriteUInt64(commit.isLocal);
257 if (errCode != E_OK) {
258 LOGE("Parcel::WriteMultiVerCommit write isLocal err!");
259 return errCode;
260 }
261 errCode = WriteString(commit.deviceInfo);
262 if (errCode != E_OK) {
263 LOGE("Parcel::WriteMultiVerCommit write deviceInfo err!");
264 }
265 return errCode;
266 }
267
ReadMultiVerCommit(MultiVerCommitNode & commit)268 uint32_t Parcel::ReadMultiVerCommit(MultiVerCommitNode &commit)
269 {
270 if (isError_) {
271 return 0;
272 }
273 uint64_t len = ReadVectorChar(commit.commitId);
274 len += ReadVectorChar(commit.leftParent);
275 len += ReadVectorChar(commit.rightParent);
276 len += ReadUInt64(commit.timestamp);
277 len += ReadUInt64(commit.version);
278 len += ReadUInt64(commit.isLocal);
279 len += ReadString(commit.deviceInfo);
280 if (isError_ || len > INT32_MAX) {
281 isError_ = true;
282 return 0;
283 }
284 return static_cast<uint32_t>(len);
285 }
WriteMultiVerCommits(const std::vector<MultiVerCommitNode> & commits)286 int Parcel::WriteMultiVerCommits(const std::vector<MultiVerCommitNode> &commits)
287 {
288 uint64_t len = commits.size();
289 int errCode = WriteUInt64(len);
290 if (errCode != E_OK) {
291 LOGE("Parcel::WriteMultiVerCommit write len err!");
292 isError_ = true;
293 return errCode;
294 }
295 for (auto &iter : commits) {
296 errCode = WriteVectorChar(iter.commitId);
297 if (errCode != E_OK) {
298 LOGE("Parcel::WriteMultiVerCommit write commitId err!");
299 return errCode;
300 }
301 errCode = WriteVectorChar(iter.leftParent);
302 if (errCode != E_OK) {
303 LOGE("Parcel::WriteMultiVerCommit write leftParent err!");
304 return errCode;
305 }
306 errCode = WriteVectorChar(iter.rightParent);
307 if (errCode != E_OK) {
308 LOGE("Parcel::WriteMultiVerCommit write rightParent err!");
309 return errCode;
310 }
311 errCode = WriteUInt64(iter.timestamp);
312 if (errCode != E_OK) {
313 LOGE("Parcel::WriteMultiVerCommit write timestamp err!");
314 return errCode;
315 }
316 errCode = WriteUInt64(iter.version);
317 if (errCode != E_OK) {
318 LOGE("Parcel::WriteMultiVerCommit write version err!");
319 return errCode;
320 }
321 errCode = WriteUInt64(iter.isLocal);
322 if (errCode != E_OK) {
323 LOGE("Parcel::WriteMultiVerCommit write isLocal err!");
324 return errCode;
325 }
326 errCode = WriteString(iter.deviceInfo);
327 if (errCode != E_OK) {
328 LOGE("Parcel::WriteMultiVerCommit write deviceInfo err!");
329 return errCode;
330 }
331 EightByteAlign();
332 }
333 EightByteAlign();
334 return errCode;
335 }
336
ReadMultiVerCommits(std::vector<MultiVerCommitNode> & commits)337 uint32_t Parcel::ReadMultiVerCommits(std::vector<MultiVerCommitNode> &commits)
338 {
339 uint64_t len = 0;
340 uint64_t size = 0;
341 len += ReadUInt64(size);
342 if (isError_) {
343 return 0;
344 }
345 if (size > DBConstant::MAX_COMMIT_SIZE) {
346 isError_ = true;
347 LOGE("Parcel::ReadMultiVerCommits commits size too large: %llu", size);
348 return 0;
349 }
350 for (uint64_t i = 0; i < size; i++) {
351 MultiVerCommitNode commit;
352 len += ReadVectorChar(commit.commitId);
353 len += ReadVectorChar(commit.leftParent);
354 len += ReadVectorChar(commit.rightParent);
355 len += ReadUInt64(commit.timestamp);
356 len += ReadUInt64(commit.version);
357 len += ReadUInt64(commit.isLocal);
358 len += ReadString(commit.deviceInfo);
359 commits.push_back(commit);
360 EightByteAlign();
361 len = BYTE_8_ALIGN(len);
362 if (isError_ || len > INT32_MAX) {
363 isError_ = true;
364 return 0;
365 }
366 }
367 len = BYTE_8_ALIGN(len);
368
369 return static_cast<uint32_t>(len);
370 }
371 #endif
372
WriteBlob(const char * buffer,uint32_t bufLen)373 int Parcel::WriteBlob(const char *buffer, uint32_t bufLen)
374 {
375 if (buffer == nullptr) {
376 LOGE("[WriteBlob] Invalid buffer.");
377 isError_ = true;
378 return -E_INVALID_ARGS;
379 }
380 if (IsError()) {
381 return -E_PARSE_FAIL;
382 }
383 if (parcelLen_ + bufLen > totalLen_) {
384 LOGE("[WriteBlob] bufLen:%u, totalLen:%llu, parcelLen:%llu", bufLen, totalLen_, parcelLen_);
385 isError_ = true;
386 return -E_PARSE_FAIL;
387 }
388 uint32_t leftLen = static_cast<uint32_t>(totalLen_ - parcelLen_);
389 int errCode = memcpy_s(bufPtr_, leftLen, buffer, bufLen);
390 if (errCode != EOK) {
391 LOGE("[WriteBlob] leftLen:%u, bufLen:%u", leftLen, bufLen);
392 isError_ = true;
393 return -E_SECUREC_ERROR;
394 }
395 uint32_t length = (BYTE_8_ALIGN(bufLen) < leftLen) ? BYTE_8_ALIGN(bufLen) : leftLen;
396 bufPtr_ += length;
397 parcelLen_ += length;
398 return E_OK;
399 }
ReadBlob(char * buffer,uint32_t bufLen)400 uint32_t Parcel::ReadBlob(char *buffer, uint32_t bufLen)
401 {
402 if (buffer == nullptr) {
403 LOGE("[ReadBlob] Invalid buffer.");
404 isError_ = true;
405 return 0;
406 }
407 if (IsError()) {
408 return 0;
409 }
410 uint32_t leftLen = static_cast<uint32_t>(totalLen_ - parcelLen_);
411 if (parcelLen_ + bufLen > totalLen_) {
412 LOGE("[ReadBlob] bufLen:%u, totalLen:%llu, parcelLen:%llu", bufLen, totalLen_, parcelLen_);
413 isError_ = true;
414 return 0;
415 }
416 int errCode = memcpy_s(buffer, bufLen, bufPtr_, bufLen);
417 if (errCode != EOK) {
418 LOGE("[ReadBlob] bufLen:%u", bufLen);
419 isError_ = true;
420 return 0;
421 }
422 uint32_t length = (BYTE_8_ALIGN(bufLen) < leftLen) ? BYTE_8_ALIGN(bufLen) : leftLen;
423 bufPtr_ += length;
424 parcelLen_ += length;
425 return length;
426 }
427
GetBoolLen()428 uint32_t Parcel::GetBoolLen()
429 {
430 return GetUInt8Len();
431 }
432
GetUInt8Len()433 uint32_t Parcel::GetUInt8Len()
434 {
435 return sizeof(uint8_t);
436 }
437
GetIntLen()438 uint32_t Parcel::GetIntLen()
439 {
440 return sizeof(int32_t);
441 }
442
GetUInt32Len()443 uint32_t Parcel::GetUInt32Len()
444 {
445 return sizeof(uint32_t);
446 }
447
GetUInt64Len()448 uint32_t Parcel::GetUInt64Len()
449 {
450 return sizeof(uint64_t);
451 }
452
GetInt64Len()453 uint32_t Parcel::GetInt64Len()
454 {
455 return sizeof(int64_t);
456 }
457
GetDoubleLen()458 uint32_t Parcel::GetDoubleLen()
459 {
460 return sizeof(double);
461 }
462
GetVectorCharLen(const std::vector<uint8_t> & data)463 uint32_t Parcel::GetVectorCharLen(const std::vector<uint8_t> &data)
464 {
465 return GetVectorLen<uint8_t>(data);
466 }
467
GetStringLen(const std::string & data)468 uint32_t Parcel::GetStringLen(const std::string &data)
469 {
470 if (data.size() > INT32_MAX) {
471 return 0;
472 }
473 uint64_t len = sizeof(uint32_t) + static_cast<uint64_t>(data.size());
474 len = BYTE_8_ALIGN(len);
475 if (len > INT32_MAX) {
476 return 0;
477 }
478 return static_cast<uint32_t>(len);
479 }
480
481 #ifndef OMIT_MULTI_VER
GetMultiVerCommitLen(const MultiVerCommitNode & commit)482 uint32_t Parcel::GetMultiVerCommitLen(const MultiVerCommitNode &commit)
483 {
484 uint64_t len = GetVectorCharLen(commit.commitId);
485 len += GetVectorCharLen(commit.leftParent);
486 len += GetVectorCharLen(commit.rightParent);
487 len += GetUInt64Len();
488 len += GetUInt64Len();
489 len += GetUInt64Len();
490 len += GetStringLen(commit.deviceInfo);
491 if (len > INT32_MAX) {
492 return 0;
493 }
494 return static_cast<uint32_t>(len);
495 }
496
GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> & commits)497 uint32_t Parcel::GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> &commits)
498 {
499 uint64_t len = GetUInt64Len();
500 for (auto &iter : commits) {
501 len += GetVectorCharLen(iter.commitId);
502 len += GetVectorCharLen(iter.leftParent);
503 len += GetVectorCharLen(iter.rightParent);
504 len += GetUInt64Len();
505 len += GetUInt64Len();
506 len += GetUInt64Len();
507 len += GetStringLen(iter.deviceInfo);
508 len = BYTE_8_ALIGN(len);
509 if (len > INT32_MAX) {
510 return 0;
511 }
512 }
513 len = BYTE_8_ALIGN(len);
514 if (len > INT32_MAX) {
515 return 0;
516 }
517 return static_cast<uint32_t>(len);
518 }
519 #endif
520
EightByteAlign()521 void Parcel::EightByteAlign()
522 {
523 bufPtr_ += BYTE_8_ALIGN(parcelLen_) - parcelLen_;
524 parcelLen_ = BYTE_8_ALIGN(parcelLen_);
525 }
526
GetEightByteAlign(uint32_t len)527 uint32_t Parcel::GetEightByteAlign(uint32_t len)
528 {
529 return BYTE_8_ALIGN(len);
530 }
531
GetAppendedLen()532 uint32_t Parcel::GetAppendedLen()
533 {
534 // 8 is 8-byte-align max append len, there are 2 8-byte-align totally
535 return sizeof(uint32_t) + sizeof(uint32_t) + 8 * 2;
536 }
537 } // namespace DistributedDB
538