Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Parasoft C/C++test 2023.1

...

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

...

*.  C Standard memory allocation functions aligned_alloc(), malloc(), calloc(), and realloc() use void * to declare parameters and return types of functions designed to work for objects of different types.

For example, the C library declares malloc() as

Code Block
  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 malloc, calloc, and realloc.

For example, the Library declares malloc as:

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.

Because objects returned by the C Standard memory allocation functions are implicitly converted into any object type, we recommend casting the results of these functions into a pointer of the allocated type because it increases the chances that the compiler will catch and diagnose a mismatch between the intended type of the object and the actual type of the object.

Noncompliant Code Example

The argument to malloc() can be any value of (unsigned) type size_t. If the program uses the allocated storage to represent an object (possibly an array) whose size is greater than the requested size, the behavior is undefined. The implicit pointer conversion lets this slip by without complaint from the compiler.

Consider the following example:

Code Block
bgColor#ffcccc
langc
 type.

Code that follows this recommendation will compile and execute equally well in C++.


h2. Non-Compliant Code Example


The argument to malloc can be *any* value of (unsigned) type size_t.  If the program uses the allocated storage to represent an object (possibly an array) whose size is greater than the requested size, the behavior is undefined.  The implicit pointer conversion lets this slip by without complaint from the compiler.

For example,

{code:bgColor=#FFcccc}
#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)); /* imminentImminent problem */
if (p != NULL) {
    p->i = 0;                 /* undefinedUndefined behavior */
	  p->d = 0.0;               /* undefinedUndefined behavior */
}
{code}

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
=#FFcccc}
p = malloc(sizeof(gadget)); /* imminentImminent problem */
{code}

quietly

...

assigns

...

p

...

to

...

point

...

to

...

storage

...

too

...

small

...

for

...

a

...

widget.

...

The

...

subsequent

...

assignments

...

to

...

p->i

...

and

...

p->d will most likely produce memory overruns.

Casting the result of malloc() to the appropriate pointer type enables the compiler to catch subsequent inadvertent pointer conversions. When allocating individual objects, the "appropriate pointer type" is a pointer to the type argument in the sizeof expression passed to malloc().

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
 produce undefined behavior. They'll likely produce memory overruns.


h2. Compliant Solution


Casting the result of malloc to the appropriate pointer type enables the compiler to catch subsequent inadvertant pointer conversions.  When allocating individual objects, the "appropriate pointer type" is a pointer to the type argument in the sizeof expression passed to malloc, as in:

{code:bgColor=#ccccff}
widget *p;

/* ... */

p = (gadget *)malloc(sizeof(gadget)); /* invalidInvalid assignment */
{code}

Here, malloc allocates space for a gadget and the cast immediately converts the returned pointer to a gadget *.  This lets the compiler detect the invalid assignment, because it attempts to convert a gadget * into a widget *.

Repeating the same type in the sizeof expression and the pointer cast is easy to do, but still invites errors.  Packaging the repetition in a macro, such as:

{code:bgColor=#ccccff}

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));

Compliant Solution (Macros)

Repeating the same type in the sizeof expression and the pointer cast is easy to do but still invites errors. Packaging the repetition in a macro, such as

Code Block
bgColor#ccccff
langc
#define MALLOC(type) ((type *)malloc(sizeof(type)))
{code}

further

...

reduces

...

the

...

possibility

...

of

...

error.

{:
Code Block
bgColor#ccccff
langc
=#ccccff}
widget *p;

/* ... */

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

Here,

...

the

...

entire

...

allocation

...

expression

...

(to

...

the

...

right

...

of

...

the

...

assignment

...

operator)

...

allocates

...

storage

...

for

...

a

...

widget

...

and

...

returns

...

a

...

widget

...

*.

...

If

...

p

...

were

...

not

...

a

...

widget

...

*,

...

the

...

compiler

...

would

...

complain

...

about

...

the

...

assignment.

...

When allocating an array with N elements of type T, the appropriate type in the cast expression is still T *, but the argument to malloc() should be of the form N * sizeof(T).

...

Again,

...

packaging

...

this

...

form

...

as

...

a

...

macro,

...

such

...

as

Code Block
bgColor#ccccff
langc
:

{code:bgColor=#ccccff}
#define MALLOC_ARRAY(number, type) \
    ((type *)malloc((number) * sizeof(type)))

reduces

...

the

...

chance

...

of

...

error

...

in

...

an

...

allocation expression.

Code Block
bgColor#ccccff
langc
 expression:

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 EXP39-C. Do not access a variable through a pointer of an incompatible type).

Code Block
bgColor#ccccff
langc
/* Allocates a single object using malloc() */{code}

h2. Compliant Solution
A small collection of macros can provide secure implementations for common uses for the standard memory allocation functions.

{code:bgColor=#ccccff}
#define MALLOC(type) ((type *)malloc(sizeof(type)))

allocates a single object/* Allocates an array of objects using malloc.() */

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


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

allocates/* aAllocates singlean objectarray withof aobjects flexibleusing array member using malloc.

calloc() */
#define CALLOC(number, type) \
    ((type *)calloc(number, sizeof(type)))

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


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

reallocates a single object with a flexible array member using realloc.
{code}

For example,

The following is an example:

Code Block
bgColor#ccccff
langc
enum month { Jan, Feb, /* ... */ };
typetypedef enum month month;

typedef enumstruct 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);
{code}

h2. Risk Assessment


|| Recommendation || Severity || Likelihood || Remediation Cost || Priority || Level ||
| MEM02-A | *1* (low) | *1* (unlikely) | *3* (low) | {color:green}{*}P3{*}{color} | {color:green}{*}L3{*}{color} |

h3. Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the [CERT website|https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+MEM02-A].

h2. References

\[[Summit 05|AA. C References#Summit 05]\] [Question 7.7|http://c-faq.com/malloc/cast.html], [Question 7.7b|http://c-faq.com/malloc/mallocnocast.html]

----
*[!CERT C Secure Coding Standard^button_arrow_left.png!|MEM01-A. Store a new value in pointers immediately after free()]**&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;*[!CERT C Secure Coding Standard^button_arrow_up.png!|08. Memory Management (MEM)]**&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;&nbsp; *[!CERT C Secure Coding Standard^button_arrow_right.png!|MEM03-A. Clear sensitive information stored in reusable resources returned for reuse]*

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 the macro is invoked (see INT32-C. Ensure that operations on signed integers do not result in overflow).

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

Exceptions

MEM02-C-EX1: Do not immediately cast the results of malloc() for code that will be compiled using a C90-conforming compiler because it is possible for the cast to hide a more critical defect (see DCL31-C. Declare identifiers before using them for a code example that uses malloc() without first declaring it).

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++.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MEM02-C

Low

Unlikely

Low

P3

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
alloc-without-cast
Partially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-MEM02Fully implemented
Compass/ROSE



Can detect some violations of this recommendation when checking EXP36-C. Do not cast pointers into more strictly aligned pointer types

ECLAIR
Include Page
ECLAIR_V
ECLAIR_V
CC2.MEM02Fully implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0695
Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-MEM02-a
CERT_C-MEM02-b

The result of the memory allocation function should be cast immediately
The result of the memory allocation function should be cast immediately into a pointer to the allocated type

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

908

Assistance provided: reports implicit conversions from void* to another type

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. MEM02-C


Checks for wrong allocated object size for cast (rule fully covered)

RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

alloc-without-cast
Partially checked

Related Vulnerabilities

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

Related Guidelines

Bibliography


...

Image Added Image Added Image Added