blob: a96f74eb26c062e3494db8d826371d9fb5246ea1 [file] [log] [blame]
Laurence Lundblade6ed34222018-12-18 09:46:23 -08001/*==============================================================================
2 Copyright (c) 2016-2018, The Linux Foundation.
Laurence Lundbladeac515e52020-01-30 10:44:06 -08003 Copyright (c) 2018-2020, Laurence Lundblade.
Laurence Lundblade6ed34222018-12-18 09:46:23 -08004
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8 * Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above
11 copyright notice, this list of conditions and the following
12 disclaimer in the documentation and/or other materials provided
13 with the distribution.
14 * Neither the name of The Linux Foundation nor the names of its
15 contributors, nor the name "Laurence Lundblade" may be used to
16 endorse or promote products derived from this software without
17 specific prior written permission.
18
19THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Laurence Lundbladeac515e52020-01-30 10:44:06 -080030 =============================================================================*/
Laurence Lundblade6ed34222018-12-18 09:46:23 -080031
Laurence Lundbladeac515e52020-01-30 10:44:06 -080032/*=============================================================================
Laurence Lundblade6ed34222018-12-18 09:46:23 -080033 FILE: UsefulBuf.c
34
35 DESCRIPTION: General purpose input and output buffers
36
37 EDIT HISTORY FOR FILE:
38
39 This section contains comments describing changes made to the module.
40 Notice that changes are listed in reverse chronological order.
41
Laurence Lundbladeac515e52020-01-30 10:44:06 -080042 when who what, where, why
43 -------- ---- ---------------------------------------------------
44 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
45 01/08/2020 llundblade Documentation corrections & improved code formatting.
46 11/08/2019 llundblade Re check pointer math and update comments
47 3/6/2019 llundblade Add UsefulBuf_IsValue()
48 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
49 the end of memory when the bytes to find is longer
50 than the bytes to search.
51 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
52 for < or > for unequal length buffers. Added
53 UsefulBuf_Set() function.
54 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
55 11/13/16 llundbla Initial Version.
Laurence Lundblade6ed34222018-12-18 09:46:23 -080056
Laurence Lundbladeac515e52020-01-30 10:44:06 -080057 ============================================================================*/
Laurence Lundblade6ed34222018-12-18 09:46:23 -080058
59#include "UsefulBuf.h"
60
Laurence Lundbladeac515e52020-01-30 10:44:06 -080061// used to catch use of uninitialized or corrupted UsefulOutBuf
62#define USEFUL_OUT_BUF_MAGIC (0x0B0F)
Laurence Lundblade6ed34222018-12-18 09:46:23 -080063
64
65/*
66 Public function -- see UsefulBuf.h
67 */
68UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
69{
Laurence Lundbladeac515e52020-01-30 10:44:06 -080070 // Do this with subtraction so it doesn't give erroneous
71 // result if uOffset + Src.len overflows
Laurence Lundblade6ed34222018-12-18 09:46:23 -080072 if(uOffset > Dest.len || Src.len > Dest.len - uOffset) { // uOffset + Src.len > Dest.len
73 return NULLUsefulBufC;
74 }
75
76 memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
77
78 return (UsefulBufC){Dest.ptr, Src.len + uOffset};
79}
80
81
82/*
83 Public function -- see UsefulBuf.h
84 */
85int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
86{
87 // use the comparisons rather than subtracting lengths to
88 // return an int instead of a size_t
89 if(UB1.len < UB2.len) {
90 return -1;
91 } else if (UB1.len > UB2.len) {
92 return 1;
93 } // else UB1.len == UB2.len
94
95 return memcmp(UB1.ptr, UB2.ptr, UB1.len);
96}
97
98
Laurence Lundbladed85dbb72019-03-07 18:27:18 -080099/*
100 Public function -- see UsefulBuf.h
101 */
102size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
103{
104 if(UsefulBuf_IsNULLOrEmptyC(UB)) {
105 /* Not a match */
106 return 0;
107 }
108
109 const uint8_t * const pEnd = (uint8_t *)UB.ptr + UB.len;
110 for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
111 if(*p != uValue) {
112 /* Byte didn't match */
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800113 /* Cast from signed to unsigned . Safe because the loop increments.*/
114 return (size_t)(p - (uint8_t *)UB.ptr);
Laurence Lundbladed85dbb72019-03-07 18:27:18 -0800115 }
116 }
117
118 /* Success. All bytes matched */
119 return SIZE_MAX;
120}
121
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800122
123/*
124 Public function -- see UsefulBuf.h
125 */
126size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
127{
128 if(BytesToSearch.len < BytesToFind.len) {
129 return SIZE_MAX;
130 }
131
132 for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
133 if(!UsefulBuf_Compare((UsefulBufC){((uint8_t *)BytesToSearch.ptr) + uPos, BytesToFind.len}, BytesToFind)) {
134 return uPos;
135 }
136 }
137
138 return SIZE_MAX;
139}
140
141
142/*
143 Public function -- see UsefulBuf.h
144
145 Code Reviewers: THIS FUNCTION DOES POINTER MATH
146 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700147void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800148{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700149 pMe->magic = USEFUL_OUT_BUF_MAGIC;
150 UsefulOutBuf_Reset(pMe);
151 pMe->UB = Storage;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800152
153#if 0
154 // This check is off by default.
155
156 // The following check fails on ThreadX
157
158 // Sanity check on the pointer and size to be sure we are not
159 // passed a buffer that goes off the end of the address space.
160 // Given this test, we know that all unsigned lengths less than
161 // me->size are valid and won't wrap in any pointer additions
162 // based off of pStorage in the rest of this code.
163 const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
164 if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) // Check #0
165 me->err = 1;
166#endif
167}
168
169
170
171/*
172 Public function -- see UsefulBuf.h
173
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800174 The core of UsefulOutBuf -- put some bytes in the buffer without writing off
175 the end of it.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800176
177 Code Reviewers: THIS FUNCTION DOES POINTER MATH
178
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800179 This function inserts the source buffer, NewData, into the destination
180 buffer, me->UB.ptr.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800181
182 Destination is represented as:
183 me->UB.ptr -- start of the buffer
184 me->UB.len -- size of the buffer UB.ptr
185 me->data_len -- length of value data in UB
186
187 Source is data:
188 NewData.ptr -- start of source buffer
189 NewData.len -- length of source buffer
190
191 Insertion point:
192 uInsertionPos.
193
194 Steps:
195
196 0. Corruption checks on UsefulOutBuf
197
198 1. Figure out if the new data will fit or not
199
200 2. Is insertion position in the range of valid data?
201
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800202 3. If insertion point is not at the end, slide data to the right of the
203 insertion point to the right
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800204
205 4. Put the new data in at the insertion position.
206
207 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700208void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800209{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700210 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800211 // Already in error state.
212 return;
213 }
214
215 /* 0. Sanity check the UsefulOutBuf structure */
216 // A "counter measure". If magic number is not the right number it
217 // probably means me was not initialized or it was corrupted. Attackers
218 // can defeat this, but it is a hurdle and does good with very
219 // little code.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700220 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
221 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800222 return; // Magic number is wrong due to uninitalization or corrption
223 }
224
225 // Make sure valid data is less than buffer size. This would only occur
226 // if there was corruption of me, but it is also part of the checks to
227 // be sure there is no pointer arithmatic under/overflow.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700228 if(pMe->data_len > pMe->UB.len) { // Check #1
229 pMe->err = 1;
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800230 // Offset of valid data is off the end of the UsefulOutBuf due to
231 // uninitialization or corruption
232 return;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800233 }
234
235 /* 1. Will it fit? */
Laurence Lundblade234fe422019-12-02 13:04:34 -0800236 // WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800237 // Check #1 makes sure subtraction in RoomLeft will not wrap around
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700238 if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { // Check #2
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800239 // The new data will not fit into the the buffer.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700240 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800241 return;
242 }
243
244 /* 2. Check the Insertion Position */
Laurence Lundblade234fe422019-12-02 13:04:34 -0800245 // This, with Check #1, also confirms that uInsertionPos <= me->data_len and
246 // that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
247 // address space.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700248 if(uInsertionPos > pMe->data_len) { // Check #3
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800249 // Off the end of the valid data in the buffer.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700250 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800251 return;
252 }
253
254 /* 3. Slide existing data to the right */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700255 uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #1
256 size_t uNumBytesToMove = pMe->data_len - uInsertionPos; // PtrMath #2
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800257 uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; // PtrMath #3
258
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700259 if(uNumBytesToMove && pMe->UB.ptr) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800260 // To know memmove won't go off end of destination, see PtrMath #4
Laurence Lundblade234fe422019-12-02 13:04:34 -0800261 // Use memove because it handles overlapping buffers
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800262 memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
263 }
264
265 /* 4. Put the new data in */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700266 uint8_t *pInsertionPoint = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; // PtrMath #5
267 if(pMe->UB.ptr) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800268 // To know memmove won't go off end of destination, see PtrMath #6
269 memmove(pInsertionPoint, NewData.ptr, NewData.len);
270 }
Laurence Lundblade234fe422019-12-02 13:04:34 -0800271 pMe->data_len += NewData.len;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800272}
273
274
275/*
276 Rationale that describes why the above pointer math is safe
277
278 PtrMath #1 will never wrap around over because
279 Check #0 in UsefulOutBuf_Init makes sure me->UB.ptr + me->UB.len doesn't wrap
280 Check #1 makes sure me->data_len is less than me->UB.len
281 Check #3 makes sure uInsertionPos is less than me->data_len
282
283 PtrMath #2 will never wrap around under because
284 Check #3 makes sure uInsertionPos is less than me->data_len
285
Laurence Lundblade234fe422019-12-02 13:04:34 -0800286 PtrMath #3 will never wrap around over because
287 PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
288 Check #2 that NewData.len will fit in the unused space left in me->UB
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800289
290 PtrMath #4 will never wrap under because
291 Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
292 Check #3 makes sure uInsertionPos is less than me->data_len
293 Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
294 This algebraically rearranges to me->size > uInsertionPos + NewData.len
295
296 PtrMath #5 is exactly the same as PtrMath #1
297
298 PtrMath #6 will never wrap under because
299 Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
300 Check #1 makes sure me->data_len is less than me->size
301 Check #3 makes sure uInsertionPos is less than me->data_len
302 */
303
304
305/*
306 Public function -- see UsefulBuf.h
307 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700308UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800309{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700310 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800311 return NULLUsefulBufC;
312 }
313
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700314 if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
315 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800316 return NULLUsefulBufC;
317 }
318
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700319 return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800320}
321
322
323/*
324 Public function -- see UsefulBuf.h
325
326 Copy out the data accumulated in to the output buffer.
327 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700328UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800329{
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700330 const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800331 if(UsefulBuf_IsNULLC(Tmp)) {
332 return NULLUsefulBufC;
333 }
334 return UsefulBuf_Copy(pDest, Tmp);
335}
336
337
338
339
340/*
341 Public function -- see UsefulBuf.h
342
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800343 The core of UsefulInputBuf -- consume bytes without going off end of buffer.
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800344
345 Code Reviewers: THIS FUNCTION DOES POINTER MATH
346 */
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700347const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800348{
349 // Already in error state. Do nothing.
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700350 if(pMe->err) {
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800351 return NULL;
352 }
353
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700354 if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800355 // Number of bytes asked for at current position are more than available
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700356 pMe->err = 1;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800357 return NULL;
358 }
359
360 // This is going to succeed
Laurence Lundblade852a33c2019-06-11 09:00:07 -0700361 const void * const result = ((uint8_t *)pMe->UB.ptr) + pMe->cursor;
Laurence Lundbladeac515e52020-01-30 10:44:06 -0800362 // Will not overflow because of check using UsefulInputBuf_BytesAvailable()
363 pMe->cursor += uAmount;
Laurence Lundblade6ed34222018-12-18 09:46:23 -0800364 return result;
365}
366