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 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &len, sizeof(uint32_t));
172 if (errCode != EOK) {
173 LOGE("[WriteString] bufPtr:%d, totalLen:%" PRIu64 ", parcelLen:%" PRIu64, bufPtr_ != nullptr, totalLen_,
174 parcelLen_);
175 isError_ = true;
176 return -E_SECUREC_ERROR;
177 }
178 bufPtr_ += sizeof(uint32_t);
179 if (inVal.size() == 0) {
180 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
181 parcelLen_ += BYTE_8_ALIGN(stepLen);
182 return errCode;
183 }
184 errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_ - sizeof(uint32_t), inVal.c_str(), inVal.size());
185 if (errCode != EOK) {
186 LOGE("[WriteString] totalLen:%" PRIu64 ", parcelLen:%" PRIu64 ", inVal.size:%zu.",
187 totalLen_, parcelLen_, inVal.size());
188 isError_ = true;
189 return -E_SECUREC_ERROR;
190 }
191 bufPtr_ += inVal.size();
192 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
193 parcelLen_ += BYTE_8_ALIGN(stepLen);
194 return E_OK;
195 }
196
ReadString(std::string & outVal)197 uint32_t Parcel::ReadString(std::string &outVal)
198 {
199 if (IsError()) {
200 return 0;
201 }
202 if (bufPtr_ == nullptr || parcelLen_ + sizeof(uint32_t) > totalLen_) {
203 LOGE("[ReadString] bufPtr:%d, totalLen:%" PRIu64 ", parcelLen:%" PRIu64, bufPtr_ != nullptr, totalLen_,
204 parcelLen_);
205 isError_ = true;
206 return 0;
207 }
208 uint32_t len = *(reinterpret_cast<uint32_t *>(bufPtr_));
209 len = NetToHost(len);
210 uint64_t stepLen = static_cast<uint64_t>(len) + sizeof(uint32_t);
211 if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) {
212 LOGE("[ReadString] stepLen:%" PRIu64 ", totalLen:%" PRIu64 ", parcelLen:%" PRIu64, stepLen, totalLen_,
213 parcelLen_);
214 isError_ = true;
215 return 0;
216 }
217 outVal.resize(len);
218 outVal.assign(bufPtr_ + sizeof(uint32_t), bufPtr_ + stepLen);
219 bufPtr_ += BYTE_8_ALIGN(stepLen);
220 parcelLen_ += BYTE_8_ALIGN(stepLen);
221 stepLen = BYTE_8_ALIGN(stepLen);
222 return static_cast<uint32_t>(stepLen);
223 }
224
IsContinueRead()225 bool Parcel::IsContinueRead()
226 {
227 return (parcelLen_ < totalLen_);
228 }
229
230 #ifndef OMIT_MULTI_VER
WriteMultiVerCommit(const MultiVerCommitNode & commit)231 int Parcel::WriteMultiVerCommit(const MultiVerCommitNode &commit)
232 {
233 int errCode = WriteVectorChar(commit.commitId);
234 if (errCode != E_OK) {
235 LOGE("Parcel::WriteMultiVerCommit write commitId err!");
236 isError_ = true;
237 return errCode;
238 }
239 errCode = WriteVectorChar(commit.leftParent);
240 if (errCode != E_OK) {
241 LOGE("Parcel::WriteMultiVerCommit write leftParent err!");
242 return errCode;
243 }
244 errCode = WriteVectorChar(commit.rightParent);
245 if (errCode != E_OK) {
246 LOGE("Parcel::WriteMultiVerCommit write rightParent err!");
247 return errCode;
248 }
249 errCode = WriteUInt64(commit.timestamp);
250 if (errCode != E_OK) {
251 LOGE("Parcel::WriteMultiVerCommit write timestamp err!");
252 return errCode;
253 }
254 errCode = WriteUInt64(commit.version);
255 if (errCode != E_OK) {
256 LOGE("Parcel::WriteMultiVerCommit write version err!");
257 return errCode;
258 }
259 errCode = WriteUInt64(commit.isLocal);
260 if (errCode != E_OK) {
261 LOGE("Parcel::WriteMultiVerCommit write isLocal err!");
262 return errCode;
263 }
264 errCode = WriteString(commit.deviceInfo);
265 if (errCode != E_OK) {
266 LOGE("Parcel::WriteMultiVerCommit write deviceInfo err!");
267 }
268 return errCode;
269 }
270
ReadMultiVerCommit(MultiVerCommitNode & commit)271 uint32_t Parcel::ReadMultiVerCommit(MultiVerCommitNode &commit)
272 {
273 if (isError_) {
274 return 0;
275 }
276 uint64_t len = ReadVectorChar(commit.commitId);
277 len += ReadVectorChar(commit.leftParent);
278 len += ReadVectorChar(commit.rightParent);
279 len += ReadUInt64(commit.timestamp);
280 len += ReadUInt64(commit.version);
281 len += ReadUInt64(commit.isLocal);
282 len += ReadString(commit.deviceInfo);
283 if (isError_ || len > INT32_MAX) {
284 isError_ = true;
285 return 0;
286 }
287 return static_cast<uint32_t>(len);
288 }
WriteMultiVerCommits(const std::vector<MultiVerCommitNode> & commits)289 int Parcel::WriteMultiVerCommits(const std::vector<MultiVerCommitNode> &commits)
290 {
291 uint64_t len = commits.size();
292 int errCode = WriteUInt64(len);
293 if (errCode != E_OK) {
294 LOGE("Parcel::WriteMultiVerCommit write len err!");
295 isError_ = true;
296 return errCode;
297 }
298 for (auto &iter : commits) {
299 errCode = WriteVectorChar(iter.commitId);
300 if (errCode != E_OK) {
301 LOGE("Parcel::WriteMultiVerCommit write commitId err!");
302 return errCode;
303 }
304 errCode = WriteVectorChar(iter.leftParent);
305 if (errCode != E_OK) {
306 LOGE("Parcel::WriteMultiVerCommit write leftParent err!");
307 return errCode;
308 }
309 errCode = WriteVectorChar(iter.rightParent);
310 if (errCode != E_OK) {
311 LOGE("Parcel::WriteMultiVerCommit write rightParent err!");
312 return errCode;
313 }
314 errCode = WriteUInt64(iter.timestamp);
315 if (errCode != E_OK) {
316 LOGE("Parcel::WriteMultiVerCommit write timestamp err!");
317 return errCode;
318 }
319 errCode = WriteUInt64(iter.version);
320 if (errCode != E_OK) {
321 LOGE("Parcel::WriteMultiVerCommit write version err!");
322 return errCode;
323 }
324 errCode = WriteUInt64(iter.isLocal);
325 if (errCode != E_OK) {
326 LOGE("Parcel::WriteMultiVerCommit write isLocal err!");
327 return errCode;
328 }
329 errCode = WriteString(iter.deviceInfo);
330 if (errCode != E_OK) {
331 LOGE("Parcel::WriteMultiVerCommit write deviceInfo err!");
332 return errCode;
333 }
334 EightByteAlign();
335 }
336 EightByteAlign();
337 return errCode;
338 }
339
ReadMultiVerCommits(std::vector<MultiVerCommitNode> & commits)340 uint32_t Parcel::ReadMultiVerCommits(std::vector<MultiVerCommitNode> &commits)
341 {
342 uint64_t len = 0;
343 uint64_t size = 0;
344 len += ReadUInt64(size);
345 if (isError_) {
346 return 0;
347 }
348 if (size > DBConstant::MAX_COMMIT_SIZE) {
349 isError_ = true;
350 LOGE("Parcel::ReadMultiVerCommits commits size too large: %" PRIu64, size);
351 return 0;
352 }
353 for (uint64_t i = 0; i < size; i++) {
354 MultiVerCommitNode commit;
355 len += ReadVectorChar(commit.commitId);
356 len += ReadVectorChar(commit.leftParent);
357 len += ReadVectorChar(commit.rightParent);
358 len += ReadUInt64(commit.timestamp);
359 len += ReadUInt64(commit.version);
360 len += ReadUInt64(commit.isLocal);
361 len += ReadString(commit.deviceInfo);
362 commits.push_back(commit);
363 EightByteAlign();
364 len = BYTE_8_ALIGN(len);
365 if (isError_ || len > INT32_MAX) {
366 isError_ = true;
367 return 0;
368 }
369 }
370 len = BYTE_8_ALIGN(len);
371
372 return static_cast<uint32_t>(len);
373 }
374 #endif
375
WriteBlob(const char * buffer,uint32_t bufLen)376 int Parcel::WriteBlob(const char *buffer, uint32_t bufLen)
377 {
378 if (buffer == nullptr) {
379 LOGE("[WriteBlob] Invalid buffer.");
380 isError_ = true;
381 return -E_INVALID_ARGS;
382 }
383 if (IsError()) {
384 return -E_PARSE_FAIL;
385 }
386 if (parcelLen_ + bufLen > totalLen_) {
387 LOGE("[WriteBlob] bufLen:%" PRIu32 ", totalLen:%" PRIu64 ", parcelLen:%" PRIu64, bufLen, totalLen_, parcelLen_);
388 isError_ = true;
389 return -E_PARSE_FAIL;
390 }
391 uint32_t leftLen = static_cast<uint32_t>(totalLen_ - parcelLen_);
392 int errCode = memcpy_s(bufPtr_, leftLen, buffer, bufLen);
393 if (errCode != EOK) {
394 LOGE("[WriteBlob] leftLen:%" PRIu32 ", bufLen:%" PRIu32, leftLen, bufLen);
395 isError_ = true;
396 return -E_SECUREC_ERROR;
397 }
398 uint32_t length = (BYTE_8_ALIGN(bufLen) < leftLen) ? BYTE_8_ALIGN(bufLen) : leftLen;
399 bufPtr_ += length;
400 parcelLen_ += length;
401 return E_OK;
402 }
ReadBlob(char * buffer,uint32_t bufLen)403 uint32_t Parcel::ReadBlob(char *buffer, uint32_t bufLen)
404 {
405 if (buffer == nullptr) {
406 LOGE("[ReadBlob] Invalid buffer.");
407 isError_ = true;
408 return 0;
409 }
410 if (IsError()) {
411 return 0;
412 }
413 uint32_t leftLen = static_cast<uint32_t>(totalLen_ - parcelLen_);
414 if (parcelLen_ + bufLen > totalLen_) {
415 LOGE("[ReadBlob] bufLen:%" PRIu32 ", totalLen:%" PRIu64 ", parcelLen:%" PRIu64, bufLen, totalLen_, parcelLen_);
416 isError_ = true;
417 return 0;
418 }
419 int errCode = memcpy_s(buffer, bufLen, bufPtr_, bufLen);
420 if (errCode != EOK) {
421 LOGE("[ReadBlob] bufLen:%u", bufLen);
422 isError_ = true;
423 return 0;
424 }
425 uint32_t length = (BYTE_8_ALIGN(bufLen) < leftLen) ? BYTE_8_ALIGN(bufLen) : leftLen;
426 bufPtr_ += length;
427 parcelLen_ += length;
428 return length;
429 }
430
GetBoolLen()431 uint32_t Parcel::GetBoolLen()
432 {
433 return GetUInt8Len();
434 }
435
GetUInt8Len()436 uint32_t Parcel::GetUInt8Len()
437 {
438 return sizeof(uint8_t);
439 }
440
GetIntLen()441 uint32_t Parcel::GetIntLen()
442 {
443 return sizeof(int32_t);
444 }
445
GetUInt32Len()446 uint32_t Parcel::GetUInt32Len()
447 {
448 return sizeof(uint32_t);
449 }
450
GetUInt64Len()451 uint32_t Parcel::GetUInt64Len()
452 {
453 return sizeof(uint64_t);
454 }
455
GetInt64Len()456 uint32_t Parcel::GetInt64Len()
457 {
458 return sizeof(int64_t);
459 }
460
GetDoubleLen()461 uint32_t Parcel::GetDoubleLen()
462 {
463 return sizeof(double);
464 }
465
GetVectorCharLen(const std::vector<uint8_t> & data)466 uint32_t Parcel::GetVectorCharLen(const std::vector<uint8_t> &data)
467 {
468 return GetVectorLen<uint8_t>(data);
469 }
470
GetStringLen(const std::string & data)471 uint32_t Parcel::GetStringLen(const std::string &data)
472 {
473 if (data.size() > INT32_MAX) {
474 return 0;
475 }
476 uint64_t len = sizeof(uint32_t) + static_cast<uint64_t>(data.size());
477 len = BYTE_8_ALIGN(len);
478 if (len > INT32_MAX) {
479 return 0;
480 }
481 return static_cast<uint32_t>(len);
482 }
483
484 #ifndef OMIT_MULTI_VER
GetMultiVerCommitLen(const MultiVerCommitNode & commit)485 uint32_t Parcel::GetMultiVerCommitLen(const MultiVerCommitNode &commit)
486 {
487 uint64_t len = GetVectorCharLen(commit.commitId);
488 len += GetVectorCharLen(commit.leftParent);
489 len += GetVectorCharLen(commit.rightParent);
490 len += GetUInt64Len();
491 len += GetUInt64Len();
492 len += GetUInt64Len();
493 len += GetStringLen(commit.deviceInfo);
494 if (len > INT32_MAX) {
495 return 0;
496 }
497 return static_cast<uint32_t>(len);
498 }
499
GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> & commits)500 uint32_t Parcel::GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> &commits)
501 {
502 uint64_t len = GetUInt64Len();
503 for (auto &iter : commits) {
504 len += GetVectorCharLen(iter.commitId);
505 len += GetVectorCharLen(iter.leftParent);
506 len += GetVectorCharLen(iter.rightParent);
507 len += GetUInt64Len();
508 len += GetUInt64Len();
509 len += GetUInt64Len();
510 len += GetStringLen(iter.deviceInfo);
511 len = BYTE_8_ALIGN(len);
512 if (len > INT32_MAX) {
513 return 0;
514 }
515 }
516 len = BYTE_8_ALIGN(len);
517 if (len > INT32_MAX) {
518 return 0;
519 }
520 return static_cast<uint32_t>(len);
521 }
522 #endif
523
EightByteAlign()524 void Parcel::EightByteAlign()
525 {
526 if (IsError()) {
527 LOGE("EightByteAlign already error");
528 return;
529 }
530 if (BYTE_8_ALIGN(parcelLen_) > totalLen_) {
531 LOGE("byte 8 align failed");
532 isError_ = true;
533 return;
534 }
535 bufPtr_ += BYTE_8_ALIGN(parcelLen_) - parcelLen_;
536 parcelLen_ = BYTE_8_ALIGN(parcelLen_);
537 }
538
GetEightByteAlign(uint32_t len)539 uint32_t Parcel::GetEightByteAlign(uint32_t len)
540 {
541 return BYTE_8_ALIGN(len);
542 }
543
GetAppendedLen()544 uint32_t Parcel::GetAppendedLen()
545 {
546 // 8 is 8-byte-align max append len, there are 2 8-byte-align totally
547 return sizeof(uint32_t) + sizeof(uint32_t) + 8 * 2;
548 }
549 } // namespace DistributedDB
550