summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Colomar <alx@kernel.org>2023-12-06 22:26:04 +0100
committerAlejandro Colomar <alx@kernel.org>2023-12-06 22:39:53 +0100
commit628d27c3c1d8362a7e73198460b8c6a739be4973 (patch)
tree77f34ca29044c5d8acf3df80b09f6e99334721f7
parent30cdb698f6f1af19f13b26c9a1b64bb67b45768a (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.328
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);
}