diff options
author | Alejandro Colomar <alx@kernel.org> | 2023-12-06 22:26:04 +0100 |
---|---|---|
committer | Alejandro Colomar <alx@kernel.org> | 2023-12-06 22:39:53 +0100 |
commit | 628d27c3c1d8362a7e73198460b8c6a739be4973 (patch) | |
tree | 77f34ca29044c5d8acf3df80b09f6e99334721f7 | |
parent | 30cdb698f6f1af19f13b26c9a1b64bb67b45768a (diff) |
strtol.3: Clarify that the base should be tested beforehand, if at all
Normally, the base need not be tested, and the only interesting errno
value should be ERANGE.
If the base needs to be tested, it should be tested in a call that
would not otherwise fail. Otherwise, it would be easy to trigger
Undefined Behavior. Consider the following example:
errno = 0;
val = strtol("foo", &end, -42);
There's no portable way to know if the call failed due to the string or
the base.
Cc: Matthew House <mattlloydhouse@gmail.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
-rw-r--r-- | man3/strtol.3 | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/man3/strtol.3 b/man3/strtol.3 index 1f1f98216..8ea93cb59 100644 --- a/man3/strtol.3 +++ b/man3/strtol.3 @@ -184,8 +184,8 @@ on both success and failure, the calling program should set .I errno to 0 before the call, and then determine if an error occurred by checking whether -.I errno -has a nonzero value after the call. +.I errno == ERANGE +after the call. .P According to POSIX.1, in locales other than "C" and "POSIX", @@ -206,6 +206,21 @@ may be equivalent to .BR strtoll () or to .BR strtol (). +.SH CAVEATS +If the +.I base +needs to be tested, +it should be tested in a call where the string is known to succeed. +Otherwise, it's impossible to portably differentiate the errors. +.P +.in +4n +.EX +errno = 0; +strtol("0", NULL, base); +if (errno == EINVAL) + goto unsupported_base; +.EE +.in .SH EXAMPLES The program shown below demonstrates the use of .BR strtol (). @@ -262,11 +277,18 @@ main(int argc, char *argv[]) base = (argc > 2) ? atoi(argv[2]) : 0; \& errno = 0; /* To distinguish success/failure after call */ + strtol("0", NULL, base); + if (errno == EINVAL) { + perror("strtol"); + exit(EXIT_FAILURE); + } +\& + errno = 0; /* To distinguish success/failure after call */ val = strtol(str, &endptr, base); \& /* Check for various possible errors. */ \& - if (errno != 0) { + if (errno == ERANGE) { perror("strtol"); exit(EXIT_FAILURE); } |