blob: 0e1c3a1913e7167133a53e2e15e4a1da41f12598 [file] [log] [blame]
Laurence Lundblade41e40d52024-12-01 10:29:33 -08001/* ==========================================================================
2 * decode_nesting.c -- All inline implementation of QCBORDecodeNesting
3 *
4 * Copyright (c) 2016-2018, The Linux Foundation.
5 * Copyright (c) 2018-2024, Laurence Lundblade.
6 * Copyright (c) 2021, Arm Limited.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: BSD-3-Clause
10 *
11 * Forked from qcbor_decode.c on 11/28/24
12 * ========================================================================== */
13
14#ifndef decode_nesting_h
15#define decode_nesting_h
16
17#include "qcbor/qcbor_private.h"
18
19
20/* When this was not all explicitly inline, the compiler decided to
21 * inline everything on its own, so we know there's no loss by
22 * making it all inline.
23 */
24
25static inline void
26DecodeNesting_Init(QCBORDecodeNesting *pNesting)
27{
28 /* Assumes that *pNesting has been zero'd before this call. */
29 pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
30 pNesting->pCurrent = &(pNesting->pLevels[0]);
31}
32
33
34static inline bool
35DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
36{
37 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
38 /* Not a map or array */
39 return false;
40 }
41
42#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
43 if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
44 /* Is indefinite */
45 return false;
46 }
47
48#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
49
50 /* All checks passed; is a definte length map or array */
51 return true;
52}
53
54
55static inline bool
56DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
57{
58 if(pNesting->pCurrentBounded == NULL) {
59 return false;
60 }
61
62 uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
63#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
64 if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
65 uItemDataType = QCBOR_TYPE_ARRAY;
66 }
67#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
68
69 if(uItemDataType != uType) {
70 return false;
71 }
72
73 return true;
74}
75
76
77static inline bool
78DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
79{
80 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
81 return true;
82 }
83 if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
84 return true;
85 }
86 return false;
87}
88
89
90static inline bool
91DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
92{
93 if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
94 return true;
95 } else {
96 return false;
97 }
98}
99
100
101static inline bool
102DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
103{
104 if(pNesting->pCurrentBounded == NULL) {
105 /* No bounded map or array set up */
106 return false;
107 }
108 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
109 /* Not a map or array; end of those is by byte count */
110 return false;
111 }
112 if(!DecodeNesting_IsCurrentBounded(pNesting)) {
113 /* In a traveral at a level deeper than the bounded level */
114 return false;
115 }
116 /* Works for both definite- and indefinitelength maps/arrays */
117 if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
118 pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
119 /* Count is not zero, still unconsumed item */
120 return false;
121 }
122 /* All checks passed, got to the end of an array or map*/
123 return true;
124}
125
126
127static inline bool
128DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
129{
130 /* Must only be called on map / array */
131 if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
132 return true;
133 } else {
134 return false;
135 }
136}
137
138
139static inline bool
140DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
141{
142 if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
143 return true;
144 } else {
145 return false;
146 }
147}
148
149
150static inline bool
151DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
152{
153 if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
154 return true;
155 } else {
156 return false;
157 }
158}
159
160
161static inline bool
162DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
163{
164 if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
165 /* is a byte string */
166 return true;
167 }
168 return false;
169}
170
171
172static inline uint8_t
173DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
174{
175 const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
176 /* Limit in DecodeNesting_Descend against more than
177 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
178 */
179 return (uint8_t)nLevel;
180}
181
182
183
184
185static inline void
186DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
187{
188 /* Only call on a definite-length array / map */
189 pNesting->pCurrent->u.ma.uCountCursor--;
190}
191
192
193static inline void
194DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
195{
196 pNesting->pCurrent->u.ma.uCountCursor = 0;
197}
198
199static inline void
200DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
201{
202 if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
203 pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
204 }
205}
206
207static inline void
208DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
209{
210 /* Only call on a definite-length array / map */
211 pNesting->pCurrent->u.ma.uCountCursor++;
212}
213
214
215
216
217static inline void
218DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
219{
220 pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
221}
222
223
224static inline QCBORError
225DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
226{
227 /* Error out if nesting is too deep */
228 if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
229 return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
230 }
231
232 /* The actual descend */
233 pNesting->pCurrent++;
234
235 pNesting->pCurrent->uLevelType = uType;
236
237 return QCBOR_SUCCESS;
238}
239
240static inline QCBORError
241DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
242 const uint8_t uQCBORType,
243 const uint16_t uCount)
244{
245 QCBORError uError = QCBOR_SUCCESS;
246
247 if(uCount == 0) {
248 /* Nothing to do for empty definite-length arrays. They are just are
249 * effectively the same as an item that is not a map or array.
250 */
251 goto Done;
252 /* Empty indefinite-length maps and arrays are handled elsewhere */
253 }
254
255 /* Rely on check in QCBOR_Private_DecodeArrayOrMap() for definite-length
256 * arrays and maps that are too long */
257
258 uError = DecodeNesting_Descend(pNesting, uQCBORType);
259 if(uError != QCBOR_SUCCESS) {
260 goto Done;
261 }
262
263 pNesting->pCurrent->u.ma.uCountCursor = uCount;
264 pNesting->pCurrent->u.ma.uCountTotal = uCount;
265
266 DecodeNesting_ClearBoundedMode(pNesting);
267
268Done:
269 return uError;;
270}
271
272
273static inline QCBORError
274DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
275 uint32_t uEndOffset,
276 uint32_t uStartOffset)
277{
278 QCBORError uError;
279
280 uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
281 if(uError != QCBOR_SUCCESS) {
282 goto Done;
283 }
284
285 /* Fill in the new byte string level */
286 pNesting->pCurrent->u.bs.uSavedEndOffset = uEndOffset;
287 pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
288
289 /* Bstr wrapped levels are always bounded */
290 pNesting->pCurrentBounded = pNesting->pCurrent;
291
292Done:
293 return uError;;
294}
295
296
297static inline void
298DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
299{
300 pNesting->pCurrent--;
301}
302
303
304
305
306static inline void
307DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
308{
309 pNesting->pCurrent = pNesting->pCurrentBounded;
310}
311
312static inline void
313DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
314{
315 /* Should be only called on maps and arrays */
316 /*
317 * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
318 * larger than DecodeNesting_EnterBoundedMode which keeps it less than
319 * uin32_t so the cast is safe.
320 */
321 pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
322
323 if(bIsEmpty) {
324 pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
325 }
326}
327
328static inline QCBORError
329DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
330 bool bIsEmpty,
331 size_t uOffset)
332{
333 /*
334 * Should only be called on map/array.
335 *
336 * Have descended into this before this is called. The job here is
337 * just to mark it in bounded mode.
338 *
339 * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
340 * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
341 *
342 * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
343 */
344 if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
345 return QCBOR_ERR_INPUT_TOO_LARGE;
346 }
347
348 pNesting->pCurrentBounded = pNesting->pCurrent;
349
350 DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
351
352 return QCBOR_SUCCESS;
353}
354
355
356static inline uint32_t
357DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
358{
359 return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
360}
361
362
363static inline uint8_t
364DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
365{
366 const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
367 /* Limit in DecodeNesting_Descend against more than
368 * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
369 */
370 return (uint8_t)nLevel;
371}
372
373
374
375
376static inline uint32_t
377DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
378{
379 return pNesting->pCurrentBounded->u.ma.uStartOffset;
380}
381
382
383static inline void
384DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
385{
386 pNesting->pCurrent = pNesting->pCurrentBounded - 1;
387}
388
389
390static inline void
391DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
392{
393 while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
394 pNesting->pCurrentBounded--;
395 if(DecodeNesting_IsCurrentBounded(pNesting)) {
396 break;
397 }
398 }
399}
400
401
402
403
404static inline void
405DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
406 QCBORDecodeNesting *pSave)
407{
408 *pSave = *pNesting;
409}
410
411
412static inline void
413DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
414 const QCBORDecodeNesting *pSave)
415{
416 *pNesting = *pSave;
417}
418
419#endif /* decode_nesting_h */