Re: bug with printf positional arguments?
Corinna Vinschen <[email protected]>
| Newsgroups | gmane.comp.lib.newlib |
|---|---|
| Message-ID | <ZMEfInC5pnRaPmS/@calimero.vinschen.de> |
On Jul 3 15:49, Jon Turney wrote:
> On 03/07/2023 12:14, Corinna Vinschen wrote:
> > On Jun 28 14:28, Jon Turney wrote:
> > >
> > > The following trivial program (extracted from a glib testcase)
> > >
> > > > #include <stdio.h>
> > > >
> > > > int main()
> > > > {
> > > > printf ("%1$*2$.*3$s", "abc", 5, 2);
> > > > }
> > >
> > > does not produce the expected output of " ab", on 64-bit Cygwin.
> > >
> > > From a bit of staring at and stepping through get_args() in
> > > libc/stdio/vfprintf.c, it looks like the problem is (something like) we
> > > don't have the knowledge that the first positional variadic argument should
> > > be treated as a pointer, at the point that we store it's value, so it gets
> > > treated as an integer (the default), which is going to lead to truncation on
> > > LP64 platforms.
> > >
> > > A straightforward way to fix this eludes me.
> >
> > Can you point out where in the code this problem occurs, so maybe
> > we can discuss the necessary code changes in this thread?
>
> Sure, I'll try:
>
> Let's suppose you're executing the STC above. This is what I think
> happens...
>
> We end up in _vprintf_r.
>
> We hit line 1072, which digests the '1', and on the following '$', knows to
> interpret this as a positional argument and stores it.
>
> The subsequent '*' is processed at line 967 as introducing the width, where
> we chomp the '2', which again the following '$' indicates should be treated
> as a positional arg.
>
> We hit GET_ARG for the first time, to retrieve the width, which invokes
> get_arg() to do the work (as we haven't yet stored the requested arg in
> args[]).
>
> get_arg() digests the format string (again) using a state machine (to
> populate args[] with the positional parameters)
>
> The state machine moves through START (action NUMBER) -> WDIG (action
> GETPOS) -> DONE.
>
> Stopping here looks like maybe an error in the state machine design?
>
> The loop starting at line 2310 iterates over the seen args, fetching their
> values. Because we haven't processed the 's' at the end in the GETARG state,
> we retrieve the first argument using the default case, as an integer (32
> bits, truncating the 64-bit pointer value) (it looks like we're maybe also
> lucking out on handling the width properly, as we're never hitting the PWPOS
> state to record that it should be treated as an INT).
After going a bit cross-eyed looking at the code, I *seriously* wonder,
if we shouldn't start with fresh vfprintf_r/vfwprintf_r, using copies of
the most recent FreeBSD vfprintf/vfwprintf, and just carefully tweak them
to match our build system...
Corinna