1*b586599bSYuichi Sugiyama // SPDX-License-Identifier: BSD-3-Clause
22e6f5bf1SYuichi Sugiyama /* ==========================================================================
32e6f5bf1SYuichi Sugiyama * Copyright (c) 2016-2018, The Linux Foundation.
42e6f5bf1SYuichi Sugiyama * Copyright (c) 2018-2024, Laurence Lundblade.
52e6f5bf1SYuichi Sugiyama * All rights reserved.
62e6f5bf1SYuichi Sugiyama *
72e6f5bf1SYuichi Sugiyama * Redistribution and use in source and binary forms, with or without
82e6f5bf1SYuichi Sugiyama * modification, are permitted provided that the following conditions are
92e6f5bf1SYuichi Sugiyama * met:
102e6f5bf1SYuichi Sugiyama * * Redistributions of source code must retain the above copyright
112e6f5bf1SYuichi Sugiyama * notice, this list of conditions and the following disclaimer.
122e6f5bf1SYuichi Sugiyama * * Redistributions in binary form must reproduce the above
132e6f5bf1SYuichi Sugiyama * copyright notice, this list of conditions and the following
142e6f5bf1SYuichi Sugiyama * disclaimer in the documentation and/or other materials provided
152e6f5bf1SYuichi Sugiyama * with the distribution.
162e6f5bf1SYuichi Sugiyama * * Neither the name of The Linux Foundation nor the names of its
172e6f5bf1SYuichi Sugiyama * contributors, nor the name "Laurence Lundblade" may be used to
182e6f5bf1SYuichi Sugiyama * endorse or promote products derived from this software without
192e6f5bf1SYuichi Sugiyama * specific prior written permission.
202e6f5bf1SYuichi Sugiyama *
212e6f5bf1SYuichi Sugiyama * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
222e6f5bf1SYuichi Sugiyama * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
232e6f5bf1SYuichi Sugiyama * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
242e6f5bf1SYuichi Sugiyama * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
252e6f5bf1SYuichi Sugiyama * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
262e6f5bf1SYuichi Sugiyama * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
272e6f5bf1SYuichi Sugiyama * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
282e6f5bf1SYuichi Sugiyama * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
292e6f5bf1SYuichi Sugiyama * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
302e6f5bf1SYuichi Sugiyama * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
312e6f5bf1SYuichi Sugiyama * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322e6f5bf1SYuichi Sugiyama * ========================================================================= */
332e6f5bf1SYuichi Sugiyama
342e6f5bf1SYuichi Sugiyama
352e6f5bf1SYuichi Sugiyama
362e6f5bf1SYuichi Sugiyama /*=============================================================================
372e6f5bf1SYuichi Sugiyama FILE: UsefulBuf.c
382e6f5bf1SYuichi Sugiyama
392e6f5bf1SYuichi Sugiyama DESCRIPTION: General purpose input and output buffers
402e6f5bf1SYuichi Sugiyama
412e6f5bf1SYuichi Sugiyama EDIT HISTORY FOR FILE:
422e6f5bf1SYuichi Sugiyama
432e6f5bf1SYuichi Sugiyama This section contains comments describing changes made to the module.
442e6f5bf1SYuichi Sugiyama Notice that changes are listed in reverse chronological order.
452e6f5bf1SYuichi Sugiyama
462e6f5bf1SYuichi Sugiyama when who what, where, why
472e6f5bf1SYuichi Sugiyama -------- ---- ---------------------------------------------------
482e6f5bf1SYuichi Sugiyama 21/05/2024 llundblade Comment formatting and some code tidiness.
492e6f5bf1SYuichi Sugiyama 19/12/2022 llundblade Don't pass NULL to memmove when adding empty data.
502e6f5bf1SYuichi Sugiyama 4/11/2022 llundblade Add GetOutPlace and Advance to UsefulOutBuf
512e6f5bf1SYuichi Sugiyama 3/6/2021 mcr/llundblade Fix warnings related to --Wcast-qual
522e6f5bf1SYuichi Sugiyama 01/28/2020 llundblade Refine integer signedness to quiet static analysis.
532e6f5bf1SYuichi Sugiyama 01/08/2020 llundblade Documentation corrections & improved code formatting.
542e6f5bf1SYuichi Sugiyama 11/08/2019 llundblade Re check pointer math and update comments
552e6f5bf1SYuichi Sugiyama 3/6/2019 llundblade Add UsefulBuf_IsValue()
562e6f5bf1SYuichi Sugiyama 09/07/17 llundbla Fix critical bug in UsefulBuf_Find() -- a read off
572e6f5bf1SYuichi Sugiyama the end of memory when the bytes to find is longer
582e6f5bf1SYuichi Sugiyama than the bytes to search.
592e6f5bf1SYuichi Sugiyama 06/27/17 llundbla Fix UsefulBuf_Compare() bug. Only affected comparison
602e6f5bf1SYuichi Sugiyama for < or > for unequal length buffers. Added
612e6f5bf1SYuichi Sugiyama UsefulBuf_Set() function.
622e6f5bf1SYuichi Sugiyama 05/30/17 llundbla Functions for NULL UsefulBufs and const / unconst
632e6f5bf1SYuichi Sugiyama 11/13/16 llundbla Initial Version.
642e6f5bf1SYuichi Sugiyama
652e6f5bf1SYuichi Sugiyama ============================================================================*/
662e6f5bf1SYuichi Sugiyama
672e6f5bf1SYuichi Sugiyama #include "UsefulBuf.h"
682e6f5bf1SYuichi Sugiyama
692e6f5bf1SYuichi Sugiyama /* used to catch use of uninitialized or corrupted UsefulOutBuf */
702e6f5bf1SYuichi Sugiyama #define USEFUL_OUT_BUF_MAGIC (0x0B0F)
712e6f5bf1SYuichi Sugiyama
722e6f5bf1SYuichi Sugiyama
732e6f5bf1SYuichi Sugiyama /*
742e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
752e6f5bf1SYuichi Sugiyama */
UsefulBuf_CopyOffset(UsefulBuf Dest,size_t uOffset,const UsefulBufC Src)762e6f5bf1SYuichi Sugiyama UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
772e6f5bf1SYuichi Sugiyama {
782e6f5bf1SYuichi Sugiyama /* Do this with subtraction so it doesn't give an erroneous
792e6f5bf1SYuichi Sugiyama * result if uOffset + Src.len overflows. Right side is equivalent to
802e6f5bf1SYuichi Sugiyama * uOffset + Src.len > Dest.len
812e6f5bf1SYuichi Sugiyama */
822e6f5bf1SYuichi Sugiyama if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
832e6f5bf1SYuichi Sugiyama return NULLUsefulBufC;
842e6f5bf1SYuichi Sugiyama }
852e6f5bf1SYuichi Sugiyama
862e6f5bf1SYuichi Sugiyama memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
872e6f5bf1SYuichi Sugiyama
882e6f5bf1SYuichi Sugiyama return (UsefulBufC){Dest.ptr, Src.len + uOffset};
892e6f5bf1SYuichi Sugiyama }
902e6f5bf1SYuichi Sugiyama
912e6f5bf1SYuichi Sugiyama
922e6f5bf1SYuichi Sugiyama /*
932e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
942e6f5bf1SYuichi Sugiyama */
UsefulBuf_Compare(const UsefulBufC UB1,const UsefulBufC UB2)952e6f5bf1SYuichi Sugiyama int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
962e6f5bf1SYuichi Sugiyama {
972e6f5bf1SYuichi Sugiyama /* Use comparisons rather than subtracting lengths to
982e6f5bf1SYuichi Sugiyama * return an int instead of a size_t
992e6f5bf1SYuichi Sugiyama */
1002e6f5bf1SYuichi Sugiyama if(UB1.len < UB2.len) {
1012e6f5bf1SYuichi Sugiyama return -1;
1022e6f5bf1SYuichi Sugiyama } else if (UB1.len > UB2.len) {
1032e6f5bf1SYuichi Sugiyama return 1;
1042e6f5bf1SYuichi Sugiyama } /* else UB1.len == UB2.len */
1052e6f5bf1SYuichi Sugiyama
1062e6f5bf1SYuichi Sugiyama return memcmp(UB1.ptr, UB2.ptr, UB1.len);
1072e6f5bf1SYuichi Sugiyama }
1082e6f5bf1SYuichi Sugiyama
1092e6f5bf1SYuichi Sugiyama
1102e6f5bf1SYuichi Sugiyama /*
1112e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
1122e6f5bf1SYuichi Sugiyama */
UsefulBuf_IsValue(const UsefulBufC UB,uint8_t uValue)1132e6f5bf1SYuichi Sugiyama size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
1142e6f5bf1SYuichi Sugiyama {
1152e6f5bf1SYuichi Sugiyama if(UsefulBuf_IsNULLOrEmptyC(UB)) {
1162e6f5bf1SYuichi Sugiyama /* Not a match */
1172e6f5bf1SYuichi Sugiyama return 0;
1182e6f5bf1SYuichi Sugiyama }
1192e6f5bf1SYuichi Sugiyama
1202e6f5bf1SYuichi Sugiyama const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
1212e6f5bf1SYuichi Sugiyama for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
1222e6f5bf1SYuichi Sugiyama if(*p != uValue) {
1232e6f5bf1SYuichi Sugiyama /* Byte didn't match */
1242e6f5bf1SYuichi Sugiyama /* Cast from signed to unsigned. Safe because the loop increments.*/
1252e6f5bf1SYuichi Sugiyama return (size_t)(p - (const uint8_t *)UB.ptr);
1262e6f5bf1SYuichi Sugiyama }
1272e6f5bf1SYuichi Sugiyama }
1282e6f5bf1SYuichi Sugiyama
1292e6f5bf1SYuichi Sugiyama /* Success. All bytes matched */
1302e6f5bf1SYuichi Sugiyama return SIZE_MAX;
1312e6f5bf1SYuichi Sugiyama }
1322e6f5bf1SYuichi Sugiyama
1332e6f5bf1SYuichi Sugiyama
1342e6f5bf1SYuichi Sugiyama /*
1352e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
1362e6f5bf1SYuichi Sugiyama */
UsefulBuf_FindBytes(UsefulBufC BytesToSearch,UsefulBufC BytesToFind)1372e6f5bf1SYuichi Sugiyama size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
1382e6f5bf1SYuichi Sugiyama {
1392e6f5bf1SYuichi Sugiyama if(BytesToSearch.len < BytesToFind.len) {
1402e6f5bf1SYuichi Sugiyama return SIZE_MAX;
1412e6f5bf1SYuichi Sugiyama }
1422e6f5bf1SYuichi Sugiyama
1432e6f5bf1SYuichi Sugiyama for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
1442e6f5bf1SYuichi Sugiyama UsefulBufC SearchNext;
1452e6f5bf1SYuichi Sugiyama
1462e6f5bf1SYuichi Sugiyama SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
1472e6f5bf1SYuichi Sugiyama SearchNext.len = BytesToFind.len;
1482e6f5bf1SYuichi Sugiyama if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
1492e6f5bf1SYuichi Sugiyama return uPos;
1502e6f5bf1SYuichi Sugiyama }
1512e6f5bf1SYuichi Sugiyama }
1522e6f5bf1SYuichi Sugiyama
1532e6f5bf1SYuichi Sugiyama return SIZE_MAX;
1542e6f5bf1SYuichi Sugiyama }
1552e6f5bf1SYuichi Sugiyama
1562e6f5bf1SYuichi Sugiyama
1572e6f5bf1SYuichi Sugiyama /*
1582e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
1592e6f5bf1SYuichi Sugiyama *
1602e6f5bf1SYuichi Sugiyama * Code Reviewers: THIS FUNCTION DOES POINTER MATH
1612e6f5bf1SYuichi Sugiyama */
UsefulOutBuf_Init(UsefulOutBuf * pMe,UsefulBuf Storage)1622e6f5bf1SYuichi Sugiyama void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
1632e6f5bf1SYuichi Sugiyama {
1642e6f5bf1SYuichi Sugiyama pMe->magic = USEFUL_OUT_BUF_MAGIC;
1652e6f5bf1SYuichi Sugiyama UsefulOutBuf_Reset(pMe);
1662e6f5bf1SYuichi Sugiyama pMe->UB = Storage;
1672e6f5bf1SYuichi Sugiyama
1682e6f5bf1SYuichi Sugiyama #if 0
1692e6f5bf1SYuichi Sugiyama /* This check is off by default.
1702e6f5bf1SYuichi Sugiyama *
1712e6f5bf1SYuichi Sugiyama * The following check fails on ThreadX
1722e6f5bf1SYuichi Sugiyama *
1732e6f5bf1SYuichi Sugiyama * Sanity check on the pointer and size to be sure we are not
1742e6f5bf1SYuichi Sugiyama * passed a buffer that goes off the end of the address space.
1752e6f5bf1SYuichi Sugiyama * Given this test, we know that all unsigned lengths less than
1762e6f5bf1SYuichi Sugiyama * me->size are valid and won't wrap in any pointer additions
1772e6f5bf1SYuichi Sugiyama * based off of pStorage in the rest of this code.
1782e6f5bf1SYuichi Sugiyama */
1792e6f5bf1SYuichi Sugiyama const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
1802e6f5bf1SYuichi Sugiyama if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
1812e6f5bf1SYuichi Sugiyama me->err = 1;
1822e6f5bf1SYuichi Sugiyama #endif
1832e6f5bf1SYuichi Sugiyama }
1842e6f5bf1SYuichi Sugiyama
1852e6f5bf1SYuichi Sugiyama
1862e6f5bf1SYuichi Sugiyama
1872e6f5bf1SYuichi Sugiyama /*
1882e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
1892e6f5bf1SYuichi Sugiyama *
1902e6f5bf1SYuichi Sugiyama * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
1912e6f5bf1SYuichi Sugiyama * the end of it.
1922e6f5bf1SYuichi Sugiyama *
1932e6f5bf1SYuichi Sugiyama * Code Reviewers: THIS FUNCTION DOES POINTER MATH
1942e6f5bf1SYuichi Sugiyama *
1952e6f5bf1SYuichi Sugiyama * This function inserts the source buffer, NewData, into the destination
1962e6f5bf1SYuichi Sugiyama * buffer, me->UB.ptr.
1972e6f5bf1SYuichi Sugiyama *
1982e6f5bf1SYuichi Sugiyama * Destination is represented as:
1992e6f5bf1SYuichi Sugiyama * me->UB.ptr -- start of the buffer
2002e6f5bf1SYuichi Sugiyama * me->UB.len -- size of the buffer UB.ptr
2012e6f5bf1SYuichi Sugiyama * me->data_len -- length of value data in UB
2022e6f5bf1SYuichi Sugiyama *
2032e6f5bf1SYuichi Sugiyama * Source is data:
2042e6f5bf1SYuichi Sugiyama * NewData.ptr -- start of source buffer
2052e6f5bf1SYuichi Sugiyama * NewData.len -- length of source buffer
2062e6f5bf1SYuichi Sugiyama *
2072e6f5bf1SYuichi Sugiyama * Insertion point:
2082e6f5bf1SYuichi Sugiyama * uInsertionPos.
2092e6f5bf1SYuichi Sugiyama *
2102e6f5bf1SYuichi Sugiyama * Steps:
2112e6f5bf1SYuichi Sugiyama *
2122e6f5bf1SYuichi Sugiyama * 0. Corruption checks on UsefulOutBuf
2132e6f5bf1SYuichi Sugiyama *
2142e6f5bf1SYuichi Sugiyama * 1. Figure out if the new data will fit or not
2152e6f5bf1SYuichi Sugiyama *
2162e6f5bf1SYuichi Sugiyama * 2. Is insertion position in the range of valid data?
2172e6f5bf1SYuichi Sugiyama *
2182e6f5bf1SYuichi Sugiyama * 3. If insertion point is not at the end, slide data to the right of the
2192e6f5bf1SYuichi Sugiyama * insertion point to the right
2202e6f5bf1SYuichi Sugiyama *
2212e6f5bf1SYuichi Sugiyama * 4. Put the new data in at the insertion position.
2222e6f5bf1SYuichi Sugiyama *
2232e6f5bf1SYuichi Sugiyama */
UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf * pMe,UsefulBufC NewData,size_t uInsertionPos)2242e6f5bf1SYuichi Sugiyama void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
2252e6f5bf1SYuichi Sugiyama {
2262e6f5bf1SYuichi Sugiyama if(pMe->err) {
2272e6f5bf1SYuichi Sugiyama /* Already in error state. */
2282e6f5bf1SYuichi Sugiyama return;
2292e6f5bf1SYuichi Sugiyama }
2302e6f5bf1SYuichi Sugiyama
2312e6f5bf1SYuichi Sugiyama /* 0. Sanity check the UsefulOutBuf structure
2322e6f5bf1SYuichi Sugiyama * A "counter measure". If magic number is not the right number it
2332e6f5bf1SYuichi Sugiyama * probably means pMe was not initialized or it was corrupted. Attackers
2342e6f5bf1SYuichi Sugiyama * can defeat this, but it is a hurdle and does good with very
2352e6f5bf1SYuichi Sugiyama * little code.
2362e6f5bf1SYuichi Sugiyama */
2372e6f5bf1SYuichi Sugiyama if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
2382e6f5bf1SYuichi Sugiyama pMe->err = 1;
2392e6f5bf1SYuichi Sugiyama return; /* Magic number is wrong due to uninitalization or corrption */
2402e6f5bf1SYuichi Sugiyama }
2412e6f5bf1SYuichi Sugiyama
2422e6f5bf1SYuichi Sugiyama /* Make sure valid data is less than buffer size. This would only occur
2432e6f5bf1SYuichi Sugiyama * if there was corruption of me, but it is also part of the checks to
2442e6f5bf1SYuichi Sugiyama * be sure there is no pointer arithmatic under/overflow.
2452e6f5bf1SYuichi Sugiyama */
2462e6f5bf1SYuichi Sugiyama if(pMe->data_len > pMe->UB.len) { /* Check #1 */
2472e6f5bf1SYuichi Sugiyama pMe->err = 1;
2482e6f5bf1SYuichi Sugiyama /* Offset of valid data is off the end of the UsefulOutBuf due to
2492e6f5bf1SYuichi Sugiyama * uninitialization or corruption
2502e6f5bf1SYuichi Sugiyama */
2512e6f5bf1SYuichi Sugiyama return;
2522e6f5bf1SYuichi Sugiyama }
2532e6f5bf1SYuichi Sugiyama
2542e6f5bf1SYuichi Sugiyama /* 1. Will it fit?
2552e6f5bf1SYuichi Sugiyama * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
2562e6f5bf1SYuichi Sugiyama * Check #1 makes sure subtraction in RoomLeft will not wrap around
2572e6f5bf1SYuichi Sugiyama */
2582e6f5bf1SYuichi Sugiyama if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
2592e6f5bf1SYuichi Sugiyama /* The new data will not fit into the the buffer. */
2602e6f5bf1SYuichi Sugiyama pMe->err = 1;
2612e6f5bf1SYuichi Sugiyama return;
2622e6f5bf1SYuichi Sugiyama }
2632e6f5bf1SYuichi Sugiyama
2642e6f5bf1SYuichi Sugiyama /* 2. Check the Insertion Position
2652e6f5bf1SYuichi Sugiyama * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
2662e6f5bf1SYuichi Sugiyama * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
2672e6f5bf1SYuichi Sugiyama * address space.
2682e6f5bf1SYuichi Sugiyama */
2692e6f5bf1SYuichi Sugiyama if(uInsertionPos > pMe->data_len) { /* Check #3 */
2702e6f5bf1SYuichi Sugiyama /* Off the end of the valid data in the buffer. */
2712e6f5bf1SYuichi Sugiyama pMe->err = 1;
2722e6f5bf1SYuichi Sugiyama return;
2732e6f5bf1SYuichi Sugiyama }
2742e6f5bf1SYuichi Sugiyama
2752e6f5bf1SYuichi Sugiyama /* 3. Slide existing data to the right */
2762e6f5bf1SYuichi Sugiyama if (!UsefulOutBuf_IsBufferNULL(pMe)) {
2772e6f5bf1SYuichi Sugiyama uint8_t *pSourceOfMove = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
2782e6f5bf1SYuichi Sugiyama size_t uNumBytesToMove = pMe->data_len - uInsertionPos; /* PtrMath #2 */
2792e6f5bf1SYuichi Sugiyama uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
2802e6f5bf1SYuichi Sugiyama
2812e6f5bf1SYuichi Sugiyama /* To know memmove won't go off end of destination, see PtrMath #4.
2822e6f5bf1SYuichi Sugiyama * Use memove because it handles overlapping buffers
2832e6f5bf1SYuichi Sugiyama */
2842e6f5bf1SYuichi Sugiyama memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
2852e6f5bf1SYuichi Sugiyama
2862e6f5bf1SYuichi Sugiyama /* 4. Put the new data in */
2872e6f5bf1SYuichi Sugiyama uint8_t *pInsertionPoint = pSourceOfMove;
2882e6f5bf1SYuichi Sugiyama /* To know memmove won't go off end of destination, see PtrMath #5 */
2892e6f5bf1SYuichi Sugiyama if(NewData.ptr != NULL) {
2902e6f5bf1SYuichi Sugiyama memmove(pInsertionPoint, NewData.ptr, NewData.len);
2912e6f5bf1SYuichi Sugiyama }
2922e6f5bf1SYuichi Sugiyama }
2932e6f5bf1SYuichi Sugiyama
2942e6f5bf1SYuichi Sugiyama pMe->data_len += NewData.len;
2952e6f5bf1SYuichi Sugiyama }
2962e6f5bf1SYuichi Sugiyama
2972e6f5bf1SYuichi Sugiyama
2982e6f5bf1SYuichi Sugiyama /*
2992e6f5bf1SYuichi Sugiyama * Rationale that describes why the above pointer math is safe
3002e6f5bf1SYuichi Sugiyama *
3012e6f5bf1SYuichi Sugiyama * PtrMath #1 will never wrap around over because
3022e6f5bf1SYuichi Sugiyama * Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
3032e6f5bf1SYuichi Sugiyama * Check #1 makes sure me->data_len is less than me->UB.len
3042e6f5bf1SYuichi Sugiyama * Check #3 makes sure uInsertionPos is less than me->data_len
3052e6f5bf1SYuichi Sugiyama *
3062e6f5bf1SYuichi Sugiyama * PtrMath #2 will never wrap around under because
3072e6f5bf1SYuichi Sugiyama * Check #3 makes sure uInsertionPos is less than me->data_len
3082e6f5bf1SYuichi Sugiyama *
3092e6f5bf1SYuichi Sugiyama * PtrMath #3 will never wrap around over because
3102e6f5bf1SYuichi Sugiyama * PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
3112e6f5bf1SYuichi Sugiyama * Check #2 that NewData.len will fit in the unused space left in me->UB
3122e6f5bf1SYuichi Sugiyama *
3132e6f5bf1SYuichi Sugiyama * PtrMath #4 will never wrap under because
3142e6f5bf1SYuichi Sugiyama * Calculation for extent or memmove is uRoomInDestination = me->UB.len - (uInsertionPos + NewData.len)
3152e6f5bf1SYuichi Sugiyama * Check #3 makes sure uInsertionPos is less than me->data_len
3162e6f5bf1SYuichi Sugiyama * Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
3172e6f5bf1SYuichi Sugiyama * This algebraically rearranges to me->size > uInsertionPos + NewData.len
3182e6f5bf1SYuichi Sugiyama *
3192e6f5bf1SYuichi Sugiyama * PtrMath #5 will never wrap under because
3202e6f5bf1SYuichi Sugiyama * Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
3212e6f5bf1SYuichi Sugiyama * Check #1 makes sure me->data_len is less than me->size
3222e6f5bf1SYuichi Sugiyama * Check #3 makes sure uInsertionPos is less than me->data_len
3232e6f5bf1SYuichi Sugiyama */
3242e6f5bf1SYuichi Sugiyama
3252e6f5bf1SYuichi Sugiyama
3262e6f5bf1SYuichi Sugiyama /*
3272e6f5bf1SYuichi Sugiyama * Public function for advancing data length. See qcbor/UsefulBuf.h
3282e6f5bf1SYuichi Sugiyama */
UsefulOutBuf_Advance(UsefulOutBuf * pMe,size_t uAmount)3292e6f5bf1SYuichi Sugiyama void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
3302e6f5bf1SYuichi Sugiyama {
3312e6f5bf1SYuichi Sugiyama /* This function is a trimmed down version of
3322e6f5bf1SYuichi Sugiyama * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
3332e6f5bf1SYuichi Sugiyama * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
3342e6f5bf1SYuichi Sugiyama * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
3352e6f5bf1SYuichi Sugiyama * rarely used.
3362e6f5bf1SYuichi Sugiyama */
3372e6f5bf1SYuichi Sugiyama
3382e6f5bf1SYuichi Sugiyama if(pMe->err) {
3392e6f5bf1SYuichi Sugiyama /* Already in error state. */
3402e6f5bf1SYuichi Sugiyama return;
3412e6f5bf1SYuichi Sugiyama }
3422e6f5bf1SYuichi Sugiyama
3432e6f5bf1SYuichi Sugiyama /* 0. Sanity check the UsefulOutBuf structure
3442e6f5bf1SYuichi Sugiyama *
3452e6f5bf1SYuichi Sugiyama * A "counter measure". If magic number is not the right number it
3462e6f5bf1SYuichi Sugiyama * probably means me was not initialized or it was
3472e6f5bf1SYuichi Sugiyama * corrupted. Attackers can defeat this, but it is a hurdle and
3482e6f5bf1SYuichi Sugiyama * does good with very little code.
3492e6f5bf1SYuichi Sugiyama */
3502e6f5bf1SYuichi Sugiyama if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
3512e6f5bf1SYuichi Sugiyama pMe->err = 1;
3522e6f5bf1SYuichi Sugiyama return; /* Magic number is wrong due to uninitalization or corrption */
3532e6f5bf1SYuichi Sugiyama }
3542e6f5bf1SYuichi Sugiyama
3552e6f5bf1SYuichi Sugiyama /* Make sure valid data is less than buffer size. This would only
3562e6f5bf1SYuichi Sugiyama * occur if there was corruption of me, but it is also part of the
3572e6f5bf1SYuichi Sugiyama * checks to be sure there is no pointer arithmatic
3582e6f5bf1SYuichi Sugiyama * under/overflow.
3592e6f5bf1SYuichi Sugiyama */
3602e6f5bf1SYuichi Sugiyama if(pMe->data_len > pMe->UB.len) { /* Check #1 */
3612e6f5bf1SYuichi Sugiyama pMe->err = 1;
3622e6f5bf1SYuichi Sugiyama /* Offset of valid data is off the end of the UsefulOutBuf due
3632e6f5bf1SYuichi Sugiyama * to uninitialization or corruption.
3642e6f5bf1SYuichi Sugiyama */
3652e6f5bf1SYuichi Sugiyama return;
3662e6f5bf1SYuichi Sugiyama }
3672e6f5bf1SYuichi Sugiyama
3682e6f5bf1SYuichi Sugiyama /* 1. Will it fit?
3692e6f5bf1SYuichi Sugiyama *
3702e6f5bf1SYuichi Sugiyama * WillItFit() is the same as: NewData.len <= (me->UB.len -
3712e6f5bf1SYuichi Sugiyama * me->data_len) Check #1 makes sure subtraction in RoomLeft will
3722e6f5bf1SYuichi Sugiyama * not wrap around
3732e6f5bf1SYuichi Sugiyama */
3742e6f5bf1SYuichi Sugiyama if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
3752e6f5bf1SYuichi Sugiyama /* The new data will not fit into the the buffer. */
3762e6f5bf1SYuichi Sugiyama pMe->err = 1;
3772e6f5bf1SYuichi Sugiyama return;
3782e6f5bf1SYuichi Sugiyama }
3792e6f5bf1SYuichi Sugiyama
3802e6f5bf1SYuichi Sugiyama pMe->data_len += uAmount;
3812e6f5bf1SYuichi Sugiyama }
3822e6f5bf1SYuichi Sugiyama
3832e6f5bf1SYuichi Sugiyama
3842e6f5bf1SYuichi Sugiyama /*
3852e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
3862e6f5bf1SYuichi Sugiyama */
UsefulOutBuf_OutUBuf(UsefulOutBuf * pMe)3872e6f5bf1SYuichi Sugiyama UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
3882e6f5bf1SYuichi Sugiyama {
3892e6f5bf1SYuichi Sugiyama if(pMe->err) {
3902e6f5bf1SYuichi Sugiyama return NULLUsefulBufC;
3912e6f5bf1SYuichi Sugiyama }
3922e6f5bf1SYuichi Sugiyama
3932e6f5bf1SYuichi Sugiyama if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
3942e6f5bf1SYuichi Sugiyama pMe->err = 1;
3952e6f5bf1SYuichi Sugiyama return NULLUsefulBufC;
3962e6f5bf1SYuichi Sugiyama }
3972e6f5bf1SYuichi Sugiyama
3982e6f5bf1SYuichi Sugiyama return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
3992e6f5bf1SYuichi Sugiyama }
4002e6f5bf1SYuichi Sugiyama
4012e6f5bf1SYuichi Sugiyama
4022e6f5bf1SYuichi Sugiyama /*
4032e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
4042e6f5bf1SYuichi Sugiyama *
4052e6f5bf1SYuichi Sugiyama * Copy out the data accumulated in to the output buffer.
4062e6f5bf1SYuichi Sugiyama */
UsefulOutBuf_CopyOut(UsefulOutBuf * pMe,UsefulBuf pDest)4072e6f5bf1SYuichi Sugiyama UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
4082e6f5bf1SYuichi Sugiyama {
4092e6f5bf1SYuichi Sugiyama const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
4102e6f5bf1SYuichi Sugiyama if(UsefulBuf_IsNULLC(Tmp)) {
4112e6f5bf1SYuichi Sugiyama return NULLUsefulBufC;
4122e6f5bf1SYuichi Sugiyama }
4132e6f5bf1SYuichi Sugiyama return UsefulBuf_Copy(pDest, Tmp);
4142e6f5bf1SYuichi Sugiyama }
4152e6f5bf1SYuichi Sugiyama
4162e6f5bf1SYuichi Sugiyama
4172e6f5bf1SYuichi Sugiyama
4182e6f5bf1SYuichi Sugiyama
4192e6f5bf1SYuichi Sugiyama /*
4202e6f5bf1SYuichi Sugiyama * Public function -- see UsefulBuf.h
4212e6f5bf1SYuichi Sugiyama *
4222e6f5bf1SYuichi Sugiyama * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
4232e6f5bf1SYuichi Sugiyama *
4242e6f5bf1SYuichi Sugiyama * Code Reviewers: THIS FUNCTION DOES POINTER MATH
4252e6f5bf1SYuichi Sugiyama */
UsefulInputBuf_GetBytes(UsefulInputBuf * pMe,size_t uAmount)4262e6f5bf1SYuichi Sugiyama const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
4272e6f5bf1SYuichi Sugiyama {
4282e6f5bf1SYuichi Sugiyama /* Already in error state. Do nothing. */
4292e6f5bf1SYuichi Sugiyama if(pMe->err) {
4302e6f5bf1SYuichi Sugiyama return NULL;
4312e6f5bf1SYuichi Sugiyama }
4322e6f5bf1SYuichi Sugiyama
4332e6f5bf1SYuichi Sugiyama if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
4342e6f5bf1SYuichi Sugiyama /* Number of bytes asked for is more than available */
4352e6f5bf1SYuichi Sugiyama pMe->err = 1;
4362e6f5bf1SYuichi Sugiyama return NULL;
4372e6f5bf1SYuichi Sugiyama }
4382e6f5bf1SYuichi Sugiyama
4392e6f5bf1SYuichi Sugiyama /* This is going to succeed */
4402e6f5bf1SYuichi Sugiyama const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
4412e6f5bf1SYuichi Sugiyama /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
4422e6f5bf1SYuichi Sugiyama pMe->cursor += uAmount;
4432e6f5bf1SYuichi Sugiyama return result;
4442e6f5bf1SYuichi Sugiyama }
445