Versions Compared

Key

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

...

In the following example, the test for integer wrap was omitted for the unsigned multiplication based on the assumption that MAX_TABLE_SIZE * sizeof(char *) cannot exceed SIZE_MAX. While we know this is true, it cannot do any harm to codify this assumption.

Code Block
bgColor#ccccff
langc
assert(size <= SIZE_MAX/sizeof(char *));
table_size = size * sizeof(char *);

...

In particular, assertions are generally unsuitable for server programs or embedded systems in deployment. A failed assertion can lead to a denial-of-service attack if triggered by a malicious user, such as size being, in some way, derived from client input. In such situations, a soft failure mode, such as writing to a log file and rejecting the request, is more appropriate.

Code Block
bgColor#ccccff
langc
if (size > SIZE_MAX/sizeof(char *)) {
  fprintf(
    log_file, 
    __FILE__ ": size %zu exceeds SIZE_MAX/sizeof(char *)\n", 
    size
  );
  size = SIZE_MAX/sizeof(char *);
}
table_size = size * sizeof(char *);

...

The noncompliant code example below uses the assert() macro to verify that memory allocation succeeded. Because memory availability depends on the overall state of the system and can become exhausted at any point during a process lifetime, a robust program must be prepared to gracefully handle and recover from its exhaustion. Therefore, using the assert() macro to verify that a memory allocation succeeded would be inappropriate because doing so might lead to an abrupt termination of the process, opening up the possibility of a denial-of-service attack. See also recommendation MEM11-C. Do not assume infinite heap space and rule MEM32-C. Detect and handle memory allocation errors.

Code Block
bgColor#ffcccc
langc
char *dupstring(const char *str) {
  size_t len;
  char *dup;

  len = strlen(str);
  dup = (char *)malloc(len + 1);
  assert(NULL != dup);

  memcpy(dup, str, len + 1);
  return dup;
}

...

The compliant solution below demonstrates how to detect and handle possible memory exhaustion.

Code Block
bgColor#ccccff
langc
char *dupstring(const char *str) {
  size_t len;
  char *dup;

  len = strlen(str);
  dup = (char*)malloc(len + 1);
  /* detect and handle memory allocation error */
  if (NULL == dup) {
      return NULL; 
  }

  memcpy(dup, str, len + 1);
  return dup;
}

...