blob: 6e99c4359d6d060cfe0b66533b6a0de35619f19b [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladeb239c652024-05-26 08:07:05 -07002 * Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundblade534112f2025-02-26 15:12:47 -07003 * Copyright (c) 2018-2025, Laurence Lundblade.
Laurence Lundbladeb239c652024-05-26 08:07:05 -07004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials provided
14 * with the distribution.
15 * * Neither the name of The Linux Foundation nor the names of its
16 * contributors, nor the name "Laurence Lundblade" may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * ========================================================================= */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080032
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080033
Laurence Lundblade624405d2018-09-18 20:10:47 -070034
Laurence Lundbladeee851742020-01-08 08:37:05 -080035/*=============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036 FILE: UsefulBuf.c
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038 DESCRIPTION: General purpose input and output buffers
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070040 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080041
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070042 This section contains comments describing changes made to the module.
43 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080044
Laurence Lundbladeee851742020-01-08 08:37:05 -080045 when who what, where, why
46 -------- ---- ---------------------------------------------------
Laurence Lundblade534112f2025-02-26 15:12:47 -070047 02/21/2025 llundblade Improve magic number to detect lack of initialization.
48 02/21/2025 llundblade Bug fixes to UsefulOutBuf_Compare().
49 02/21/2025 llundblade Rename to UsefulOutBuf_OutSubString().
Laurence Lundbladee2226742024-08-16 10:50:23 -070050 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladeb239c652024-05-26 08:07:05 -070051 21/05/2024 llundblade Comment formatting and some code tidiness.
Laurence Lundbladede2e1502024-08-26 11:37:05 -070052 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -070053 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070054 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
55 19/11/2023 llundblade Add UsefulOutBuf_Swap().
56 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070057 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
58 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070059 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080060 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
61 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080062 11/08/2019 llundblade Re check pointer math and update comments
63 3/6/2019 llundblade Add UsefulBuf_IsValue()
64 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
65 the end of memory when the bytes to find is longer
66 than the bytes to search.
67 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
68 for < or > for unequal length buffers. Added
69 UsefulBuf_Set() function.
70 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
71 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080072
Laurence Lundbladeee851742020-01-08 08:37:05 -080073 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070074
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070075#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070076
Laurence Lundbladeb239c652024-05-26 08:07:05 -070077/* used to catch use of uninitialized or corrupted UsefulOutBuf */
Laurence Lundbladeee851742020-01-08 08:37:05 -080078#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079
Laurence Lundblade041ffa52018-10-07 11:43:51 +070080
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053081/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070082 * Public function -- see UsefulBuf.h
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053083 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070084UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
85{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070086 /* Do this with subtraction so it doesn't give an erroneous
87 * result if uOffset + Src.len overflows. Right side is equivalent to
88 * uOffset + Src.len > Dest.len
89 */
90 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080091 return NULLUsefulBufC;
92 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080093
Laurence Lundblade570fab52018-10-13 18:28:27 +080094 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080095
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080096 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070097}
98
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053099
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700100/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700101 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102 */
103int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
104{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700105 /* Use comparisons rather than subtracting lengths to
106 * return an int instead of a size_t
107 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108 if(UB1.len < UB2.len) {
109 return -1;
110 } else if (UB1.len > UB2.len) {
111 return 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700112 } /* else UB1.len == UB2.len */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800113
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700114 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
115}
116
117
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800118/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700119 * Public function -- see UsefulBuf.h
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800120 */
121size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
122{
123 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
124 /* Not a match */
125 return 0;
126 }
127
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800128 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800129 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
130 if(*p != uValue) {
131 /* Byte didn't match */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700132 /* Cast from signed to unsigned. Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800133 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800134 }
135 }
136
137 /* Success. All bytes matched */
138 return SIZE_MAX;
139}
140
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700141
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700142/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700143 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144 */
145size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
146{
147 if(BytesToSearch.len < BytesToFind.len) {
148 return SIZE_MAX;
149 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800150
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700151 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700152 UsefulBufC SearchNext;
153
154 SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
155 SearchNext.len = BytesToFind.len;
156 if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700157 return uPos;
158 }
159 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800160
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161 return SIZE_MAX;
162}
163
164
165/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700166 * Public function -- see UsefulBuf.h
Laurence Lundblade68769332024-11-03 13:09:20 -0800167 */
168UsefulBufC
169UsefulBuf_SkipLeading(UsefulBufC String, uint8_t uByte)
170{
171 for(;String.len; String.len--) {
172 if(*(const uint8_t *)String.ptr != uByte) {
173 break;
174 }
175 String.ptr = (const uint8_t *)String.ptr + 1;
176 }
177
178 return String;
179}
180
181
182
183/*
184 * Public function -- see UsefulBuf.h
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700185 *
186 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700187 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100188void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700189{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100190 pMe->magic = USEFUL_OUT_BUF_MAGIC;
191 UsefulOutBuf_Reset(pMe);
192 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800193
Laurence Lundblade2296db52018-09-14 18:08:39 -0700194#if 0
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700195 /* This check is off by default.
196 *
197 * The following check fails on ThreadX
198 *
199 * Sanity check on the pointer and size to be sure we are not
200 * passed a buffer that goes off the end of the address space.
201 * Given this test, we know that all unsigned lengths less than
202 * me->size are valid and won't wrap in any pointer additions
203 * based off of pStorage in the rest of this code.
204 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530205 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700206 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700207 me->err = 1;
208#endif
209}
210
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700211
212
213/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700214 * Public function -- see UsefulBuf.h
215 *
216 * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
217 * the end of it.
218 *
219 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
220 *
221 * This function inserts the source buffer, NewData, into the destination
222 * buffer, me->UB.ptr.
223 *
224 * Destination is represented as:
225 * me->UB.ptr -- start of the buffer
226 * me->UB.len -- size of the buffer UB.ptr
227 * me->data_len -- length of value data in UB
228 *
229 * Source is data:
230 * NewData.ptr -- start of source buffer
231 * NewData.len -- length of source buffer
232 *
233 * Insertion point:
234 * uInsertionPos.
235 *
236 * Steps:
237 *
238 * 0. Corruption checks on UsefulOutBuf
239 *
240 * 1. Figure out if the new data will fit or not
241 *
242 * 2. Is insertion position in the range of valid data?
243 *
244 * 3. If insertion point is not at the end, slide data to the right of the
245 * insertion point to the right
246 *
247 * 4. Put the new data in at the insertion position.
248 *
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700249 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100250void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700252 /* 0. Sanity check the UsefulOutBuf structure
253 * A "counter measure". If magic number is not the right number it
254 * probably means pMe was not initialized or it was corrupted. Attackers
255 * can defeat this, but it is a hurdle and does good with very
256 * little code.
257 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100258 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
259 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700260 return; /* Magic number is wrong due to uninitalization or corrption */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261 }
262
Laurence Lundblade534112f2025-02-26 15:12:47 -0700263 if(pMe->err) {
264 /* Already in error state. */
265 return;
266 }
267
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700268 /* Make sure valid data is less than buffer size. This would only occur
269 * if there was corruption of me, but it is also part of the checks to
270 * be sure there is no pointer arithmatic under/overflow.
271 */
272 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100273 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700274 /* Offset of valid data is off the end of the UsefulOutBuf due to
275 * uninitialization or corruption
276 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800277 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700278 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800279
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700280 /* 1. Will it fit?
281 * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
282 * Check #1 makes sure subtraction in RoomLeft will not wrap around
283 */
284 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
285 /* The new data will not fit into the the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100286 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700287 return;
288 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700290 /* 2. Check the Insertion Position
291 * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
292 * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
293 * address space.
294 */
295 if(uInsertionPos > pMe->data_len) { /* Check #3 */
296 /* Off the end of the valid data in the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100297 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 return;
299 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800300
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700301 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300302 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700303 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
304 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
305 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800306
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700307 /* To know memmove won't go off end of destination, see PtrMath #4.
308 * Use memove because it handles overlapping buffers
309 */
Laurence Lundblade74f68412018-09-13 12:18:49 -0700310 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800311
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300312 /* 4. Put the new data in */
313 uint8_t *pInsertionPoint = pSourceOfMove;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700314 /* To know memmove won't go off end of destination, see PtrMath #5 */
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700315 if(NewData.ptr != NULL) {
316 memmove(pInsertionPoint, NewData.ptr, NewData.len);
317 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300319
Laurence Lundblade61209742019-11-08 13:16:43 -0800320 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700321}
322
323
324/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700325 * Rationale that describes why the above pointer math is safe
326 *
327 * PtrMath #1 will never wrap around over because
328 * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
329 * Check #1 makes sure me->data_len is less than me->UB.len
330 * Check #3 makes sure uInsertionPos is less than me->data_len
331 *
332 * PtrMath #2 will never wrap around under because
333 * Check #3 makes sure uInsertionPos is less than me->data_len
334 *
335 * PtrMath #3 will never wrap around over because
336 * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
337 * Check #2 that NewData.len will fit in the unused space left in me->UB
338 *
339 * PtrMath #4 will never wrap under because
340 * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
341 * Check #3 makes sure uInsertionPos is less than me->data_len
342 * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
343 * This algebraically rearranges to me->size > uInsertionPos + NewData.len
344 *
345 * PtrMath #5 will never wrap under because
346 * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
347 * Check #1 makes sure me->data_len is less than me->size
348 * Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700349 */
350
351
352/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600353 * Public function for advancing data length. See qcbor/UsefulBuf.h
354 */
355void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
356{
357 /* This function is a trimmed down version of
358 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
359 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
360 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
361 * rarely used.
362 */
363
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600364 /* 0. Sanity check the UsefulOutBuf structure
365 *
366 * A "counter measure". If magic number is not the right number it
367 * probably means me was not initialized or it was
368 * corrupted. Attackers can defeat this, but it is a hurdle and
369 * does good with very little code.
370 */
371 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
372 pMe->err = 1;
373 return; /* Magic number is wrong due to uninitalization or corrption */
374 }
375
Laurence Lundblade534112f2025-02-26 15:12:47 -0700376 if(pMe->err) {
377 /* Already in error state. */
378 return;
379 }
380
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600381 /* Make sure valid data is less than buffer size. This would only
382 * occur if there was corruption of me, but it is also part of the
383 * checks to be sure there is no pointer arithmatic
384 * under/overflow.
385 */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700386 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600387 pMe->err = 1;
388 /* Offset of valid data is off the end of the UsefulOutBuf due
389 * to uninitialization or corruption.
390 */
391 return;
392 }
393
394 /* 1. Will it fit?
395 *
396 * WillItFit() is the same as: NewData.len <= (me->UB.len -
397 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
398 * not wrap around
399 */
400 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
401 /* The new data will not fit into the the buffer. */
402 pMe->err = 1;
403 return;
404 }
405
406 pMe->data_len += uAmount;
407}
408
409
410/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700411 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700412 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100413UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414{
Laurence Lundblade534112f2025-02-26 15:12:47 -0700415 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
416 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700417 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800419
Laurence Lundblade534112f2025-02-26 15:12:47 -0700420 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700421 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800423
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100424 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700425}
426
427
428/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700429 * Public function -- see UsefulBuf.h
430 *
431 * Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700432 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100433UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100435 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530436 if(UsefulBuf_IsNULLC(Tmp)) {
437 return NULLUsefulBufC;
438 }
439 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440}
441
442
Laurence Lundbladee2226742024-08-16 10:50:23 -0700443/*
444 * Public function -- see UsefulBuf.h
445 *
446 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
447 */
Laurence Lundblade534112f2025-02-26 15:12:47 -0700448UsefulBufC UsefulOutBuf_OutSubString(UsefulOutBuf *pMe,
449 const size_t uStart,
450 const size_t uLen)
Laurence Lundbladee2226742024-08-16 10:50:23 -0700451{
452 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
453
454 if(UsefulBuf_IsNULLC(Tmp)) {
455 return NULLUsefulBufC;
456 }
457
458 if(uStart > Tmp.len) {
459 return NULLUsefulBufC;
460 }
461
462 if(Tmp.len - uStart < uLen) {
463 return NULLUsefulBufC;
464 }
465
466 UsefulBufC SubString;
467 SubString.ptr = (const uint8_t *)Tmp.ptr + uStart;
468 SubString.len = uLen;
469
470 return SubString;
471}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700472
473
474/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700475 * Public function -- see UsefulBuf.h
476 *
477 * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
478 *
479 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700480 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100481const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700483 /* Already in error state. Do nothing. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100484 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700485 return NULL;
486 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800487
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100488 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700489 /* Number of bytes asked for is more than available */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100490 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700491 return NULL;
492 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800493
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700494 /* This is going to succeed */
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800495 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700496 /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800497 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700498 return result;
499}
500
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700501
502/*
503 * Public function -- see UsefulBuf.h
504 *
505 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
506 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700507int
508UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
509 const size_t uOffset1,
510 const size_t uLen1,
511 const size_t uOffset2,
512 const size_t uLen2)
513{
514 UsefulBufC UB1;
515 UsefulBufC UB2;
516
517 const size_t uInputSize = UsefulInputBuf_GetBufferLength(pUInBuf);
518
519 /* Careful length check that works even if uLen1 + uOffset1 > SIZE_MAX */
520 if(uOffset1 > uInputSize || uLen1 > uInputSize - uOffset1) {
521 return 1;
522 }
523 UB1.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset1;
524 UB1.len = uLen1;
525
526 /* Careful length check that works even if uLen2 + uOffset2 > SIZE_MAX */
527 if(uOffset2 > uInputSize || uLen2 > uInputSize - uOffset2) {
528 return -1;
529 }
530 UB2.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset2;
531 UB2.len = uLen2;
532
533 return UsefulBuf_Compare(UB1, UB2);
534}
535
536
537/*
538 * Public function -- see UsefulBuf.h
539 *
540 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
541 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700542int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
543 const size_t uStart1, const size_t uLen1,
544 const size_t uStart2, const size_t uLen2)
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700545{
546 const uint8_t *pBase;
547 const uint8_t *pEnd;
548 const uint8_t *p1;
549 const uint8_t *p2;
Laurence Lundblade534112f2025-02-26 15:12:47 -0700550 const uint8_t *p1Start;
551 const uint8_t *p2Start;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700552 const uint8_t *p1End;
553 const uint8_t *p2End;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700554 int uComparison;
Laurence Lundblade534112f2025-02-26 15:12:47 -0700555 size_t uComparedLen1;
556 size_t uComparedLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700557
Laurence Lundblade534112f2025-02-26 15:12:47 -0700558 pBase = pMe->UB.ptr;
559 pEnd = (const uint8_t *)pBase + pMe->data_len;
560 p1Start = pBase + uStart1;
561 p2Start = pBase + uStart2;
562 p1End = p1Start + uLen1;
563 p2End = p2Start + uLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700564
565 uComparison = 0;
Laurence Lundblade534112f2025-02-26 15:12:47 -0700566 for(p1 = p1Start, p2 = p2Start;
567 p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End;
568 p1++, p2++) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700569 uComparison = *p2 - *p1;
570 if(uComparison != 0) {
Laurence Lundblade534112f2025-02-26 15:12:47 -0700571 break;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700572 }
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700573 }
574
Laurence Lundblade534112f2025-02-26 15:12:47 -0700575 /* Loop might have terminated because strings were off
576 * the end of the buffer. Compute actual lengths compared.
577 */
578 uComparedLen1 = uLen1;
579 if(p1 >= pEnd) {
580 uComparedLen1 = (size_t)(p1 - p1Start);
581 }
582 uComparedLen2 = uLen2;
583 if(p2 >= pEnd) {
584 uComparedLen2 = (size_t)(p2 - p2Start);
585 }
586
587 if(uComparison == 0) {
588 /* All bytes were equal, now check the lengths */
589 if(uComparedLen2 > uComparedLen1) {
590 /* string 1 is a substring of string 2 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700591 uComparison = 1;
Laurence Lundblade534112f2025-02-26 15:12:47 -0700592 } else if(uComparedLen1 > uComparedLen2) {
593 /* string 2 is a substring of string 1 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700594 uComparison = -1;
Laurence Lundblade534112f2025-02-26 15:12:47 -0700595 } else {
596 /* do nothing, uComparison already is 0 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700597 }
598 }
599
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700600 return uComparison;
601}
602
603
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700604
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700605/**
606 * @brief Reverse order of bytes in a buffer.
607 *
608 * This reverses bytes starting at pStart, up to, but not including
609 * the byte at pEnd
610 */
611static void
612UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
613{
614 uint8_t uTmp;
615
616 while(pStart < pEnd) {
617 pEnd--;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700618 uTmp = *pStart;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700619 *pStart = *pEnd;
620 *pEnd = uTmp;
621 pStart++;
622 }
623}
624
625
626/*
627 * Public function -- see UsefulBuf.h
628 *
629 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
630 */
631void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
632{
633 uint8_t *pBase;
634
635 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
636 return;
637 }
638
639 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
640 return;
641 }
642
643 /* This is the "reverse" algorithm to swap two memory regions */
644 pBase = pMe->UB.ptr;
645 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
646 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
647 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
648}
649
650
651/*
652 * Public function -- see UsefulBuf.h
653 */
654UsefulBufC
655UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
656{
657 UsefulBufC ReturnValue;
658
659 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
660
661 if(UsefulBuf_IsNULLC(ReturnValue)) {
662 return NULLUsefulBufC;
663 }
664
665 if(uOffset >= ReturnValue.len) {
666 return NULLUsefulBufC;
667 }
668
669 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
670 ReturnValue.len -= uOffset;
671
672 return ReturnValue;
673}