crt: Provide *_recalloc functions
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ö <martin@martin.st>
diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am
index e02f03e..b705b86 100644
--- a/mingw-w64-crt/Makefile.am
+++ b/mingw-w64-crt/Makefile.am
@@ -324,7 +324,10 @@
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 @@
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 0000000..297393a
--- /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 <malloc.h>
+#include <string.h>
+
+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 0000000..e374d09
--- /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 <malloc.h>
+#include <string.h>
+
+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 0000000..82d6a11
--- /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 <malloc.h>
+#include <string.h>
+
+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 b53f19b..37014c4 100644
--- a/mingw-w64-headers/crt/crtdbg.h
+++ b/mingw-w64-headers/crt/crtdbg.h
@@ -161,11 +161,9 @@
#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 70f34dc..48ae0db 100644
--- a/mingw-w64-headers/crt/malloc.h
+++ b/mingw-w64-headers/crt/malloc.h
@@ -102,11 +102,9 @@
_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 969848d..4829713 100644
--- a/mingw-w64-headers/crt/stdlib.h
+++ b/mingw-w64-headers/crt/stdlib.h
@@ -458,11 +458,9 @@
_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)