Main Content

CWE Rule 467

Use of sizeof() on a Pointer Type

Since R2023a

Description

Rule Description

The code calls sizeof() on a malloced pointer type, which always returns the wordsize/8. This can produce an unexpected result if the programmer intended to determine how much memory has been allocated.

Polyspace Implementation

The rule checker checks for these issues:

  • Possible misuse of sizeof

  • Wrong type used in sizeof

Examples

expand all

Issue

This issue occurs when Polyspace® Bug Finder™ detects possibly unintended results from the use of sizeof operator. For instance:

  • You use the sizeof operator on an array parameter name, expecting the array size. However, the array parameter name by itself is a pointer. The sizeof operator returns the size of that pointer.

  • You use the sizeof operator on an array element, expecting the array size. However, the operator returns the size of the array element.

  • The size argument of certain functions such as strncmp or wcsncpy is incorrect because you used the sizeof operator earlier with possibly incorrect expectations. For instance:

    • In a function call strncmp(string1, string2, num), num is obtained from an incorrect use of the sizeof operator on a pointer.

    • In a function call wcsncpy(destination, source, num), num is the not the number of wide characters but a size in bytes obtained by using the sizeof operator. For instance, you use wcsncpy(destination, source, sizeof(destination) - 1) instead of wcsncpy(destination, source, (sizeof(desintation)/sizeof(wchar_t)) - 1).

Risk

Incorrect use of the sizeof operator can cause the following issues:

  • If you expect the sizeof operator to return array size and use the return value to constrain a loop, the number of loop runs are smaller than what you expect.

  • If you use the return value of sizeof operator to allocate a buffer, the buffer size is smaller than what you require. Insufficient buffer can lead to resultant weaknesses such as buffer overflows.

  • If you use the return value of sizeof operator incorrectly in a function call, the function does not behave as you expect.

Fix

Possible fixes are:

  • Do not use the sizeof operator on an array parameter name or array element to determine array size.

    The best practice is to pass the array size as a separate function parameter and use that parameter in the function body.

  • Use the sizeof operator carefully to determine the number argument of functions such as strncmp or wcsncpy. For instance, for wide string functions such as wcsncpy, use the number of wide characters as argument instead of the number of bytes.

Example — sizeof Used Incorrectly to Determine Array Size
#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < sizeof(a)/sizeof(int); i++)  //Noncompliant
{
        a[i] = i + 1;
    }
}

In this example, sizeof(a) returns the size of the pointer a and not the array size.

Correction — Determine Array Size in Another Way

One possible correction is to use another means to determine the array size.

#define MAX_SIZE 1024

void func(int a[MAX_SIZE]) {
    int i;

    for (i = 0; i < MAX_SIZE; i++)    {
        a[i] = i + 1;
    }
}
Issue

This issue occurs when both of the following conditions hold:

  1. You assign the address of a block of memory to a pointer, or transfer data between two blocks of memory. The assignment or copy uses the sizeof operator.

    For instance, you initialize a pointer using malloc(sizeof(type)) or copy data between two addresses using memcpy(destination_ptr, source_ptr, sizeof(type)).

  2. You use an incorrect type as argument of the sizeof operator. For instance:

    • You might be using the pointer type instead of the type that the pointer points to. For example, to initialize a type* pointer, you might be using malloc(sizeof(type*)) instead of malloc(sizeof(type)).

    • You might be using a completely unrelated type as sizeof argument. For example, to initialize a type* pointer, you might be using malloc(sizeof(anotherType)).

Risk

Irrespective of what type stands for, the expression sizeof(type*) always returns a fixed size. The size returned is the pointer size on your platform in bytes. The appearance of sizeof(type*) often indicates an unintended usage. The error can cause allocation of a memory block that is much smaller than what you need and lead to weaknesses such as buffer overflows.

For instance, assume that structType is a structure with ten int variables. If you initialize a structType* pointer using malloc(sizeof(structType*)) on a 32-bit platform, the pointer is assigned a memory block of four bytes. However, to be allocated completely for one structType variable, the structType* pointer must point to a memory block of sizeof(structType) = 10 * sizeof(int) bytes. The required size is much greater than the actual allocated size of four bytes.

Fix

To initialize a type* pointer, replace sizeof(type*) in your pointer initialization expression with sizeof(type).

Example — Allocate a Char Array With sizeof
#include <stdlib.h>

void test_case_1(void) {
    char* str;

    str = (char*)malloc(sizeof(char*) * 5);  //Noncompliant
    free(str);

}

In this example, memory is allocated for the character pointer str using a malloc of five char pointers. However, str is a pointer to a character, not a pointer to a character pointer. Therefore the sizeof argument, char*, is incorrect.

Correction — Match Pointer Type to sizeof Argument

One possible correction is to match the argument to the pointer type. In this example, str is a character pointer, therefore the argument must also be a character.

#include <stdlib.h>

void test_case_1(void) {
    char* str;

    str = (char*)malloc(sizeof(char) * 5);
    free(str);

}

Check Information

Category: Pointer Issues

Version History

Introduced in R2023a