From 94f451e0702a6b4776abd5e013d514b5aaa7e2e2 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 27 Mar 2020 21:52:42 -0300 Subject: [PATCH] Ensure COWData does not reallocate on push back, fixes #22561 (cherry picked from commit 0c24a844ecff77cb956ce052e47ccf6d4c774666) --- core/cowdata.h | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/core/cowdata.h b/core/cowdata.h index 4fdcaf3cea3..e733f7cd2b0 100644 --- a/core/cowdata.h +++ b/core/cowdata.h @@ -252,7 +252,9 @@ Error CowData::resize(int p_size) { ERR_FAIL_COND_V(p_size < 0, ERR_INVALID_PARAMETER); - if (p_size == size()) + int current_size = size(); + + if (p_size == current_size) return OK; if (p_size == 0) { @@ -265,24 +267,27 @@ Error CowData::resize(int p_size) { // possibly changing size, copy on write _copy_on_write(); + size_t current_alloc_size = _get_alloc_size(current_size); size_t alloc_size; ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY); - if (p_size > size()) { + if (p_size > current_size) { - if (size() == 0) { - // alloc from scratch - uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true); - ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY); - *(ptr - 1) = 0; //size, currently none - *(ptr - 2) = 1; //refcount + if (alloc_size != current_alloc_size) { + if (current_size == 0) { + // alloc from scratch + uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true); + ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY); + *(ptr - 1) = 0; //size, currently none + *(ptr - 2) = 1; //refcount - _ptr = (T *)ptr; + _ptr = (T *)ptr; - } else { - void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true); - ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); - _ptr = (T *)(_ptrnew); + } else { + void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true); + ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); + _ptr = (T *)(_ptrnew); + } } // construct the newly created elements @@ -297,7 +302,7 @@ Error CowData::resize(int p_size) { *_get_size() = p_size; - } else if (p_size < size()) { + } else if (p_size < current_size) { if (!__has_trivial_destructor(T)) { // deinitialize no longer needed elements @@ -307,10 +312,12 @@ Error CowData::resize(int p_size) { } } - void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true); - ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); + if (alloc_size != current_alloc_size) { + void *_ptrnew = (T *)Memory::realloc_static(_ptr, alloc_size, true); + ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); - _ptr = (T *)(_ptrnew); + _ptr = (T *)(_ptrnew); + } *_get_size() = p_size; }