Re: [PATCH v1] xstrtol: Remove dead code

Alejandro Colomar <[email protected]> Fri, 19 Jul 2024 01:32:56 +0200
Newsgroups dev.linux.lists.liba2i
Message-ID <sp6uygkj4rspyhqgk6azglvwtkv2j4dhg6jglrifv5unowfpll@is236cpbm37v>
--a4hyyi26hqfgkx32
Content-Type: text/plain; protected-headers=v1; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
From: Alejandro Colomar <[email protected]>
To: Bruno Haible <[email protected]>
Cc: [email protected], Paul Eggert <[email protected]>, 
	=?utf-8?B?xJBvw6BuIFRy4bqnbiBDw7RuZw==?= Danh <[email protected]>, Eli Schwartz <[email protected]>, Sam James <[email protected]>, 
	Serge Hallyn <[email protected]>, Iker Pedrosa <[email protected]>, 
	Michael Vetter <[email protected]>, [email protected]
Subject: Re: [PATCH v1] xstrtol: Remove dead code
References: <[email protected]>
 <8009158.qOBuL9xsDt@nimes>
 <kul6qwyrvq2xdevjjkkblsalg7ycwg6x7ey725kans5myqjcai@3jm56c5famlt>
 <2licxuxsw37hpyss5izkqu6x4lfwcduxwbrgw7a4fqaibydwlx@o6y73xqtyrnx>
MIME-Version: 1.0
In-Reply-To: <2licxuxsw37hpyss5izkqu6x4lfwcduxwbrgw7a4fqaibydwlx@o6y73xqtyrnx>

On Fri, Jul 19, 2024 at 12:14:19AM GMT, Alejandro Colomar wrote:
> [CC -=3D Andrew, per explicit request]
>=20
> On Thu, Jul 18, 2024 at 11:25:11PM GMT, Alejandro Colomar wrote:
> > On Thu, Jul 18, 2024 at 11:09:40PM GMT, Bruno Haible wrote:
> > > Hi Alejandro,
>=20
> Hi Bruno,
>=20
> > > > strtol(3) has a limited set of possible states:
> > > > ...
> > > > The condition '*endp !=3D s && errno !=3D 0 && errno !=3D ERANGE' is
> > > > unreachable.  The only errno possible if '*endp !=3D s' is ERANGE.
> > >=20
> > > Such a statement can be true if you look at the standards (ISO C, POS=
IX).
> > >=20
> > > However, there's a difference between what the standards say and what=
 the
