Bug 29753 - atoi() is documented to return 0 on error, but return -1 if outside the range of long
Summary: atoi() is documented to return 0 on error, but return -1 if outside the range...
Status: RESOLVED MOVED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-11-06 17:11 UTC by Thomas Habets
Modified: 2022-12-06 14:41 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Habets 2022-11-06 17:11:13 UTC
The manpage is clear enough:

```
RETURN VALUE
       The converted value or 0 on error.
[…]
No checks for overflow or underflow are done.
```

This is not really true. atoi() uses strtol() to convert from string to long, and the results may be under or overflow, in which case strtol() returns LONG_MIN and LONG_MAX, respectively.

LONG_MIN cast to `int` is 0, which lives up to the manpage just fine ("0 on error"), assuming underflow is an error.

LONG_MAX cast to `int` is -1.


So the behavior doesn't violate POSIX. But is surprising. And arguably is incorrectly documented. There is, in fact, a range check, but but against long, not int. "Error" is not defined in the manpage. Is over/underflow an error?

It's kinda handled, kinda not, with the effect that over and underflow have different return values.


For atol() range checks are fully done. The strtol() manpage documents it, per above.


It's not clear to me what the right fix is, here. Because enough code relies on the current (IMO in the case of atoi() broken)) behavior maybe a clarification to the manpage is in order, to say:
1. Instead of "No checks for overflow or underflow are done" say "for atoi() the return value in case of under/overflow is undefined".
2. For atol() document the current behavior of "for atol() and atoll() under/overflow is returned as LONG_MIN/LONG_MAX and LLONG_MIN/LLONG_MAX, respectively".

(2) seems safe as this is already the documented behavior of strtol().


My research/rant on the properties of parsing and casting integers:

https://blog.habets.se/2022/10/No-way-to-parse-integers-in-C.html
https://blog.habets.se/2022/11/Integer-handling-is-broken.html
Comment 1 Andreas Schwab 2022-11-10 09:59:23 UTC
This should be reported to the manpage project.  The glibc documentation has always been saying "need not dectect overflow errors".
Comment 2 Thomas Habets 2022-11-10 10:21:20 UTC
Oh, I didn't realize that manpages were managed as a different project. Thanks.

Looks like I should go here:
https://www.kernel.org/doc/man-pages/reporting_bugs.html

So assuming that maintainers here think that the behavior should not be changed, I guess this bug can be closed?
Comment 3 Sam James 2022-11-10 10:23:38 UTC
For discoverability purposes, could you link to the man-pages report you make in this bug, and vice-versa? Thanks.
Comment 4 Andreas Schwab 2022-12-06 14:41:44 UTC
Moved to man-pages bug tracker.