Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

An object of type void * is a generic data pointer. It can point to any data object. For any incomplete or object type T, C permits implicit conversion from T * to void * or from void * to T *. The Standard C Library uses void * to declare parameters and return types of functions designed to work for objects of different types. Such is the case with the standard memory allocation functions aligned_alloc(), malloc(), calloc(), and realloc().

For example, C Library declares malloc() as

Code Block

void *malloc(size_t);

Calling malloc(s) allocates memory for an object whose size is s and returns either a null pointer or a pointer to the allocated memory. A program can implicitly convert the pointer that malloc() returns into a different pointer type.

...

Code Block
bgColor#ffcccc
langc

#include <stdlib.h>

typedef struct gadget gadget;
struct gadget {
  int i;
  double d;
};

typedef struct widget widget;
struct widget {
  char c[10];
  int i;
  double d;
};

widget *p;

/* ... */

p = malloc(sizeof(gadget)); /* imminent problem */
if (p != NULL) {
  p->i = 0;               /* undefined behavior */
  p->d = 0.0;             /* undefined behavior */
}

An implementation may add padding to a gadget or widget so that sizeof(gadget) equals sizeof(widget), but this is highly unlikely. More likely, sizeof(gadget) is less than sizeof(widget). In that case,

Code Block
bgColor#FFcccc
langc

p = malloc(sizeof(gadget)); /* imminent problem */

...

In this code example, malloc() allocates space for a gadget, and the cast immediately converts the returned pointer to a gadget *:

Code Block
bgColor#ffcccc
langc

widget *p;

/* ... */

p = (gadget *)malloc(sizeof(gadget)); /* invalid assignment */

This lets the compiler detect the invalid assignment because it attempts to convert a gadget * into a widget *.

Compliant Solution (

...

Hand-

...

Coded)

This compliant solution repeats the same type in the sizeof expression and the pointer cast.

Code Block
bgColor#ccccff
langc

widget *p;

/* ... */

p = (widget *)malloc(sizeof(widget));

...

Code Block
bgColor#ccccff
langc

#define MALLOC(type) ((type *)malloc(sizeof(type)))

...

Code Block
bgColor#ccccff
langc

widget *p;

/* ... */

p = MALLOC(widget);     /* OK */
if (p != NULL) {
  p->i = 0;           /* OK */
  p->d = 0.0;         /* OK */
}

...

Code Block
bgColor#ccccff
langc

#define MALLOC_ARRAY(number, type) \
    ((type *)malloc((number) * sizeof(type)))

...

Code Block
bgColor#ccccff
langc

enum { N = 16 };
widget *p;

/* ... */

p = MALLOC_ARRAY(N, widget);    /* OK */

A small collection of macros can provide secure implementations for common uses for the standard memory allocation functions. The omission of a REALLOC() macro is intentional. (See recommendation MEM08-C. Use realloc() only to resize dynamically allocated arrays.)

Code Block
bgColor#ccccff
langc

/* allocates a single object using malloc(). */
#define MALLOC(type) ((type *)malloc(sizeof(type)))

/* allocates an array of objects using malloc(). */
#define MALLOC_ARRAY(number, type) \
    ((type *)malloc((number) * sizeof(type)))

/* allocates a single object with a flexible
 * array member using malloc(). */
#define MALLOC_FLEX(stype, number, etype) \
    ((stype *)malloc(sizeof(stype) \
    + (number) * sizeof(etype)))

/* allocates an array of objects using calloc(). */
#define CALLOC(number, type) \
    ((type *)calloc(number, sizeof(type)))

/* reallocates an array of objects using realloc(). */
#define REALLOC_ARRAY(pointer, number, type) \
    ((type *)realloc(pointer, (number) * sizeof(type)))

/* reallocates a single object with a flexible
 * array member using realloc(). */
#define REALLOC_FLEX(pointer, stype, number, etype) \
    ((stype *)realloc(pointer, sizeof(stype) \
    + (number) * sizeof(etype)))

...

Code Block
bgColor#ccccff
langc

enum month { Jan, Feb, /* ... */ };
typedef enum month month;

typedef struct date date;
struct date {
  unsigned char dd;
  month mm;
  unsigned yy;
};

typedef struct string string;
struct string {
  size_t length;
  char text[];
};

date *d, *week, *fortnight;
string *name;

d = MALLOC(date);
week = MALLOC_ARRAY(7, date);
name = MALLOC_FLEX(string, 16, char);
fortnight = CALLOC(14, date);

If one or more of the operands to the multiplication operations used in many of these macro definitions can be influenced by untrusted data, these operands should be checked for overflow before invoking the macro is invoked. (See rule INT32-C. Ensure that operations on signed integers do not result in overflow.)

The use of type-generic function-like functionlike macros is an allowed exception (PRE00-EX4) to recommendation PRE00-C. Prefer inline or static functions to function-like macros.

Risk Assessment

Failing to cast the result of a memory allocation function call into a pointer to the allocated type can result in inadvertent pointer conversions. Code that follows this recommendation will compile and execute equally well in C++.

...

sectioncan

Can detect violations of this rule with CERT C Rule Pack

section

.

can

Can detect some violations of this recommendation when checking

guideline

EXP36-C. Do not convert pointers into more strictly aligned pointer types.

Tool

Version

Checker

Description

LDRA tool suite

Include Page
LDRA_V
LDRA_V

 

 

section

Fortify SCA

section

V. 5.0

 

Section

Compass/ROSE

 

 

Section

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

...

CERT C++ Secure Coding Standard: MEM02-CPP. Immediately cast the result of a memory allocation function call into a pointer to the allocated type

ISO/IEC 9899:19992011 Section 7.2022.3, "Memory management functions"

Bibliography

[Summit 2005] Question 7.7 and Question 7.7b

...