blob: 41770102baa72ed24bacaeb60215e68e52fcedaf [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 Lundblade9b2ae8a2024-07-12 11:00:20 -070047 1/7/2024 llundblade Add UsefulInputBuf_Compare().
Laurence Lundbladeb239c652024-05-26 08:07:05 -070048 21/05/2024 llundblade Comment formatting and some code tidiness.
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -070049 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070050 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
51 19/11/2023 llundblade Add UsefulOutBuf_Swap().
52 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070053 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
54 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070055 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080056 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
57 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080058 11/08/2019 llundblade Re check pointer math and update comments
59 3/6/2019 llundblade Add UsefulBuf_IsValue()
60 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
61 the end of memory when the bytes to find is longer
62 than the bytes to search.
63 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
64 for < or > for unequal length buffers. Added
65 UsefulBuf_Set() function.
66 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
67 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080068
Laurence Lundbladeee851742020-01-08 08:37:05 -080069 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070070
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070071#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070072
Laurence Lundbladeb239c652024-05-26 08:07:05 -070073/* used to catch use of uninitialized or corrupted UsefulOutBuf */
Laurence Lundbladeee851742020-01-08 08:37:05 -080074#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070075
Laurence Lundblade041ffa52018-10-07 11:43:51 +070076
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053077/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070078 * Public function -- see UsefulBuf.h
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053079 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070080UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
81{
Laurence Lundbladeb239c652024-05-26 08:07:05 -070082 /* Do this with subtraction so it doesn't give an erroneous
83 * result if uOffset + Src.len overflows. Right side is equivalent to
84 * uOffset + Src.len > Dest.len
85 */
86 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080087 return NULLUsefulBufC;
88 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080089
Laurence Lundblade570fab52018-10-13 18:28:27 +080090 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080091
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080092 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070093}
94
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053095
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070096/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -070097 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070098 */
99int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
100{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700101 /* Use comparisons rather than subtracting lengths to
102 * return an int instead of a size_t
103 */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 if(UB1.len < UB2.len) {
105 return -1;
106 } else if (UB1.len > UB2.len) {
107 return 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700108 } /* else UB1.len == UB2.len */
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800109
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700110 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
111}
112
113
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800114/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700115 * Public function -- see UsefulBuf.h
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800116 */
117size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
118{
119 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
120 /* Not a match */
121 return 0;
122 }
123
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800124 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800125 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
126 if(*p != uValue) {
127 /* Byte didn't match */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700128 /* Cast from signed to unsigned. Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800129 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800130 }
131 }
132
133 /* Success. All bytes matched */
134 return SIZE_MAX;
135}
136
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700137
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700138/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700139 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700140 */
141size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
142{
143 if(BytesToSearch.len < BytesToFind.len) {
144 return SIZE_MAX;
145 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800146
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700147 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700148 UsefulBufC SearchNext;
149
150 SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
151 SearchNext.len = BytesToFind.len;
152 if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153 return uPos;
154 }
155 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800156
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700157 return SIZE_MAX;
158}
159
160
161/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700162 * Public function -- see UsefulBuf.h
163 *
164 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700165 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100166void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700167{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100168 pMe->magic = USEFUL_OUT_BUF_MAGIC;
169 UsefulOutBuf_Reset(pMe);
170 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800171
Laurence Lundblade2296db52018-09-14 18:08:39 -0700172#if 0
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700173 /* This check is off by default.
174 *
175 * The following check fails on ThreadX
176 *
177 * Sanity check on the pointer and size to be sure we are not
178 * passed a buffer that goes off the end of the address space.
179 * Given this test, we know that all unsigned lengths less than
180 * me->size are valid and won't wrap in any pointer additions
181 * based off of pStorage in the rest of this code.
182 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530183 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700184 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700185 me->err = 1;
186#endif
187}
188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189
190
191/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700192 * Public function -- see UsefulBuf.h
193 *
194 * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
195 * the end of it.
196 *
197 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
198 *
199 * This function inserts the source buffer, NewData, into the destination
200 * buffer, me->UB.ptr.
201 *
202 * Destination is represented as:
203 * me->UB.ptr -- start of the buffer
204 * me->UB.len -- size of the buffer UB.ptr
205 * me->data_len -- length of value data in UB
206 *
207 * Source is data:
208 * NewData.ptr -- start of source buffer
209 * NewData.len -- length of source buffer
210 *
211 * Insertion point:
212 * uInsertionPos.
213 *
214 * Steps:
215 *
216 * 0. Corruption checks on UsefulOutBuf
217 *
218 * 1. Figure out if the new data will fit or not
219 *
220 * 2. Is insertion position in the range of valid data?
221 *
222 * 3. If insertion point is not at the end, slide data to the right of the
223 * insertion point to the right
224 *
225 * 4. Put the new data in at the insertion position.
226 *
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700227 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100228void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700229{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100230 if(pMe->err) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700231 /* Already in error state. */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700232 return;
233 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800234
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700235 /* 0. Sanity check the UsefulOutBuf structure
236 * A "counter measure". If magic number is not the right number it
237 * probably means pMe was not initialized or it was corrupted. Attackers
238 * can defeat this, but it is a hurdle and does good with very
239 * little code.
240 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100241 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
242 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700243 return; /* Magic number is wrong due to uninitalization or corrption */
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700244 }
245
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700246 /* Make sure valid data is less than buffer size. This would only occur
247 * if there was corruption of me, but it is also part of the checks to
248 * be sure there is no pointer arithmatic under/overflow.
249 */
250 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100251 pMe->err = 1;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700252 /* Offset of valid data is off the end of the UsefulOutBuf due to
253 * uninitialization or corruption
254 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800255 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800257
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700258 /* 1. Will it fit?
259 * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
260 * Check #1 makes sure subtraction in RoomLeft will not wrap around
261 */
262 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
263 /* The new data will not fit into the the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100264 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700265 return;
266 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800267
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700268 /* 2. Check the Insertion Position
269 * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
270 * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
271 * address space.
272 */
273 if(uInsertionPos > pMe->data_len) { /* Check #3 */
274 /* Off the end of the valid data in the buffer. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100275 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700276 return;
277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800278
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700279 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300280 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700281 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
282 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
283 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800284
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700285 /* To know memmove won't go off end of destination, see PtrMath #4.
286 * Use memove because it handles overlapping buffers
287 */
Laurence Lundblade74f68412018-09-13 12:18:49 -0700288 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300290 /* 4. Put the new data in */
291 uint8_t *pInsertionPoint = pSourceOfMove;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700292 /* To know memmove won't go off end of destination, see PtrMath #5 */
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700293 if(NewData.ptr != NULL) {
294 memmove(pInsertionPoint, NewData.ptr, NewData.len);
295 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700296 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300297
Laurence Lundblade61209742019-11-08 13:16:43 -0800298 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700299}
300
301
302/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700303 * Rationale that describes why the above pointer math is safe
304 *
305 * PtrMath #1 will never wrap around over because
306 * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
307 * Check #1 makes sure me->data_len is less than me->UB.len
308 * Check #3 makes sure uInsertionPos is less than me->data_len
309 *
310 * PtrMath #2 will never wrap around under because
311 * Check #3 makes sure uInsertionPos is less than me->data_len
312 *
313 * PtrMath #3 will never wrap around over because
314 * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
315 * Check #2 that NewData.len will fit in the unused space left in me->UB
316 *
317 * PtrMath #4 will never wrap under because
318 * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
319 * Check #3 makes sure uInsertionPos is less than me->data_len
320 * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
321 * This algebraically rearranges to me->size > uInsertionPos + NewData.len
322 *
323 * PtrMath #5 will never wrap under because
324 * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
325 * Check #1 makes sure me->data_len is less than me->size
326 * Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700327 */
328
329
330/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600331 * Public function for advancing data length. See qcbor/UsefulBuf.h
332 */
333void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
334{
335 /* This function is a trimmed down version of
336 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
337 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
338 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
339 * rarely used.
340 */
341
342 if(pMe->err) {
343 /* Already in error state. */
344 return;
345 }
346
347 /* 0. Sanity check the UsefulOutBuf structure
348 *
349 * A "counter measure". If magic number is not the right number it
350 * probably means me was not initialized or it was
351 * corrupted. Attackers can defeat this, but it is a hurdle and
352 * does good with very little code.
353 */
354 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
355 pMe->err = 1;
356 return; /* Magic number is wrong due to uninitalization or corrption */
357 }
358
359 /* Make sure valid data is less than buffer size. This would only
360 * occur if there was corruption of me, but it is also part of the
361 * checks to be sure there is no pointer arithmatic
362 * under/overflow.
363 */
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700364 if(pMe->data_len > pMe->UB.len) { /* Check #1 */
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600365 pMe->err = 1;
366 /* Offset of valid data is off the end of the UsefulOutBuf due
367 * to uninitialization or corruption.
368 */
369 return;
370 }
371
372 /* 1. Will it fit?
373 *
374 * WillItFit() is the same as: NewData.len <= (me->UB.len -
375 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
376 * not wrap around
377 */
378 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
379 /* The new data will not fit into the the buffer. */
380 pMe->err = 1;
381 return;
382 }
383
384 pMe->data_len += uAmount;
385}
386
387
388/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700389 * Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100391UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100393 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700394 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700395 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800396
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100397 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
398 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700399 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700400 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800401
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100402 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700403}
404
405
406/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700407 * Public function -- see UsefulBuf.h
408 *
409 * Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700410 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100411UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700412{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100413 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530414 if(UsefulBuf_IsNULLC(Tmp)) {
415 return NULLUsefulBufC;
416 }
417 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700418}
419
420
421
422
423/*
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700424 * Public function -- see UsefulBuf.h
425 *
426 * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
427 *
428 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700429 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100430const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700431{
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700432 /* Already in error state. Do nothing. */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100433 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700434 return NULL;
435 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800436
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100437 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700438 /* Number of bytes asked for is more than available */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100439 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700440 return NULL;
441 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800442
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700443 /* This is going to succeed */
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800444 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeb239c652024-05-26 08:07:05 -0700445 /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800446 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700447 return result;
448}
449
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700450
451/*
452 * Public function -- see UsefulBuf.h
453 *
454 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
455 */
Laurence Lundblade9b2ae8a2024-07-12 11:00:20 -0700456int
457UsefulInputBuf_Compare(UsefulInputBuf *pUInBuf,
458 const size_t uOffset1,
459 const size_t uLen1,
460 const size_t uOffset2,
461 const size_t uLen2)
462{
463 UsefulBufC UB1;
464 UsefulBufC UB2;
465
466 const size_t uInputSize = UsefulInputBuf_GetBufferLength(pUInBuf);
467
468 /* Careful length check that works even if uLen1 + uOffset1 > SIZE_MAX */
469 if(uOffset1 > uInputSize || uLen1 > uInputSize - uOffset1) {
470 return 1;
471 }
472 UB1.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset1;
473 UB1.len = uLen1;
474
475 /* Careful length check that works even if uLen2 + uOffset2 > SIZE_MAX */
476 if(uOffset2 > uInputSize || uLen2 > uInputSize - uOffset2) {
477 return -1;
478 }
479 UB2.ptr = (const uint8_t *)pUInBuf->UB.ptr + uOffset2;
480 UB2.len = uLen2;
481
482 return UsefulBuf_Compare(UB1, UB2);
483}
484
485
486/*
487 * Public function -- see UsefulBuf.h
488 *
489 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
490 */
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700491int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
492 const size_t uStart1, const size_t uLen1,
493 const size_t uStart2, const size_t uLen2)
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700494{
495 const uint8_t *pBase;
496 const uint8_t *pEnd;
497 const uint8_t *p1;
498 const uint8_t *p2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700499 const uint8_t *p1End;
500 const uint8_t *p2End;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700501 int uComparison;
502
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700503 pBase = pMe->UB.ptr;
504 pEnd = (const uint8_t *)pBase + pMe->data_len;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700505 p1 = pBase + uStart1;
506 p2 = pBase + uStart2;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700507 p1End = p1 + uLen1;
508 p2End = p2 + uLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700509
510 uComparison = 0;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700511 while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700512 uComparison = *p2 - *p1;
513 if(uComparison != 0) {
514 break;;
515 }
516 p1++;
517 p2++;
518 }
519
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700520 if(uComparison == 0 && p1 != p1End && p2 != p2End) {
521 if(uLen1 > uLen2) {
522 uComparison = 1;
523 } else if(uLen2 < uLen1){
524 uComparison = -1;
525 } else {
526 return 0;
527 }
528 }
529
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700530 return uComparison;
531}
532
533
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700534
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700535/**
536 * @brief Reverse order of bytes in a buffer.
537 *
538 * This reverses bytes starting at pStart, up to, but not including
539 * the byte at pEnd
540 */
541static void
542UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
543{
544 uint8_t uTmp;
545
546 while(pStart < pEnd) {
547 pEnd--;
Laurence Lundbladedee0d4e2024-03-03 13:46:33 -0700548 uTmp = *pStart;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700549 *pStart = *pEnd;
550 *pEnd = uTmp;
551 pStart++;
552 }
553}
554
555
556/*
557 * Public function -- see UsefulBuf.h
558 *
559 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
560 */
561void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
562{
563 uint8_t *pBase;
564
565 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
566 return;
567 }
568
569 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
570 return;
571 }
572
573 /* This is the "reverse" algorithm to swap two memory regions */
574 pBase = pMe->UB.ptr;
575 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
576 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
577 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
578}
579
580
581/*
582 * Public function -- see UsefulBuf.h
583 */
584UsefulBufC
585UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
586{
587 UsefulBufC ReturnValue;
588
589 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
590
591 if(UsefulBuf_IsNULLC(ReturnValue)) {
592 return NULLUsefulBufC;
593 }
594
595 if(uOffset >= ReturnValue.len) {
596 return NULLUsefulBufC;
597 }
598
599 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
600 ReturnValue.len -= uOffset;
601
602 return ReturnValue;
603}