1 /* $OpenBSD: buf.c,v 1.29 2020/01/13 13:54:44 espie Exp $ */ 2 /* $NetBSD: buf.c,v 1.9 1996/12/31 17:53:21 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1999 Marc Espie. 6 * 7 * Extensive code changes for the OpenBSD project. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 22 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 /* 31 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 32 * Copyright (c) 1988, 1989 by Adam de Boor 33 * Copyright (c) 1989 by Berkeley Softworks 34 * All rights reserved. 35 * 36 * This code is derived from software contributed to Berkeley by 37 * Adam de Boor. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 */ 63 64 /*- 65 * buf.c -- 66 * Functions for automatically expanded buffers. 67 */ 68 69 #include <assert.h> 70 #include <ctype.h> 71 #include <limits.h> 72 #include <stddef.h> 73 #include <stdint.h> 74 #include <stdlib.h> 75 #include <string.h> 76 #include <stdio.h> 77 #include <stdarg.h> 78 #include "config.h" 79 #include "defines.h" 80 #include "buf.h" 81 #include "stats.h" 82 #include "memory.h" 83 84 #ifdef STATS_BUF 85 #define DO_STAT_BUF(bp, nb) \ 86 STAT_BUFS_EXPANSION++; \ 87 if ((bp)->endPtr - (bp)->buffer == 1) \ 88 STAT_WEIRD_INEFFICIENT++; 89 #else 90 #define DO_STAT_BUF(a, b) 91 #endif 92 93 static void 94 fatal_overflow() 95 { 96 fprintf(stderr, "buffer size overflow\n"); 97 exit(2); 98 } 99 100 #define BUF_DEF_SIZE 256U /* Default buffer size */ 101 #define BUF_MARGIN 256U /* Make sure we are comfortable */ 102 103 /* BufExpand(bp, nb) 104 * Expand buffer bp to hold up to nb additional 105 * chars. Makes sure there's always room for an extra '\0' char 106 * at the end of the buffer for Buf_Retrieve. */ 107 void 108 BufExpand(Buffer bp, size_t nb) 109 { 110 size_t occupied = bp->inPtr - bp->buffer; 111 size_t size = bp->endPtr - bp->buffer; 112 DO_STAT_BUF(bp, nb); 113 114 do { 115 if (size <= SIZE_MAX/2) { 116 size *= 2 ; 117 } else { 118 fatal_overflow(); 119 } 120 assert(size >= occupied); 121 } while (size - occupied < nb+1+BUF_MARGIN); 122 bp->buffer = erealloc(bp->buffer, size); 123 bp->inPtr = bp->buffer +occupied; 124 bp->endPtr = bp->buffer + size; 125 } 126 127 void 128 Buf_AddChars(Buffer bp, size_t numBytes, const char *bytesPtr) 129 { 130 assert(bp->endPtr >= bp->inPtr); 131 if ((size_t)(bp->endPtr - bp->inPtr) < numBytes+1) 132 BufExpand(bp, numBytes); 133 134 memcpy(bp->inPtr, bytesPtr, numBytes); 135 bp->inPtr += numBytes; 136 } 137 138 void 139 Buf_printf(Buffer bp, const char *fmt, ...) 140 { 141 va_list va; 142 int n; 143 va_start(va, fmt); 144 n = vsnprintf(bp->inPtr, bp->endPtr - bp->inPtr, fmt, va); 145 va_end(va); 146 if (n+1 > bp->endPtr - bp->inPtr) { 147 va_list vb; 148 BufExpand(bp, n); 149 va_start(vb, fmt); 150 (void)vsnprintf(bp->inPtr, bp->endPtr - bp->inPtr, fmt, vb); 151 va_end(vb); 152 } 153 bp->inPtr += n; 154 } 155 156 void 157 Buf_Reinit(Buffer bp, size_t size) 158 { 159 if (bp->buffer == NULL) 160 Buf_Init(bp, size); 161 else 162 Buf_Reset(bp); 163 } 164 165 void 166 Buf_Init(Buffer bp, size_t size) 167 { 168 #ifdef STATS_BUF 169 STAT_TOTAL_BUFS++; 170 if (size == 0) 171 STAT_DEFAULT_BUFS++; 172 if (size == 1) 173 STAT_WEIRD_BUFS++; 174 #endif 175 if (size == 0) 176 size = BUF_DEF_SIZE; 177 bp->inPtr = bp->endPtr = bp->buffer = emalloc(size); 178 bp->endPtr += size; 179 } 180