Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: added another malloc example

...

Code Block
bgColor#FFcccc
langc

size_t utf8_to_ucs(wchar_t *ucs, size_t n, const char *utf8) {
  setlocale(LC_CTYPE, "en_US.UTF-8");
  return mbstowcs(ucs, utf8, n);
}

...

Code Block
bgColor#ccccFF
langc

size_t utf8_to_ucs(wchar_t *ucs, size_t n, const char *utf8) {
  const char *save;
  save = setlocale(LC_CTYPE, "en_US.UTF-8");
  if (NULL == save) {
    /* Propagate error to caller */
    return (size_t)-1;
  }

  n = mbstowcs(ucs, utf8, n);
  if (NULL == setlocale(LC_CTYPE, save))
    n = -1;

  return n;
}

...

Code Block
bgColor#FFcccc
langc

volatile sig_atomic_t interrupted;

void handle_interrupt(int signo) {
  interrupted = 1;
}

int f() {
  int result = 0;

  signal(SIGINT, handle_interrupt);

  while (0 == result && 0 == interrupted) {
    /* Perform a lengthy computation */
  }

  /* Indicate success or failure */
  return interrupted ? -1 : result;
}

...

Code Block
bgColor#ccccFF
langc

volatile sig_atomic_t interrupted;

void handle_interrupt(int signo) {
  interrupted = 1;
}

int f() {
  int result = 0;
  void (*saved_handler)(int);
  saved_handler = signal(SIGINT, handle_interrupt);

  if (SIG_ERR == saved_handler) {
    /* Indicate failure */
    return -1;
  }

  while (0 == result && 0 == interrupted) {
    /* Perform a lengthy computation */
  }

  if (SIG_ERR == signal(SIGINT, saved_handler))
    return -1;

  /* Indicate success or failure */
  return interrupted ? -1 : result;
}

...

In this noncompliant code example, temp_num, tmp2, andnum_of_records are under the control of a malicious user.  The attacker can easily cause malloc() to fail by providing a large value for num_of_records

Code Block
bgColor#FFCCCC
langc
signal_info * start = malloc(num_of_records * sizeof(signal_info));
signal_info * point = (signal_info *)start;
point = start + temp_num - 1; 
memcpy(point->sig_desc, tmp2, strlen(tmp2));
/* ... */ 

When malloc() fails, it returns a null pointer that is assigned to start. If start is a null, an attacker can provide a value for temp_num that when scaled by the the sizeof signal_info references a writable address to which control is eventually transferred. The contents of the string referenced by tmp2 can then be used to overwrite the address resulting in an arbitrary code execution vulnerability.

Compliant Solution (malloc())

To correct this error, ensure the pointer returned by malloc() is not null. This also ensures compliance with rule MEM32-C. Detect and handle memory allocation errors.

Code Block
bgColor#ccccff
langc
signal_info * start = malloc(num_of_records * sizeof(signal_info));
if (start == NULL) {
  /* Handle Allocation Error */
}
signal_info * point = (signal_info *)start;
point = start + temp_num - 1; 
memcpy(point->sig_desc, tmp2, strlen(tmp2));
/* ... */ 

Noncompliant Code Example (malloc())

In this noncompliant code example, input_string is copied into dynamically allocated memory referenced by str. However, the result of malloc() is not checked before str is referenced. Consequently, if malloc() fails, the program has undefined behavior. (See undefined behavior 103 in Annex J.) In practice, this typically leads to an abnormal termination of the process, thus providing an opportunity for a denial-of-service attack. In some cases, it may be the source of other vulnerabilities, as well. (See the #Related Vulnerabilities section.)

...

Code Block
bgColor#FFcccc
langc

void f(char *input_string) {
  size_t size = strlen(input_string) + 1;
  char *str = (char *)malloc(size);
  strcpy(str, input_string);
  /* ... */
}

Anchor
cs_malloc
cs_malloc

Compliant Solution (malloc())

The malloc() function, as well as the other memory allocation functions, returns either a null pointer or a pointer to the allocated space. Always test the returned pointer to ensure it is not NULL before referencing the pointer. Handle the error condition appropriately when the returned pointer is NULL. When recovery from the allocation failure isn't possible, propagate the failure to the caller.

Code Block
bgColor#ccccff
langc

int f(char *input_string) {
  size_t size = strlen(input_string) + 1;
  char *str = (char *)malloc(size);
  if (str == NULL) {
    /* Handle allocation failure and return error status */
    return -1;
  }
  strcpy(str, input_string);
  /* ... */
  free(str);
  return 0;
}

...