xref: /reactos/sdk/lib/ucrt/heap/recalloc.cpp (revision 53d808d2)
1 //
2 // recalloc.cpp
3 //
4 //      Copyright (c) Microsoft Corporation. All rights reserved.
5 //
6 // Implementation of _recalloc()
7 //
8 #include <corecrt_internal.h>
9 #include <malloc.h>
10 #include <string.h>
11 
12 
13 
14 // This function provides the logic for the _recalloc() function.  It is called
15 // only in the Release CRT (in the Debug CRT, the debug heap has its own
16 // implementation of _recalloc()).
17 //
18 // This function must be marked noinline, otherwise recalloc and
19 // _recalloc_base will have identical COMDATs, and the linker will fold
20 // them when calling one from the CRT. This is necessary because recalloc
21 // needs to support users patching in custom implementations.
22 extern "C" __declspec(noinline) void* __cdecl _recalloc_base(
23     void*  const block,
24     size_t const count,
25     size_t const size
26     )
27 {
28     // Ensure that (count * size) does not overflow
29     _VALIDATE_RETURN_NOEXC(count == 0 || (_HEAP_MAXREQ / count) >= size, ENOMEM, nullptr);
30 
31     size_t const old_block_size = block != nullptr ? _msize_base(block) : 0;
32     size_t const new_block_size = count * size;
33 
34     void* const new_block = _realloc_base(block, new_block_size);
35 
36     // If the reallocation succeeded and the new block is larger, zero-fill the
37     // new bytes:
38     if (new_block != nullptr && old_block_size < new_block_size)
39     {
40         memset(static_cast<char*>(new_block) + old_block_size, 0, new_block_size - old_block_size);
41     }
42 
43     return new_block;
44 }
45 
46 // Reallocates a block of memory in the heap.
47 //
48 // This function reallocates the block pointed to by 'block' such that it is
49 // 'count * size' bytes in size.  The new size may be either greater or less
50 // than the original size of the block.  If the new size is greater than the
51 // original size, the new bytes are zero-filled.  This function shares its
52 // implementation with the realloc() function; consult the comments of that
53 // function for more information about the implementation.
54 //
55 // This function supports patching and therefore must be marked noinline.
56 // Both _recalloc_dbg and _recalloc_base must also be marked noinline
57 // to prevent identical COMDAT folding from substituting calls to _recalloc
58 // with either other function or vice versa.
59 extern "C" __declspec(noinline) _CRTRESTRICT void* __cdecl _recalloc(
60     void*  const block,
61     size_t const count,
62     size_t const size
63     )
64 {
65     #ifdef _DEBUG
66     return _recalloc_dbg(block, count, size, _NORMAL_BLOCK, nullptr, 0);
67     #else
68     return _recalloc_base(block, count, size);
69     #endif
70 }
71