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

...

malloc(),

...

calloc(),

...

and

...

realloc().

...

For

...

example,

...

C Library

...

declares

...

malloc

...

() as:

Code Block

void *malloc(size_t);

Calling

...

malloc(

...

n

...

)

...

allocates

...

memory

...

for

...

an

...

object

...

whose

...

size

...

is

...

n

...

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 that follows this recommendation will compile and execute equally well in C++.

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 Block
bgColor#FFcccc
 malloc returns into a different pointer 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)); /* imminent problem */
if (p != NULL) {
    p->i = 0;               /* undefined behavior */
	  p->d = 0.0;             /* undefined behavior */
}
{code}

An

...

implementation

...

may

...

add

...

padding

...

to

...

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

quietly

...

assigns

...

p

...

to

...

point

...

to

...

storage

...

too

...

small

...

for

...

a

...

widget.

...

The

...

subsequent

...

assignments

...

to

...

p->i

...

and

...

p->d

...

produce

...

undefined

...

behavior.

...

They'll

...

likely

...

produce

...

memory

...

overruns.

Compliant Solution

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(), as in:

Code Block
bgColor#ccccff



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)); /* invalid 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 Block
bgColor
#ccccff
}
#define MALLOC(type) ((type *)malloc(sizeof(type)))
{code}

further

...

reduces

...

the

...

possibility

...

of

...

error.

{:=
Code Block
bgColor
#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.

...

Compliant Solution

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
}
#define MALLOC_ARRAY(number, type) \
    ((type *)malloc(number * sizeof(type)))

reduces the chance of error in an allocation expression:

enum { N = 16 };
widget *p;

/* ... */

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

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

Compliant Solution

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

Code Block
bgColor#ccccff


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

allocates a single object using {{malloc()}}.

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

allocates an array of objects using {{malloc()}}.

#define MALLOC_FLEX(stype, number, etype) \
    ((stype *)malloc(sizeof(stype) + number * sizeof(etype)))

allocates a single object with a flexible array member using {{malloc()}}.

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

allocates an array of objects using {{calloc()}}.

#define REALLOC_ARRAY(pointer, number, type) \
    ((type *)realloc(pointer, number * sizeof(type)))

reallocates an array of 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,

Code Block
bgColor#ccccff


enum month { Jan, Feb, ... };
type enum month month;

typedef enum 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

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.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MEM02-A

1 (low)

1 (unlikely)

3 (low)

P3

L3

Related Vulnerabilities

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

References

Wiki Markup
\[[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]

...

...

MEM01-A.

...

Store

...

a

...

new

...

value

...

in

...

pointers

...

immediately

...

after

...

free()

...

      08. Memory Management (MEM)       MEM03-A.

...

Clear

...

sensitive

...

information

...

stored

...

in

...

reusable

...

resources

...

returned

...

for

...

reuse

...