blob: d98ebd58621cbffc2f6d90de5baa5fa148b5643d [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
2Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, are permitted provided that the following conditions are
6met:
7 * Redistributions of source code must retain the above copyright
8 notice, this list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above
10 copyright notice, this list of conditions and the following
11 disclaimer in the documentation and/or other materials provided
12 with the distribution.
13 * Neither the name of The Linux Foundation nor the names of its
14 contributors may be used to endorse or promote products derived
15 from this software without specific prior written permission.
16
17THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28==============================================================================*/
29
30/*===================================================================================
31 FILE: UsefulBuf.c
32
33 DESCRIPTION: General purpose input and output buffers
34
35 EDIT HISTORY FOR FILE:
36
37 This section contains comments describing changes made to the module.
38 Notice that changes are listed in reverse chronological order.
39
40 when who what, where, why
41 -------- ---- ---------------------------------------------------
42 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
43 the end of memory when the bytes to find is longer
44 than the bytes to search.
45 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
46 for < or > for unequal length buffers. Added
47 UsefulBuf_Set() function.
48 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
49 11/13/16 llundbla Initial Version.
50
51 =====================================================================================*/
52
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070053#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070054
55#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs
56
57/*
58 Public function -- see UsefulBuf.h
59 */
Laurence Lundblade2296db52018-09-14 18:08:39 -070060UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070061{
Laurence Lundblade2296db52018-09-14 18:08:39 -070062 if(Src.len > Dest.len)
63 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070064
Laurence Lundblade2296db52018-09-14 18:08:39 -070065 memcpy(Dest.ptr, Src.ptr, Src.len);
66
67 return((UsefulBufC){Dest.ptr, Src.len});
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070068}
69
70/*
71 Public function -- see UsefulBuf.h
72 */
73int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
74{
75 // use the comparisons rather than subtracting lengths to
76 // return an int instead of a size_t
77 if(UB1.len < UB2.len) {
78 return -1;
79 } else if (UB1.len > UB2.len) {
80 return 1;
81 } // else UB1.len == UB2.len
82
83 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
84}
85
86
87/*
88 Public function -- see UsefulBuf.h
89 */
90void UsefulBuf_Set(UsefulBuf *pDest, uint8_t value)
91{
92 memset(pDest->ptr, value, pDest->len);
93}
94
95
96/*
97 returns SIZE_MAX when there is no match
98 */
99size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
100{
101 if(BytesToSearch.len < BytesToFind.len) {
102 return SIZE_MAX;
103 }
104
105 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
106 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
107 return uPos;
108 }
109 }
110
111 return SIZE_MAX;
112}
113
114
115/*
116 Public function -- see UsefulBuf.h
117
118 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
119
120 THIS FUNCTION DOES POINTER MATH
121 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700122#if NODEF
123void UsefulOutBuf_InitOld(UsefulOutBuf *me, void *pStorage, size_t uStorageSize)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700124{
125 me->magic = USEFUL_OUT_BUF_MAGIC;
126 UsefulOutBuf_Reset(me);
127
128 me->UB.ptr = pStorage;
129 me->size = uStorageSize;
130
131 // The following check fails on ThreadX
132#if 0
133 // Sanity check on the pointer and size to be sure we are not
134 // passed a buffer that goes off the end of the address space.
135 // Given this test, we know that all unsigned lengths less than
136 // me->size are valid and won't wrap in any pointer additions
137 // based off of pStorage in the rest of this code.
138 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
139 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
140 me->err = 1;
141#endif
142}
Laurence Lundblade2296db52018-09-14 18:08:39 -0700143#endif
144
145void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
146{
147 me->magic = USEFUL_OUT_BUF_MAGIC;
148 UsefulOutBuf_Reset(me);
149 me->UB = Storage;
150
151 // The following check fails on ThreadX
152#if 0
153 // Sanity check on the pointer and size to be sure we are not
154 // passed a buffer that goes off the end of the address space.
155 // Given this test, we know that all unsigned lengths less than
156 // me->size are valid and won't wrap in any pointer additions
157 // based off of pStorage in the rest of this code.
158 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
159 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
160 me->err = 1;
161#endif
162}
163
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164
165
166/*
167 Public function -- see UsefulBuf.h
168
169 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
170
171 Code Reviewers: THIS FUNCTION DOES POINTER MATH
172
173 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
174
175 Destination is represented as:
176 me->UB.ptr -- start of the buffer
177 me->UB.len -- length of valid data in the buffer
178 me->size -- size of the buffer UB.ptr
179
180 Source is data:
181 NewData.ptr -- start of source buffer
182 NewData.len -- length of source buffer
183
184 Insertion point:
185 uInsertionPos.
186
187 Steps:
188
189 0. Corruption checks on UsefulOutBuf
190
191 1. Figure out if the new data will fit or not
192
193 2. Is insertion position in the range of valid data?
194
195 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
196
197 4. Put the new data in at the insertion position.
198
199 */
200void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
201{
202 if(me->err) {
203 // Already in error state.
204 return;
205 }
206
207 /* 0. Sanity check the UsefulOutBuf structure */
208 // A "counter measure". If magic number is not the right number it
209 // probably means me was not initialized or it was corrupted. Attackers
210 // can defeat this, but it is a hurdle and does good with very
211 // little code.
212 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
213 me->err = 1;
214 return; // Magic number is wrong due to uninitalization or corrption
215 }
216
217 // Make sure valid data is less than buffer size. This would only occur
218 // if there was corruption of me, but it is also part of the checks to
219 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700220 if(me->data_len > me->UB.len) { // Check #1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700221 me->err = 1;
222 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
223 }
224
225 /* 1. Will it fit? */
226 // WillItFit() is the same as: NewData.len <= (me->size - me->UB.len)
227 // Check #1 makes sure subtraction in RoomLeft will not wrap around
228 if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
229 // The new data will not fit into the the buffer.
230 me->err = 1;
231 return;
232 }
233
234 /* 2. Check the Insertion Position */
235 // This, with Check #1, also confirms that uInsertionPos <= me->size
236 if(uInsertionPos > me->UB.len) { // Check #3
237 // Off the end of the valid data in the buffer.
238 me->err = 1;
239 return;
240 }
241
242 /* 3. Slide existing data to the right */
243 uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
244 size_t uNumBytesToMove = me->UB.len - uInsertionPos; // PtrMath #2
245 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade2296db52018-09-14 18:08:39 -0700246 size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247
248 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700249 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700250 }
251
252 /* 4. Put the new data in */
253 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundblade2296db52018-09-14 18:08:39 -0700254 uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255 if(me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700256 memmove(pInsertionPoint, NewData.ptr, NewData.len);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700258 me->data_len += NewData.len ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259}
260
261
262/*
263 Rationale that describes why the above pointer math is safe
264
265 PtrMath #1 will never wrap around over because
266 Check #0 in UsefulOutBuf_Init makes sure me-UB.ptr + me->size doesn't wrap
267 Check #1 makes sure me->UB.len is less than me->size
268 Check #3 makes sure uInsertionPos is less than me->UB.len
269
270 PtrMath #2 will never wrap around under because
271 Check #3 makes sure uInsertionPos is less than me->UB.len
272
273 PtrMath #3 will never wrap around over because todo
274 PtrMath #1 is checked resulting in pStartOfDataToMove being between me->UB.ptr and a maximum valid ptr
275
276 PtrMath #4 will never wrap under because
277 Check #3 makes sure uInsertionPos is less than me->UB.len
278 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
279 This algebraically rearranges to me->size > uInsertionPos + NewData.len
280
281 PtrMath #5 is exactly the same as PtrMath #1
282
283 PtrMath #6 will never wrap under because
284 Check #1 makes sure me->UB.len is less than me->size
285 Check #3 makes sure uInsertionPos is less than me->UB.len
286 */
287
288
289/*
Laurence Lundblade2296db52018-09-14 18:08:39 -0700290 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700291 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700292UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293{
294 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700295 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700296 }
297
298 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
299 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700300 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700301 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700302
303 return(UsefulBufC){me->UB.ptr,me->data_len};
304}
305
306
307UsefulBufC UsefulOutBuf_CopyOut2(UsefulOutBuf *me, UsefulBuf pDest)
308{
309 UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
310 if(UsefulBuf_IsNULL(Tmp)) {
311 return NULLUsefulBufC;
312 }
313
314 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700315}
316
317
318/*
319 Public function -- see UsefulBuf.h
320
321 Copy out the data accumulated in the output buffer.
322
323 */
324int UsefulOutBuf_CopyOut(UsefulOutBuf *me, void *pBuf, size_t uBufSize, size_t *puCopied)
325{
Laurence Lundblade2296db52018-09-14 18:08:39 -0700326 UsefulBufC B = UsefulOutBuf_CopyOut2(me, (UsefulBuf){pBuf, uBufSize});
327 if(UsefulBuf_IsNULL(B)) {
328 return 1; // was in error state or was corrupted or pBuf too small
329 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700330
Laurence Lundblade2296db52018-09-14 18:08:39 -0700331 *puCopied = B.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700332
333 return 0;
334}
335
336
337
338
339/*
340 Public function -- see UsefulBuf.h
341
342 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
343
344 Code Reviewers: THIS FUNCTION DOES POINTER MATH
345 */
346const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
347{
348 // Already in error state. Do nothing.
349 if(me->err) {
350 return NULL;
351 }
352
353 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
354 // The number of bytes asked for at current position are more than available
355 me->err = 1;
356 return NULL;
357 }
358
359 // This is going to succeed
360 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
361 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
362 return result;
363}
364