The standard functions malloc(),
calloc(), and
realloc() allocate
objects, regions of memory to store values. The
malloc() function allocates uninitialized
space for an object of the specified size.
malloc() maintains multiple lists of free
objects according to size, allocating from the appropriate list or requesting
memory from the kernel. The allocated space is suitably aligned (after
possible pointer coercion) for storage of any type of object.

The calloc() function allocates space for an
array of nmemb objects, each of the specified
size. The space is initialized to zero.

The realloc() function changes the size of
the object pointed to by ptr to
size bytes and returns a pointer to the
(possibly moved) object. If ptr is not
NULL, it must be a pointer returned by an
earlier call to an allocation or reallocation function that was not freed in
between. The contents of the object are unchanged up to the lesser of the new
and old sizes. If the new size is larger, the value of the newly allocated
portion of the object is indeterminate and uninitialized. If the space cannot
be allocated, the object pointed to by ptr is
unchanged. If ptr is
NULL,
realloc() behaves like
malloc() and allocates a new object.

The free() function causes the space pointed
to by ptr to be either placed on a list of
free blocks to make it available for future allocation or, when appropriate,
to be returned to the kernel using
munmap(2). If
ptr is
NULL, no action occurs. If
ptr was previously freed by
free() or a reallocation function, the
behavior is undefined and the double free is a security concern.

Designed for safe allocation of arrays, the
reallocarray() function is similar to
realloc() except it operates on
nmemb members of size
size and checks for integer overflow in the
calculation nmemb *
size.

Used for the allocation of memory holding sensitive data, the
recallocarray() and
freezero() functions guarantee that memory
becoming unallocated is explicitly discarded,
meaning pages of memory are disposed via
munmap(2) and cached free
objects are cleared with
explicit_bzero(3).

The recallocarray() function is similar to
reallocarray() except it ensures newly
allocated memory is cleared similar to
calloc(). If
ptr is
NULL,
oldnmemb is ignored and the call is
equivalent to calloc(). If
ptr is not
NULL,
oldnmemb must be a value such that
oldnmemb *
size is the size of the earlier allocation
that returned ptr, otherwise the behaviour is
undefined.

The freezero() function is similar to the
free() function except it ensures memory is
explicitly discarded. If ptr is
NULL, no action occurs. If
ptr is not
NULL, the
size argument must be equal or smaller than
the size of the earlier allocation that returned
ptr.
freezero() guarantees the memory range
starting at ptr with length
size is discarded while deallocating the
whole object originally allocated.

Consider calloc() or the extensions
reallocarray() and
recallocarray() when there is
multiplication in the size argument of
malloc() or
realloc(). For example, avoid this common
idiom as it may lead to integer overflow:

if ((p = malloc(num * size)) == NULL)
err(1, NULL);

A drop-in replacement is the OpenBSD extension
reallocarray():

if ((p = reallocarray(NULL, num, size)) == NULL)
err(1, NULL);

Alternatively, calloc() may be used at the
cost of initialization overhead.

When using realloc(), be careful to avoid the
following idiom:

size += 50;
if ((p = realloc(p, size)) == NULL)
return (NULL);

Do not adjust the variable describing how much memory has been allocated until
the allocation has been successful. This can cause aberrant program behavior
if the incorrect size value is used. In most cases, the above sample will also
result in a leak of memory. As stated earlier, a return value of
NULL indicates that the old object still
remains allocated. Better code looks like this:

The recallocarray() function should be used
for resizing objects containing sensitive data like keys. To avoid leaking
information, it guarantees memory is cleared before placing it on the internal
free list. Deallocation of such an object should be done by calling
freezero().

If any of the functions detect an error condition, a message will be printed to
file descriptor 2 (not using stdio). Errors will result in the process being
aborted.

Here is a brief description of the error messages and what they mean:

“out of memory”

If the X option is specified it is an
error for the allocation functions to return
NULL.

“bogus pointer (double free?)”

An attempt to free() or reallocate an
unallocated pointer was made.

“chunk is already free”

There was an attempt to free a chunk that had already been freed.

“use after free”

A chunk has been modified after it was freed.

“modified chunk-pointer”

The pointer passed to free() or a
reallocation function has been modified.

“chunk canary corrupted address offset@length”

A byte after the requested size has been overwritten, indicating a heap
overflow. The offset at which corruption was detected is printed before
the @, and the requested length of the allocation after the @.

“recorded old size oldsize != size”

recallocarray() has detected that the
given old size does not equal the recorded size in its meta data. Enabling
option C allows
recallocarray() to catch more of these
cases.

“recursive call”

An attempt was made to call recursively into these functions, i.e., from a
signal handler. This behavior is not supported. In particular, signal
handlers should not use any of the
malloc() functions nor utilize any
other functions which may call malloc()
(e.g., stdio(3)
routines).

A free() internal kernel function and a
predecessor to malloc(),
alloc(), first appeared in
Version 1 AT&T UNIX. C library functions
alloc() and
free() appeared in
Version 6 AT&T UNIX. The functions
malloc(),
calloc(), and
realloc() first appeared in
Version 7 AT&T UNIX.

A new implementation by Chris Kingsley was introduced in
4.2BSD, followed by a complete rewrite by Poul-Henning
Kamp which appeared in FreeBSD 2.2 and was included in
OpenBSD 2.0. These implementations were all
sbrk(2) based. In
OpenBSD 3.8, Thierry Deval rewrote
malloc to use the
mmap(2) system call, making the
page addresses returned by malloc random. A
rewrite by Otto Moerbeek introducing a new central data structure and more
randomization appeared in OpenBSD 4.4.

The reallocarray() function appeared in
OpenBSD 5.6. The
recallocarray() function appeared in
OpenBSD 6.1. The
freezero() function appeared in
OpenBSD 6.2.

When using malloc(), be wary of signed
integer and size_t overflow especially when
there is multiplication in the size argument.

Signed integer overflow will cause undefined behavior which compilers typically
handle by wrapping back around to negative numbers. Depending on the input,
this can result in allocating more or less memory than intended.

An unsigned overflow has defined behavior which will wrap back around and return
less memory than intended.

A signed or unsigned integer overflow is a security
risk if less memory is returned than intended. Subsequent code may corrupt the
heap by writing beyond the memory that was allocated. An attacker may be able
to leverage this heap corruption to execute arbitrary code.

Consider using calloc(),
reallocarray() or
recallocarray() instead of using
multiplication in malloc() and
realloc() to avoid these problems on
OpenBSD.