Main Content

ISO/IEC TS 17961 [liberr]

Failing to detect and handle standard library errors

Description

Rule Definition

Failing to detect and handle standard library errors.1

Polyspace Implementation

This checker checks for these issues:

  • Returned value of a sensitive function not checked.

  • Unprotected dynamic memory allocation.

Examples

expand all

Issue

Returned value of a sensitive function not checked occurs when you call sensitive standard functions, but you:

  • Ignore the return value.

  • Use an output or a return value without testing the validity of the return value.

For this defect, two type of functions are considered: sensitive and critical sensitive.

A sensitive function is a standard function that can encounter:

  • 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

A critical sensitive function is a sensitive function that performs one of these critical or vulnerable tasks:

  • Set privileges (for example, setuid)

  • Create a jail (for example, chroot)

  • Create a process (for example, fork)

  • Create a thread (for example, thrd_create)

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

Risk

If you do not check the return value of functions that perform sensitive or critical sensitive tasks, 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, 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.

Example - Sensitive Function Return Ignored
#include<stdio.h>
#include <wchar.h>
#include <locale.h>
void initialize(size_t n, size_t* size, wchar_t *wcs, const char *utf8) {

	scanf("%d",&n); //Noncompliant
	setlocale (LC_CTYPE, "en_US.UTF-8");   //Noncompliant
	*size = mbstowcs (wcs, utf8, n);
}

This example shows a call to the sensitive function scanf(). The return value of scanf() is ignored, causing a defect. Similarly, the pointer returned by setlocale is not checked. When setlocal returns a NULL pointer, the call to mbstowcs might fail or produce unexpected results. Polyspace flags these calls to sensitive functions when their returns are not checked.

Correction — Cast Function to (void)

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

#include<stdio.h>
#include <wchar.h>
#include <locale.h>
void initialize(size_t n, size_t* size, wchar_t *wcs, const char *utf8) {

	(void)scanf("%d",&n); //Compliant
	(void)setlocale (LC_CTYPE, "en_US.UTF-8");   //Compliant
	*size = mbstowcs (wcs, utf8, n);
}
Correction — Test Return Value

One possible correction is to test the return value of scanf and setlocale to check for errors.

#include<stdio.h>
#include <wchar.h>
#include <locale.h>
void initialize(size_t n, size_t* size, wchar_t *wcs, const char *utf8) {

	int flag = scanf("%d",&n); 
	if(flag>0){ //Compliant
		// action
	}
	char* status = setlocale (LC_CTYPE, "en_US.UTF-8");   
	if(status!=NULL){//Compliant
		*size = mbstowcs (wcs, utf8, n);
	}
	
}
Example - Critical Function Return Ignored
#include <threads.h>
int thrd_func(void);
void initialize() {
    thrd_t thr;
	int n = 1;

    (void) thrd_create(&thr,thrd_func,&n); 
}

In this example, a critical function thrd_create is called and its return value is ignored by casting to void, but because thrd_create is a critical function, Polyspace does not ignore this Return value of a sensitive function not checked defect.

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 <threads.h>
int thrd_func(void);
void initialize() {
	thrd_t thr;
	int n = 1;
	if( thrd_success!= thrd_create(&thr,thrd_func,&n) ){
		// handle error
		
	}
}
Issue

Unprotected dynamic memory allocation occurs when you do not check after dynamic memory allocation whether the memory allocation succeeded.

Risk

When memory is dynamically allocated using malloc, calloc, or realloc, it returns a value NULL if the requested memory is not available. If the code following the allocation accesses the memory block without checking for this NULL value, this access is not protected from failures.

Fix

Check the return value of malloc, calloc, or realloc for NULL before accessing the allocated memory location.

#define SIZE 10
//...
int *ptr = malloc(SIZE * sizeof(int));

if(ptr) /* Check for NULL */ 
{
   /* Memory access through ptr */
}

Example - Unprotected dynamic memory allocation error
#include <stdlib.h>

void Assign_Value(void) 
{
  int* p = (int*)calloc(5, sizeof(int));

  *p = 2;  
  /* Defect: p is not checked for NULL value */

  free(p);
}

If the memory allocation fails, the function calloc returns NULL to p. Before accessing the memory through p, the code does not check whether p is NULL

Correction — Check for NULL Value

One possible correction is to check whether p has value NULL before dereference.

#include <stdlib.h>

void Assign_Value(void)
 {
   int* p = (int*)calloc(5, sizeof(int));

   /* Fix: Check if p is NULL */
   if(p!=NULL) *p = 2; 

   free(p);
 }

Check Information

Decidability: Undecidable

Version History

Introduced in R2019a

expand all


1 Extracts from the standard "ISO/IEC TS 17961 Technical Specification - 2013-11-15" are reproduced with the agreement of AFNOR. Only the original and complete text of the standard, as published by AFNOR Editions - accessible via the website www.boutique.afnor.org - has normative value.