ISO/IEC TS 17961 [inverrno]
Incorrectly setting and using errno
Description
Rule Definition
Incorrectly setting and using errno.1
Polyspace Implementation
This checker checks for these issues:
Misuse of errno.
Errno not checked.
Errno not reset.
Examples
Misuse of errno
Misuse of errno occurs when
you check errno
for error conditions in situations
where checking errno
does not guarantee
the absence of errors. In some cases, checking errno
can
lead to false positives.
For instance, you check errno
following calls
to the functions:
fopen
: If you follow the ISO® Standard, the function might not seterrno
on errors.atof
: If you follow the ISO Standard, the function does not seterrno
.signal
: Theerrno
value indicates an error only if the function returns theSIG_ERR
error indicator.
The ISO C Standard does not enforce that these functions
set errno
on errors. Whether the functions set errno
or
not is implementation-dependent.
To detect errors, if you check errno
alone,
the validity of this check also becomes implementation-dependent.
In some cases, the errno
value indicates
an error only if the function returns a specific error indicator.
If you check errno
before checking the function
return value, you can see false positives.
For information on how to detect errors, see the documentation for that specific function.
Typically, the functions return an out-of-band error indicator to indicate errors. For instance:
fopen
returns a null pointer if an error occurs.signal
returns theSIG_ERR
error indicator and setserrno
to a positive value. Checkerrno
only after you have checked the function return value.
errno
After fopen
Call#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define fatal_error() abort()
const char *temp_filename = "/tmp/demo.txt";
FILE *func()
{
FILE *fileptr;
errno = 0;
fileptr = fopen(temp_filename, "w+b");
if (errno != 0) {
if (fileptr != NULL) {
(void)fclose(fileptr);
}
/* Handle error */
fatal_error();
}
return fileptr;
}
In this example, errno
is the first variable
that is checked after a call to fopen
. You might
expect that fopen
changes errno
to
a nonzero value if an error occurs. If you run this code with an implementation
of fopen
that does not set errno
on
errors, you might miss an error condition. In this situation, fopen
can
return a null pointer that escapes detection.
fopen
After
CallOne possible correction is to only check the return value of fopen
for
a null pointer.
#include <stdio.h> #include <stdlib.h> #include <errno.h> #define fatal_error() abort() const char *temp_filename = "/tmp/demo.txt"; FILE *func() { FILE *fileptr; fileptr = fopen(temp_filename, "w+b"); if (fileptr == NULL) { fatal_error(); } return fileptr; }
Errno not checked
Errno not checked occurs when
you call a function that sets errno
to indicate
error conditions, but do not check errno
after
the call. For these functions, checking errno
is
the only reliable way to determine
if an error occurred.
Functions that set errno
on errors include:
fgetwc
,strtol
, andwcstol
.For a comprehensive list of functions, see documentation about errno.
POSIX®
errno
-setting functions such asencrypt
andsetkey
.
To see if the function call completed without errors, check errno
for
error values.
The return values of these errno
-setting
functions do not indicate errors. The return value can be one of the
following:
void
Even if an error occurs, the return value can be the same as the value from a successful call. Such return values are called in-band error indicators.
You can determine if an error occurred only by checking errno
.
For instance, strtol
converts a string to
a long integer and returns the integer. If the result of conversion
overflows, the function returns LONG_MAX
and sets errno
to ERANGE
.
However, the function can also return LONG_MAX
from
a successful conversion. Only by
checking errno
can you distinguish between an error
and a successful
conversion.
Before calling the function, set errno
to
zero.
After the function call, to see if an error occurred, compare errno
to
zero. Alternatively, compare errno
to known error
indicator values. For instance, strtol
sets errno
to ERANGE
to
indicate errors.
The error message in the Polyspace® result shows the error indicator value that you can compare to.
errno
Not Checked After Call to strtol
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(int argc, char *argv[]) {
char *str, *endptr;
int base;
str = argv[1];
base = 10;
long val = strtol(str, &endptr, base);
printf("Return value of strtol() = %ld\n", val);
}
You are using the return value of strtol
without
checking errno
.
errno
After CallBefore calling strtol
, set
errno
to zero. After a call to strtol
,
check the return value for LONG_MIN
or
LONG_MAX
and errno
for
ERANGE
.
#include<stdlib.h> #include<stdio.h> #include<errno.h> #include<limits.h> int main(int argc, char *argv[]) { char *str, *endptr; int base; str = argv[1]; base = 10; errno = 0; long val = strtol(str, &endptr, base); if((val == LONG_MIN || val == LONG_MAX) && errno == ERANGE) { printf("strtol error"); exit(EXIT_FAILURE); } printf("Return value of strtol() = %ld\n", val); }
Errno not reset
Errno not reset occurs when
you do not reset errno
before calling a function
that sets errno
to indicate error conditions. However,
you check errno
for those error conditions after
the function call.
An errno
-setting function sets errno
to nonzero values to indicate error conditions.
If you do not set errno
to zero before calling an errno
-setting function,a nonzero value of errno
might be left over from a previous call to an errno
-setting function. Using errno
to check errors can then lead you to falsely conclude that an error occurred from the most recent call.
errno
is set to 0 at program startup but is not automatically reset after an error occurs. You must explicitly set errno
to 0 when required.
Before calling a function that sets errno
to
indicate error conditions, reset errno
to zero
explicitly.
errno
Not Reset Before Call to strtod
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <float.h>
#define fatal_error() abort()
double func(const char *s1, const char *s2)
{
double f1;
f1 = strtod (s1, NULL);
if (0 == errno) {
double f2 = strtod (s2, NULL);
if (0 == errno) {
long double result = (long double)f1 + f2;
if ((result <= (long double)DBL_MAX) && (result >= (long double)-DBL_MAX))
{
return (double)result;
}
}
}
fatal_error();
return 0.0;
}
In this example, errno
is not reset to 0
before the first call to strtod
. Checking errno
for
0 later can lead to a false positive.
errno
Before CallOne possible correction is to reset errno
to
0 before calling strtod
.
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <float.h> #define fatal_error() abort() double func(const char *s1, const char *s2) { double f1; errno = 0; f1 = strtod (s1, NULL); if (0 == errno) { double f2 = strtod (s2, NULL); if (0 == errno) { long double result = (long double)f1 + f2; if ((result <= (long double)DBL_MAX) && (result >= (long double)-DBL_MAX)) { return (double)result; } } } fatal_error(); return 0.0; }
Check Information
Decidability: Undecidable |
Version History
Introduced in R2019aR2024a: Rule violation displayed differently and more functions covered
Starting R2024a, the rule violation appears on the call to an errno
-setting function if you do not set errno
to zero before the call but test errno
for error conditions after the call. Previously, instead of the function call, the rule violation appeared on the subsequent test of errno
.
The checker also covers a wider range of errno
-setting functions.
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.
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)