• 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 "hc_tlv_parser.h"
17  #include <stddef.h>
18  
19  #define MAX_TLV_LENGTH (48 * 1024)
20  
ParseTlvHead(TlvBase * tlv,HcParcel * parcel)21  HcBool ParseTlvHead(TlvBase *tlv, HcParcel *parcel)
22  {
23  #ifdef IS_BIG_ENDIAN
24      if (!ParcelReadUint16Revert(parcel, &tlv->tag)) {
25          return HC_FALSE;
26      }
27  #else
28      if (!ParcelReadUint16(parcel, &tlv->tag)) {
29          return HC_FALSE;
30      }
31  #endif
32  
33      if (tlv->tag != tlv->checkTag) {
34          return HC_FALSE;
35      }
36  #ifdef IS_BIG_ENDIAN
37      if (!ParcelReadUint16Revert(parcel, &tlv->length)) {
38          return HC_FALSE;
39      }
40  #else
41      if (!ParcelReadUint16(parcel, &tlv->length)) {
42          return HC_FALSE;
43      }
44  #endif
45      if (tlv->length > MAX_TLV_LENGTH) {
46          return HC_FALSE;
47      }
48      return HC_TRUE;
49  }
50  
ParseTlvNode(TlvBase * tlv,HcParcel * parcel,HcBool strict)51  int32_t ParseTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool strict)
52  {
53      if (!ParseTlvHead(tlv, parcel)) {
54          return TLV_FAIL;
55      } else {
56          if (GetParcelDataSize(parcel) < tlv->length) {
57              return TLV_FAIL;
58          }
59  
60          int ret = tlv->parse(tlv, parcel, strict);
61          if (ret < 0 || ret > MAX_TLV_LENGTH) {
62              return TLV_FAIL;
63          } else {
64              return ret + sizeof(tlv->tag) + sizeof(tlv->length);
65          }
66      }
67  }
68  
GetlenTlvNode(TlvBase * tlv)69  int32_t GetlenTlvNode(TlvBase *tlv)
70  {
71      int32_t bodyLen = tlv->getlen(tlv);
72      if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) {
73          return TLV_FAIL;
74      } else {
75          tlv->length = bodyLen + sizeof(tlv->tag) + sizeof(tlv->length);
76          return tlv->length;
77      }
78  }
79  
DeinitTlvNode(TlvBase * tlv)80  void DeinitTlvNode(TlvBase *tlv)
81  {
82      if (tlv != NULL) {
83          tlv->deinit(tlv);
84      }
85  }
86  
EncodeTlvNode(TlvBase * tlv,HcParcel * parcel,HcBool isRoot)87  int32_t EncodeTlvNode(TlvBase *tlv, HcParcel *parcel, HcBool isRoot)
88  {
89      int32_t bodyLen = tlv->getlen(tlv);
90      if (bodyLen < 0 || bodyLen > MAX_TLV_LENGTH) {
91          return TLV_FAIL;
92      } else if (bodyLen == 0) {
93          if (isRoot) {
94              ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t), 0);
95          }
96  #ifdef IS_BIG_ENDIAN
97          ParcelWriteUint16Revert(parcel, tlv->checkTag);
98          ParcelWriteUint16Revert(parcel, bodyLen);
99  #else
100          ParcelWriteUint16(parcel, tlv->checkTag);
101          ParcelWriteUint16(parcel, bodyLen);
102  #endif
103          return sizeof(tlv->tag) + sizeof(tlv->length);
104      } else { // has value
105          if (isRoot) {
106              ResetParcel(parcel, sizeof(uint16_t) + sizeof(uint16_t) + bodyLen, 0);
107          }
108          int32_t encodeLen;
109          tlv->length = (uint16_t)bodyLen;
110  #ifdef IS_BIG_ENDIAN
111          ParcelWriteUint16Revert(parcel, tlv->checkTag);
112          ParcelWriteUint16Revert(parcel, tlv->length);
113  #else
114          ParcelWriteUint16(parcel, tlv->checkTag);
115          ParcelWriteUint16(parcel, tlv->length);
116  #endif
117          encodeLen = tlv->encode(tlv, parcel);
118          if (encodeLen < 0 || encodeLen > MAX_TLV_LENGTH) {
119              return TLV_FAIL;
120          } else {
121              return encodeLen + sizeof(tlv->tag) + sizeof(tlv->length);
122          }
123      }
124  }
125  
GetEmptyStructNode(TlvBase * tlv,unsigned short tag)126  TlvBase* GetEmptyStructNode(TlvBase *tlv, unsigned short tag)
127  {
128      if (tlv == NULL) {
129          return NULL;
130      }
131  
132      unsigned int index;
133      unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
134      unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
135      for (index = 0; index < memberCount; ++index) {
136          TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
137          if (tlvChild->checkTag == tag && tlvChild->hasValue == 0) {
138              return tlvChild;
139          }
140      }
141  
142      return NULL;
143  }
144  
CheckStructNodeAllHasValue(TlvBase * tlv)145  int32_t CheckStructNodeAllHasValue(TlvBase *tlv)
146  {
147      if (tlv == NULL) {
148          return 0;
149      } else {
150          unsigned int index;
151          unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
152          unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
153          for (index = 0; index < memberCount; ++index) {
154              TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
155              if (tlvChild->hasValue == 0) {
156                  return -1;
157              }
158          }
159      }
160  
161      return 0;
162  }
163  
SetStructNodeHasValue(TlvBase * tlv)164  void SetStructNodeHasValue(TlvBase *tlv)
165  {
166      if (tlv != NULL) {
167          tlv->hasValue = 1;
168      }
169  }
170  
ParseAndSkipTlvUnknownNode(HcParcel * parcel)171  int32_t ParseAndSkipTlvUnknownNode(HcParcel *parcel)
172  {
173      // read tag
174      uint16_t tag = 0;
175      if (!ParcelReadUint16(parcel, &tag)) {
176          return TLV_FAIL;
177      }
178  
179      // read length
180      uint16_t length = 0;
181      if (!ParcelReadUint16(parcel, &length)) {
182          return TLV_FAIL;
183      }
184  
185      // pop data
186      if (!ParcelPopFront(parcel, length)) {
187          return TLV_FAIL;
188      }
189  
190      return sizeof(tag) + sizeof(length) + length;
191  }
192  
ParseTlvStruct(TlvBase * tlv,HcParcel * parcel,HcBool strict)193  int32_t ParseTlvStruct(TlvBase *tlv, HcParcel *parcel, HcBool strict)
194  {
195      uint32_t childTotalLength = 0;
196      do {
197          uint16_t tag = 0;
198          if (!ParcelReadWithoutPopData(parcel, &tag, sizeof(tag))) {
199              return TLV_FAIL;
200          }
201          TlvBase *tlvChild = GetEmptyStructNode(tlv, tag);
202          if (tlvChild == NULL) {
203              if (strict) {
204                  return TLV_FAIL;
205              }
206  
207              int32_t unknownChildLength = ParseAndSkipTlvUnknownNode(parcel);
208              if (unknownChildLength < 0 || unknownChildLength > MAX_TLV_LENGTH) {
209                  return TLV_FAIL;
210              }
211              childTotalLength += unknownChildLength;
212              if (childTotalLength > MAX_TLV_LENGTH) {
213                  return TLV_FAIL;
214              }
215          } else {
216              int32_t childLength = ParseTlvNode(tlvChild, parcel, strict);
217              if (childLength < 0 || childLength > MAX_TLV_LENGTH) {
218                  return TLV_FAIL;
219              }
220              SetStructNodeHasValue(tlvChild);
221              childTotalLength += childLength;
222              if (childTotalLength > MAX_TLV_LENGTH) {
223                  return TLV_FAIL;
224              }
225          }
226      } while (childTotalLength < tlv->length);
227  
228      if (childTotalLength > tlv->length) {
229          return TLV_FAIL;
230      }
231  
232      if (strict && CheckStructNodeAllHasValue(tlv) != 0) {
233          return TLV_FAIL;
234      }
235  
236      return childTotalLength;
237  }
238  
EncodeTlvStruct(TlvBase * tlv,HcParcel * parcel)239  int32_t EncodeTlvStruct(TlvBase *tlv, HcParcel *parcel)
240  {
241      unsigned int index;
242      unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
243      unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
244  
245      uint32_t totalLen = 0;
246      for (index = 0; index < memberCount; ++index) {
247          TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
248          int32_t childLen = EncodeTlvNode(tlvChild, parcel, HC_FALSE);
249          if (childLen < 0 || childLen > MAX_TLV_LENGTH) {
250              return TLV_FAIL;
251          } else {
252              totalLen += childLen;
253          }
254          if (totalLen > MAX_TLV_LENGTH) {
255              return TLV_FAIL;
256          }
257      }
258  
259      return totalLen;
260  }
261  
GetLenTlvStruct(TlvBase * tlv)262  int32_t GetLenTlvStruct(TlvBase *tlv)
263  {
264      unsigned int index;
265      unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
266      unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
267      uint32_t childTotalLength = 0;
268  
269      for (index = 0; index < memberCount; ++index) {
270          TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
271          int32_t childLength = GetlenTlvNode(tlvChild);
272          if (childLength <= 0 || childLength > MAX_TLV_LENGTH) {
273              return TLV_FAIL;
274          } else {
275              childTotalLength += childLength;
276          }
277          if (childTotalLength > MAX_TLV_LENGTH) {
278              return TLV_FAIL;
279          }
280      }
281  
282      return childTotalLength;
283  }
284  
DeinitTlvStruct(TlvBase * tlv)285  void DeinitTlvStruct(TlvBase *tlv)
286  {
287      unsigned int index;
288      unsigned int memberCount = *(unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offsetCount));
289      unsigned int *offset = (unsigned int *)((char *)tlv + offsetof(TlvOffsetExample, offset));
290  
291      for (index = 0; index < memberCount; ++index) {
292          TlvBase *tlvChild = (TlvBase *)(((char *)tlv) + offset[index]);
293          DeinitTlvNode(tlvChild);
294      }
295  }
296  
DecodeTlvMessage(TlvBase * msg,HcParcel * parcel,HcBool strict)297  HcBool DecodeTlvMessage(TlvBase *msg, HcParcel *parcel, HcBool strict)
298  {
299      if (msg == NULL || parcel == NULL) {
300          return HC_FALSE;
301      } else {
302          int32_t msgLen = ParseTlvNode(msg, parcel, strict);
303          if (msgLen > MAX_TLV_LENGTH) {
304              return HC_FALSE;
305          }
306          if ((int32_t)(msg->length + sizeof(msg->length) + sizeof(msg->tag)) != msgLen) {
307              return HC_FALSE;
308          }
309  
310          if (GetParcelDataSize(parcel) != 0) {
311              return HC_FALSE;
312          }
313      }
314  
315      return HC_TRUE;
316  }
317  
318  
EncodeTlvMessage(TlvBase * msg,HcParcel * parcel)319  HcBool EncodeTlvMessage(TlvBase *msg, HcParcel *parcel)
320  {
321      if (msg == NULL || parcel == NULL) {
322          return HC_FALSE;
323      } else {
324          if (EncodeTlvNode(msg, parcel, HC_TRUE) < 0) {
325              return HC_FALSE;
326          }
327      }
328  
329      return HC_TRUE;
330  }
331  
ParseTlvBuffer(TlvBase * tlv,HcParcel * parcel,HcBool strict)332  int32_t ParseTlvBuffer(TlvBase *tlv, HcParcel *parcel, HcBool strict)
333  {
334      (void)strict;
335      TlvBuffer *realTlv = (TlvBuffer *)(tlv);
336      if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data, tlv->length, HC_FALSE)) {
337          return tlv->length;
338      } else {
339          return TLV_FAIL;
340      }
341  }
342  
GetlenTlvBuffer(TlvBase * tlv)343  int32_t GetlenTlvBuffer(TlvBase *tlv)
344  {
345      TlvBuffer *realTlv = (TlvBuffer *)(tlv);
346      return (int32_t)GetParcelDataSize(&realTlv->data);
347  }
348  
EncodeTlvBuffer(TlvBase * tlv,HcParcel * parcel)349  int32_t EncodeTlvBuffer(TlvBase *tlv, HcParcel *parcel)
350  {
351      TlvBuffer *realTlv = (TlvBuffer *)(tlv);
352      int32_t len = GetlenTlvBuffer(tlv);
353      if (len <= 0 || len > MAX_TLV_LENGTH) {
354          return TLV_FAIL;
355      }
356  
357      if (ParcelReadParcel(&realTlv->data, parcel, len, HC_TRUE)) {
358          return len;
359      } else {
360          return TLV_FAIL;
361      }
362  }
363  
DeinitTlvBuffer(TlvBase * tlv)364  void DeinitTlvBuffer(TlvBase *tlv)
365  {
366      DeleteParcel(&((TlvBuffer *)tlv)->data);
367  }
368  
InitTlvBuffer(TlvBuffer * tlv,unsigned short checkTag)369  void InitTlvBuffer(TlvBuffer *tlv, unsigned short checkTag)
370  {
371      (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base));
372      tlv->base.parse = ParseTlvBuffer;
373      tlv->base.getlen = GetlenTlvBuffer;
374      tlv->base.encode = EncodeTlvBuffer;
375      tlv->base.deinit = DeinitTlvBuffer;
376      tlv->base.checkTag = checkTag;
377      tlv->data = CreateParcel(PARCEL_DEFAULT_LENGTH, PARCEL_DEFAULT_ALLOC_UNIT);
378  }
379  
ParseTlvString(TlvBase * tlv,HcParcel * parcel,HcBool strict)380  int32_t ParseTlvString(TlvBase *tlv, HcParcel *parcel, HcBool strict)
381  {
382      (void)strict;
383      TlvString *realTlv = (TlvString *)(tlv);
384      ClearParcel(&realTlv->data.parcel);
385      if (tlv->length == 0 || ParcelReadParcel(parcel, &realTlv->data.parcel, tlv->length, HC_FALSE)) {
386          return tlv->length;
387      } else {
388          return TLV_FAIL;
389      }
390  }
391  
GetlenTlvString(TlvBase * tlv)392  int32_t GetlenTlvString(TlvBase *tlv)
393  {
394      TlvString *realTlv = (TlvString *)(tlv);
395      return (int32_t)GetParcelDataSize(&realTlv->data.parcel);
396  }
397  
EncodeTlvString(TlvBase * tlv,HcParcel * parcel)398  int32_t EncodeTlvString(TlvBase *tlv, HcParcel *parcel)
399  {
400      TlvString *realTlv = (TlvString *)(tlv);
401      int32_t len = GetlenTlvString(tlv);
402      if (len <= 0 || len > MAX_TLV_LENGTH) {
403          return TLV_FAIL;
404      }
405  
406      if (ParcelReadParcel(&realTlv->data.parcel, parcel, len, HC_TRUE)) {
407          return len;
408      } else {
409          return TLV_FAIL;
410      }
411  }
412  
DeinitTlvString(TlvBase * tlv)413  void DeinitTlvString(TlvBase *tlv)
414  {
415      DeleteString(&((TlvString*)tlv)->data);
416  }
417  
InitTlvString(TlvString * tlv,unsigned short checkTag)418  void InitTlvString(TlvString *tlv, unsigned short checkTag)
419  {
420      (void)memset_s(&tlv->base, sizeof(tlv->base), 0, sizeof(tlv->base));
421      tlv->base.parse = ParseTlvString;
422      tlv->base.getlen = GetlenTlvString;
423      tlv->base.encode = EncodeTlvString;
424      tlv->base.deinit = DeinitTlvString;
425      tlv->base.checkTag = checkTag;
426      tlv->data = CreateString();
427  }
428  
GetTag(unsigned short checkTag,unsigned short defaultTag)429  unsigned short GetTag(unsigned short checkTag, unsigned short defaultTag)
430  {
431      if (checkTag == USE_DEFAULT_TAG) {
432          return defaultTag;
433      } else {
434          return checkTag;
435      }
436  }
437  
DeinitTlvFixMember(TlvBase * tlv)438  void DeinitTlvFixMember(TlvBase* tlv)
439  {
440      (void)tlv;
441      return;
442  }
443  
444  #ifdef IS_BIG_ENDIAN
445  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NEED_REVERT)
446  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NEED_REVERT)
447  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NEED_REVERT)
448  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NEED_REVERT)
449  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NEED_REVERT)
450  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NEED_REVERT)
451  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NEED_REVERT)
452  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NEED_REVERT)
453  #else
454  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt64, NO_REVERT)
455  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt32, NO_REVERT)
456  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt16, NO_REVERT)
457  DEFINE_TLV_FIX_LENGTH_TYPE(TlvInt8, NO_REVERT)
458  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint64, NO_REVERT)
459  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint32, NO_REVERT)
460  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint16, NO_REVERT)
461  DEFINE_TLV_FIX_LENGTH_TYPE(TlvUint8, NO_REVERT)
462  #endif
463