C & C++ Dynamic Memory Management

Chapter 4 - Dynamic Memory Management(4.1 - 4.5)

  • Book by Robert C. Seacord

This chapter of Book Secure Coding in C And C++ describes dynamic memory management in C and C++ on Linux and Windows platforms. It discusses common dynamic memory management errors, and assesses the corresponding security risks

Buffer Overflow:

  • stack (staic memory management)
  • heap (dynamic memory management)

C Memory Management

4 memory allocation functions

#include <stdlib.h>
  • malloc(size_t size): aligned to the most strictly aligned object, not initialized
  • aligned_alloc(size_t alignment, size_t size): define alignment
  • realloc(void *p, size_t size): changes the size of the memory block.
  • calloc(size_t nmemb, size_t size): set to 0

1 memory deallocation function

  • free(void *p). It frees the memory space pointed to by p, which must have been returned by a previous call to aligned_alloc(), malloc(), calloc(), or realloc().

Free means cancelling the mapping between the pointer and the allocated memory.

Allocated storage duration

  • If malloc() is called within a function, the allocated memory will still exist after the function returns.

Alignment

  • A fundamental alignment is less than or equal to the greatest alignment supported by the compiler in all contexts. The alignment of the max_align_t type is as great as is supported by a compiler in all contexts.
  • If a program requests an alignment that is greater than alignof(max_align_t), the program is not portable because support for an overaligned type is optional.
  • A type having an extended alignment requirement is also called an overaligned type.
  • If you call the realloc() function on a pointer returned from aligned_alloc(), the C Standard does not require that the stricter-than-normal alignment be preserved. This issue is described further by The CERT C Secure Coding Standard [Seacord 2008], “MEM36-C. Check for alignment of memory space before calling realloc() function.”

alloca() and Variable-Length Arrays

  • The alloca() function allocates memory in the stack frame of the caller. This memory is automatically freed when the function that called alloca() returns. The alloca() function returns a pointer to the beginning of the allocated space.
  • alloca(), which must not be freed. Calling free() on a pointer not obtained by calling a memory allocation function is a serious error and undefined behavior.

Allocation Failure

This will throw an exception:

T* p1 = new T; // throws bad_alloc on failure

Common C Memory Management Errors

  • Initialization Errors
  • Failing to Check Return Values
  • Dereferencing Null or Invalid Pointers
  • Referencing Freed Memory
  • Freeing Memory Multiple Times
  • Memory Leaks
  • Zero-Length Alocations

C++ Memory Management

No exception:

T* p2 = new(std::nothrow) T; // returns 0 on failure

Resource Acquisition Is Initialization(RAII)

To keep track of a resource, create an object and associate the resource’s lifetime with the object’s lifetime. This allows you to use C++’s object-management facilities to manage resources.

Deallocation Functions

void operator delete(void *);
void operator delete(void *, size_t);
void operator delete[](void *);
void operator delete[](void *, size_t);

4.4 Common C++ Memory Management Errors

  • failing to correctly handle allocation failures
    • Incorrect Use of the new Operator
    • Improperly Paired Memory Management Functions: free with new, etc…
1 int *ip = new int(8);
2 ...
3 free(ip); // wrong!
4 ip = static_cast<int *>(malloc(sizeof(int)));
5 *ip = 8;
6 ...
7 delete ip; // wrong!
  • Dereferencing null pointers
  • Writing to already freed memory
  • Freeing the same memory multiple times
  • Improperly paired memory management functions
  • Failure to distinguish scalars and arrays
  • Improper use of allocation functions

Correct Pairing of Memory Allocation and Deallocation functions

Allocator Deallocator
aligned_alloc(), calloc(), malloc(), realloc() free()
operator new() operator delete()
operator new operator delete
Member new() Member delete()
Member new Member delete
Placement new() Destructor
alloca() Function return

Notes:

  • C++ uses new and delete to manage memory:
    • new and delete for object
    • new[] and delete[] for object array
  • new will call operator new, and operator new will call malloc(), and the consturct function, and return the pointer.
  • delete will call destruction function to clear the object, and call operator delete(), and therefore the free() to free the space.
  • There will be extra space before new[x] than new to store the number of the objects, the delete will ignore this difference.
  • It is less dangerous to leak memory than to free the same memory twice.
  • Double Free the memory will get the error message:
*** glibc detected *** ./test.out: double free or corruption (fasttop): 0x0000000000970010 ***

Memory Managers

Memory managers manage both allocated and free memory in the heap.

Dynamic storage allocation requires an algorithm for finding and reserving a chunk of n contiguous bytes.

Reference