Main Content

Returned value of a sensitive function not checked

Sensitive functions called without checking for unexpected return values and errors

Description

This defect occurs when you call sensitive standard functions that return information about possible errors and you do one of the following:

  • Ignore the return value.

    You simply do not assign the return value to a variable, or explicitly cast the return value to void.

  • Use an output from the function (return value or argument passed by reference) without testing the return value for errors.

The checker considers a function as sensitive if the function call is prone to failure because of reasons such as:

  • Exhausted system resources (for example, when allocating resources).

  • Changed privileges or permissions.

  • Tainted sources when reading, writing, or converting data from external sources.

  • Unsupported features despite an existing API.

The checker only considers functions where the return value indicates if the function completed without errors.

Some of these functions can perform critical tasks such as:

  • Set privileges (for example, setuid)

  • Create a jail (for example, chroot)

  • Create a process (for example, fork)

  • Create a thread (for example, pthread_create)

  • Lock or unlock mutex (for example, pthread_mutex_lock)

  • Lock or unlock memory segments (for example, mlock)

Risk

If you do not check the return value of functions that perform sensitive tasks and indicate error information through their return values, your program can behave unexpectedly. Errors from these functions can propagate throughout the program causing incorrect output, security vulnerabilities, and possibly system failures.

Fix

Before continuing with the program, test the return value of critical sensitive functions.

For sensitive functions that are not critical, you can explicitly ignore a return value by casting the function to void. Polyspace® does not raise this defect for sensitive functions cast to void. This resolution is not accepted for critical sensitive functions because they perform more vulnerable tasks.

Examples

expand all

#include <pthread.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

void initialize() {
    pthread_attr_t attr;

    pthread_attr_init(&attr);//Noncompliant 
}
int read_file(int argc, char *argv[])
{
  FILE *in;
  if (argc != 2) {
    /* Handle error */
  }

  in = fmemopen (argv[1], strlen (argv[1]), "r");   
  return 0; //Noncompliant

}

This example shows calls to the sensitive POSIX functions pthread_attr_init and fmemopen. Their return values are ignored, causing defect.

Correction — Cast Function to (void)

One possible correction is to cast the function to void. This fix informs Polyspace and any reviewers that you are explicitly ignoring the return value of the sensitive function.

#include <pthread.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

void initialize() {
    pthread_attr_t attr;

    (void)pthread_attr_init(&attr);//Compliant 
}
int read_file(int argc, char *argv[])
{
  FILE *in;
  if (argc != 2) {
    /* Handle error */
  }

  (void)fmemopen (argv[1], strlen (argv[1]), "r"); //Compliant
  
  return 0; 
}
Correction — Test Return Value

One possible correction is to test the return value of pthread_attr_init and fmemopen to check for errors.

#include <pthread.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>

void initialize() {
    pthread_attr_t attr;

    int result = pthread_attr_init(&attr);//Compliant 
	if(result != 0){
		//Handle fatal error
	} 
}
int read_file(int argc, char *argv[])
{
  FILE *in;
  if (argc != 2) {
    /* Handle error */
  }

  in = fmemopen (argv[1], strlen (argv[1]), "r"); 
  if (in==NULL){
	  // Handle error
  }
  return 0;//Compliant 
}
#include <pthread.h>
extern void *start_routine(void *);

void returnnotchecked() {
    pthread_t thread_id;
    pthread_attr_t attr;
    void *res;

    (void)pthread_attr_init(&attr);
    (void)pthread_create(&thread_id, &attr, &start_routine, ((void *)0));
    pthread_join(thread_id,  &res); 
}

In this example, two critical functions are called: pthread_create and pthread_join. The return value of the pthread_create is ignored by casting to void, but because pthread_create is a critical function (not just a sensitive function), Polyspace does not ignore this Return value of a sensitive function not checked defect. The other critical function, pthread_join, returns value that is ignored implicitly. pthread_join uses the return value of pthread_create, which was not checked.

Correction — Test the Return Value of Critical Functions

The correction for this defect is to check the return value of these critical functions to verify the function performed as expected.

#include <pthread.h>
#include <stdlib.h>
#define fatal_error() abort()

extern void *start_routine(void *);

void returnnotchecked() {
    pthread_t thread_id;
    pthread_attr_t attr;
    void *res;
    int result;

    (void)pthread_attr_init(&attr);
    result = pthread_create(&thread_id, &attr, &start_routine, NULL);
    if (result != 0) {
        /* Handle error */
        fatal_error();
    }

    result = pthread_join(thread_id,  &res);
    if (result != 0) {
        /* Handle error */
        fatal_error();
    }
}

Result Information

Group: Security
Language: C | C++
Default: Off
Command-Line Syntax: RETURN_NOT_CHECKED
Impact: High

Version History

Introduced in R2016b

expand all