• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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