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