blob: dcd7d34ac3f445a9b69b9d9fec7cd841b3034e76 [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 Lundbladedc6e28e2018-10-11 19:19:27 +053088 if(Src.len > Dest.len) {
Laurence Lundblade2296db52018-09-14 18:08:39 -070089 return NULLUsefulBufC;
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053090 }
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070091
Laurence Lundblade2296db52018-09-14 18:08:39 -070092 memcpy(Dest.ptr, Src.ptr, Src.len);
93
94 return((UsefulBufC){Dest.ptr, Src.len});
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070095}
96
Laurence Lundblade041ffa52018-10-07 11:43:51 +070097
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053098/*
99 Public function -- see UsefulBuf.h
100 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700101UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
102{
Laurence Lundblade7566b9f2018-10-12 09:13:32 +0800103 // Do this with subtraction so it doesn't give erroneous result if uOffset + Src.len overflows
104 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
105 return NULLUsefulBufC;
106 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700107
Laurence Lundblade570fab52018-10-13 18:28:27 +0800108 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700109
Laurence Lundblade7566b9f2018-10-12 09:13:32 +0800110 return((UsefulBufC){Dest.ptr, Src.len + uOffset});
Laurence Lundblade041ffa52018-10-07 11:43:51 +0700111}
112
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530113
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700114/*
115 Public function -- see UsefulBuf.h
116 */
117int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
118{
119 // use the comparisons rather than subtracting lengths to
120 // return an int instead of a size_t
121 if(UB1.len < UB2.len) {
122 return -1;
123 } else if (UB1.len > UB2.len) {
124 return 1;
125 } // else UB1.len == UB2.len
126
127 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
128}
129
130
Laurence Lundbladeda3f0822018-09-18 19:49:02 -0700131
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700132/*
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530133 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700134 */
135size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
136{
137 if(BytesToSearch.len < BytesToFind.len) {
138 return SIZE_MAX;
139 }
140
141 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
142 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
143 return uPos;
144 }
145 }
146
147 return SIZE_MAX;
148}
149
150
151/*
152 Public function -- see UsefulBuf.h
153
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530154 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700155 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700156void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
157{
158 me->magic = USEFUL_OUT_BUF_MAGIC;
159 UsefulOutBuf_Reset(me);
160 me->UB = Storage;
161
Laurence Lundblade2296db52018-09-14 18:08:39 -0700162#if 0
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530163 // This check is off by default.
164
165 // The following check fails on ThreadX
166
Laurence Lundblade2296db52018-09-14 18:08:39 -0700167 // Sanity check on the pointer and size to be sure we are not
168 // passed a buffer that goes off the end of the address space.
169 // Given this test, we know that all unsigned lengths less than
170 // me->size are valid and won't wrap in any pointer additions
171 // based off of pStorage in the rest of this code.
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530172 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
173 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
Laurence Lundblade2296db52018-09-14 18:08:39 -0700174 me->err = 1;
175#endif
176}
177
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700178
179
180/*
181 Public function -- see UsefulBuf.h
182
183 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
184
185 Code Reviewers: THIS FUNCTION DOES POINTER MATH
186
187 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
188
189 Destination is represented as:
190 me->UB.ptr -- start of the buffer
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700191 me->UB.len -- size of the buffer UB.ptr
192 me->data_len -- length of value data in UB
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700193
194 Source is data:
195 NewData.ptr -- start of source buffer
196 NewData.len -- length of source buffer
197
198 Insertion point:
199 uInsertionPos.
200
201 Steps:
202
203 0. Corruption checks on UsefulOutBuf
204
205 1. Figure out if the new data will fit or not
206
207 2. Is insertion position in the range of valid data?
208
209 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
210
211 4. Put the new data in at the insertion position.
212
213 */
214void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
215{
216 if(me->err) {
217 // Already in error state.
218 return;
219 }
220
221 /* 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.
226 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
227 me->err = 1;
228 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 Lundblade2296db52018-09-14 18:08:39 -0700234 if(me->data_len > me->UB.len) { // Check #1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700235 me->err = 1;
236 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
237 }
238
239 /* 1. Will it fit? */
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700240 // WillItFit() is the same as: NewData.len <= (me->size - me->data_len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700241 // Check #1 makes sure subtraction in RoomLeft will not wrap around
242 if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
243 // The new data will not fit into the the buffer.
244 me->err = 1;
245 return;
246 }
247
248 /* 2. Check the Insertion Position */
249 // This, with Check #1, also confirms that uInsertionPos <= me->size
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530250 if(uInsertionPos > me->data_len) { // Check #3
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700251 // Off the end of the valid data in the buffer.
252 me->err = 1;
253 return;
254 }
255
256 /* 3. Slide existing data to the right */
257 uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700258 size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700259 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade2296db52018-09-14 18:08:39 -0700260 size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700261
262 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700263 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700264 }
265
266 /* 4. Put the new data in */
267 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundblade2296db52018-09-14 18:08:39 -0700268 uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700269 if(me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700270 memmove(pInsertionPoint, NewData.ptr, NewData.len);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700271 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700272 me->data_len += NewData.len ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273}
274
275
276/*
277 Rationale that describes why the above pointer math is safe
278
279 PtrMath #1 will never wrap around over because
280 Check #0 in UsefulOutBuf_Init makes sure me-UB.ptr + me->size doesn't wrap
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700281 Check #1 makes sure me->data_len is less than me->UB.len
282 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700283
284 PtrMath #2 will never wrap around under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700285 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286
287 PtrMath #3 will never wrap around over because todo
288 PtrMath #1 is checked resulting in pStartOfDataToMove being between me->UB.ptr and a maximum valid ptr
289
290 PtrMath #4 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700291 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700292 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
293 This algebraically rearranges to me->size > uInsertionPos + NewData.len
294
295 PtrMath #5 is exactly the same as PtrMath #1
296
297 PtrMath #6 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700298 Check #1 makes sure me->data_len is less than me->size
299 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700300 */
301
302
303/*
Laurence Lundblade2296db52018-09-14 18:08:39 -0700304 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700305 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700306UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700307{
308 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700309 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700310 }
311
312 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
313 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700314 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700315 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700316
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530317 return(UsefulBufC){me->UB.ptr,me->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318}
319
320
321/*
322 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700323
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530324 Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700325 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530326UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700327{
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530328 UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
329 if(UsefulBuf_IsNULLC(Tmp)) {
330 return NULLUsefulBufC;
331 }
332 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700333}
334
335
336
337
338/*
339 Public function -- see UsefulBuf.h
340
341 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
342
343 Code Reviewers: THIS FUNCTION DOES POINTER MATH
344 */
345const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
346{
347 // Already in error state. Do nothing.
348 if(me->err) {
349 return NULL;
350 }
351
352 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
353 // The number of bytes asked for at current position are more than available
354 me->err = 1;
355 return NULL;
356 }
357
358 // This is going to succeed
359 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
360 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
361 return result;
362}
363