• 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 (32 * 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