• 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 "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