From e1ff62d7f9acfbcb748e636f097fd2e6cc21d249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Tue, 8 Apr 2025 00:20:47 +0200 Subject: [PATCH] crt: Provide *_recalloc functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are natively available since msvcr80.dll, they are not available in msvcrt.dll. Provide compatibility emulation into all import libraries where they are not available. Compatibility emulation needs to use _msize() or _aligned_msize() functions to figure out the previous size and properly clear the expanded memory as *calloc functions require. Memory allocated by these mingw-w64 emulation functions can be normally released by the appropriate CRT free() or _aligned_free() function. Signed-off-by: Martin Storsjö --- mingw-w64-crt/Makefile.am | 6 +++++ mingw-w64-crt/misc/_aligned_offset_recalloc.c | 25 +++++++++++++++++++ mingw-w64-crt/misc/_aligned_recalloc.c | 25 +++++++++++++++++++ mingw-w64-crt/misc/_recalloc.c | 25 +++++++++++++++++++ mingw-w64-headers/crt/crtdbg.h | 2 -- mingw-w64-headers/crt/malloc.h | 2 -- mingw-w64-headers/crt/stdlib.h | 2 -- 7 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 mingw-w64-crt/misc/_aligned_offset_recalloc.c create mode 100644 mingw-w64-crt/misc/_aligned_recalloc.c create mode 100644 mingw-w64-crt/misc/_recalloc.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index e02f03e4e..b705b8673 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -324,7 +324,10 @@ src_msvcrt=\ misc/__sys_errlist.c \ misc/__sys_nerr.c \ misc/_aligned_msize.c \ + misc/_aligned_offset_recalloc.c \ + misc/_aligned_recalloc.c \ misc/_configthreadlocale.c \ + misc/_recalloc.c \ misc/_set_purecall_handler.c \ misc/imaxdiv.c \ misc/invalid_parameter_handler.c \ @@ -813,9 +816,12 @@ src_pre_msvcr80=\ misc/__sys_errlist.c \ misc/__sys_nerr.c \ misc/_aligned_msize.c \ + misc/_aligned_offset_recalloc.c \ + misc/_aligned_recalloc.c \ misc/_configthreadlocale.c \ misc/_get_errno.c \ misc/_initterm_e.c \ + misc/_recalloc.c \ misc/_set_errno.c \ misc/btowc.c \ misc/imaxabs.c \ diff --git a/mingw-w64-crt/misc/_aligned_offset_recalloc.c b/mingw-w64-crt/misc/_aligned_offset_recalloc.c new file mode 100644 index 000000000..297393a26 --- /dev/null +++ b/mingw-w64-crt/misc/_aligned_offset_recalloc.c @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +void * __cdecl _aligned_offset_recalloc(void *memory, size_t count, size_t size, size_t alignment, size_t offset) +{ + void *new_memory; + size_t previous_size; + size_t total_size; + if (__builtin_mul_overflow(count, size, &total_size)) + return NULL; + previous_size = memory ? _aligned_msize(memory, alignment, offset) : 0; + if (previous_size == (size_t)-1) + return NULL; + new_memory = _aligned_offset_realloc(memory, total_size, alignment, offset); + if (new_memory && previous_size < total_size) + memset(new_memory + previous_size, 0, total_size - previous_size); + return new_memory; +} +void * (__cdecl *__MINGW_IMP_SYMBOL(_aligned_offset_recalloc))(void *, size_t, size_t, size_t, size_t) = _aligned_offset_recalloc; diff --git a/mingw-w64-crt/misc/_aligned_recalloc.c b/mingw-w64-crt/misc/_aligned_recalloc.c new file mode 100644 index 000000000..e374d0907 --- /dev/null +++ b/mingw-w64-crt/misc/_aligned_recalloc.c @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +void * __cdecl _aligned_recalloc(void *memory, size_t count, size_t size, size_t alignment) +{ + void *new_memory; + size_t previous_size; + size_t total_size; + if (__builtin_mul_overflow(count, size, &total_size)) + return NULL; + previous_size = memory ? _aligned_msize(memory, alignment, 0) : 0; + if (previous_size == (size_t)-1) + return NULL; + new_memory = _aligned_realloc(memory, total_size, alignment); + if (new_memory && previous_size < total_size) + memset(new_memory + previous_size, 0, total_size - previous_size); + return new_memory; +} +void * (__cdecl *__MINGW_IMP_SYMBOL(_aligned_recalloc))(void *, size_t, size_t, size_t) = _aligned_recalloc; diff --git a/mingw-w64-crt/misc/_recalloc.c b/mingw-w64-crt/misc/_recalloc.c new file mode 100644 index 000000000..82d6a11db --- /dev/null +++ b/mingw-w64-crt/misc/_recalloc.c @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +void * __cdecl _recalloc(void *memory, size_t count, size_t size) +{ + void *new_memory; + size_t previous_size; + size_t total_size; + if (__builtin_mul_overflow(count, size, &total_size)) + return NULL; + previous_size = memory ? _msize(memory) : 0; + if (previous_size == (size_t)-1) + return NULL; + new_memory = realloc(memory, total_size); + if (new_memory && previous_size < total_size) + memset(new_memory + previous_size, 0, total_size - previous_size); + return new_memory; +} +void * (__cdecl *__MINGW_IMP_SYMBOL(_recalloc))(void *, size_t, size_t) = _recalloc; diff --git a/mingw-w64-headers/crt/crtdbg.h b/mingw-w64-headers/crt/crtdbg.h index b53f19bcf..37014c4fb 100644 --- a/mingw-w64-headers/crt/crtdbg.h +++ b/mingw-w64-headers/crt/crtdbg.h @@ -161,11 +161,9 @@ extern "C" { #define _aligned_offset_malloc_dbg(s,a,o,f,l) _aligned_offset_malloc(s,a,o) #define _aligned_offset_realloc_dbg(p,s,a,o,f,l) _aligned_offset_realloc(p,s,a,o) -#if __MSVCRT_VERSION__ >= 0x900 #define _recalloc_dbg(p,c,s,t,f,l) _recalloc(p,c,s) #define _aligned_recalloc_dbg(p,c,s,a,f,l) _aligned_realloc(p,c,s,a) #define _aligned_offset_recalloc_dbg(p,c,s,a,o,f,l) _aligned_offset_recalloc(p,c,s,a,o) -#endif #define _aligned_msize_dbg(p,a,o) _aligned_msize(p,a,o) #define _malloca_dbg(s,t,f,l) _malloca(s) diff --git a/mingw-w64-headers/crt/malloc.h b/mingw-w64-headers/crt/malloc.h index 70f34dc7c..48ae0db90 100644 --- a/mingw-w64-headers/crt/malloc.h +++ b/mingw-w64-headers/crt/malloc.h @@ -102,11 +102,9 @@ extern "C" { _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset); _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment); _CRTIMP void *__cdecl _aligned_offset_realloc(void *_Memory,size_t _Size,size_t _Alignment,size_t _Offset); -# if __MSVCRT_VERSION__ >= 0x900 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size); _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment); _CRTIMP void *__cdecl _aligned_offset_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment,size_t _Offset); -# endif _CRTIMP size_t __cdecl _aligned_msize(void *_Memory,size_t _Alignment,size_t _Offset); #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC) diff --git a/mingw-w64-headers/crt/stdlib.h b/mingw-w64-headers/crt/stdlib.h index 969848d64..482971357 100644 --- a/mingw-w64-headers/crt/stdlib.h +++ b/mingw-w64-headers/crt/stdlib.h @@ -458,11 +458,9 @@ float __cdecl __MINGW_NOTHROW strtof(const char * __restrict__ _Str,char ** __re _CRTIMP void *__cdecl _aligned_offset_malloc(size_t _Size,size_t _Alignment,size_t _Offset); _CRTIMP void *__cdecl _aligned_realloc(void *_Memory,size_t _Size,size_t _Alignment); _CRTIMP void *__cdecl _aligned_offset_realloc(void *_Memory,size_t _Size,size_t _Alignment,size_t _Offset); -# if __MSVCRT_VERSION__ >= 0x900 _CRTIMP void *__cdecl _recalloc(void *_Memory,size_t _Count,size_t _Size); _CRTIMP void *__cdecl _aligned_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment); _CRTIMP void *__cdecl _aligned_offset_recalloc(void *_Memory,size_t _Count,size_t _Size,size_t _Alignment,size_t _Offset); -# endif _CRTIMP size_t __cdecl _aligned_msize(void *_Memory,size_t _Alignment,size_t _Offset); #if defined(_DEBUG) && defined(_CRTDBG_MAP_ALLOC)