blob: f13dad273c612b5e3a1c2ae5915fd340f815dd84 [file] [log] [blame]
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001/*==============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018-2019, Laurence Lundblade.
Laurence Lundblade6ed34222018-12-18 09:46:23 -08004
5Redistribution 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.
18
19THIS 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.
30 ==============================================================================*/
31
32/*===================================================================================
33 FILE: UsefulBuf.c
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
42 when who what, where, why
43 -------- ---- ---------------------------------------------------
Laurence Lundbladed85dbb72019-03-07 18:27:18 -080044 3/6/2019 llundblade Add UsefulBuf_IsValue()
Laurence Lundblade6ed34222018-12-18 09:46:23 -080045 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
46 the end of memory when the bytes to find is longer
47 than the bytes to search.
48 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
49 for < or > for unequal length buffers. Added
50 UsefulBuf_Set() function.
51 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
52 11/13/16 llundbla Initial Version.
53
54 =====================================================================================*/
55
56#include "UsefulBuf.h"
57
58#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs
59
60
61/*
62 Public function -- see UsefulBuf.h
63 */
64UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
65{
66 // Do this with subtraction so it doesn't give erroneous result if uOffset + Src.len overflows
67 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
68 return NULLUsefulBufC;
69 }
70
71 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
72
73 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
74}
75
76
77/*
78 Public function -- see UsefulBuf.h
79 */
80int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
81{
82 // use the comparisons rather than subtracting lengths to
83 // return an int instead of a size_t
84 if(UB1.len < UB2.len) {
85 return -1;
86 } else if (UB1.len > UB2.len) {
87 return 1;
88 } // else UB1.len == UB2.len
89
90 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
91}
92
93
Laurence Lundbladed85dbb72019-03-07 18:27:18 -080094/*
95 Public function -- see UsefulBuf.h
96 */
97size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
98{
99 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
100 /* Not a match */
101 return 0;
102 }
103
104 const uint8_t * const pEnd = (uint8_t *)UB.ptr + UB.len;
105 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
106 if(*p != uValue) {
107 /* Byte didn't match */
108 return p - (uint8_t *)UB.ptr;
109 }
110 }
111
112 /* Success. All bytes matched */
113 return SIZE_MAX;
114}
115
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800116
117/*
118 Public function -- see UsefulBuf.h
119 */
120size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
121{
122 if(BytesToSearch.len < BytesToFind.len) {
123 return SIZE_MAX;
124 }
125
126 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
127 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
128 return uPos;
129 }
130 }
131
132 return SIZE_MAX;
133}
134
135
136/*
137 Public function -- see UsefulBuf.h
138
139 Code Reviewers: THIS FUNCTION DOES POINTER MATH
140 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700141void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800142{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700143 pMe->magic = USEFUL_OUT_BUF_MAGIC;
144 UsefulOutBuf_Reset(pMe);
145 pMe->UB = Storage;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800146
147#if 0
148 // This check is off by default.
149
150 // The following check fails on ThreadX
151
152 // Sanity check on the pointer and size to be sure we are not
153 // passed a buffer that goes off the end of the address space.
154 // Given this test, we know that all unsigned lengths less than
155 // me->size are valid and won't wrap in any pointer additions
156 // based off of pStorage in the rest of this code.
157 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
158 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
159 me->err = 1;
160#endif
161}
162
163
164
165/*
166 Public function -- see UsefulBuf.h
167
168 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
169
170 Code Reviewers: THIS FUNCTION DOES POINTER MATH
171
172 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
173
174 Destination is represented as:
175 me->UB.ptr -- start of the buffer
176 me->UB.len -- size of the buffer UB.ptr
177 me->data_len -- length of value data in UB
178
179 Source is data:
180 NewData.ptr -- start of source buffer
181 NewData.len -- length of source buffer
182
183 Insertion point:
184 uInsertionPos.
185
186 Steps:
187
188 0. Corruption checks on UsefulOutBuf
189
190 1. Figure out if the new data will fit or not
191
192 2. Is insertion position in the range of valid data?
193
194 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
195
196 4. Put the new data in at the insertion position.
197
198 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700199void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800200{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700201 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800202 // Already in error state.
203 return;
204 }
205
206 /* 0. Sanity check the UsefulOutBuf structure */
207 // A "counter measure". If magic number is not the right number it
208 // probably means me was not initialized or it was corrupted. Attackers
209 // can defeat this, but it is a hurdle and does good with very
210 // little code.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700211 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
212 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800213 return; // Magic number is wrong due to uninitalization or corrption
214 }
215
216 // Make sure valid data is less than buffer size. This would only occur
217 // if there was corruption of me, but it is also part of the checks to
218 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700219 if(pMe->data_len > pMe->UB.len) { // Check #1
220 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800221 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
222 }
223
224 /* 1. Will it fit? */
225 // WillItFit() is the same as: NewData.len <= (me->size - me->data_len)
226 // Check #1 makes sure subtraction in RoomLeft will not wrap around
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700227 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800228 // The new data will not fit into the the buffer.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700229 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800230 return;
231 }
232
233 /* 2. Check the Insertion Position */
234 // This, with Check #1, also confirms that uInsertionPos <= me->data_len
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700235 if(uInsertionPos > pMe->data_len) { // Check #3
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800236 // Off the end of the valid data in the buffer.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700237 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800238 return;
239 }
240
241 /* 3. Slide existing data to the right */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700242 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
243 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800244 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
245
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700246 if(uNumBytesToMove && pMe->UB.ptr) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800247 // To know memmove won't go off end of destination, see PtrMath #4
248 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
249 }
250
251 /* 4. Put the new data in */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700252 uint8_t *pInsertionPoint = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #5
253 if(pMe->UB.ptr) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800254 // To know memmove won't go off end of destination, see PtrMath #6
255 memmove(pInsertionPoint, NewData.ptr, NewData.len);
256 }
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700257 pMe->data_len += NewData.len ;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800258}
259
260
261/*
262 Rationale that describes why the above pointer math is safe
263
264 PtrMath #1 will never wrap around over because
265 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
266 Check #1 makes sure me->data_len is less than me->UB.len
267 Check #3 makes sure uInsertionPos is less than me->data_len
268
269 PtrMath #2 will never wrap around under because
270 Check #3 makes sure uInsertionPos is less than me->data_len
271
272 PtrMath #3 will never wrap around over because todo
273 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and a maximum valid ptr
274 Check #2 that NewData.len will fit
275
276 PtrMath #4 will never wrap under because
277 Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
278 Check #3 makes sure uInsertionPos is less than me->data_len
279 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
280 This algebraically rearranges to me->size > uInsertionPos + NewData.len
281
282 PtrMath #5 is exactly the same as PtrMath #1
283
284 PtrMath #6 will never wrap under because
285 Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
286 Check #1 makes sure me->data_len is less than me->size
287 Check #3 makes sure uInsertionPos is less than me->data_len
288 */
289
290
291/*
292 Public function -- see UsefulBuf.h
293 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700294UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800295{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700296 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800297 return NULLUsefulBufC;
298 }
299
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700300 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
301 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800302 return NULLUsefulBufC;
303 }
304
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700305 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800306}
307
308
309/*
310 Public function -- see UsefulBuf.h
311
312 Copy out the data accumulated in to the output buffer.
313 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700314UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800315{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700316 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800317 if(UsefulBuf_IsNULLC(Tmp)) {
318 return NULLUsefulBufC;
319 }
320 return UsefulBuf_Copy(pDest, Tmp);
321}
322
323
324
325
326/*
327 Public function -- see UsefulBuf.h
328
329 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
330
331 Code Reviewers: THIS FUNCTION DOES POINTER MATH
332 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700333const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800334{
335 // Already in error state. Do nothing.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700336 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800337 return NULL;
338 }
339
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700340 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800341 // The number of bytes asked for at current position are more than available
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700342 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800343 return NULL;
344 }
345
346 // This is going to succeed
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700347 const void * const result = ((uint8_t *)pMe->UB.ptr) + pMe->cursor;
348 pMe->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800349 return result;
350}
351