diff --git a/numpy/_core/src/multiarray/stringdtype/static_string.c b/numpy/_core/src/multiarray/stringdtype/static_string.c index f5c2025e183a..c437fab2d336 100644 --- a/numpy/_core/src/multiarray/stringdtype/static_string.c +++ b/numpy/_core/src/multiarray/stringdtype/static_string.c @@ -155,8 +155,6 @@ vstring_buffer(npy_string_arena *arena, _npy_static_string_u *string) return (char *)((size_t)arena->buffer + string->vstring.offset); } -#define ARENA_EXPAND_FACTOR 1.25 - static char * arena_malloc(npy_string_arena *arena, npy_string_realloc_func r, size_t size) { @@ -168,25 +166,17 @@ arena_malloc(npy_string_arena *arena, npy_string_realloc_func r, size_t size) else { string_storage_size = size + sizeof(size_t); } - if ((arena->size - arena->cursor) <= string_storage_size) { - // realloc the buffer so there is enough room - // first guess is to double the size of the buffer - size_t newsize; - if (arena->size == 0) { - newsize = string_storage_size; - } - else if (((ARENA_EXPAND_FACTOR * arena->size) - arena->cursor) > - string_storage_size) { - newsize = (size_t)(ARENA_EXPAND_FACTOR * arena->size); + if ((arena->size - arena->cursor) < string_storage_size) { + size_t minsize = arena->cursor + string_storage_size; + if (minsize < arena->cursor) { + return NULL; // overflow means out of memory } - else { - newsize = arena->size + string_storage_size; - } - // If there enough room for both the payload and its header - if ((arena->cursor + string_storage_size) > newsize) { - // need extra room beyond the expansion factor, leave some padding - newsize = (size_t)(ARENA_EXPAND_FACTOR * (arena->cursor + string_storage_size)); + // Allocate 25% more than needed for this string. + size_t newsize = minsize + minsize / 4; + if (newsize < minsize) { + return NULL; // overflow means out of memory } + // passing a NULL buffer to realloc is the same as malloc char *newbuf = r(arena->buffer, newsize); if (newbuf == NULL) {