1 /*==============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018-2022, Laurence Lundblade.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above
11 copyright notice, this list of conditions and the following
12 disclaimer in the documentation and/or other materials provided
13 with the distribution.
14 * Neither the name of The Linux Foundation nor the names of its
15 contributors, nor the name "Laurence Lundblade" may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 =============================================================================*/
31
32 /*=============================================================================
33 FILE: UsefulBuf.c
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42 when who what, where, why
43 -------- ---- ---------------------------------------------------
44 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
45 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
46 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
47 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
48 01/08/2020 llundblade Documentation corrections & improved code formatting.
49 11/08/2019 llundblade Re check pointer math and update comments
50 3/6/2019 llundblade Add UsefulBuf_IsValue()
51 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
52 the end of memory when the bytes to find is longer
53 than the bytes to search.
54 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
55 for < or > for unequal length buffers. Added
56 UsefulBuf_Set() function.
57 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
58 11/13/16 llundbla Initial Version.
59
60 ============================================================================*/
61
62 #define ENABLE_DECODE_ROUTINES
63 #include "qcbor/UsefulBuf.h"
64
65 // used to catch use of uninitialized or corrupted UsefulOutBuf
66 #define USEFUL_OUT_BUF_MAGIC (0x0B0F)
67
68 int
69 memcmp(const void *s1, const void *s2, size_t n);
70
71 /*
72 Public function -- see UsefulBuf.h
73 */
74 UsefulBufC
UsefulBuf_CopyOffset(UsefulBuf Dest,size_t uOffset,const UsefulBufC Src)75 UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
76 {
77 // Do this with subtraction so it doesn't give erroneous
78 // result if uOffset + Src.len overflows
79 if (uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset +
80 // Src.len >
81 // Dest.len
82 return NULLUsefulBufC;
83 }
84
85 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
86
87 return (UsefulBufC){ Dest.ptr, Src.len + uOffset };
88 }
89
90 /*
91 Public function -- see UsefulBuf.h
92 */
93 int
UsefulBuf_Compare(const UsefulBufC UB1,const UsefulBufC UB2)94 UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
95 {
96 // use the comparisons rather than subtracting lengths to
97 // return an int instead of a size_t
98 if (UB1.len < UB2.len) {
99 return -1;
100 } else if (UB1.len > UB2.len) {
101 return 1;
102 } // else UB1.len == UB2.len
103
104 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
105 }
106
107 /*
108 Public function -- see UsefulBuf.h
109 */
110 size_t
UsefulBuf_IsValue(const UsefulBufC UB,uint8_t uValue)111 UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
112 {
113 if (UsefulBuf_IsNULLOrEmptyC(UB)) {
114 /* Not a match */
115 return 0;
116 }
117
118 const uint8_t *const pEnd = (const uint8_t *)UB.ptr + UB.len;
119 for (const uint8_t *p = UB.ptr; p < pEnd; p++) {
120 if (*p != uValue) {
121 /* Byte didn't match */
122 /* Cast from signed to unsigned . Safe because the loop
123 * increments.*/
124 return (size_t)(p - (const uint8_t *)UB.ptr);
125 }
126 }
127
128 /* Success. All bytes matched */
129 return SIZE_MAX;
130 }
131
132 /*
133 Public function -- see UsefulBuf.h
134 */
135 size_t
UsefulBuf_FindBytes(UsefulBufC BytesToSearch,UsefulBufC BytesToFind)136 UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
137 {
138 if (BytesToSearch.len < BytesToFind.len) {
139 return SIZE_MAX;
140 }
141
142 for (size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len;
143 uPos++) {
144 if (!UsefulBuf_Compare(
145 (UsefulBufC){ ((const uint8_t *)BytesToSearch.ptr) +
146 uPos,
147 BytesToFind.len },
148 BytesToFind)) {
149 return uPos;
150 }
151 }
152
153 return SIZE_MAX;
154 }
155
156 /*
157 Public function -- see UsefulBuf.h
158
159 Code Reviewers: THIS FUNCTION DOES POINTER MATH
160 */
161 void
UsefulOutBuf_Init(UsefulOutBuf * pMe,UsefulBuf Storage)162 UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
163 {
164 pMe->magic = USEFUL_OUT_BUF_MAGIC;
165 UsefulOutBuf_Reset(pMe);
166 pMe->UB = Storage;
167
168 #if 0
169 // This check is off by default.
170
171 // The following check fails on ThreadX
172
173 // Sanity check on the pointer and size to be sure we are not
174 // passed a buffer that goes off the end of the address space.
175 // Given this test, we know that all unsigned lengths less than
176 // me->size are valid and won't wrap in any pointer additions
177 // based off of pStorage in the rest of this code.
178 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
179 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
180 me->err = 1;
181 #endif
182 }
183
184 /*
185 Public function -- see UsefulBuf.h
186
187 The core of UsefulOutBuf -- put some bytes in the buffer without writing off
188 the end of it.
189
190 Code Reviewers: THIS FUNCTION DOES POINTER MATH
191
192 This function inserts the source buffer, NewData, into the destination
193 buffer, me->UB.ptr.
194
195 Destination is represented as:
196 me->UB.ptr -- start of the buffer
197 me->UB.len -- size of the buffer UB.ptr
198 me->data_len -- length of value data in UB
199
200 Source is data:
201 NewData.ptr -- start of source buffer
202 NewData.len -- length of source buffer
203
204 Insertion point:
205 uInsertionPos.
206
207 Steps:
208
209 0. Corruption checks on UsefulOutBuf
210
211 1. Figure out if the new data will fit or not
212
213 2. Is insertion position in the range of valid data?
214
215 3. If insertion point is not at the end, slide data to the right of the
216 insertion point to the right
217
218 4. Put the new data in at the insertion position.
219
220 */
221 void
UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf * pMe,UsefulBufC NewData,size_t uInsertionPos)222 UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData,
223 size_t uInsertionPos)
224 {
225 if (pMe->err) {
226 // Already in error state.
227 return;
228 }
229
230 /* 0. Sanity check the UsefulOutBuf structure */
231 // A "counter measure". If magic number is not the right number it
232 // probably means me was not initialized or it was corrupted. Attackers
233 // can defeat this, but it is a hurdle and does good with very
234 // little code.
235 if (pMe->magic != USEFUL_OUT_BUF_MAGIC) {
236 pMe->err = 1;
237 return; // Magic number is wrong due to uninitalization or
238 // corrption
239 }
240
241 // Make sure valid data is less than buffer size. This would only occur
242 // if there was corruption of me, but it is also part of the checks to
243 // be sure there is no pointer arithmatic under/overflow.
244 if (pMe->data_len > pMe->UB.len) { // Check #1
245 pMe->err = 1;
246 // Offset of valid data is off the end of the UsefulOutBuf due
247 // to uninitialization or corruption
248 return;
249 }
250
251 /* 1. Will it fit? */
252 // WillItFit() is the same as: NewData.len <= (me->UB.len -
253 // me->data_len) Check #1 makes sure subtraction in RoomLeft will not
254 // wrap around
255 if (!UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
256 // The new data will not fit into the the buffer.
257 pMe->err = 1;
258 return;
259 }
260
261 /* 2. Check the Insertion Position */
262 // This, with Check #1, also confirms that uInsertionPos <= me->data_len
263 // and that uInsertionPos + pMe->UB.ptr will not wrap around the end of
264 // the address space.
265 if (uInsertionPos > pMe->data_len) { // Check #3
266 // Off the end of the valid data in the buffer.
267 pMe->err = 1;
268 return;
269 }
270
271 /* 3. Slide existing data to the right */
272 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
273 uint8_t *pSourceOfMove =
274 ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
275 size_t uNumBytesToMove =
276 pMe->data_len - uInsertionPos; // PtrMath
277 // #2
278 uint8_t *pDestinationOfMove =
279 pSourceOfMove + NewData.len; // PtrMath
280 // #3
281
282 // To know memmove won't go off end of destination, see PtrMath
283 // #4 Use memove because it handles overlapping buffers
284 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
285
286 /* 4. Put the new data in */
287 uint8_t *pInsertionPoint = pSourceOfMove;
288 // To know memmove won't go off end of destination, see PtrMath
289 // #5
290 if (NewData.ptr != NULL) {
291 memmove(pInsertionPoint, NewData.ptr, NewData.len);
292 }
293 }
294
295 pMe->data_len += NewData.len;
296 }
297
298 /*
299 Rationale that describes why the above pointer math is safe
300
301 PtrMath #1 will never wrap around over because
302 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't
303 wrap Check #1 makes sure me->data_len is less than me->UB.len Check #3 makes
304 sure uInsertionPos is less than me->data_len
305
306 PtrMath #2 will never wrap around under because
307 Check #3 makes sure uInsertionPos is less than me->data_len
308
309 PtrMath #3 will never wrap around over because
310 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr
311 and me->UB.ptr + me->data_len Check #2 that NewData.len will fit in the unused
312 space left in me->UB
313
314 PtrMath #4 will never wrap under because
315 Calculation for extent or memmove is uRoomInDestination = me->UB.len -
316 (uInsertionPos + NewData.len) Check #3 makes sure uInsertionPos is less than
317 me->data_len Check #3 allows Check #2 to be refactored as NewData.Len >
318 (me->size - uInsertionPos) This algebraically rearranges to me->size >
319 uInsertionPos + NewData.len
320
321 PtrMath #5 will never wrap under because
322 Calculation for extent of memove is uRoomInDestination = me->UB.len -
323 uInsertionPos; Check #1 makes sure me->data_len is less than me->size Check #3
324 makes sure uInsertionPos is less than me->data_len
325 */
326
327 /*
328 * Public function for advancing data length. See qcbor/UsefulBuf.h
329 */
330 void
UsefulOutBuf_Advance(UsefulOutBuf * pMe,size_t uAmount)331 UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
332 {
333 /* This function is a trimmed down version of
334 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
335 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
336 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
337 * rarely used.
338 */
339
340 if (pMe->err) {
341 /* Already in error state. */
342 return;
343 }
344
345 /* 0. Sanity check the UsefulOutBuf structure
346 *
347 * A "counter measure". If magic number is not the right number it
348 * probably means me was not initialized or it was
349 * corrupted. Attackers can defeat this, but it is a hurdle and
350 * does good with very little code.
351 */
352 if (pMe->magic != USEFUL_OUT_BUF_MAGIC) {
353 pMe->err = 1;
354 return; /* Magic number is wrong due to uninitalization or
355 corrption */
356 }
357
358 /* Make sure valid data is less than buffer size. This would only
359 * occur if there was corruption of me, but it is also part of the
360 * checks to be sure there is no pointer arithmatic
361 * under/overflow.
362 */
363 if (pMe->data_len > pMe->UB.len) { // Check #1
364 pMe->err = 1;
365 /* Offset of valid data is off the end of the UsefulOutBuf due
366 * to uninitialization or corruption.
367 */
368 return;
369 }
370
371 /* 1. Will it fit?
372 *
373 * WillItFit() is the same as: NewData.len <= (me->UB.len -
374 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
375 * not wrap around
376 */
377 if (!UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
378 /* The new data will not fit into the the buffer. */
379 pMe->err = 1;
380 return;
381 }
382
383 pMe->data_len += uAmount;
384 }
385
386 /*
387 Public function -- see UsefulBuf.h
388 */
389 UsefulBufC
UsefulOutBuf_OutUBuf(UsefulOutBuf * pMe)390 UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
391 {
392 if (pMe->err) {
393 return NULLUsefulBufC;
394 }
395
396 if (pMe->magic != USEFUL_OUT_BUF_MAGIC) {
397 pMe->err = 1;
398 return NULLUsefulBufC;
399 }
400
401 return (UsefulBufC){ pMe->UB.ptr, pMe->data_len };
402 }
403
404 /*
405 Public function -- see UsefulBuf.h
406
407 Copy out the data accumulated in to the output buffer.
408 */
409 UsefulBufC
UsefulOutBuf_CopyOut(UsefulOutBuf * pMe,UsefulBuf pDest)410 UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
411 {
412 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
413 if (UsefulBuf_IsNULLC(Tmp)) {
414 return NULLUsefulBufC;
415 }
416 return UsefulBuf_Copy(pDest, Tmp);
417 }
418
419 /*
420 Public function -- see UsefulBuf.h
421
422 The core of UsefulInputBuf -- consume bytes without going off end of buffer.
423
424 Code Reviewers: THIS FUNCTION DOES POINTER MATH
425 */
426 const void *
UsefulInputBuf_GetBytes(UsefulInputBuf * pMe,size_t uAmount)427 UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
428 {
429 // Already in error state. Do nothing.
430 if (pMe->err) {
431 return NULL;
432 }
433
434 if (!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
435 // Number of bytes asked for at current position are more than
436 // available
437 pMe->err = 1;
438 return NULL;
439 }
440
441 // This is going to succeed
442 const void *const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
443 // Will not overflow because of check using
444 // UsefulInputBuf_BytesAvailable()
445 pMe->cursor += uAmount;
446 return result;
447 }
448