Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can I assume about the behaviour of atoi() on error?

The standard C library function atoi is documented in ISO 9899:2011 as:

7.22.1 Numeric conversion functions

1 The functions atof, atoi, atol, and atoll need not affect the value of the integer expression errno on an error. If the value of the result cannot be represented, the behavior is undefined.

...

7.22.1.2 The atoi, atol, and atoll functions

Synopsis

#include <stdlib.h>
int atoi(const char *nptr);
long int atol(const char *nptr);
long long int atoll(const char *nptr);

Description

2 The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively. Except for the behavior on error, they are equivalent to

atoi: (int)strtol(nptr, (char **)NULL, 10)
atol: strtol(nptr, (char **)NULL, 10)
atoll: strtoll(nptr, (char **)NULL, 10)

Returns

3 The atoi, atol, and atoll functions return the converted value.

What is the intended behaviour when string pointed to by nptr cannot be parsed as an integer? The following four opinions seem to exist:

  • No conversion is performed and zero is returned. This is the documentation given by some references like this one.

  • Behaviour is like that of strtol except that errno might not be set. This emerges from taking “Except for the behavior on error” as a reference to §7.22.1 ¶1.

  • Behaviour is unspecified. This is what POSIX says:

    The call atoi(str) shall be equivalent to:

    (int) strtol(str, (char **)NULL, 10)
    

    except that the handling of errors may differ. If the value cannot be represented, the behavior is undefined.

    Furthermore, the section Application Usage states:

    The atoi() function is subsumed by strtol() but is retained because it is used extensively in existing code. If the number is not known to be in range, strtol() should be used because atoi() is not required to perform any error checking.

    Note that POSIX claims that the specification is aligned to ISO 9899:1999 (which contains the same language as ISO 9899:2011 as far as I'm concerned):

    The functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1-2008 defers to the ISO C standard.

    According to my local POSIX committee member, this is the historical behaviour of UNIX.

  • Behaviour is undefined. This interpretation arises because §7.22.1.2 ¶2 never explicitly says what happens on error. Behaviour that is neither defined nor explicitly implementation defined or unspecified is undefined.

Which of these interpretations is correct? Please try to refer to authoritative documentation.

like image 359
fuz Avatar asked Jul 15 '16 09:07

fuz


1 Answers

What is the intended behaviour when string pointed to by nptr cannot be parsed as an integer?

To be clear, this question applies to

// Case 1
value = atoi("");
value = atoi("  ");
value = atoi("wxyz");

and not the following:

// Case 2
// NULL does not point to a string
value = atoi(NULL);
// Convert the initial portion, yet has following junk
value = atoi("123xyz");
value = atoi("123 ");

And maybe/maybe not the following depending on usage of integer.

// Case 3
// Can be parsed as an _integer_, yet overflows an `int`.
value = atoi("12345678901234567890123456789012345678901234567890");

The "non-Case 2" behavior of ato*() depends on the meaning of error in

The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively. Except for the behavior on error, they are equivalent to
atoi: (int)strtol(nptr, (char **)NULL, 10)
...
C11dr §7.22.1.2 2


Certainly error includes case 3: "If the correct value is outside the range of representable values". strto*(), though maybe not ato*(), in this case does set the error number errrno defined in <errno.h>. Since the specification of ato*() does not apply to this error, overflow, the result, is UB per

Undefined behavior is otherwise indicated in this International Standard by the words ‘‘undefined behavior’’ or by the omission of any explicit definition of behavior. C11dr §4 2


For case 1, the behavior of strto*() is well defined and is not specified to affect errno. The spec goes into detail (§7.22.1.4 4) and calls these "no conversion", not an error. So it can asserted the case 1 strto*() behavior is not an error, but a "no conversion". Thus per ...

"If no conversion could be performed, zero is returned. C11dr §7.22.1.4 8

... atoi("") must return 0.

like image 105
chux - Reinstate Monica Avatar answered Nov 07 '22 01:11

chux - Reinstate Monica