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