[PATCH] inttypes.h: strtoi(), strtou(): Prefer reporting ERANGE over ENOTSUP

Alejandro Colomar alx at kernel.org
Wed Jan 24 18:16:23 UTC 2024


If both ERANGE and ENOTSUP conditions happen, ENOTSUP can be tested
secondarily as `*end != '\0'`.  However, there's no secondary mechanism
to test ERANGE.  Thus, it is important to report ERANGE, and let the
user check *end if necessary.

Most NetBSD and Debian existing code assumed that strtoi/u() reported
ERANGE with preference, and so there were several bugs caused by the old
behavior.  In fact, there was only one place where it was the other way
around: the implementation of strtonum().  This change of behavior fixes
several bugs in various code bases.

The implementation of strtonum() has been adjusted to keep its behavior
unmodified.

NetBSD has changed the behavior of their implementation after my bug
report, so this patch makes our API compatible with theirs.

Link: <https://lists.sr.ht/~hallyn/shadow/%3CZZoQDms6Sv6e5SPE%40debian%3E>
Link: <https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=57828>
Cc: Guillem Jover <guillem at hadrons.org>
Cc: Thorsten Glaser <tg at mirbsd.de>
Cc: christos <christos at netbsd.org>
Cc: Taylor R Campbell <riastradh at netbsd.org>
Cc: Mouse <mouse at Rodents-Montreal.ORG>
Cc: roy <roy at netbsd.org>
Cc: <tech-userlevel at netbsd.org>
Signed-off-by: Alejandro Colomar <alx at kernel.org>
---
 man/strtoi.3bsd |  4 +++-
 man/strtou.3bsd |  4 +++-
 src/strtoi.c    | 14 ++++++--------
 src/strtonum.c  |  6 ++++--
 src/strtou.c    | 14 ++++++--------
 5 files changed, 22 insertions(+), 20 deletions(-)

diff --git a/man/strtoi.3bsd b/man/strtoi.3bsd
index 15102da..d58e30a 100644
--- a/man/strtoi.3bsd
+++ b/man/strtoi.3bsd
@@ -2,6 +2,7 @@
 .\"
 .\" Copyright (c) 1990, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright 2024, Alejandro Colomar <alx at kernel.org>
 .\"
 .\" This code is derived from software contributed to Berkeley by
 .\" Chris Torek and the American National Standards Committee X3,
@@ -195,7 +196,8 @@ .Sh ERRORS
 .Ar base
 is not between 2 and 36 and does not contain the special value 0.
 .It Bq Er ENOTSUP
-The string contained non-numeric characters that did not get converted.
+The string contained non-numeric characters that did not get converted,
+after a valid number.
 In this case,
 .Fa endptr
 points to the first unconverted character.
diff --git a/man/strtou.3bsd b/man/strtou.3bsd
index d7e02eb..6a70be0 100644
--- a/man/strtou.3bsd
+++ b/man/strtou.3bsd
@@ -2,6 +2,7 @@
 .\"
 .\" Copyright (c) 1990, 1991, 1993
 .\"	The Regents of the University of California.  All rights reserved.
+.\" Copyright 2024, Alejandro Colomar <alx at kernel.org>
 .\"
 .\" This code is derived from software contributed to Berkeley by
 .\" Chris Torek and the American National Standards Committee X3,
@@ -195,7 +196,8 @@ .Sh ERRORS
 .Ar base
 is not between 2 and 36 and does not contain the special value 0.
 .It Bq Er ENOTSUP
-The string contained non-numeric characters that did not get converted.
+The string contained non-numeric characters that did not get converted,
+after a valid number.
 In this case,
 .Fa endptr
 points to the first unconverted character.
diff --git a/src/strtoi.c b/src/strtoi.c
index 9e3771d..91e8442 100644
--- a/src/strtoi.c
+++ b/src/strtoi.c
@@ -3,6 +3,7 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright 2024, Alejandro Colomar <alx at kernel.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -73,14 +74,8 @@ strtoi(const char *__restrict nptr,
 	*rstatus = errno;
 	errno = serrno;
 
-	if (*rstatus == 0) {
-		/* No digits were found */
-		if (nptr == *endptr)
-			*rstatus = ECANCELED;
-		/* There are further characters after number */
-		else if (**endptr != '\0')
-			*rstatus = ENOTSUP;
-	}
+	if (*rstatus == 0 && nptr == *endptr)
+		*rstatus = ECANCELED;
 
 	if (im < lo) {
 		if (*rstatus == 0)
@@ -93,5 +88,8 @@ strtoi(const char *__restrict nptr,
 		return hi;
 	}
 
+	if (*rstatus == 0 && **endptr != '\0')
+		*rstatus = ENOTSUP;
+
 	return im;
 }
diff --git a/src/strtonum.c b/src/strtonum.c
index 2fa0fcf..6d006cf 100644
--- a/src/strtonum.c
+++ b/src/strtonum.c
@@ -2,6 +2,7 @@
 /*-
  * Copyright (c) 2014 The NetBSD Foundation, Inc.
  * All rights reserved.
+ * Copyright 2024, Alejandro Colomar <alx at kernel.org>
  *
  * This code is derived from software contributed to The NetBSD Foundation
  * by Christos Zoulas.
@@ -40,20 +41,21 @@ strtonum(const char *nptr, long long minval, long long maxval,
          const char **errstr)
 {
 	int e;
+	char *end;
 	long long rv;
 	const char *resp;
 
 	if (errstr == NULL)
 		errstr = &resp;
 
-	rv = (long long)strtoi(nptr, NULL, 10, minval, maxval, &e);
+	rv = (long long)strtoi(nptr, &end, 10, minval, maxval, &e);
 
 	if (e == 0) {
 		*errstr = NULL;
 		return rv;
 	}
 
-	if (e == ERANGE)
+	if (e == ERANGE && *end == '\0')
 		*errstr = (rv == maxval ? "too large" : "too small");
 	else
 		*errstr = "invalid";
diff --git a/src/strtou.c b/src/strtou.c
index 0e22a88..da7fbf5 100644
--- a/src/strtou.c
+++ b/src/strtou.c
@@ -3,6 +3,7 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
+ * Copyright 2024, Alejandro Colomar <alx at kernel.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -73,14 +74,8 @@ strtou(const char *__restrict nptr,
 	*rstatus = errno;
 	errno = serrno;
 
-	if (*rstatus == 0) {
-		/* No digits were found */
-		if (nptr == *endptr)
-			*rstatus = ECANCELED;
-		/* There are further characters after number */
-		else if (**endptr != '\0')
-			*rstatus = ENOTSUP;
-	}
+	if (*rstatus == 0 && nptr == *endptr)
+		*rstatus = ECANCELED;
 
 	if (im < lo) {
 		if (*rstatus == 0)
@@ -93,5 +88,8 @@ strtou(const char *__restrict nptr,
 		return hi;
 	}
 
+	if (*rstatus == 0 && **endptr != '\0')
+		*rstatus = ENOTSUP;
+
 	return im;
 }
-- 
2.43.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/libbsd/attachments/20240124/8191f2c1/attachment.sig>


More information about the libbsd mailing list