Missing error handling while converting a string to a number, using C stdlib functionsCXX-W2023
The process of parsing numbers from strings can result in several errors that need to be detected and addressed when using a C Standard Library function. These errors include cases where the string does not contain a number, or contains a number that is out of range.
To handle these error conditions, it is recommended to use one of the C
Standard Library strto*()
(like strtol()
, strtoll()
, strtoimax()
and
others) functions to parse integer or floating-point numbers from strings.
These functions provide more robust error handling compared to ato*()
(like
atoi()
, atol()
, and others) or sscanf
.
It is also essential to use the strtol()
function to convert to smaller
signed integer types, such as signed int, signed short, and signed char, and
test the result against the range limits for that type. Similarly, use the
strtoul()
function to convert to smaller unsigned integer types, such as
unsigned int
, unsigned short
, and unsigned char
, and test the result
against the range limits for that type.
Bad practice
#include <stdlib.h>
int main() {
long int si = std::atol("sa");
}
Recommended
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
char *end;
long int si;
errno = 0;
const long sl = strtol(buff, &end, 10);
if (end == buff) {
fprintf(stderr, "%s: not a decimal number\n", buff);
} else if ('\0' != *end) {
fprintf(stderr, "%s: extra characters at end of input: %s\n", buff, end);
} else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
fprintf(stderr, "%s out of range of type long\n", buff);
} else if (sl > INT_MAX) {
fprintf(stderr, "%ld greater than INT_MAX\n", sl);
} else if (sl < INT_MIN) {
fprintf(stderr, "%ld less than INT_MIN\n", sl);
} else {
si = sl;
/* Process si */
}
}