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