1 /* Variable-sized buffer with on-stack default allocation. 2 Copyright (C) 2015-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19 #ifndef _LIBC 20 # include <libc-config.h> 21 #endif 22 23 #include <scratch_buffer.h> 24 #include <errno.h> 25 #include <string.h> 26 27 bool __libc_scratch_buffer_grow_preserve(struct scratch_buffer * buffer)28__libc_scratch_buffer_grow_preserve (struct scratch_buffer *buffer) 29 { 30 size_t new_length = 2 * buffer->length; 31 void *new_ptr; 32 33 if (buffer->data == buffer->__space.__c) 34 { 35 /* Move buffer to the heap. No overflow is possible because 36 buffer->length describes a small buffer on the stack. */ 37 new_ptr = malloc (new_length); 38 if (new_ptr == NULL) 39 return false; 40 memcpy (new_ptr, buffer->__space.__c, buffer->length); 41 } 42 else 43 { 44 /* Buffer was already on the heap. Check for overflow. */ 45 if (__glibc_likely (new_length >= buffer->length)) 46 new_ptr = realloc (buffer->data, new_length); 47 else 48 { 49 __set_errno (ENOMEM); 50 new_ptr = NULL; 51 } 52 53 if (__glibc_unlikely (new_ptr == NULL)) 54 { 55 /* Deallocate, but buffer must remain valid to free. */ 56 free (buffer->data); 57 scratch_buffer_init (buffer); 58 return false; 59 } 60 } 61 62 /* Install new heap-based buffer. */ 63 buffer->data = new_ptr; 64 buffer->length = new_length; 65 return true; 66 } 67 libc_hidden_def (__libc_scratch_buffer_grow_preserve) 68