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