blob: 282b6adb6ba820582401f97d802f34d55316eba2 [file] [log] [blame]
Laurence Lundbladeb69cad72018-09-13 11:09:01 -07001/*==============================================================================
Laurence Lundbladed92a6162018-11-01 11:38:35 +07002 Copyright (c) 2016-2018, The Linux Foundation.
3 Copyright (c) 2018, Laurence Lundblade.
4 All rights reserved.
Laurence Lundblade624405d2018-09-18 20:10:47 -07005
Laurence Lundblade0dbc9172018-11-01 14:17:21 +07006Redistribution and use in source and binary forms, with or without
7modification, are permitted provided that the following conditions are
8met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above
12 copyright notice, this list of conditions and the following
13 disclaimer in the documentation and/or other materials provided
14 with the distribution.
15 * Neither the name of The Linux Foundation nor the names of its
16 contributors, nor the name "Laurence Lundblade" may be used to
17 endorse or promote products derived from this software without
18 specific prior written permission.
Laurence Lundblade624405d2018-09-18 20:10:47 -070019
Laurence Lundblade0dbc9172018-11-01 14:17:21 +070020THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
21WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
23ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
24BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
29OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundblade624405d2018-09-18 20:10:47 -070031 ==============================================================================*/
32
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070033/*===================================================================================
34 FILE: UsefulBuf.c
35
36 DESCRIPTION: General purpose input and output buffers
37
38 EDIT HISTORY FOR FILE:
39
40 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
42
43 when who what, where, why
44 -------- ---- ---------------------------------------------------
45 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
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070056#include "UsefulBuf.h"
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070057
58#define USEFUL_OUT_BUF_MAGIC (0x0B0F) // used to catch use of uninitialized or corrupted UOBs
59
Laurence Lundblade041ffa52018-10-07 11:43:51 +070060
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053061/*
62 Public function -- see UsefulBuf.h
63 */
Laurence Lundblade041ffa52018-10-07 11:43:51 +070064UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
65{
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080066 // 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 }
Laurence Lundblade041ffa52018-10-07 11:43:51 +070070
Laurence Lundblade570fab52018-10-13 18:28:27 +080071 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade041ffa52018-10-07 11:43:51 +070072
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -080073 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
Laurence Lundblade041ffa52018-10-07 11:43:51 +070074}
75
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053076
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070077/*
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 Lundbladeda3f0822018-09-18 19:49:02 -070094
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070095/*
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053096 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070097 */
98size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
99{
100 if(BytesToSearch.len < BytesToFind.len) {
101 return SIZE_MAX;
102 }
103
104 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
105 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
106 return uPos;
107 }
108 }
109
110 return SIZE_MAX;
111}
112
113
114/*
115 Public function -- see UsefulBuf.h
116
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530117 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700118 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700119void UsefulOutBuf_Init(UsefulOutBuf *me, UsefulBuf Storage)
120{
121 me->magic = USEFUL_OUT_BUF_MAGIC;
122 UsefulOutBuf_Reset(me);
123 me->UB = Storage;
124
Laurence Lundblade2296db52018-09-14 18:08:39 -0700125#if 0
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530126 // This check is off by default.
127
128 // The following check fails on ThreadX
129
Laurence Lundblade2296db52018-09-14 18:08:39 -0700130 // Sanity check on the pointer and size to be sure we are not
131 // passed a buffer that goes off the end of the address space.
132 // Given this test, we know that all unsigned lengths less than
133 // me->size are valid and won't wrap in any pointer additions
134 // based off of pStorage in the rest of this code.
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530135 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
136 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
Laurence Lundblade2296db52018-09-14 18:08:39 -0700137 me->err = 1;
138#endif
139}
140
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700141
142
143/*
144 Public function -- see UsefulBuf.h
145
146 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
147
148 Code Reviewers: THIS FUNCTION DOES POINTER MATH
149
150 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
151
152 Destination is represented as:
153 me->UB.ptr -- start of the buffer
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700154 me->UB.len -- size of the buffer UB.ptr
155 me->data_len -- length of value data in UB
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700156
157 Source is data:
158 NewData.ptr -- start of source buffer
159 NewData.len -- length of source buffer
160
161 Insertion point:
162 uInsertionPos.
163
164 Steps:
165
166 0. Corruption checks on UsefulOutBuf
167
168 1. Figure out if the new data will fit or not
169
170 2. Is insertion position in the range of valid data?
171
172 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
173
174 4. Put the new data in at the insertion position.
175
176 */
177void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
178{
179 if(me->err) {
180 // Already in error state.
181 return;
182 }
183
184 /* 0. Sanity check the UsefulOutBuf structure */
185 // A "counter measure". If magic number is not the right number it
186 // probably means me was not initialized or it was corrupted. Attackers
187 // can defeat this, but it is a hurdle and does good with very
188 // little code.
189 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
190 me->err = 1;
191 return; // Magic number is wrong due to uninitalization or corrption
192 }
193
194 // Make sure valid data is less than buffer size. This would only occur
195 // if there was corruption of me, but it is also part of the checks to
196 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade2296db52018-09-14 18:08:39 -0700197 if(me->data_len > me->UB.len) { // Check #1
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700198 me->err = 1;
199 return; // Offset of valid data is off the end of the UsefulOutBuf due to uninitialization or corruption
200 }
201
202 /* 1. Will it fit? */
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700203 // WillItFit() is the same as: NewData.len <= (me->size - me->data_len)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700204 // Check #1 makes sure subtraction in RoomLeft will not wrap around
205 if(! UsefulOutBuf_WillItFit(me, NewData.len)) { // Check #2
206 // The new data will not fit into the the buffer.
207 me->err = 1;
208 return;
209 }
210
211 /* 2. Check the Insertion Position */
212 // This, with Check #1, also confirms that uInsertionPos <= me->size
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530213 if(uInsertionPos > me->data_len) { // Check #3
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700214 // Off the end of the valid data in the buffer.
215 me->err = 1;
216 return;
217 }
218
219 /* 3. Slide existing data to the right */
220 uint8_t *pSourceOfMove = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #1
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700221 size_t uNumBytesToMove = me->data_len - uInsertionPos; // PtrMath #2
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700222 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
Laurence Lundblade2296db52018-09-14 18:08:39 -0700223 size_t uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len); // PtrMath #4
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700224
225 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700226 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700227 }
228
229 /* 4. Put the new data in */
230 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundblade2296db52018-09-14 18:08:39 -0700231 uRoomInDestination = me->UB.len - uInsertionPos; // PtrMath #6
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700232 if(me->UB.ptr) {
Laurence Lundblade74f68412018-09-13 12:18:49 -0700233 memmove(pInsertionPoint, NewData.ptr, NewData.len);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700234 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700235 me->data_len += NewData.len ;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700236}
237
238
239/*
240 Rationale that describes why the above pointer math is safe
241
242 PtrMath #1 will never wrap around over because
243 Check #0 in UsefulOutBuf_Init makes sure me-UB.ptr + me->size doesn't wrap
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700244 Check #1 makes sure me->data_len is less than me->UB.len
245 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700246
247 PtrMath #2 will never wrap around under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700248 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700249
250 PtrMath #3 will never wrap around over because todo
251 PtrMath #1 is checked resulting in pStartOfDataToMove being between me->UB.ptr and a maximum valid ptr
252
253 PtrMath #4 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700254 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700255 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
256 This algebraically rearranges to me->size > uInsertionPos + NewData.len
257
258 PtrMath #5 is exactly the same as PtrMath #1
259
260 PtrMath #6 will never wrap under because
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700261 Check #1 makes sure me->data_len is less than me->size
262 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700263 */
264
265
266/*
Laurence Lundblade2296db52018-09-14 18:08:39 -0700267 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700268 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700269UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700270{
271 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700272 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273 }
274
275 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
276 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700277 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700278 }
Laurence Lundblade2296db52018-09-14 18:08:39 -0700279
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800280 return (UsefulBufC){me->UB.ptr,me->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281}
282
283
284/*
285 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700286
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530287 Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700288 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530289UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700290{
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800291 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530292 if(UsefulBuf_IsNULLC(Tmp)) {
293 return NULLUsefulBufC;
294 }
295 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700296}
297
298
299
300
301/*
302 Public function -- see UsefulBuf.h
303
304 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
305
306 Code Reviewers: THIS FUNCTION DOES POINTER MATH
307 */
308const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
309{
310 // Already in error state. Do nothing.
311 if(me->err) {
312 return NULL;
313 }
314
315 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
316 // The number of bytes asked for at current position are more than available
317 me->err = 1;
318 return NULL;
319 }
320
321 // This is going to succeed
322 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
323 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
324 return result;
325}
326