blob: ea6978c731d17e4a49fa67cbb3c87523a707d54b [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
Laurence Lundbladeda3f0822018-09-18 19:49:02 -070087
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070088
89
90/*
91 returns SIZE_MAX when there is no match
92 */
93size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
94{
95 if(BytesToSearch.len < BytesToFind.len) {
96 return SIZE_MAX;
97 }
98
99 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
100 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
101 return uPos;
102 }
103 }
104
105 return SIZE_MAX;
106}
107
108
109/*
110 Public function -- see UsefulBuf.h
111
112 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
113
114 THIS FUNCTION DOES POINTER MATH
115 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700116#if NODEF
117void UsefulOutBuf_InitOld(UsefulOutBuf *me, void *pStorage, size_t uStorageSize)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118{
119 me->magic = USEFUL_OUT_BUF_MAGIC;
120 UsefulOutBuf_Reset(me);
121
122 me->UB.ptr = pStorage;
123 me->size = uStorageSize;
124
125 // The following check fails on ThreadX
126#if 0
127 // Sanity check on the pointer and size to be sure we are not
128 // passed a buffer that goes off the end of the address space.
129 // Given this test, we know that all unsigned lengths less than
130 // me->size are valid and won't wrap in any pointer additions
131 // based off of pStorage in the rest of this code.
132 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
133 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
134 me->err = 1;
135#endif
136}
Laurence Lundblade2296db52018-09-14 18:08:39 -0700137#endif
138
139void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
140{
141 me->magic = USEFUL_OUT_BUF_MAGIC;
142 UsefulOutBuf_Reset(me);
143 me->UB = Storage;
144
145 // The following check fails on ThreadX
146#if 0
147 // Sanity check on the pointer and size to be sure we are not
148 // passed a buffer that goes off the end of the address space.
149 // Given this test, we know that all unsigned lengths less than
150 // me->size are valid and won't wrap in any pointer additions
151 // based off of pStorage in the rest of this code.
152 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
153 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
154 me->err = 1;
155#endif
156}
157
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700158
159
160/*
161 Public function -- see UsefulBuf.h
162
163 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
164
165 Code Reviewers: THIS FUNCTION DOES POINTER MATH
166
167 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
168
169 Destination is represented as:
170 me->UB.ptr -- start of the buffer
171 me->UB.len -- length of valid data in the buffer
172 me->size -- size of the buffer UB.ptr
173
174 Source is data:
175 NewData.ptr -- start of source buffer
176 NewData.len -- length of source buffer
177
178 Insertion point:
179 uInsertionPos.
180
181 Steps:
182
183 0. Corruption checks on UsefulOutBuf
184
185 1. Figure out if the new data will fit or not
186
187 2. Is insertion position in the range of valid data?
188
189 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
190
191 4. Put the new data in at the insertion position.
192
193 */
194void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
195{
196 if(me->err) {
197 // Already in error state.
198 return;
199 }
200
201 /* 0. Sanity check the UsefulOutBuf structure */
202 // A "counter measure". If magic number is not the right number it
203 // probably means me was not initialized or it was corrupted. Attackers
204 // can defeat this, but it is a hurdle and does good with very
205 // little code.
206 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
207 me->err = 1;
208 return; // Magic number is wrong due to uninitalization or corrption
209 }
210
211 // Make sure valid data is less than buffer size. This would only occur
212 // if there was corruption of me, but it is also part of the checks to
213 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700214 if(me->data_len > me->UB.len) { // Check #1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700215 me->err = 1;
216 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
217 }
218
219 /* 1. Will it fit? */
220 // WillItFit() is the same as: NewData.len <= (me->size - me->UB.len)
221 // Check #1 makes sure subtraction in RoomLeft will not wrap around
222 if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
223 // The new data will not fit into the the buffer.
224 me->err = 1;
225 return;
226 }
227
228 /* 2. Check the Insertion Position */
229 // This, with Check #1, also confirms that uInsertionPos <= me->size
230 if(uInsertionPos > me->UB.len) { // Check #3
231 // Off the end of the valid data in the buffer.
232 me->err = 1;
233 return;
234 }
235
236 /* 3. Slide existing data to the right */
237 uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
238 size_t uNumBytesToMove = me->UB.len - uInsertionPos; // PtrMath #2
239 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade2296db52018-09-14 18:08:39 -0700240 size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700241
242 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700243 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700244 }
245
246 /* 4. Put the new data in */
247 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundblade2296db52018-09-14 18:08:39 -0700248 uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700249 if(me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700250 memmove(pInsertionPoint, NewData.ptr, NewData.len);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700252 me->data_len += NewData.len ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700253}
254
255
256/*
257 Rationale that describes why the above pointer math is safe
258
259 PtrMath #1 will never wrap around over because
260 Check #0 in UsefulOutBuf_Init makes sure me-UB.ptr + me->size doesn't wrap
261 Check #1 makes sure me->UB.len is less than me->size
262 Check #3 makes sure uInsertionPos is less than me->UB.len
263
264 PtrMath #2 will never wrap around under because
265 Check #3 makes sure uInsertionPos is less than me->UB.len
266
267 PtrMath #3 will never wrap around over because todo
268 PtrMath #1 is checked resulting in pStartOfDataToMove being between me->UB.ptr and a maximum valid ptr
269
270 PtrMath #4 will never wrap under because
271 Check #3 makes sure uInsertionPos is less than me->UB.len
272 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
273 This algebraically rearranges to me->size > uInsertionPos + NewData.len
274
275 PtrMath #5 is exactly the same as PtrMath #1
276
277 PtrMath #6 will never wrap under because
278 Check #1 makes sure me->UB.len is less than me->size
279 Check #3 makes sure uInsertionPos is less than me->UB.len
280 */
281
282
283/*
Laurence Lundblade2296db52018-09-14 18:08:39 -0700284 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700285 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700286UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700287{
288 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700289 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700290 }
291
292 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
293 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700294 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700295 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700296
297 return(UsefulBufC){me->UB.ptr,me->data_len};
298}
299
300
301UsefulBufC UsefulOutBuf_CopyOut2(UsefulOutBuf *me, UsefulBuf pDest)
302{
303 UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700304 if(UsefulBuf_IsNULLC(Tmp)) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700305 return NULLUsefulBufC;
306 }
307
308 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700309}
310
311
312/*
313 Public function -- see UsefulBuf.h
314
315 Copy out the data accumulated in the output buffer.
316
317 */
318int UsefulOutBuf_CopyOut(UsefulOutBuf *me, void *pBuf, size_t uBufSize, size_t *puCopied)
319{
Laurence Lundblade2296db52018-09-14 18:08:39 -0700320 UsefulBufC B = UsefulOutBuf_CopyOut2(me, (UsefulBuf){pBuf, uBufSize});
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700321 if(UsefulBuf_IsNULLC(B)) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700322 return 1; // was in error state or was corrupted or pBuf too small
323 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700324
Laurence Lundblade2296db52018-09-14 18:08:39 -0700325 *puCopied = B.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700326
327 return 0;
328}
329
330
331
332
333/*
334 Public function -- see UsefulBuf.h
335
336 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
337
338 Code Reviewers: THIS FUNCTION DOES POINTER MATH
339 */
340const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
341{
342 // Already in error state. Do nothing.
343 if(me->err) {
344 return NULL;
345 }
346
347 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
348 // The number of bytes asked for at current position are more than available
349 me->err = 1;
350 return NULL;
351 }
352
353 // This is going to succeed
354 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
355 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
356 return result;
357}
358