diff --git a/common/lib/libc/stdlib/_strtoi.h b/common/lib/libc/stdlib/_strtoi.h index e6b0ce778b60..b838608f6b52 100644 --- a/common/lib/libc/stdlib/_strtoi.h +++ b/common/lib/libc/stdlib/_strtoi.h @@ -1,4 +1,4 @@ -/* $NetBSD: _strtoi.h,v 1.2 2015/01/18 17:55:22 christos Exp $ */ +/* $NetBSD: _strtoi.h,v 1.3 2024/01/20 16:13:39 christos Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -100,26 +100,26 @@ INT_FUNCNAME(_int_, _FUNCNAME, _l)(const char * __restrict nptr, errno = serrno; #endif - if (*rstatus == 0) { - /* No digits were found */ - if (nptr == *endptr) - *rstatus = ECANCELED; - /* There are further characters after number */ - else if (**endptr != '\0') - *rstatus = ENOTSUP; - } + /* No digits were found */ + if (*rstatus == 0 && nptr == *endptr) + *rstatus = ECANCELED; if (im < lo) { if (*rstatus == 0) *rstatus = ERANGE; return lo; } + if (im > hi) { if (*rstatus == 0) *rstatus = ERANGE; return hi; } + /* There are further characters after number */ + if (*rstatus == 0 && **endptr != '\0') + *rstatus = ENOTSUP; + return im; } diff --git a/lib/libc/stdlib/strtoi.3 b/lib/libc/stdlib/strtoi.3 index c0d10c0c4ff1..6799aaf6a15a 100644 --- a/lib/libc/stdlib/strtoi.3 +++ b/lib/libc/stdlib/strtoi.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: strtoi.3,v 1.7 2017/07/03 21:32:50 wiz Exp $ +.\" $NetBSD: strtoi.3,v 1.8 2024/01/20 16:13:39 christos Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -36,12 +36,12 @@ .\" Created by Kamil Rytarowski, based on ID: .\" NetBSD: strtol.3,v 1.31 2015/03/11 09:57:35 wiz Exp .\" -.Dd November 13, 2015 +.Dd January 20, 2024 .Dt STRTOI 3 .Os .Sh NAME .Nm strtoi -.Nd convert string value to an intmax_t integer +.Nd convert a string value to an intmax_t integer .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -58,8 +58,7 @@ .Sh DESCRIPTION The .Fn strtoi -function -converts the string in +function converts the string in .Fa nptr to an .Ft intmax_t @@ -117,10 +116,11 @@ is taken as 10 (decimal) unless the next character is .Ql 0 , in which case it is taken as 8 (octal). .Pp -The remainder of the string is converted to a +The remainder of the string is converted to an .Em intmax_t value in the obvious manner, -stopping at the first character which is not a valid digit +stopping at the end of the string +or at the first character which is not a valid digit in the given base. (In bases above 10, the letter .Ql A @@ -201,6 +201,12 @@ or the range given was invalid, i.e. > .Fa hi . .El +.Pp +The range check is important than the unconverted characters check, +and it is performed first. +If a program needs to know if there were unconverted characters when an +out of range number has been provided, it needs to supply and test +.Fa endptr. .Sh SEE ALSO .Xr atof 3 , .Xr atoi 3 , diff --git a/lib/libc/stdlib/strtonum.c b/lib/libc/stdlib/strtonum.c index 35ae6d2bda62..fb92a0361161 100644 --- a/lib/libc/stdlib/strtonum.c +++ b/lib/libc/stdlib/strtonum.c @@ -1,4 +1,4 @@ -/* $NetBSD: strtonum.c,v 1.6 2018/12/06 06:29:56 kamil Exp $ */ +/* $NetBSD: strtonum.c,v 1.7 2024/01/20 16:13:39 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. * All rights reserved. @@ -29,7 +29,7 @@ */ #include -__RCSID("$NetBSD: strtonum.c,v 1.6 2018/12/06 06:29:56 kamil Exp $"); +__RCSID("$NetBSD: strtonum.c,v 1.7 2024/01/20 16:13:39 christos Exp $"); #include "namespace.h" @@ -46,26 +46,33 @@ strtonum(const char *nptr, long long minval, long long maxval, int e; long long rv; const char *resp; + char *eptr; if (errstr == NULL) errstr = &resp; - if (minval > maxval) { - *errstr = "invalid"; - return 0; - } + if (minval > maxval) + goto out; - rv = (long long)strtoi(nptr, NULL, 10, minval, maxval, &e); + rv = (long long)strtoi(nptr, &eptr, 10, minval, maxval, &e); - if (e == 0) { + switch (e) { + case 0: *errstr = NULL; return rv; + case ECANCELED: + case ENOTSUP: + goto out; + case ERANGE: + if (*eptr) + goto out; + *errstr = rv == maxval ? "too large" : "too small"; + return 0; + default: + abort(); } - if (e == ERANGE) - *errstr = (rv == maxval ? "too large" : "too small"); - else - *errstr = "invalid"; - +out: + *errstr = "invalid"; return 0; } diff --git a/lib/libc/stdlib/strtou.3 b/lib/libc/stdlib/strtou.3 index 98ceb8ce5cbf..eb9b74927f4f 100644 --- a/lib/libc/stdlib/strtou.3 +++ b/lib/libc/stdlib/strtou.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: strtou.3,v 1.7 2017/07/03 21:32:50 wiz Exp $ +.\" $NetBSD: strtou.3,v 1.8 2024/01/20 16:13:39 christos Exp $ .\" .\" Copyright (c) 1990, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -36,12 +36,12 @@ .\" Created by Kamil Rytarowski, based on ID: .\" NetBSD: strtoul.3,v 1.29 2015/03/10 13:00:58 christos Exp .\" -.Dd November 13, 2015 +.Dd January 20, 2024 .Dt STRTOU 3 .Os .Sh NAME .Nm strtou -.Nd convert a string to an uintmax_t integer +.Nd convert a string value to an uintmax_t integer .Sh LIBRARY .Lb libc .Sh SYNOPSIS @@ -120,7 +120,7 @@ The remainder of the string is converted to an .Em uintmax_t value in the obvious manner, stopping at the end of the string -or at the first character that does not produce a valid digit +or at the first character which is not a valid digit in the given base. (In bases above 10, the letter .Ql A @@ -195,12 +195,18 @@ In this case, .Fa endptr points to the first unconverted character. .It Bq Er ERANGE -The given string was out of range; the value converted has been clamped; or -the range given was invalid, i.e. +The given string was out of range; the value converted has been clamped; +or the range given was invalid, i.e. .Fa lo > .Fa hi . .El +.Pp +The range check is important than the unconverted characters check, +and it is performed first. +If a program needs to know if there were unconverted characters when an +out of range number has been provided, it needs to supply and test +.Fa endptr. .Sh SEE ALSO .Xr atof 3 , .Xr atoi 3 ,