On 09/12/2022 19:33, Alejandro Colomar wrote:
Hi Ian,
On 12/9/22 20:28, Ian Abbott wrote:
On 09/12/2022 18:59, Alejandro Colomar wrote:
On 12/8/22 13:34, Ian Abbott wrote:
The `scanf()` function does not intentionally set `errno` to `ERANGE`.
That is just a side effect of the code that it uses to perform
conversions. It also does not work as reliably as indicated in the
'man' page when the target integer type is narrower than `long`.
Typically (at least in glibc) for target integer types narrower than
`long`, the number has to exceed the range of `long` (for signed
conversions) or `unsigned long` (for unsigned conversions) for `errno`
to be set to `ERANGE`.
Documenting `ERANGE` in the ERRORS section kind of implies that
`scanf()` should return `EOF` when an integer overflow is encountered,
which it doesn't (and doing so would violate the C standard).
Just remove any mention of the `ERANGE` error to avoid confusion.
Fixes: 646af540e467 ("Add an ERRORS section documenting at least
some of the errors that may occur for scanf().")
Cc: Michael Kerrisk <mtk.manpages@xxxxxxxxx>
Signed-off-by: Ian Abbott <abbotti@xxxxxxxxx>
I see. How about saying something like "it may also fail for any of
any errors that functions used to perform the conversions may fail"?
It depends what you mean by "fail". These errors do not make scanf
return EOF.
Just to clarify. Does scanf(3) _never_ fail (EOF) due to ERANGE? Or is
it that ERANGE sometimes makes it fail, sometimes not?
The glibc implementation certainly doesn't return EOF when ERANGE is
detected. __vfscanf_internal() in stdio-common/vfscan-internal.c does
not contain any code to deal with ERANGE - it's just a side-effect of
the calls to __strtol_internal(), __strtoul_internal(),
__strtoll_internal(), or __strtoull_internal().
If it's the former, I agree with your patch. When a function hasn't
reported failure, errno is unspecified.
If it's the latter, I'd write something about it.
For the glibc implementation, it's the former.
Technically, the behavior is undefined if the result of the conversion
cannot be represented in the object being assigned to by scanf. (In
the case of glibc, that probably results in either the integer object
being set to a truncated version of the input integer, or the integer
object being set to a truncated version of LONG_MIN or LONG_MAX,
depending on the actual number.)
Hmm, UB. Under UB, anything can change, so error reporting is already
unreliable. If EOF+ERANGE can _only_ happen under UB, I'd rather remove
the paragraph. Please confirm.
Yes, it is UB as per C17 7.21.6 paragraph 10: "[...] Unless assignment
suppression was indicated by a *, the result of the conversion is placed
in the object pointed to by the first argument following the format
argument that has not already received a conversion result. If this
object does not have an appropriate type, or if the result of the
conversion cannot be represented in the object, the behavior is undefined."
Setting errno to 0 before calling scanf and expecting errno to have a
meaningful value when scanf returns something other than EOF is bogus
usage.
Yep, that's bogus.
Cheers,
Alex
Best regards,
Ian
--
-=( Ian Abbott <abbotti@xxxxxxxxx> || MEV Ltd. is a company )=-
-=( registered in England & Wales. Regd. number: 02862268. )=-
-=( Regd. addr.: S11 & 12 Building 67, Europa Business Park, )=-
-=( Bird Hall Lane, STOCKPORT, SK3 0XA, UK. || www.mev.co.uk )=-