Main Content

CERT C: Rec. MEM04-C

Beware of zero-length allocations

Description

Rule Definition

Beware of zero-length allocations.1

Polyspace Implementation

The rule checker checks for these issues:

  • Zero length memory allocation

  • Variable length array with nonpositive size.

  • Tainted size of variable length array.

Extend Checker

A default Bug Finder analysis might not flag a Tainted size of variable length array issue for certain inputs that originate outside of the current analysis boundary. See Sources of Tainting in a Polyspace Analysis. To consider any data that does not originate in the current scope of Polyspace analysis as tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary.

Examples

expand all

Issue

Zero length memory allocation occurs when a memory allocation function such as malloc or calloc takes a size argument (or number of elements) that might contain the value zero.

Risk

According to the C Standard (C11, Subclause 7.22.3), if zero-sized memory is requested from a memory allocation function, the behavior is implementation-defined. In some implementations, the function might return NULL and your existing guards against NULL might suffice to protect against the zero length allocation. In other cases, the function might return a memory region that must not be accessed. Attempts to dereference this region results in undefined behavior.

Fix

Check the size to be passed to malloc, or the size and number of elements to be passed to calloc, for zero.

Example – Possibly Zero Size Argument to malloc
#include <stdlib.h>

void  func(unsigned int size) {
    int *list = (int *)malloc(size);//Noncompliant
    if (list == NULL) {
      /* Handle allocation error */
    }
    else {
    /* Continue processing list */
    }
}

In this example, the variable size might contain the value zero leading to a zero length memory allocation.

Correction – Check for Zero Before Using Variable as Size

Validate external inputs for zero values before using as size argument to the malloc function.

#include <stdlib.h>

void  func(unsigned int size) {
    if(size == 0) {
        /* Handle zero size error */
    }
    else {
        int *list = (int *)malloc(size);
        if (list == NULL) {
          /* Handle allocation error */
        }
        else {
          /* Continue processing list */
        }
    }
}
Issue

Variable length array with non-positive size occurs when size of a variable-length array is zero or negative.

Risk

If the size of a variable-length array is zero or negative, unexpected behavior can occur, such as stack overflow.

Fix

When you declare a variable-length array as a local variable in a function:

  • If you use a function parameter as the array size, check that the parameter is positive.

  • If you use the result of a computation on a function parameter as the array size, check that the result is positive.

You can place a test for positive value either before the function call or the array declaration in the function body.

Example - Nonpositive Array Size
int input(void);

void add_scalar(int n, int m) {
    int r=0;
    int arr[m][n]; //Noncompliant
    for (int i=0; i<m; i++) {
        for (int j=0; j<n; j++) {
            arr[i][j] = input();
            r += arr[i][j];
        }
    }
}

void main() {
    add_scalar(2,2);
    add_scalar(-1,2);
    add_scalar(2,0);
}

In this example, the second and third calls to add_scalar result in a negative and zero size of arr.

Correction — Make Array Size Positive

One possible correction is fix or remove calls that result in a nonpositive array size.

Issue

Tainted size of variable length array detects variable length arrays (VLA) whose size is from an unsecure source.

Risk

If an attacker changed the size of your VLA to an unexpected value, it can cause your program to crash or behave unexpectedly.

If the size is non-positive, the behavior of the VLA is undefined. Your program does not perform as expected.

If the size is unbounded, the VLA can cause memory exhaustion or stack overflow.

Fix

Validate your VLA size to make sure that it is positive and less than a maximum value.

Example - User Input Used as Size of VLA
#include<stdio.h>
#inclule<stdlib.h>
#define LIM 40

long squaredSum(int size) {

	int tabvla[size]; //Noncompliant
	long res = 0;
	for (int i=0 ; i<LIM-1 ; ++i) {
		tabvla[i] = i*i;
		res += tabvla[i];
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

In this example, a variable length array size is based on an input argument. Because this input argument value is not checked, the size may be negative or too large.

Correction — Check VLA Size

One possible correction is to check the size variable before creating the variable length array. This example checks if the size is larger than 0 and less than 40, before creating the VLA

#include <stdio.h>
#include <stdlib.h>
#define LIM 40

long squaredSum(int size) {
	long res = 0;
	if (size>0 && size<LIM){
		int tabvla[size];
		for (int i=0 ; i<size || i<LIM-1 ; ++i) {
			tabvla[i] = i*i;
			res += tabvla[i];
		}
	}else{
		res = -1;
	}
	return res;
}
int main(){
	int size;
	scanf("%d",&size);
	//...
	long result = squaredSum(size);
	//...
	return 0;
}

Check Information

Group: Rec. 08. Memory Management (MEM)

Version History

Introduced in R2019a


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.