Versions Compared

Key

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

...

In this compliant solution, the result of realloc() is assigned to the temporary pointer q and validated before it is assigned to the original pointer p.:

Code Block
bgColor#ccccff
langc
void *p;
void *q;
size_t new_size= /* nonzero size */;

q = realloc(p, new_size);
if (q == NULL)   {
 /* Handle error */
}
else {
  p = q;
}

...

In the following noncompliant code example, snprinf() is assumed to succeed. However, if the call fails (for example, because of insufficient memory, as described in GNU libc bug 441945), the subsequent call to log_message() is likely to result in undefined behavior since because the character buffer is not initialized and need not be null-terminated.

...

When the length of the formatted string is unbounded, it is best to invoke the function twice, once with a NULL buffer to determine the size of output, then dynamically allocate a buffer of sufficient size, and finally call snprintf() again to format the output into the dynamically allocated buffer. Even with this approach the success of all calls still needs to be tested, and any errors still need to be appropriately handled. A possible optimization is to first attempt to format the string into a reasonably small buffer allocated on the stack and only when the buffer turns out to be too small allocate one of a sufficient size dynamically. This approach is shown in the following compliant solution.:

Code Block
bgColor#ccccff
langc
void f(int i, int width, int prec) {
  char buffer[20];
  char *buf = buffer;
  int n  = sizeof buffer;
  const char fmt[] = "i = %*.*i";

  n = snprintf(buf, n, fmt, width, prec, i);
  if (n < 0) {
    /* Handle snprintf() error */
    strcpy(buffer, "unknown error");
    goto write_log;
  }

  if (n < sizeof buffer)
    goto write_log;

  buf = (char*)malloc(n + 1);
  if (NULL == buf) {
    /* Handle malloc() error */
    strcpy(buffer, "unknown error");
    goto write_log;
  }

  n = snprintf(buf, n, fmt, width, prec, i);
  if (n < 0) {
    /* Handle snprintf() error */
    strcpy(buffer, "unknown error");
  }

write_log:
  log_message(buf);

  if (buf != buffer)
    free(buf);
}

...

A compliant solution avoids assuming that fmemopen() and open_memstream() succeed regardless of its arguments and tests the return value of the function before using the file pointers in and out.:

Code Block
bgColor#ccccff
langc
int main(int argc, char *argv[])
{
FILE *out;
FILE *in;
 
if (argc != 2) {
	/* Handle error */
}
 
in = fmemopen(argv[1], strlen(argv[1]), "r");


if (in == NULL){
	/* Handle error */
}
/* Use in */
 
out = open_memstream(&ptr, &size);

if (out == NULL){
	/* Handle error */

}
/* Use out */
 
}

...

Tool

Version

Checker

Description

Compass/ROSE

  

Can detect violations of this recommendation when checking for violations of EXP12-C. Do not ignore values returned by functions and EXP34-C. Do not dereference null pointers.

Coverity

Include Page
Coverity_V
Coverity_V

CHECKED_RETURN

Finds inconsistencies in how function call return values are handled. Coverity Prevent cannot discover all violations of this recommendation, so further verification is necessary.

Fortify SCA

5.0

 

 

LDRA tool suite

Include Page
LDRA_V
LDRA_V

80 D

Partially implemented.
PRQA QA-C
Include Page
PRQA_V
PRQA_V

3200

Partially implemented.

Related Coding Practices

...