> > > systems actually do. The Gnulib documentation contains thousands of e=
xamples
> > > of such differences.
> > >=20
> > > Gnulib therefore (almost) never assumes that there are no possible er=
rno
> > > values besides the ones listed in the standards.
> > >   - Some systems return "wrong" errno values. Example: [1]
> > >   - Some systems fail with ENOMEM when memory is tight. Who says that
> > >     an implementation of strtol() cannot use malloc() ? Some implemen=
tations
> > >     of strtod() do use malloc().
> > >=20
> > > So, what you call "dead code", I call "defensive programming". I woul=
d not
> > > like to apply this patch.
>=20
> On the other hand, I'm not sure that defensive programming is valid in
> this case.  I already discussed this topic with Serge (but we didn't
> have in mind any specific implementation) some time ago, and,
>=20
> We'd need to know the precise specification of that system that can set
> errno =3D ENOMEM.
>=20
> Is *endp guaranteed to be set?  Or may it be unset (as happens with
> EINVAL)?
>=20
> If it is allowed to keep *endp unset, then the first `if (*p =3D=3D s)`
> would already be UB.  And for truly being defensive, we'd need to assume
> that it may leave *endp unset.  Thus we cannot read that until we know
> that no errno has been set.  But then comes the problem that some
> systems set EINVAL on what strtoi(3) calls ECANCELED.  To work with all
> of those systems, we'd probably need to pass a dummy NULL to make sure
> we can inspect *endp regardless of strtol(3) having set it or not:
>=20
> intmax_t
> strtoi(char *s, char **restrict endp, int base,
>     intmax_t min, intmax_t max, int *restrict status)
> {
> 	int        errno_saved, st;
> 	char       *e;
> 	char       **ep;
> 	intmax_t   n;
>=20
> 	e =3D NULL;
> 	ep =3D &e;
>=20
> 	if (status =3D=3D NULL)
> 		status =3D &st;
>=20
> 	if (base !=3D 0 && (base < 2 || base > 36)) {
> 		*status =3D EINVAL;
> 		return MAX(min, MIN(max, 0));
> 	}
>=20
> 	errno_saved =3D errno;
> 	errno =3D 0;
>=20
> 	n =3D strtoimax(s, ep, base);
>=20
> 	if (errno =3D=3D ERANGE || n < min || n > max)
> 		*status =3D ERANGE;
> 	else if (e =3D=3D s && (errno =3D=3D 0 || errno =3D=3D EINVAL))
> 		*status =3D ECANCELED;
> 	else if (errno !=3D 0)
> 		*status =3D errno;
> 	else if (*e !=3D '\0')
> 		*status =3D ENOTSUP;
> 	else
> 		*status =3D 0;

Hmm, bug there.  I should have written:

	if (errno =3D=3D ERANGE)
		*status =3D ERANGE;
	else if (e =3D=3D s && (errno =3D=3D 0 || errno =3D=3D EINVAL))
		*status =3D ECANCELED;
	else if (errno !=3D 0)
		*status =3D errno;
	else if (n < min || n > max)
		*status =3D ERANGE;
	else if (*e !=3D '\0')
		*status =3D ENOTSUP;
	else
		*status =3D 0;

>=20
> 	errno =3D errno_saved;
>=20
> 	if (endp !=3D NULL)
> 		*endp =3D e;
>=20
> 	return MAX(min, MIN(max, n));
> }
>=20
> Does this make sense?
>=20
> Have a lovely night!
> Alex
>=20
> >=20
> > Makes sense.  I think we should document that possibility in the manual
> > page.  Maybe say that other errno values are possible in some systems?
> > Otherwise, it's already a hell of a function to take care of, and most
> > uses don't handle that possibility at the moment.  (Yet more reasons to
> > use a wrapper that returns -1 & sets errno on error, as the rest of
> > libc.)
> >=20
> > Would you send a patch?  (I'd write it myself, but you probably can
> > provide more info in the commit message.)
> >=20
> > Have a lovely night!
> > Alex
> >=20
> > >=20
> > > Bruno
> > >=20
> > > [1] https://www.gnu.org/software/gnulib/manual/html_node/getlogin_005=
fr.html
> > >=20
> > >=20
> > >=20
> >=20
> > --=20
> > <https://www.alejandro-colomar.es/>
>=20
>=20
>=20
> --=20
> <https://www.alejandro-colomar.es/>



--=20
<https://www.alejandro-colomar.es/>

--a4hyyi26hqfgkx32
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEE6jqH8KTroDDkXfJAnowa+77/2zIFAmaZpiIACgkQnowa+77/
2zKwIBAAoB8ekfPiexoy0lrjOAIfN91fU2kCR4iMVify9IQjmqLxjp7aMRHOuVeO
oQuKn8qXeVkz6/DR0kQny1NZcOjHU8xVi04RnBT+FbCnwBNRuWx7EM6kwIP61Wuy
pd6ZFeltPwA/8SvQY2uPGkjMvsidL1JN2XO8wvwYV8e7ptMr7FL7fbUgBy/rGBV6
CQe+4BCacn6tkJfb4PAFj/wO55XiYGjLFJgUct+LEBd2uFMr3r8oiGGCDrzVaRDs
CuI+cXhCKlW+l4xT6Z2HFhOTVpn9Go8y1tIaWdDFcNVeD3reQtCjZ1Kjj77OVpTx
fj9XQgEj1Fla8D3YFtTyWJl98mDcjGFgIdWLAqa5uJH4mHPlTumQ8im0hmVAB7MS
aQ62QdFNRFoQfxt7zar+ObZIhCko9rjluZwQKbI0UX/Xk0W/XUsSgzqzjjbq1+A5
kTYLvLKDmSrF4K+RPsCXCOAU+NsbRLvKitKMOWUjy1B/046EmGoYRTQCmdtnSU9m
WuJHrSJyvCX+9L7uok1JOYYVzAFqsdUtSlpJlInA+cJ6sZ11wpfZu2yWD4m5NJ0r
/mu6mTkbfkKAkH1s/cQ+G7mS5QFscang43m5MYca87pNv4Kqc7jXrJTcFBqFJ+TL
FqpcVVwBpuPQ6wl059ttd8j228vgUsCzRe3S8trCywmD2LL9c9c=
=rcOi
-----END PGP SIGNATURE-----

--a4hyyi26hqfgkx32--