<?xml version='1.0' encoding='utf-8' ?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<section id="sect-Defensive_Coding-C-Allocators">
  <title>Memory allocators</title>

  <section>
    <title><function>malloc</function> and related functions</title>
    <para>
      The C library interfaces for memory allocation are provided by
      <function>malloc</function>, <function>free</function> and
      <function>realloc</function>, and the
      <function>calloc</function> function.  In addition to these
      generic functions, there are derived functions such as
      <function>strdup</function> which perform allocation using
      <function>malloc</function> internally, but do not return
      untyped heap memory (which could be used for any object).
    </para>
    <para>
      The C compiler knows about these functions and can use their
      expected behavior for optimizations.  For instance, the compiler
      assumes that an existing pointer (or a pointer derived from an
      existing pointer by arithmetic) will not point into the memory
      area returned by <function>malloc</function>.
    </para>
    <para>
      If the allocation fails, <function>realloc</function> does not
      free the old pointer.  Therefore, the idiom <literal>ptr =
      realloc(ptr, size);</literal> is wrong because the memory
      pointed to by <literal>ptr</literal> leaks in case of an error.
    </para>
    <section>
      <title>Use-after-free errors</title>
      <para>
	After <function>free</function>, the pointer is invalid.
	Further pointer dereferences are not allowed (and are usually
	detected by <application>valgrind</application>).  Less obvious
	is that any <emphasis>use</emphasis> of the old pointer value is
	not allowed, either.  In particular, comparisons with any other
	pointer (or the null pointer) are undefined according to the C
	standard.
      </para>
      <para>
	The same rules apply to <function>realloc</function> if the
	memory area cannot be enlarged in-place.  For instance, the
	compiler may assume that a comparison between the old and new
	pointer will always return false, so it is impossible to detect
	movement this way.
      </para>
    </section>
    <section>
      <title>Handling memory allocation errors</title>
      <para>
	Recovering from out-of-memory errors is often difficult or even
	impossible.  In these cases, <function>malloc</function> and
	other allocation functions return a null pointer.  Dereferencing
	this pointer lead to a crash.  Such dereferences can even be
	exploitable for code execution if the dereference is combined
	with an array subscript.
      </para>
      <para>
	In general, if you cannot check all allocation calls and
	handle failure, you should abort the program on allocation
	failure, and not rely on the null pointer dereference to
	terminate the process.  See
	<xref
	linkend="sect-Defensive_Coding-Tasks-Serialization-Decoders"/>
	for related memory allocation concerns.
      </para>
    </section>
  </section>

  <section id="sect-Defensive_Coding-C-Allocators-alloca">
    <title><function>alloca</function> and other forms of stack-based
    allocation</title>
    <para>
      Allocation on the stack is risky because stack overflow checking
      is implicit.  There is a guard page at the end of the memory
      area reserved for the stack.  If the program attempts to read
      from or write to this guard page, a <literal>SIGSEGV</literal>
      signal is generated and the program typically terminates.
    </para>
    <para>
      This is sufficient for detecting typical stack overflow
      situations such as unbounded recursion, but it fails when the
      stack grows in increments larger than the size of the guard
      page.  In this case, it is possible that the stack pointer ends
      up pointing into a memory area which has been allocated for a
      different purposes.  Such misbehavior can be exploitable.
    </para>
    <para>
      A common source for large stack growth are calls to
      <function>alloca</function> and related functions such as
      <function>strdupa</function>.  These functions should be avoided
      because of the lack of error checking.  (They can be used safely
      if the allocated size is less than the page size (typically,
      4096 bytes), but this case is relatively rare.)  Additionally,
      relying on <function>alloca</function> makes it more difficult
      to reorgnize the code because it is not allowed to use the
      pointer after the function calling <function>alloca</function>
      has returned, even if this function has been inlined into its
      caller.
    </para>
    <para>
      Similar concerns apply to <emphasis>variable-length
      arrays</emphasis> (VLAs), a feature of the C99 standard which
      started as a GNU extension.  For large objects exceeding the
      page size, there is no error checking, either.
    </para>
    <para>
      In both cases, negative or very large sizes can trigger a
      stack-pointer wraparound, and the stack pointer and end up
      pointing into caller stack frames, which is fatal and can be
      exploitable.
    </para>
    <para>
      If you want to use <function>alloca</function> or VLAs for
      performance reasons, consider using a small on-stack array (less
      than the page size, large enough to fulfill most requests).  If
      the requested size is small enough, use the on-stack array.
      Otherwise, call <function>malloc</function>.  When exiting the
      function, check if <function>malloc</function> had been called,
      and free the buffer as needed.
    </para>
  </section>

  <section id="sect-Defensive_Coding-C-Allocators-Arrays">
    <title>Array allocation</title>
    <para>
      When allocating arrays, it is important to check for overflows.
      The <function>calloc</function> function performs such checks.
    </para>
    <para>
      If <function>malloc</function> or <function>realloc</function>
      is used, the size check must be written manually.  For instance,
      to allocate an array of <literal>n</literal> elements of type
      <literal>T</literal>, check that the requested size is not
      greater than <literal>n / sizeof(T)</literal>.
    </para>
  </section>

  <section>
    <title>Custom memory allocators</title>
    <para>
      Custom memory allocates come in two forms: replacements for
      <function>malloc</function>, and completely different interfaces
      for memory management.  Both approaches can reduce the
      effectiveness of <application>valgrind</application> and similar
      tools, and the heap corruption detection provided by GNU libc, so
      they should be avoided.
    </para>
    <para>
      Memory allocators are difficult to write and contain many
      performance and security pitfalls.
    </para>
    <itemizedlist>
      <listitem>
	<para>
	  When computing array sizes or rounding up allocation
	  requests (to the next allocation granularity, or for
	  alignment purposes), checks for arithmetic overflow are
	  required.
	</para>
      </listitem>
      <listitem>
	<para>
	  Size computations for array allocations need overflow
	  checking.  See <xref
	  linkend="sect-Defensive_Coding-C-Allocators-Arrays"/>.
	</para>
      </listitem>
      <listitem>
	<para>
	  It can be difficult to beat well-tuned general-purpose
	  allocators.  In micro-benchmarks, pool allocators can show
	  huge wins, and size-specific pools can reduce internal
	  fragmentation.  But often, utilization of individual pools
	  is poor, and 
	</para>
      </listitem>
    </itemizedlist>
  </section>

  <section>
    <title>Conservative garbage collection</title>
    <para>
      Garbage collection can be an alternative to explicit memory
      management using <function>malloc</function> and
      <function>free</function>.  The Boehm-Dehmers-Weiser allocator
      can be used from C programs, with minimal type annotations.
      Performance is competitive with <function>malloc</function> on
      64-bit architectures, especially for multi-threaded programs.
      The stop-the-world pauses may be problematic for some real-time
      applications, though.
    </para>
    <para>
      However, using a conservative garbage collector may reduce
      opertunities for code reduce because once one library in a
      program uses garbage collection, the whole process memory needs
      to be subject to it, so that no pointers are missed.  The
      Boehm-Dehmers-Weiser collector also reserves certain signals for
      internal use, so it is not fully transparent to the rest of the
      program.
    </para>
  </section>
</section>

