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