CXX.ERRNO.NOT_SET

Errno is not reset to zero before calling library function

The CXX.ERRNO.NOT_SET checker flags cases where the value of errno is not reset to zero before calling a library function.

Vulnerability and risk

The value of errno may be incorrectly set by any previous call of a library function. If code checks the value of errno after calling library function, without resetting it first, it can lead to the incorrect execution of code.

Mitigation and prevention

Always reset the value of errno to zero before calling any library function that sets the value of errno.

Vulnerable code example 1

1  #include <errno.h>
2  #include <limits.h>
3  #include <stdlib.h>
4    
5  void func(const char *c_str) {
6    unsigned long number;
7    char *endptr;
8     
9    number = strtoul(c_str, &endptr, 0);
10   if (errno == ERANGE) {
11     /* Handle error */
12   } else {
13     /* Computation succeeded */
14   }
15 }

In this noncompliant example, the code fails to set the value of errno to zero before invoking strtoul(). If an error occurs, strtoul() returns a valid value (ULONG_MAX), so errno is the only means of determining if strtoul() ran successfully.

Fixed code example 1

1  #include <errno.h>
2  #include <limits.h>
3  #include <stdlib.h>
4    
5  void func(const char *c_str) {
6    unsigned long number;
7    char *endptr;
8    
9    errno = 0;
10   number = strtoul(c_str, &endptr, 0);
11   if (errno == ERANGE) {
12     /* Handle error */
13   } else {
14     /* Computation succeeded */
15   }
16 }

In this fixed example, the code sets the value of errno to zero before the call to strtoul() and then inspects the value of errno after the call.

Vulnerable code example 2

1  #include <errno.h>
2  #include <stdio.h>
3    
4  void func(const char *filename) {
5    FILE *fileptr;
6   
7    errno = 0;
8    fileptr = fopen(filename, "rb");
9    if (errno != 0) {
10     /* Handle error */
11   }
12 }

In this noncompliant example, the code may fail to diagnose errors because fopen() may not set the value of errno even if an error occurs.

Fixed code example 2

1  #include <stdio.h>
2    
3  void func(const char *filename) {
4    FILE *fileptr = fopen(filename, "rb");
5    if (fileptr == NULL)  {
6      /* An error occurred in fopen() */
7    }

The C Standard makes no mention of errno when describing fopen(). In this compliant example, the code uses the results of the call to fopen() to determine failure and does not check the value of errno.