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 number of bytes of available memory to n, which is then passed to memset():

...

For calls that take a pointer and an integer size, the given size should not be greater than the element count of the pointer.  This compliant solution ensures that the value of n is not greater than the size number of bytes 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) {
  char *p = (char *)malloc(nchars);
  /* ...  */
  const size_t n = nchars;
  /* ...  */
  memset(p, 0, n);
}

Noncompliant Code Example (Pointer + Integer)

In this noncompliant code example, the element count of the array a is ARR_SIZE elements.  Because memset() expects a byte count, the size of the array is scaled incorrectly by sizeof(int) instead of sizeof(float), which can form an invalid pointer on architectures where sizeof(int) != sizeof(float).

...

In this compliant solution, the element count required by memset is () is properly calculated without resorting to scaling.

...

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) {
    /* ... */
  }
}

This example is also a violation of violates ARR01-C. Do not apply the sizeof operator to a pointer when taking the size of an 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) {
    /* ... */
  }
}

Noncompliant Code Example (One Pointer + Two Integers)

In this This noncompliant code example , the allocates a variable number of objects of type struct obj. The function checks that numObjs is small enough to prevent wrapping, in compliance with INT30-C. Ensure that unsigned integer operations do not wrap.  The size of struct obj is  is assumed to be eight bytes to account for padding.  However However, the padding is dependent on the target architecture as well as compiler settings, so this object size may be the incorrect size of the object, which then yields the incorrect. This would then yield an incorrect element count.

Code Block
bgColor#FFcccc
#include <stdint.h>
#include <stdio.h>
 
struct obj {
  char c;
  int i;
};
 
void func(FILE *f, struct obj *objs, size_t numObjs) {
  const size_t obj_size = 8;
  if (numObjs > (SIZE_MAX / obj_size) ||
      numObjs != fwrite(objs, obj_size, numObjs, f)) {
    /* Handle error */
  }
}

...

Compliant Solution (One Pointer + Two Integers)

For calls that take a pointer and two integers, generally accept one integer representing the size of an individual object, and a second integer representing the number of objects in the array.  The resulting product of the two integers should not be greater than the element count of the pointer were it expressed as an unsigned char *.   See INT30-C. Ensure that unsigned integer operations do not wrap for more information.This compliant solution uses the sizeof operator to correctly provide the object size.

Code Block
bgColor#ccccff
#include <stdint.h>
#include <stdio.h>
 
struct obj {
  char c;
  int i;
};
 
void func(FILE *f, struct obj *objs, size_t numObjs) {
  if (numObjs > (SIZE_MAX / sizeof(*objs)) ||
      numObjs != fwrite(objs, sizeof(*objs), numObjs, f)) {
    /* Handle error */
  }
}

...

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

...