blob: 847395c458dca7f7d9c8c92920dbfd9da8806729 [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 Lundbladed6e13022023-11-26 10:14:02 -07003 Copyright (c) 2018-2023, 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 Lundbladed6e13022023-11-26 10:14:02 -070044 19/11/2023 llundblade Add UsefulOutBuf_GetOutput().
45 19/11/2023 llundblade Add UsefulOutBuf_Swap().
46 19/11/2023 llundblade Add UsefulOutBuf_Compare().
Laurence Lundblade5a6fec52022-12-25 11:28:43 -070047 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
48 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
Laurence Lundbladed6e13022023-11-26 10:14:02 -070049 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
Laurence Lundblade06350ea2020-01-27 19:32:40 -080050 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
51 01/08/2020 llundblade Documentation corrections & improved code formatting.
Laurence Lundbladeee851742020-01-08 08:37:05 -080052 11/08/2019 llundblade Re check pointer math and update comments
53 3/6/2019 llundblade Add UsefulBuf_IsValue()
54 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
55 the end of memory when the bytes to find is longer
56 than the bytes to search.
57 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
58 for < or > for unequal length buffers. Added
59 UsefulBuf_Set() function.
60 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
61 11/13/16 llundbla Initial Version.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080062
Laurence Lundbladeee851742020-01-08 08:37:05 -080063 ============================================================================*/
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070064
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070065#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070066
Laurence Lundbladeee851742020-01-08 08:37:05 -080067// used to catch use of uninitialized or corrupted UsefulOutBuf
68#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070069
Laurence Lundblade041ffa52018-10-07 11:43:51 +070070
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053071/*
72 Public function -- see UsefulBuf.h
73 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070074UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
75{
Laurence Lundbladeee851742020-01-08 08:37:05 -080076 // Do this with subtraction so it doesn't give erroneous
77 // result if uOffset + Src.len overflows
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080078 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
79 return NULLUsefulBufC;
80 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080081
Laurence Lundblade570fab52018-10-13 18:28:27 +080082 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080083
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080084 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070085}
86
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053087
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070088/*
89 Public function -- see UsefulBuf.h
90 */
91int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
92{
93 // use the comparisons rather than subtracting lengths to
94 // return an int instead of a size_t
95 if(UB1.len < UB2.len) {
96 return -1;
97 } else if (UB1.len > UB2.len) {
98 return 1;
99 } // else UB1.len == UB2.len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800100
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700101 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
102}
103
104
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800105/*
106 Public function -- see UsefulBuf.h
107 */
108size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
109{
110 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
111 /* Not a match */
112 return 0;
113 }
114
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800115 const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800116 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
117 if(*p != uValue) {
118 /* Byte didn't match */
Laurence Lundblade06350ea2020-01-27 19:32:40 -0800119 /* Cast from signed to unsigned . Safe because the loop increments.*/
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800120 return (size_t)(p - (const uint8_t *)UB.ptr);
Laurence Lundbladed5e101e2019-03-06 17:23:18 -0800121 }
122 }
123
124 /* Success. All bytes matched */
125 return SIZE_MAX;
126}
127
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700128
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700129/*
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530130 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700131 */
132size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
133{
134 if(BytesToSearch.len < BytesToFind.len) {
135 return SIZE_MAX;
136 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800137
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700138 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800139 if(!UsefulBuf_Compare((UsefulBufC){((const uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700140 return uPos;
141 }
142 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800143
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700144 return SIZE_MAX;
145}
146
147
148/*
149 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800150
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530151 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100153void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade2296db52018-09-14 18:08:39 -0700154{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100155 pMe->magic = USEFUL_OUT_BUF_MAGIC;
156 UsefulOutBuf_Reset(pMe);
157 pMe->UB = Storage;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800158
Laurence Lundblade2296db52018-09-14 18:08:39 -0700159#if 0
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530160 // This check is off by default.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800161
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530162 // The following check fails on ThreadX
163
Laurence Lundblade2296db52018-09-14 18:08:39 -0700164 // Sanity check on the pointer and size to be sure we are not
165 // passed a buffer that goes off the end of the address space.
166 // Given this test, we know that all unsigned lengths less than
167 // me->size are valid and won't wrap in any pointer additions
168 // based off of pStorage in the rest of this code.
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530169 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
170 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
Laurence Lundblade2296db52018-09-14 18:08:39 -0700171 me->err = 1;
172#endif
173}
174
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700175
176
177/*
178 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800179
Laurence Lundbladeee851742020-01-08 08:37:05 -0800180 The core of UsefulOutBuf -- put some bytes in the buffer without writing off
181 the end of it.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800182
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700183 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800184
Laurence Lundbladeee851742020-01-08 08:37:05 -0800185 This function inserts the source buffer, NewData, into the destination
186 buffer, me->UB.ptr.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800187
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700188 Destination is represented as:
189 me->UB.ptr -- start of the buffer
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700190 me->UB.len -- size of the buffer UB.ptr
191 me->data_len -- length of value data in UB
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800192
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700193 Source is data:
194 NewData.ptr -- start of source buffer
195 NewData.len -- length of source buffer
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800196
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197 Insertion point:
198 uInsertionPos.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800199
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700200 Steps:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800201
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700202 0. Corruption checks on UsefulOutBuf
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800203
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700204 1. Figure out if the new data will fit or not
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800205
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700206 2. Is insertion position in the range of valid data?
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800207
Laurence Lundbladeee851742020-01-08 08:37:05 -0800208 3. If insertion point is not at the end, slide data to the right of the
209 insertion point to the right
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800210
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700211 4. Put the new data in at the insertion position.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800212
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700213 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100214void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700215{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100216 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700217 // Already in error state.
218 return;
219 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800220
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700221 /* 0. Sanity check the UsefulOutBuf structure */
222 // A "counter measure". If magic number is not the right number it
223 // probably means me was not initialized or it was corrupted. Attackers
224 // can defeat this, but it is a hurdle and does good with very
225 // little code.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100226 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
227 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700228 return; // Magic number is wrong due to uninitalization or corrption
229 }
230
231 // Make sure valid data is less than buffer size. This would only occur
232 // if there was corruption of me, but it is also part of the checks to
233 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100234 if(pMe->data_len > pMe->UB.len) { // Check #1
235 pMe->err = 1;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800236 // Offset of valid data is off the end of the UsefulOutBuf due to
237 // uninitialization or corruption
238 return;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700239 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800240
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700241 /* 1. Will it fit? */
Laurence Lundblade61209742019-11-08 13:16:43 -0800242 // WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700243 // Check #1 makes sure subtraction in RoomLeft will not wrap around
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100244 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700245 // The new data will not fit into the the buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100246 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 return;
248 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800249
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700250 /* 2. Check the Insertion Position */
Laurence Lundblade61209742019-11-08 13:16:43 -0800251 // This, with Check #1, also confirms that uInsertionPos <= me->data_len and
252 // that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
253 // address space.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100254 if(uInsertionPos > pMe->data_len) { // Check #3
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255 // Off the end of the valid data in the buffer.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100256 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257 return;
258 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260 /* 3. Slide existing data to the right */
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300261 if (!UsefulOutBuf_IsBufferNULL(pMe)) {
262 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
263 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
264 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800265
Laurence Lundblade56a79322019-01-10 09:12:37 -0800266 // To know memmove won't go off end of destination, see PtrMath #4
Laurence Lundblade61209742019-11-08 13:16:43 -0800267 // Use memove because it handles overlapping buffers
Laurence Lundblade74f68412018-09-13 12:18:49 -0700268 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800269
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300270 /* 4. Put the new data in */
271 uint8_t *pInsertionPoint = pSourceOfMove;
272 // To know memmove won't go off end of destination, see PtrMath #5
Laurence Lundblade5a6fec52022-12-25 11:28:43 -0700273 if(NewData.ptr != NULL) {
274 memmove(pInsertionPoint, NewData.ptr, NewData.len);
275 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700276 }
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300277
Laurence Lundblade61209742019-11-08 13:16:43 -0800278 pMe->data_len += NewData.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700279}
280
281
282/*
283 Rationale that describes why the above pointer math is safe
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800284
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700285 PtrMath #1 will never wrap around over because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800286 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
287 Check #1 makes sure me->data_len is less than me->UB.len
288 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700290 PtrMath #2 will never wrap around under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800291 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800292
Laurence Lundblade61209742019-11-08 13:16:43 -0800293 PtrMath #3 will never wrap around over because
294 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
295 Check #2 that NewData.len will fit in the unused space left in me->UB
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800296
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700297 PtrMath #4 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800298 Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700299 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700300 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
301 This algebraically rearranges to me->size > uInsertionPos + NewData.len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800302
Maxim Zhukov9fab6892022-12-20 20:16:07 +0300303 PtrMath #5 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800304 Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
305 Check #1 makes sure me->data_len is less than me->size
306 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700307 */
308
309
310/*
Laurence Lundbladeb24faef2022-04-26 11:03:08 -0600311 * Public function for advancing data length. See qcbor/UsefulBuf.h
312 */
313void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
314{
315 /* This function is a trimmed down version of
316 * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
317 * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
318 * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
319 * rarely used.
320 */
321
322 if(pMe->err) {
323 /* Already in error state. */
324 return;
325 }
326
327 /* 0. Sanity check the UsefulOutBuf structure
328 *
329 * A "counter measure". If magic number is not the right number it
330 * probably means me was not initialized or it was
331 * corrupted. Attackers can defeat this, but it is a hurdle and
332 * does good with very little code.
333 */
334 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
335 pMe->err = 1;
336 return; /* Magic number is wrong due to uninitalization or corrption */
337 }
338
339 /* Make sure valid data is less than buffer size. This would only
340 * occur if there was corruption of me, but it is also part of the
341 * checks to be sure there is no pointer arithmatic
342 * under/overflow.
343 */
344 if(pMe->data_len > pMe->UB.len) { // Check #1
345 pMe->err = 1;
346 /* Offset of valid data is off the end of the UsefulOutBuf due
347 * to uninitialization or corruption.
348 */
349 return;
350 }
351
352 /* 1. Will it fit?
353 *
354 * WillItFit() is the same as: NewData.len <= (me->UB.len -
355 * me->data_len) Check #1 makes sure subtraction in RoomLeft will
356 * not wrap around
357 */
358 if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
359 /* The new data will not fit into the the buffer. */
360 pMe->err = 1;
361 return;
362 }
363
364 pMe->data_len += uAmount;
365}
366
367
368/*
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800369 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700370 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100371UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700372{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100373 if(pMe->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700374 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700375 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800376
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100377 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
378 pMe->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700379 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700380 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800381
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100382 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700383}
384
385
386/*
387 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800388
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530389 Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700390 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100391UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700392{
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100393 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530394 if(UsefulBuf_IsNULLC(Tmp)) {
395 return NULLUsefulBufC;
396 }
397 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700398}
399
400
401
402
403/*
404 Public function -- see UsefulBuf.h
405
Laurence Lundbladeee851742020-01-08 08:37:05 -0800406 The core of UsefulInputBuf -- consume bytes without going off end of buffer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800407
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700408 Code Reviewers: THIS FUNCTION DOES POINTER MATH
409 */
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100410const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700411{
412 // Already in error state. Do nothing.
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100413 if(pMe->err) {
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700414 return NULL;
415 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800416
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100417 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeee851742020-01-08 08:37:05 -0800418 // Number of bytes asked for at current position are more than available
Laurence Lundblade5cc25682019-03-26 21:58:35 +0100419 pMe->err = 1;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700420 return NULL;
421 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800422
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700423 // This is going to succeed
Laurence Lundbladeb9702452021-03-08 21:02:57 -0800424 const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeee851742020-01-08 08:37:05 -0800425 // Will not overflow because of check using UsefulInputBuf_BytesAvailable()
426 pMe->cursor += uAmount;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700427 return result;
428}
429
Laurence Lundbladed6e13022023-11-26 10:14:02 -0700430
431/*
432 * Public function -- see UsefulBuf.h
433 *
434 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
435 */
436int UsefulOutBuf_Compare(UsefulOutBuf *me, size_t uStart1, size_t uStart2)
437{
438 const uint8_t *pBase;
439 const uint8_t *pEnd;
440 const uint8_t *p1;
441 const uint8_t *p2;
442 int uComparison;
443
444 pBase = me->UB.ptr;
445 pEnd = (const uint8_t *)pBase + me->data_len;
446 p1 = pBase + uStart1;
447 p2 = pBase + uStart2;
448
449 uComparison = 0;
450 while(p1 < pEnd && p2 < pEnd) {
451 uComparison = *p2 - *p1;
452 if(uComparison != 0) {
453 break;;
454 }
455 p1++;
456 p2++;
457 }
458
459 return uComparison;
460}
461
462
463/**
464 * @brief Reverse order of bytes in a buffer.
465 *
466 * This reverses bytes starting at pStart, up to, but not including
467 * the byte at pEnd
468 */
469static void
470UsefulOutBuf_Private_ReverseBytes(uint8_t *pStart, uint8_t *pEnd)
471{
472 uint8_t uTmp;
473
474 while(pStart < pEnd) {
475 pEnd--;
476 uTmp = *pStart;
477 *pStart = *pEnd;
478 *pEnd = uTmp;
479 pStart++;
480 }
481}
482
483
484/*
485 * Public function -- see UsefulBuf.h
486 *
487 * Code Reviewers: THIS FUNCTION DOES POINTER MATH
488 */
489void UsefulOutBuf_Swap(UsefulOutBuf *pMe, size_t uStartOffset, size_t uPivotOffset, size_t uEndOffset)
490{
491 uint8_t *pBase;
492
493 if(uStartOffset > pMe->data_len || uPivotOffset > pMe->data_len || uEndOffset > pMe->data_len) {
494 return;
495 }
496
497 if(uStartOffset > uPivotOffset || uStartOffset > uEndOffset || uPivotOffset > uEndOffset) {
498 return;
499 }
500
501 /* This is the "reverse" algorithm to swap two memory regions */
502 pBase = pMe->UB.ptr;
503 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uPivotOffset);
504 UsefulOutBuf_Private_ReverseBytes(pBase + uPivotOffset, pBase + uEndOffset);
505 UsefulOutBuf_Private_ReverseBytes(pBase + uStartOffset, pBase + uEndOffset);
506}
507
508
509/*
510 * Public function -- see UsefulBuf.h
511 */
512UsefulBufC
513UsefulOutBuf_OutUBufOffset(UsefulOutBuf *pMe, size_t uOffset)
514{
515 UsefulBufC ReturnValue;
516
517 ReturnValue = UsefulOutBuf_OutUBuf(pMe);
518
519 if(UsefulBuf_IsNULLC(ReturnValue)) {
520 return NULLUsefulBufC;
521 }
522
523 if(uOffset >= ReturnValue.len) {
524 return NULLUsefulBufC;
525 }
526
527 ReturnValue.ptr = (const uint8_t *)ReturnValue.ptr + uOffset;
528 ReturnValue.len -= uOffset;
529
530 return ReturnValue;
531}