blob: 964e81b1ca0ee02edf8caefbc9824063554cd600 [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 Lundblade3aee3a32018-12-17 16:17:45 -08005
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 Lundblade3aee3a32018-12-17 16:17:45 -080019
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
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080035
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070036 DESCRIPTION: General purpose input and output buffers
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080037
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070038 EDIT HISTORY FOR FILE:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080039
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070040 This section contains comments describing changes made to the module.
41 Notice that changes are listed in reverse chronological order.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080042
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070043 when who what, where, why
44 -------- ---- ---------------------------------------------------
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080045 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070046 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.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080053
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070054 =====================================================================================*/
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 Lundblade3aee3a32018-12-17 16:17:45 -080070
Laurence Lundblade570fab52018-10-13 18:28:27 +080071 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080072
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
Laurence Lundblade3aee3a32018-12-17 16:17:45 -080089
Laurence Lundbladeb69cad72018-09-13 11:09:01 -070090 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 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800103
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700104 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 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800109
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700110 return SIZE_MAX;
111}
112
113
114/*
115 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800116
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;
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800124
Laurence Lundblade2296db52018-09-14 18:08:39 -0700125#if 0
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530126 // This check is off by default.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800127
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530128 // 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
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800145
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700146 The core of UsefulOutBuf -- put some bytes in the buffer without writing off the end of it.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800147
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700148 Code Reviewers: THIS FUNCTION DOES POINTER MATH
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800149
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700150 This function inserts the source buffer, NewData, into the destination buffer, me->UB.ptr.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800151
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700152 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 Lundblade3aee3a32018-12-17 16:17:45 -0800156
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700157 Source is data:
158 NewData.ptr -- start of source buffer
159 NewData.len -- length of source buffer
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800160
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700161 Insertion point:
162 uInsertionPos.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800163
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700164 Steps:
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800165
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700166 0. Corruption checks on UsefulOutBuf
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800167
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700168 1. Figure out if the new data will fit or not
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800169
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700170 2. Is insertion position in the range of valid data?
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800171
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700172 3. If insertion point is not at the end, slide data to the right of the insertion point to the right
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800173
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700174 4. Put the new data in at the insertion position.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800175
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700176 */
177void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *me, UsefulBufC NewData, size_t uInsertionPos)
178{
179 if(me->err) {
180 // Already in error state.
181 return;
182 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800183
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700184 /* 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 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800201
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700202 /* 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 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800210
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700211 /* 2. Check the Insertion Position */
Laurence Lundblade56a79322019-01-10 09:12:37 -0800212 // This, with Check #1, also confirms that uInsertionPos <= me->data_len
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 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800218
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700219 /* 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 Lundblade3aee3a32018-12-17 16:17:45 -0800223
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700224 if(uNumBytesToMove && me->UB.ptr) {
Laurence Lundblade56a79322019-01-10 09:12:37 -0800225 // To know memmove won't go off end of destination, see PtrMath #4
Laurence Lundblade74f68412018-09-13 12:18:49 -0700226 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700227 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800228
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700229 /* 4. Put the new data in */
230 uint8_t *pInsertionPoint = ((uint8_t *)me->UB.ptr) + uInsertionPos; // PtrMath #5
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700231 if(me->UB.ptr) {
Laurence Lundblade56a79322019-01-10 09:12:37 -0800232 // To know memmove won't go off end of destination, see PtrMath #6
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
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800241
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700242 PtrMath #1 will never wrap around over because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800243 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
244 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 Lundblade3aee3a32018-12-17 16:17:45 -0800246
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700247 PtrMath #2 will never wrap around under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800248 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800249
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700250 PtrMath #3 will never wrap around over because todo
Laurence Lundblade56a79322019-01-10 09:12:37 -0800251 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and a maximum valid ptr
252 Check #2 that NewData.len will fit
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800253
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700254 PtrMath #4 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800255 Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
Laurence Lundblade9e7f4742018-09-20 18:50:31 -0700256 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700257 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
258 This algebraically rearranges to me->size > uInsertionPos + NewData.len
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800259
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700260 PtrMath #5 is exactly the same as PtrMath #1
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800261
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700262 PtrMath #6 will never wrap under because
Laurence Lundblade56a79322019-01-10 09:12:37 -0800263 Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
264 Check #1 makes sure me->data_len is less than me->size
265 Check #3 makes sure uInsertionPos is less than me->data_len
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700266 */
267
268
269/*
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800270 Public function -- see UsefulBuf.h
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700271 */
Laurence Lundblade2296db52018-09-14 18:08:39 -0700272UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *me)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700273{
274 if(me->err) {
Laurence Lundblade2296db52018-09-14 18:08:39 -0700275 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700276 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800277
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700278 if(me->magic != USEFUL_OUT_BUF_MAGIC) {
279 me->err = 1;
Laurence Lundblade2296db52018-09-14 18:08:39 -0700280 return NULLUsefulBufC;
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700281 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800282
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800283 return (UsefulBufC){me->UB.ptr,me->data_len};
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700284}
285
286
287/*
288 Public function -- see UsefulBuf.h
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800289
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530290 Copy out the data accumulated in to the output buffer.
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700291 */
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530292UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *me, UsefulBuf pDest)
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700293{
Laurence Lundblade25c6c0a2018-12-17 13:21:59 -0800294 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(me);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530295 if(UsefulBuf_IsNULLC(Tmp)) {
296 return NULLUsefulBufC;
297 }
298 return UsefulBuf_Copy(pDest, Tmp);
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700299}
300
301
302
303
304/*
305 Public function -- see UsefulBuf.h
306
307 The core of UsefulInputBuf -- consume some bytes without going off the end of the buffer.
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800308
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700309 Code Reviewers: THIS FUNCTION DOES POINTER MATH
310 */
311const void * UsefulInputBuf_GetBytes(UsefulInputBuf *me, size_t uAmount)
312{
313 // Already in error state. Do nothing.
314 if(me->err) {
315 return NULL;
316 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800317
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700318 if(!UsefulInputBuf_BytesAvailable(me, uAmount)) {
319 // The number of bytes asked for at current position are more than available
320 me->err = 1;
321 return NULL;
322 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800323
Laurence Lundbladeb69cad72018-09-13 11:09:01 -0700324 // This is going to succeed
325 const void * const result = ((uint8_t *)me->UB.ptr) + me->cursor;
326 me->cursor += uAmount; // this will not overflow because of check using UsefulInputBuf_BytesAvailable()
327 return result;
328}
329