blob: 3aa64069237a92e7f52b7c2c8715ed9faa6d0735 [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
Laurence Lundblade624405d2018-09-18 20:10:47 -070030/*==============================================================================
31 Modifications beyond the version released on CAF are under the MIT license:
32
33 Copyright 2018 Laurence Lundblade
34
35 Permission is hereby granted, free of charge, to any person obtaining
36 a copy of this software and associated documentation files (the
37 "Software"), to deal in the Software without restriction, including
38 without limitation the rights to use, copy, modify, merge, publish,
39 distribute, sublicense, and/or sell copies of the Software, and to
40 permit persons to whom the Software is furnished to do so, subject to
41 the following conditions:
42
43 The above copyright notice and this permission notice shall be included
44 in all copies or substantial portions of the Software.
45
46 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
47 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
48 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
49 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
50 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
51 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
52 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
53 SOFTWARE.
54 ==============================================================================*/
55
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056/*===================================================================================
57 FILE: UsefulBuf.c
58
59 DESCRIPTION: General purpose input and output buffers
60
61 EDIT HISTORY FOR FILE:
62
63 This section contains comments describing changes made to the module.
64 Notice that changes are listed in reverse chronological order.
65
66 when who what, where, why
67 -------- ---- ---------------------------------------------------
68 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
69 the end of memory when the bytes to find is longer
70 than the bytes to search.
71 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
72 for < or > for unequal length buffers. Added
73 UsefulBuf_Set() function.
74 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
75 11/13/16 llundbla Initial Version.
76
77 =====================================================================================*/
78
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070079#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070080
81#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs
82
83/*
84 Public function -- see UsefulBuf.h
85 */
Laurence Lundblade2296db52018-09-14 18:08:39 -070086UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070087{
Laurence Lundblade2296db52018-09-14 18:08:39 -070088 if(Src.len > Dest.len)
89 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090
Laurence Lundblade2296db52018-09-14 18:08:39 -070091 memcpy(Dest.ptr, Src.ptr, Src.len);
92
93 return((UsefulBufC){Dest.ptr, Src.len});
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070094}
95
Laurence Lundblade041ffa52018-10-07 11:43:51 +070096
97UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
98{
99 if(Src.len > Dest.len - uOffset) {
100 return NULLUsefulBufC;
101 }
102
103 memcpy(Dest.ptr + uOffset, Src.ptr, Src.len);
104
105 return((UsefulBufC){Dest.ptr, Src.len});
106}
107
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700108/*
109 Public function -- see UsefulBuf.h
110 */
111int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
112{
113 // use the comparisons rather than subtracting lengths to
114 // return an int instead of a size_t
115 if(UB1.len < UB2.len) {
116 return -1;
117 } else if (UB1.len > UB2.len) {
118 return 1;
119 } // else UB1.len == UB2.len
120
121 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
122}
123
124
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700125
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700126
127
128/*
129 returns SIZE_MAX when there is no match
130 */
131size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
132{
133 if(BytesToSearch.len < BytesToFind.len) {
134 return SIZE_MAX;
135 }
136
137 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
138 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
139 return uPos;
140 }
141 }
142
143 return SIZE_MAX;
144}
145
146
147/*
148 Public function -- see UsefulBuf.h
149
150 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
151
152 THIS FUNCTION DOES POINTER MATH
153 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700154#if NODEF
155void UsefulOutBuf_InitOld(UsefulOutBuf *me, void *pStorage, size_t uStorageSize)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156{
157 me->magic = USEFUL_OUT_BUF_MAGIC;
158 UsefulOutBuf_Reset(me);
159
160 me->UB.ptr = pStorage;
161 me->size = uStorageSize;
162
163 // The following check fails on ThreadX
164#if 0
165 // 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.
170 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
171 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
172 me->err = 1;
173#endif
174}
Laurence Lundblade2296db52018-09-14 18:08:39 -0700175#endif
176
177void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
178{
179 me->magic = USEFUL_OUT_BUF_MAGIC;
180 UsefulOutBuf_Reset(me);
181 me->UB = Storage;
182
183 // The following check fails on ThreadX
184#if 0
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700185 // TODO: fix this for new way of doing storage
Laurence Lundblade2296db52018-09-14 18:08:39 -0700186 // Sanity check on the pointer and size to be sure we are not
187 // passed a buffer that goes off the end of the address space.
188 // Given this test, we know that all unsigned lengths less than
189 // me->size are valid and won't wrap in any pointer additions
190 // based off of pStorage in the rest of this code.
191 const uintptr_t ptrM = UINTPTR_MAX - uStorageSize;
192 if(pStorage && (uintptr_t)pStorage > ptrM) // Check #0
193 me->err = 1;
194#endif
195}
196
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700197
198
199/*
200 Public function -- see UsefulBuf.h
201
202 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
203
204 Code Reviewers: THIS FUNCTION DOES POINTER MATH
205
206 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
207
208 Destination is represented as:
209 me->UB.ptr -- start of the buffer
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700210 me->UB.len -- size of the buffer UB.ptr
211 me->data_len -- length of value data in UB
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700212
213 Source is data:
214 NewData.ptr -- start of source buffer
215 NewData.len -- length of source buffer
216
217 Insertion point:
218 uInsertionPos.
219
220 Steps:
221
222 0. Corruption checks on UsefulOutBuf
223
224 1. Figure out if the new data will fit or not
225
226 2. Is insertion position in the range of valid data?
227
228 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
229
230 4. Put the new data in at the insertion position.
231
232 */
233void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
234{
235 if(me->err) {
236 // Already in error state.
237 return;
238 }
239
240 /* 0. Sanity check the UsefulOutBuf structure */
241 // A "counter measure". If magic number is not the right number it
242 // probably means me was not initialized or it was corrupted. Attackers
243 // can defeat this, but it is a hurdle and does good with very
244 // little code.
245 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
246 me->err = 1;
247 return; // Magic number is wrong due to uninitalization or corrption
248 }
249
250 // Make sure valid data is less than buffer size. This would only occur
251 // if there was corruption of me, but it is also part of the checks to
252 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700253 if(me->data_len > me->UB.len) { // Check #1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700254 me->err = 1;
255 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
256 }
257
258 /* 1. Will it fit? */
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700259 // WillItFit() is the same as: NewData.len <= (me->size - me->data_len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260 // Check #1 makes sure subtraction in RoomLeft will not wrap around
261 if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
262 // The new data will not fit into the the buffer.
263 me->err = 1;
264 return;
265 }
266
267 /* 2. Check the Insertion Position */
268 // This, with Check #1, also confirms that uInsertionPos <= me->size
269 if(uInsertionPos > me->UB.len) { // Check #3
270 // Off the end of the valid data in the buffer.
271 me->err = 1;
272 return;
273 }
274
275 /* 3. Slide existing data to the right */
276 uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700277 size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700278 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade2296db52018-09-14 18:08:39 -0700279 size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700280
281 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700282 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700283 }
284
285 /* 4. Put the new data in */
286 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundblade2296db52018-09-14 18:08:39 -0700287 uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700288 if(me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700289 memmove(pInsertionPoint, NewData.ptr, NewData.len);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700290 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700291 me->data_len += NewData.len ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700292}
293
294
295/*
296 Rationale that describes why the above pointer math is safe
297
298 PtrMath #1 will never wrap around over because
299 Check #0 in UsefulOutBuf_Init makes sure me-UB.ptr + me->size doesn't wrap
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700300 Check #1 makes sure me->data_len is less than me->UB.len
301 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700302
303 PtrMath #2 will never wrap around under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700304 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700305
306 PtrMath #3 will never wrap around over because todo
307 PtrMath #1 is checked resulting in pStartOfDataToMove being between me->UB.ptr and a maximum valid ptr
308
309 PtrMath #4 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700310 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700311 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
312 This algebraically rearranges to me->size > uInsertionPos + NewData.len
313
314 PtrMath #5 is exactly the same as PtrMath #1
315
316 PtrMath #6 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700317 Check #1 makes sure me->data_len is less than me->size
318 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700319 */
320
321
322/*
Laurence Lundblade2296db52018-09-14 18:08:39 -0700323 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700324 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700325UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700326{
327 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700328 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700329 }
330
331 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
332 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700333 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700334 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700335
336 return(UsefulBufC){me->UB.ptr,me->data_len};
337}
338
339
340UsefulBufC UsefulOutBuf_CopyOut2(UsefulOutBuf *me, UsefulBuf pDest)
341{
342 UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700343 if(UsefulBuf_IsNULLC(Tmp)) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700344 return NULLUsefulBufC;
345 }
346
347 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700348}
349
350
351/*
352 Public function -- see UsefulBuf.h
353
354 Copy out the data accumulated in the output buffer.
355
356 */
357int UsefulOutBuf_CopyOut(UsefulOutBuf *me, void *pBuf, size_t uBufSize, size_t *puCopied)
358{
Laurence Lundblade2296db52018-09-14 18:08:39 -0700359 UsefulBufC B = UsefulOutBuf_CopyOut2(me, (UsefulBuf){pBuf, uBufSize});
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700360 if(UsefulBuf_IsNULLC(B)) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700361 return 1; // was in error state or was corrupted or pBuf too small
362 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700363
Laurence Lundblade2296db52018-09-14 18:08:39 -0700364 *puCopied = B.len;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700365
366 return 0;
367}
368
369
370
371
372/*
373 Public function -- see UsefulBuf.h
374
375 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
376
377 Code Reviewers: THIS FUNCTION DOES POINTER MATH
378 */
379const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
380{
381 // Already in error state. Do nothing.
382 if(me->err) {
383 return NULL;
384 }
385
386 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
387 // The number of bytes asked for at current position are more than available
388 me->err = 1;
389 return NULL;
390 }
391
392 // This is going to succeed
393 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
394 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
395 return result;
396}
397