blob: 46b66c63d98d4a8d4b81874c8baca8db0c4acd9c [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.
3 * Copyright (c) 2018-2024, Laurence Lundblade.
4 * 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 Lundbladee2226742024-08-16 10:50:23 -070047 08/08/2024 llundblade Add UsefulOutBuf_SubString().
Laurence Lundbladeb239c652024-05-26 08:07:05 -070048 21/05/2024 llundblade Comment formatting and some code tidiness.
Laurence Lundbladede2e1502024-08-26 11:37:05 -070049 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -070050 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070051 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
52 19/11/2023 llundblade Add UsefulOutBuf_Swap().
53 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070054 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
55 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070056 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080057 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
58 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080059 11/08/2019 llundblade Re check pointer math and update comments
60 3/6/2019 llundblade Add UsefulBuf_IsValue()
61 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
62 the end of memory when the bytes to find is longer
63 than the bytes to search.
64 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
65 for < or > for unequal length buffers. Added
66 UsefulBuf_Set() function.
67 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
68 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080069
Laurence Lundbladeee851742020-01-08 08:37:05 -080070 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070071
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070072#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070073
Laurence Lundbladeb239c652024-05-26 08:07:05 -070074/* used to catch use of uninitialized or corrupted UsefulOutBuf */
Laurence Lundbladeee851742020-01-08 08:37:05 -080075#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070076
Laurence Lundblade041ffa52018-10-07 11:43:51 +070077
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053078/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070079 * Public function -- see UsefulBuf.h
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053080 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070081UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
82{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070083 /* Do this with subtraction so it doesn't give an erroneous
84 * result if uOffset + Src.len overflows. Right side is equivalent to
85 * uOffset + Src.len > Dest.len
86 */
87 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080088 return NULLUsefulBufC;
89 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080090
Laurence Lundblade570fab52018-10-13 18:28:27 +080091 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080092
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080093 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070094}
95
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053096
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070098 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070099 */
100int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
101{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700102 /* Use comparisons rather than subtracting lengths to
103 * return an int instead of a size_t
104 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700105 if(UB1.len < UB2.len) {
106 return -1;
107 } else if (UB1.len > UB2.len) {
108 return 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700109 } /* else UB1.len == UB2.len */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800110
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700111 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
112}
113
114
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800115/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700116 * Public function -- see UsefulBuf.h
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800117 */
118size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
119{
120 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
121 /* Not a match */
122 return 0;
123 }
124
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800125 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800126 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
127 if(*p != uValue) {
128 /* Byte didn't match */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700129 /* Cast from signed to unsigned. Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800130 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800131 }
132 }
133
134 /* Success. All bytes matched */
135 return SIZE_MAX;
136}
137
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700138
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700140 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141 */
142size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
143{
144 if(BytesToSearch.len < BytesToFind.len) {
145 return SIZE_MAX;
146 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800147
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700149 UsefulBufC SearchNext;
150
151 SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
152 SearchNext.len = BytesToFind.len;
153 if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700154 return uPos;
155 }
156 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800157
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158 return SIZE_MAX;
159}
160
161
162/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700163 * Public function -- see UsefulBuf.h
Laurence Lundblade68769332024-11-03 13:09:20 -0800164 */
165UsefulBufC
166UsefulBuf_SkipLeading(UsefulBufC String, uint8_t uByte)
167{
168 for(;String.len; String.len--) {
169 if(*(const uint8_t *)String.ptr != uByte) {
170 break;
171 }
172 String.ptr = (const uint8_t *)String.ptr + 1;
173 }
174
175 return String;
176}
177
178
179
180/*
181 * Public function -- see UsefulBuf.h
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700182 *
183 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100185void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700186{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100187 pMe->magic = USEFUL_OUT_BUF_MAGIC;
188 UsefulOutBuf_Reset(pMe);
189 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800190
Laurence Lundblade2296db52018-09-14 18:08:39 -0700191#if 0
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700192 /* This check is off by default.
193 *
194 * The following check fails on ThreadX
195 *
196 * Sanity check on the pointer and size to be sure we are not
197 * passed a buffer that goes off the end of the address space.
198 * Given this test, we know that all unsigned lengths less than
199 * me->size are valid and won't wrap in any pointer additions
200 * based off of pStorage in the rest of this code.
201 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530202 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700203 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700204 me->err = 1;
205#endif
206}
207
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700208
209
210/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700211 * Public function -- see UsefulBuf.h
212 *
213 * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
214 * the end of it.
215 *
216 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
217 *
218 * This function inserts the source buffer, NewData, into the destination
219 * buffer, me->UB.ptr.
220 *
221 * Destination is represented as:
222 * me->UB.ptr -- start of the buffer
223 * me->UB.len -- size of the buffer UB.ptr
224 * me->data_len -- length of value data in UB
225 *
226 * Source is data:
227 * NewData.ptr -- start of source buffer
228 * NewData.len -- length of source buffer
229 *
230 * Insertion point:
231 * uInsertionPos.
232 *
233 * Steps:
234 *
235 * 0. Corruption checks on UsefulOutBuf
236 *
237 * 1. Figure out if the new data will fit or not
238 *
239 * 2. Is insertion position in the range of valid data?
240 *
241 * 3. If insertion point is not at the end, slide data to the right of the
242 * insertion point to the right
243 *
244 * 4. Put the new data in at the insertion position.
245 *
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100247void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100249 if(pMe->err) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700250 /* Already in error state. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 return;
252 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800253
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700254 /* 0. Sanity check the UsefulOutBuf structure
255 * A "counter measure". If magic number is not the right number it
256 * probably means pMe was not initialized or it was corrupted. Attackers
257 * can defeat this, but it is a hurdle and does good with very
258 * little code.
259 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100260 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
261 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700262 return; /* Magic number is wrong due to uninitalization or corrption */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263 }
264
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700265 /* Make sure valid data is less than buffer size. This would only occur
266 * if there was corruption of me, but it is also part of the checks to
267 * be sure there is no pointer arithmatic under/overflow.
268 */
269 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100270 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700271 /* Offset of valid data is off the end of the UsefulOutBuf due to
272 * uninitialization or corruption
273 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800274 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700275 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800276
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700277 /* 1. Will it fit?
278 * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
279 * Check #1 makes sure subtraction in RoomLeft will not wrap around
280 */
281 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
282 /* The new data will not fit into the the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100283 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700284 return;
285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800286
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700287 /* 2. Check the Insertion Position
288 * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
289 * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
290 * address space.
291 */
292 if(uInsertionPos > pMe->data_len) { /* Check #3 */
293 /* Off the end of the valid data in the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100294 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700295 return;
296 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300299 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700300 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
301 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
302 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800303
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700304 /* To know memmove won't go off end of destination, see PtrMath #4.
305 * Use memove because it handles overlapping buffers
306 */
Laurence Lundblade74f68412018-09-13 12:18:49 -0700307 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800308
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300309 /* 4. Put the new data in */
310 uint8_t *pInsertionPoint = pSourceOfMove;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700311 /* To know memmove won't go off end of destination, see PtrMath #5 */
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700312 if(NewData.ptr != NULL) {
313 memmove(pInsertionPoint, NewData.ptr, NewData.len);
314 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700315 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300316
Laurence Lundblade61209742019-11-08 13:16:43 -0800317 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318}
319
320
321/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700322 * Rationale that describes why the above pointer math is safe
323 *
324 * PtrMath #1 will never wrap around over because
325 * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
326 * Check #1 makes sure me->data_len is less than me->UB.len
327 * Check #3 makes sure uInsertionPos is less than me->data_len
328 *
329 * PtrMath #2 will never wrap around under because
330 * Check #3 makes sure uInsertionPos is less than me->data_len
331 *
332 * PtrMath #3 will never wrap around over because
333 * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
334 * Check #2 that NewData.len will fit in the unused space left in me->UB
335 *
336 * PtrMath #4 will never wrap under because
337 * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
338 * Check #3 makes sure uInsertionPos is less than me->data_len
339 * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
340 * This algebraically rearranges to me->size > uInsertionPos + NewData.len
341 *
342 * PtrMath #5 will never wrap under because
343 * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
344 * Check #1 makes sure me->data_len is less than me->size
345 * Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700346 */
347
348
349/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600350 * Public function for advancing data length. See qcbor/UsefulBuf.h
351 */
352void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
353{
354 /* This function is a trimmed down version of
355 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
356 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
357 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
358 * rarely used.
359 */
360
361 if(pMe->err) {
362 /* Already in error state. */
363 return;
364 }
365
366 /* 0. Sanity check the UsefulOutBuf structure
367 *
368 * A "counter measure". If magic number is not the right number it
369 * probably means me was not initialized or it was
370 * corrupted. Attackers can defeat this, but it is a hurdle and
371 * does good with very little code.
372 */
373 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
374 pMe->err = 1;
375 return; /* Magic number is wrong due to uninitalization or corrption */
376 }
377
378 /* Make sure valid data is less than buffer size. This would only
379 * occur if there was corruption of me, but it is also part of the
380 * checks to be sure there is no pointer arithmatic
381 * under/overflow.
382 */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700383 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600384 pMe->err = 1;
385 /* Offset of valid data is off the end of the UsefulOutBuf due
386 * to uninitialization or corruption.
387 */
388 return;
389 }
390
391 /* 1. Will it fit?
392 *
393 * WillItFit() is the same as: NewData.len <= (me->UB.len -
394 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
395 * not wrap around
396 */
397 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
398 /* The new data will not fit into the the buffer. */
399 pMe->err = 1;
400 return;
401 }
402
403 pMe->data_len += uAmount;
404}
405
406
407/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700408 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100410UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700411{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100412 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700413 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800415
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100416 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
417 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700418 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700419 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800420
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100421 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700422}
423
424
425/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700426 * Public function -- see UsefulBuf.h
427 *
428 * Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700429 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100430UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700431{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100432 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530433 if(UsefulBuf_IsNULLC(Tmp)) {
434 return NULLUsefulBufC;
435 }
436 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700437}
438
439
Laurence Lundbladee2226742024-08-16 10:50:23 -0700440/*
441 * Public function -- see UsefulBuf.h
442 *
443 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
444 */
445UsefulBufC UsefulOutBuf_SubString(UsefulOutBuf *pMe,
446 const size_t uStart,
447 const size_t uLen)
448{
449 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
450
451 if(UsefulBuf_IsNULLC(Tmp)) {
452 return NULLUsefulBufC;
453 }
454
455 if(uStart > Tmp.len) {
456 return NULLUsefulBufC;
457 }
458
459 if(Tmp.len - uStart < uLen) {
460 return NULLUsefulBufC;
461 }
462
463 UsefulBufC SubString;
464 SubString.ptr = (const uint8_t *)Tmp.ptr + uStart;
465 SubString.len = uLen;
466
467 return SubString;
468}
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700469
470
471/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700472 * Public function -- see UsefulBuf.h
473 *
474 * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
475 *
476 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700477 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100478const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700479{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700480 /* Already in error state. Do nothing. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100481 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700482 return NULL;
483 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800484
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100485 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700486 /* Number of bytes asked for is more than available */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100487 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700488 return NULL;
489 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800490
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700491 /* This is going to succeed */
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800492 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700493 /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800494 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700495 return result;
496}
497
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700498
499/*
500 * Public function -- see UsefulBuf.h
501 *
502 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
503 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700504int
505UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
506 const size_t uOffset1,
507 const size_t uLen1,
508 const size_t uOffset2,
509 const size_t uLen2)
510{
511 UsefulBufC UB1;
512 UsefulBufC UB2;
513
514 const size_t uInputSize = UsefulInputBuf_GetBufferLength(pUInBuf);
515
516 /* Careful length check that works even if uLen1 + uOffset1 > SIZE_MAX */
517 if(uOffset1 > uInputSize || uLen1 > uInputSize - uOffset1) {
518 return 1;
519 }
520 UB1.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset1;
521 UB1.len = uLen1;
522
523 /* Careful length check that works even if uLen2 + uOffset2 > SIZE_MAX */
524 if(uOffset2 > uInputSize || uLen2 > uInputSize - uOffset2) {
525 return -1;
526 }
527 UB2.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset2;
528 UB2.len = uLen2;
529
530 return UsefulBuf_Compare(UB1, UB2);
531}
532
533
534/*
535 * Public function -- see UsefulBuf.h
536 *
537 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
538 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700539int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
540 const size_t uStart1, const size_t uLen1,
541 const size_t uStart2, const size_t uLen2)
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700542{
543 const uint8_t *pBase;
544 const uint8_t *pEnd;
545 const uint8_t *p1;
546 const uint8_t *p2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700547 const uint8_t *p1End;
548 const uint8_t *p2End;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700549 int uComparison;
550
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700551 pBase = pMe->UB.ptr;
552 pEnd = (const uint8_t *)pBase + pMe->data_len;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700553 p1 = pBase + uStart1;
554 p2 = pBase + uStart2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700555 p1End = p1 + uLen1;
556 p2End = p2 + uLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700557
558 uComparison = 0;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700559 while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700560 uComparison = *p2 - *p1;
561 if(uComparison != 0) {
562 break;;
563 }
564 p1++;
565 p2++;
566 }
567
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700568 if(uComparison == 0 && p1 != p1End && p2 != p2End) {
569 if(uLen1 > uLen2) {
570 uComparison = 1;
571 } else if(uLen2 < uLen1){
572 uComparison = -1;
573 } else {
574 return 0;
575 }
576 }
577
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700578 return uComparison;
579}
580
581
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700582
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700583/**
584 * @brief Reverse order of bytes in a buffer.
585 *
586 * This reverses bytes starting at pStart, up to, but not including
587 * the byte at pEnd
588 */
589static void
590UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
591{
592 uint8_t uTmp;
593
594 while(pStart < pEnd) {
595 pEnd--;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700596 uTmp = *pStart;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700597 *pStart = *pEnd;
598 *pEnd = uTmp;
599 pStart++;
600 }
601}
602
603
604/*
605 * Public function -- see UsefulBuf.h
606 *
607 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
608 */
609void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
610{
611 uint8_t *pBase;
612
613 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
614 return;
615 }
616
617 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
618 return;
619 }
620
621 /* This is the "reverse" algorithm to swap two memory regions */
622 pBase = pMe->UB.ptr;
623 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
624 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
625 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
626}
627
628
629/*
630 * Public function -- see UsefulBuf.h
631 */
632UsefulBufC
633UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
634{
635 UsefulBufC ReturnValue;
636
637 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
638
639 if(UsefulBuf_IsNULLC(ReturnValue)) {
640 return NULLUsefulBufC;
641 }
642
643 if(uOffset >= ReturnValue.len) {
644 return NULLUsefulBufC;
645 }
646
647 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
648 ReturnValue.len -= uOffset;
649
650 return ReturnValue;
651}