Versions Compared

Key

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

...

This noncompliant code example assigns a value greater than the size of available memory to n, which is then passed to memset():

Code Block
bgColor#FFcccc
#include <stdlib.h>
#include <string.h>
 
void f1(size_t nchars) {
  char *p = (char *)malloc(nchars);
  const size_t n = nchars + 1;

  memset(p, 0, n);
  /* ... */
}

Compliant Solution

This compliant solution ensures that the value of n is not greater than the size of the dynamic memory pointed to by the pointer p:

Code Block
bgColor#ccccff
#include <stdlib.h>
#include <string.h>
 
void f1(size_t nchars, size_t val) {

  char *p = (char *)malloc(nchars);
  const size_t n = val;

  if (nchars < n) {
    /* Handle Error */
  } else {
    memset(p, 0, n);
  }
  /* ... */
}

Noncompliant Code Example

In this noncompliant code example, the effective type of *p is float, and the derived type of the expression n is int. This is calculated using the first rule from TS 17961's definition of derived types (see Section 4, "Definitions" [ISO/IEC TS 17961]). Because n contains the result of a sizeof expression, its derived type is equal to the type of the operand, which is int.

Code Block
bgColor#FFcccc
void f2(#include <string.h>
 
void f2() {
  const size_t ARR_SIZE = 4;
  float a[ARR_SIZE];
  const size_t n = sizeof(int) * ARR_SIZE;
  void *p = a;

  memset(p, 0, n);
  /* ... */
}

Note: Although it is noncompliant, this code has no ill effects on architectures where sizeof(int) is equal to sizeof(float).

...

In this compliant solution, the derived type of n is also float:

Code Block
bgColor#ccccff
#include <string.h>
 
void f2() {
  const size_t ARR_SIZE = 4;
  float a[ARR_SIZE];
  const size_t n = sizeof(float) * ARR_SIZE;
  void *p = a;

  memset(p, 0, n);
  /* ... */
}

Noncompliant Code Example

In this noncompliant code example, the size of n could be greater than the size of *p. Also, the effective type of *p (int) is different from the effective type of *q (float).

Code Block
bgColor#FFcccc
#include <string.h>
 
void f3(int *a) {
  float b = 3.14;
  const size_t n = sizeof(b);
  void *p = a;
  void *q = &b;

  memcpy(p, q, n);
  /* ... */
}

Note: Although it is noncompliant, this code does not constitute a vulnerability on implementations where sizeof(int) is equal to sizeof(float).

...

This compliant solution ensures that the value of n is not greater than the minimum of the effective sizes of *p and *q and that the effective types of the two pointers are identical (float):

Code Block
bgColor#ccccff
#include <string.h>
 
void f3(float *a, size_t val) {
  float b = 3.14;
  const size_t n = val;
  void *p = a;
  void *q = &b;

  if( (n > sizeof(a)) || (n > sizeof(b)) ) {
    /* Handle error */
  } else {
    memcpy(p, q, n);
    /* ... */
  }
}

Noncompliant Code Example

In this noncompliant code example, the value of n is greater than the size of T, that is, sizeof(wchar_t). But the derived type of expression n (wchar_t *) is not the same as the type of T because its derived type will be equal to the type of p, which is wchar_t*. The derived type of n is calculated using the first rule from TS 17961's definition of derived types (see Section 4, "Definitions" [ISO/IEC TS 17961]). Because n here is a sizeof expression, its derived type is equal to the type of the operand (p), which is wchar_t *.

Code Block
bgColor#FFcccc
#include <stdlib.h>
#include <wchar.h>
 
wchar_t *f4() {
  const wchar_t *p = L"Hello, World!";
  const size_t n = sizeof(p) * (wcslen(p) + 1);

  wchar_t *q = (wchar_t*) malloc(n);
  return q;
}

...

This compliant solution ensures that the derived type of n (wchar_t) is the same as the type of T (wchar_t) and that the value of n is not less than the size of T:

Code Block
bgColor#ccccff
#include <stdlib.h>
#include <wchar.h>
 
wchar_t *f4() {
  const wchar_t *p = L"Hello, World!";
  const size_t n = sizeof(wchar_t) * (wcslen(p) + 1);

  wchar_t *q = (wchar_t*) malloc(n);
  return q;
}

...

In this noncompliant example, a diagnostic is required because the value of n is not computed correctly, allowing a possible write past the end of the object referenced by p:

Code Block
bgColor#FFcccc
#include <string.h>
 
void f4(char p[], const char *q) {
  const size_t n = sizeof(p); 
  if ((memcpy(p, q, n)) == p) {  /* violation */
    /* ... */
  }
 
  /* ... */
}
}
}

Compliant Solution

This compliant solution ensures that n is equal to the size of the character array:

Code Block
bgColor#ccccff
#include <string.h>
 
void f4(char p[], const char *q, size_t size_p) {
  const size_t n = size_p; 
  if ((memcpy(p, q, n)) == p) {  
    /* ... */
  }
 
  /* ... */
}

Risk Assessment

Depending on the library function called, the attacker may be able to use a heap overflow vulnerability to run arbitrary code.

...

Tool

Version

Checker

Description

PRQA QA-C
Include Page
PRQA_V
PRQA_V
 2931Fully implemented

Related Vulnerabilities

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

Related Guidelines

C Secure Coding StandardAPI00-C. Functions should validate their parameters
ISO/IEC TS 17961 (Draft)Forming invalid pointers by library functions [libptr]

...