blob: dae4eb19e95049a166ecfdbaf8dab11712b93a9f [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladea691a612024-02-27 02:29:01 -07003 Copyright (c) 2018-2024, Laurence Lundblade.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08004
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07005Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080018
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070019THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeee851742020-01-08 08:37:05 -080030 =============================================================================*/
Laurence Lundblade624405d2018-09-18 20:10:47 -070031
Laurence Lundbladeee851742020-01-08 08:37:05 -080032/*=============================================================================
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033 FILE: UsefulBuf.c
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080034
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070035 DESCRIPTION: General purpose input and output buffers
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080036
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070037 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080038
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070039 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080041
Laurence Lundbladeee851742020-01-08 08:37:05 -080042 when who what, where, why
43 -------- ---- ---------------------------------------------------
Laurence Lundbladea691a612024-02-27 02:29:01 -070044 28/02/2022 llundblade Rearrange UsefulOutBuf_Compare().
Laurence Lundbladed6e13022023-11-26 10:14:02 -070045 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
46 19/11/2023 llundblade Add UsefulOutBuf_Swap().
47 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070048 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
49 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070050 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080051 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
52 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080053 11/08/2019 llundblade Re check pointer math and update comments
54 3/6/2019 llundblade Add UsefulBuf_IsValue()
55 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
56 the end of memory when the bytes to find is longer
57 than the bytes to search.
58 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
59 for < or > for unequal length buffers. Added
60 UsefulBuf_Set() function.
61 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
62 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080063
Laurence Lundbladeee851742020-01-08 08:37:05 -080064 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070065
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070066#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070067
Laurence Lundbladeee851742020-01-08 08:37:05 -080068// used to catch use of uninitialized or corrupted UsefulOutBuf
69#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070070
Laurence Lundblade041ffa52018-10-07 11:43:51 +070071
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053072/*
73 Public function -- see UsefulBuf.h
74 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070075UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
76{
Laurence Lundbladeee851742020-01-08 08:37:05 -080077 // Do this with subtraction so it doesn't give erroneous
78 // result if uOffset + Src.len overflows
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080079 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
80 return NULLUsefulBufC;
81 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080082
Laurence Lundblade570fab52018-10-13 18:28:27 +080083 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080084
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080085 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070086}
87
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053088
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070089/*
90 Public function -- see UsefulBuf.h
91 */
92int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
93{
94 // use the comparisons rather than subtracting lengths to
95 // return an int instead of a size_t
96 if(UB1.len < UB2.len) {
97 return -1;
98 } else if (UB1.len > UB2.len) {
99 return 1;
100 } // else UB1.len == UB2.len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800101
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700102 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
103}
104
105
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800106/*
107 Public function -- see UsefulBuf.h
108 */
109size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
110{
111 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
112 /* Not a match */
113 return 0;
114 }
115
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800116 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800117 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
118 if(*p != uValue) {
119 /* Byte didn't match */
Laurence Lundblade06350ea2020-01-27 19:32:40 -0800120 /* Cast from signed to unsigned . Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800121 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800122 }
123 }
124
125 /* Success. All bytes matched */
126 return SIZE_MAX;
127}
128
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700129
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700130/*
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530131 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132 */
133size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
134{
135 if(BytesToSearch.len < BytesToFind.len) {
136 return SIZE_MAX;
137 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800138
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700139 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800140 if(!UsefulBuf_Compare((UsefulBufC){((const uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141 return uPos;
142 }
143 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800144
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700145 return SIZE_MAX;
146}
147
148
149/*
150 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800151
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530152 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700153 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100154void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700155{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100156 pMe->magic = USEFUL_OUT_BUF_MAGIC;
157 UsefulOutBuf_Reset(pMe);
158 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800159
Laurence Lundblade2296db52018-09-14 18:08:39 -0700160#if 0
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530161 // This check is off by default.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800162
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530163 // The following check fails on ThreadX
164
Laurence Lundblade2296db52018-09-14 18:08:39 -0700165 // Sanity check on the pointer and size to be sure we are not
166 // passed a buffer that goes off the end of the address space.
167 // Given this test, we know that all unsigned lengths less than
168 // me->size are valid and won't wrap in any pointer additions
169 // based off of pStorage in the rest of this code.
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530170 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
171 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
Laurence Lundblade2296db52018-09-14 18:08:39 -0700172 me->err = 1;
173#endif
174}
175
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700176
177
178/*
179 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800180
Laurence Lundbladeee851742020-01-08 08:37:05 -0800181 The core of UsefulOutBuf -- put some bytes in the buffer without writing off
182 the end of it.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800183
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800185
Laurence Lundbladeee851742020-01-08 08:37:05 -0800186 This function inserts the source buffer, NewData, into the destination
187 buffer, me->UB.ptr.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800188
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700189 Destination is represented as:
190 me->UB.ptr -- start of the buffer
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700191 me->UB.len -- size of the buffer UB.ptr
192 me->data_len -- length of value data in UB
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800193
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700194 Source is data:
195 NewData.ptr -- start of source buffer
196 NewData.len -- length of source buffer
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800197
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700198 Insertion point:
199 uInsertionPos.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800200
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700201 Steps:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800202
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700203 0. Corruption checks on UsefulOutBuf
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800204
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700205 1. Figure out if the new data will fit or not
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800206
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700207 2. Is insertion position in the range of valid data?
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800208
Laurence Lundbladeee851742020-01-08 08:37:05 -0800209 3. If insertion point is not at the end, slide data to the right of the
210 insertion point to the right
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800211
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700212 4. Put the new data in at the insertion position.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800213
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700214 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100215void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700216{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100217 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700218 // Already in error state.
219 return;
220 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800221
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700222 /* 0. Sanity check the UsefulOutBuf structure */
223 // A "counter measure". If magic number is not the right number it
224 // probably means me was not initialized or it was corrupted. Attackers
225 // can defeat this, but it is a hurdle and does good with very
226 // little code.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100227 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
228 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700229 return; // Magic number is wrong due to uninitalization or corrption
230 }
231
232 // Make sure valid data is less than buffer size. This would only occur
233 // if there was corruption of me, but it is also part of the checks to
234 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100235 if(pMe->data_len > pMe->UB.len) { // Check #1
236 pMe->err = 1;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800237 // Offset of valid data is off the end of the UsefulOutBuf due to
238 // uninitialization or corruption
239 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700240 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800241
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700242 /* 1. Will it fit? */
Laurence Lundblade61209742019-11-08 13:16:43 -0800243 // WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700244 // Check #1 makes sure subtraction in RoomLeft will not wrap around
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100245 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246 // The new data will not fit into the the buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100247 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700248 return;
249 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800250
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 /* 2. Check the Insertion Position */
Laurence Lundblade61209742019-11-08 13:16:43 -0800252 // This, with Check #1, also confirms that uInsertionPos <= me->data_len and
253 // that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
254 // address space.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100255 if(uInsertionPos > pMe->data_len) { // Check #3
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700256 // Off the end of the valid data in the buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100257 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700258 return;
259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800260
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300262 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
263 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
264 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
265 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800266
Laurence Lundblade56a79322019-01-10 09:12:37 -0800267 // To know memmove won't go off end of destination, see PtrMath #4
Laurence Lundblade61209742019-11-08 13:16:43 -0800268 // Use memove because it handles overlapping buffers
Laurence Lundblade74f68412018-09-13 12:18:49 -0700269 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800270
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300271 /* 4. Put the new data in */
272 uint8_t *pInsertionPoint = pSourceOfMove;
273 // To know memmove won't go off end of destination, see PtrMath #5
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700274 if(NewData.ptr != NULL) {
275 memmove(pInsertionPoint, NewData.ptr, NewData.len);
276 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700277 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300278
Laurence Lundblade61209742019-11-08 13:16:43 -0800279 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280}
281
282
283/*
284 Rationale that describes why the above pointer math is safe
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800285
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286 PtrMath #1 will never wrap around over because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800287 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
288 Check #1 makes sure me->data_len is less than me->UB.len
289 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800290
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700291 PtrMath #2 will never wrap around under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800292 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800293
Laurence Lundblade61209742019-11-08 13:16:43 -0800294 PtrMath #3 will never wrap around over because
295 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
296 Check #2 that NewData.len will fit in the unused space left in me->UB
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800297
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700298 PtrMath #4 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800299 Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700300 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700301 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
302 This algebraically rearranges to me->size > uInsertionPos + NewData.len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800303
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300304 PtrMath #5 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800305 Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
306 Check #1 makes sure me->data_len is less than me->size
307 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700308 */
309
310
311/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600312 * Public function for advancing data length. See qcbor/UsefulBuf.h
313 */
314void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
315{
316 /* This function is a trimmed down version of
317 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
318 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
319 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
320 * rarely used.
321 */
322
323 if(pMe->err) {
324 /* Already in error state. */
325 return;
326 }
327
328 /* 0. Sanity check the UsefulOutBuf structure
329 *
330 * A "counter measure". If magic number is not the right number it
331 * probably means me was not initialized or it was
332 * corrupted. Attackers can defeat this, but it is a hurdle and
333 * does good with very little code.
334 */
335 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
336 pMe->err = 1;
337 return; /* Magic number is wrong due to uninitalization or corrption */
338 }
339
340 /* Make sure valid data is less than buffer size. This would only
341 * occur if there was corruption of me, but it is also part of the
342 * checks to be sure there is no pointer arithmatic
343 * under/overflow.
344 */
345 if(pMe->data_len > pMe->UB.len) { // Check #1
346 pMe->err = 1;
347 /* Offset of valid data is off the end of the UsefulOutBuf due
348 * to uninitialization or corruption.
349 */
350 return;
351 }
352
353 /* 1. Will it fit?
354 *
355 * WillItFit() is the same as: NewData.len <= (me->UB.len -
356 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
357 * not wrap around
358 */
359 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
360 /* The new data will not fit into the the buffer. */
361 pMe->err = 1;
362 return;
363 }
364
365 pMe->data_len += uAmount;
366}
367
368
369/*
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800370 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700371 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100372UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700373{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100374 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700375 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700376 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800377
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100378 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
379 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700380 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700381 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800382
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100383 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700384}
385
386
387/*
388 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800389
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530390 Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700391 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100392UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700393{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100394 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530395 if(UsefulBuf_IsNULLC(Tmp)) {
396 return NULLUsefulBufC;
397 }
398 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700399}
400
401
402
403
404/*
405 Public function -- see UsefulBuf.h
406
Laurence Lundbladeee851742020-01-08 08:37:05 -0800407 The core of UsefulInputBuf -- consume bytes without going off end of buffer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800408
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700409 Code Reviewers: THIS FUNCTION DOES POINTER MATH
410 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100411const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700412{
413 // Already in error state. Do nothing.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100414 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700415 return NULL;
416 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800417
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100418 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800419 // Number of bytes asked for at current position are more than available
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100420 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700421 return NULL;
422 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800423
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700424 // This is going to succeed
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800425 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800426 // Will not overflow because of check using UsefulInputBuf_BytesAvailable()
427 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700428 return result;
429}
430
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700431
432/*
433 * Public function -- see UsefulBuf.h
434 *
435 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
436 */
Laurence Lundbladeda84ed72024-02-27 22:24:07 -0700437int UsefulOutBuf_Compare(UsefulOutBuf *pMe,
438 const size_t uStart1, const size_t uLen1,
439 const size_t uStart2, const size_t uLen2)
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700440{
441 const uint8_t *pBase;
442 const uint8_t *pEnd;
443 const uint8_t *p1;
444 const uint8_t *p2;
Laurence Lundbladea691a612024-02-27 02:29:01 -0700445 const uint8_t *p1End;
446 const uint8_t *p2End;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700447 int uComparison;
448
Laurence Lundbladeda84ed72024-02-27 22:24:07 -0700449 pBase = pMe->UB.ptr;
450 pEnd = (const uint8_t *)pBase + pMe->data_len;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700451 p1 = pBase + uStart1;
452 p2 = pBase + uStart2;
Laurence Lundbladea691a612024-02-27 02:29:01 -0700453 p1End = p1 + uLen1;
454 p2End = p2 + uLen2;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700455
456 uComparison = 0;
Laurence Lundbladea691a612024-02-27 02:29:01 -0700457 while(p1 < pEnd && p2 < pEnd && p1 < p1End && p2 < p2End) {
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700458 uComparison = *p2 - *p1;
459 if(uComparison != 0) {
460 break;;
461 }
462 p1++;
463 p2++;
464 }
465
Laurence Lundbladeda84ed72024-02-27 22:24:07 -0700466 if(uComparison == 0 && p1 != p1End && p2 != p2End) {
467 if(uLen1 > uLen2) {
468 uComparison = 1;
469 } else if(uLen2 < uLen1){
470 uComparison = -1;
471 } else {
472 return 0;
473 }
474 }
475
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700476 return uComparison;
477}
478
479
Laurence Lundbladea691a612024-02-27 02:29:01 -0700480
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700481/**
482 * @brief Reverse order of bytes in a buffer.
483 *
484 * This reverses bytes starting at pStart, up to, but not including
485 * the byte at pEnd
486 */
487static void
488UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
489{
490 uint8_t uTmp;
491
492 while(pStart < pEnd) {
493 pEnd--;
Laurence Lundbladeda84ed72024-02-27 22:24:07 -0700494 uTmp = *pStart;
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700495 *pStart = *pEnd;
496 *pEnd = uTmp;
497 pStart++;
498 }
499}
500
501
502/*
503 * Public function -- see UsefulBuf.h
504 *
505 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
506 */
507void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
508{
509 uint8_t *pBase;
510
511 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
512 return;
513 }
514
515 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
516 return;
517 }
518
519 /* This is the "reverse" algorithm to swap two memory regions */
520 pBase = pMe->UB.ptr;
521 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
522 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
523 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
524}
525
526
527/*
528 * Public function -- see UsefulBuf.h
529 */
530UsefulBufC
531UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
532{
533 UsefulBufC ReturnValue;
534
535 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
536
537 if(UsefulBuf_IsNULLC(ReturnValue)) {
538 return NULLUsefulBufC;
539 }
540
541 if(uOffset >= ReturnValue.len) {
542 return NULLUsefulBufC;
543 }
544
545 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
546 ReturnValue.len -= uOffset;
547
548 return ReturnValue;
549}