Robert Elz wrote, on 24 Oct 2020:
>
> Is there somewhere, anywhere, where it is possible to infer what
> range of values printf (the utility, not the C library function)
> is expected to handle?
> 
> I can find nothing in the XCU 3.printf page, nor in XBD 5 (and also
> not in XBD 12, which would be another plausible place).

You missed XBD 12.1 list item 6?

> XBD 14.limits.h gives the minimum allowed value for the maximum value
> of an integer (2^31 - 1) (ie: requires at least 32 bit int), but I can
> find nothing that says explicitly that that applies to printf the utility.

LONG_MAX is the one that applies, via XCU 1.1.2.1 Arithmetic Precision
and Operations:

    Integer variables and constants, including the values of operands
    and option-arguments, used by the standard utilities listed in
    this volume of POSIX.1-2017 shall be implemented as equivalent to
    the ISO C standard signed long data type

> Further, since printf (the utility) is really just converting text
> strings from one format to another, there's really no reason that there
> needs to be any limit at all - there's no particular reason that integers
> thousands of digits long couldn't be handled.   The standard does say that
> if overflow occurs, an error message, and non-zero exit status, must
> occur, but it doesn't ever say that overflow must occur.

XCU 1.1.2.1 implies there must be an upper limit, since signed long in
ISO C is a fixed-width type. However, I suppose an implementation could
get around that by claiming printf works as if implemented in a C
programming environment where the number of hex digits in LONG_MAX is
greater than ARG_MAX, and thus a too-large value could never be passed
to (an external) printf.

> Second question - if overflow does occur (at whatever point) what is the
> value that must be printed (in addition to the error message) from a
> numeric conversion.
> 
[...]
> what the standard says is:
> 
>      If an argument operand cannot be completely converted into an internal
>      value appropriate to the corresponding conversion specification, a
>      diagnostic message shall be written to standard error and the utility
>      shall not exit with a zero exit status, but shall continue processing
>      any remaining operands and shall write the value accumulated at the
>      time the error was detected to standard output.
> 
> The question is, what is "the value accumulated at the time the error was
> detected".

That would obviously depend on internal implementation details. In
particular, digits could be processed left-to-right or right-to-left,
so the unused digits could be from either end.

> What zsh does is:
> 
>       zsh $ printf '%d\n' 0xffffc00000000000
>       zsh: number truncated after 15 digits: ffffc00000000000
>       1152917106560335872
> 
> which makes some sense to me, I had been thinking this might be the
> correct value, before I started testing to see what was produced.
> That is, after the first 15 hex digits are consumed, that is the value
> (0xffffc0000000000 in decimal) and then when an attempt is made to
> add one more zero, we detect the overflow, and so the value that had
> been accumulated when the overflow was detected was 1152917106560335872
> (when printed via %d).
> 
> The value "everybody" else prints, 9223372036854775807, is simply 2^63-1
> (the max possible value) which most likely was never actually encountered
> during the conversion, but is just what strtoll() returns as its value.

I think that's allowed, via the usual "as if" rule.  An implementor
could claim that printf is implemented as if the "accumulated" value
is simply incremented until converting it to a hex string produces the
same digits as were supplied, or the maximum representable accumulated
value is reached.

-- 
Geoff Clare <g.cl...@opengroup.org>
The Open Group, Apex Plaza, Forbury Road, Reading, RG1 1AX, England

Reply via email to