Re: alx-0008 - Standardize strtoi(3) and strtou(3) from NetBSD

Alejandro Colomar <[email protected]> Wed, 19 Mar 2025 22:23:51 +0100
Newsgroups gmane.os.netbsd.devel.general
Message-ID <2bk4qlhebhsgby4dda4fshocgoyixmqwqlnlgwcyzywkhpbeum@yr5ko5sv6ezy>
--7fc6kx6in34552in
Content-Type: text/plain; protected-headers=v1; charset=utf-8
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
From: Alejandro Colomar <[email protected]>
To: Paul Eggert <[email protected]>
Cc: Bruno Haible <[email protected]>, [email protected], 
	[email protected], [email protected], [email protected], 
	christos <[email protected]>, 
	=?utf-8?B?xJBvw6BuIFRy4bqnbiBDw7RuZw==?= Danh <[email protected]>, Eli Schwartz <[email protected]>, 
	Guillem Jover <[email protected]>, Iker Pedrosa <[email protected]>, 
	Michael Vetter <[email protected]>, Robert Elz <[email protected]>, [email protected], 
	Sam James <[email protected]>, "Serge E. Hallyn" <[email protected]>
Subject: Re: alx-0008 - Standardize strtoi(3) and strtou(3) from NetBSD
References: <mgcfwxfmv3kpfnkkf6uj63kx5tdzl64p2zg2us4ntsu6q5xkwj@k52z5yyiywoo>
 <18739733.sWSEgdgrri@nimes>
 <mvwnrmk2xf45ivyk4kzxdxuwdk67666yt3kwafck6vo4vq2lru@wkqmoqsacqkf>
 <3237498.fEcJ0Lxnt5@nimes>
 <[email protected]>
 <azfxoxklec7hlxll52ocmjiooq7bahy7xgrplbzmfbdygbubxc@upuk7c6bckto>
 <[email protected]>
MIME-Version: 1.0
In-Reply-To: <[email protected]>

Hi Paul,

On Wed, Mar 19, 2025 at 01:39:00PM -0700, Paul Eggert wrote:
> On 2025-03-19 13:05, Alejandro Colomar wrote:
> > Please comment on the subthread where Bruno mentioned a number of places
> > in gnulib and gettext where you use strtoul(3).  I found there a few
> > bugs, plus some ways to just simplify with strtou(3).
>=20
> I looked at the Gnulib commentary in <https://lore.kernel.org/liba2i/jx46=
64ishtl34eg2npdrv5fkfdiczqnlq3vjuacjrupjvh377x@gddcftzgwmfq/>,
> as I assume that's what you're talking about. (I don't hack on gettext and
> will leave Bruno to comment on that.)

Yes, I was referring to those.

> For Gnulib, I didn't see any bugs in the three areas mentioned.
>=20
> The patch suggested to lib/getaddrinfo.c doesn't fix any bugs that I can
> see, and needs an additional wrapper to work anyway, which is introducing
> complexity.

Agree.  gnulib had dead code and not-very-readable code, but no
misbehavior.

Although, I think not reporting errors or warnings on saturation needs
justification.

> The patch suggested to lib/nproc.c is merely a minor clarity / performance
> improvement (it removes three instructions), and does not fix any bugs.
> Likewise for the patch to lib/omp-init.c. And these improvements (where t=
he
> code mistakenly worried about endptr =3D=3D NULL) fix a mistake that one =
could
> make with the proposed strtoi API, so I don't see strtoi helping there.

The test =3D=3DNULL would never make sense in strtoi(3) because it
guarantees setting *endp even on EINVAL.  Some programmers are paranoid
with strtol(3) and check for NULL, because in some systems it may keep
it uninitialized on EINVAL, but that's not portable at all.  So yes,
strtoi(3) should remove that issue.

>=20
> But thanks for the clarity / speedup idea; I installed a patch into Gnulib
> here:
>=20
> https://git.savannah.gnu.org/cgit/gnulib.git/commit/?id=3D2835ca01722fcd4=
1761383ef289d19797b13b2e8

Thanks, those changes look good.  BTW, what do you think of using
strspn(3) to simplify the c_isspace loop?

However, would you mind clarifying why you don't diagnose huge values in
the two places that you have updated?

> > > > In particular, use a functional style, with
> > > > no side effects (no pointers-to-results). Just return the result yo=
u want,
> > > > as a struct, and keep the struct simple. Two struct components shou=
ld
> > > > suffice: the scanned numeric value and a success/error indicator.
> >=20
> > That's going to complicate usage significantly.
>=20
> Please try it and see. You might be surprised at how clean and efficient
> functional programming can be, if done right. Admittedly C doesn't always
> make it easy.

Here's an example of parsing a time_t:

	time_t  t;

	if (a2i(time_t, &t, ...) =3D=3D -1)
		err(1, "a2i");

If you need to store it in a struct, you need to know what a time_t is
in the first place:

	struct foo {
		long  val;
		int   err;
	}

	struct foo  ret;

	ret =3D f(time_t, ...);
	if (ret.err !=3D 0)
		err(1, "f");

How do I know which variant of struct foo I need?


Have a lovely night!
Alex

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

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

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

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmfbNeAACgkQ64mZXMKQ
wqnHqA/9Ew5ugfmjrDl8aibX1nI3vtP+hK+VWQDfgtQ77mE8DH23i99XIyaLPdLz
p/sJH5TszFQbStwvKSUyuz/CdJoukflP++Pi3RYUIFn+fsyCXnTOKSQu9phR01LM
ZkYRfOWKxzafT5cRGJgnZAHr5BFuPsSlPsTs2bxpj0IRbCQqyQX1UE9eL+gxcL2y
U1FzVoWTmkprUjCTMHjUf/zCUicwb4gP86/youzRal09SYXFr9mfWRiW3EmYjfii
UZCTXd2xqaW0UufHz4sNQ6lWLfdB4JHdevQQy15snqgMfa+zn2NV91Ovl5e7pnD0
TV/wr5YYlfFCVv7XZ+Hb+18jDRCALF9vaY/j0nJAbQeMsb1lLspnK5DijNG1Cqqv
5/RQEHh2om77EUdjZcCjCf8dQRWw3uABATxraZ5bAT0P3zeccfpqnKcS7TGRhIq+
zqRNis0nH7VoySurxXT3yoWZsAReUXcvha8i+9Q/Dwt63cMAPbi0YFhpU/j2BvrX
vf9WnfWWzN6nbYmcWEfaQRDsqabWgcbW7IR2oq/B0PmpS4if8EimNVmVJroZInGQ
9XQ+yEK2opeRtoLilL0uwC0bh1H83Cay1kPWU4rUhnMA2ePN03iTkADPACj2HrhM
pp46PXvkem1B1CwJD6YreqIc3VrgiPHmhrkcMzwfBubceEeUfNM=
=giKx
-----END PGP SIGNATURE-----

--7fc6kx6in34552in--