NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
lib/60708: lib/: printf(3) leaves a positional %F argument untyped
>Number: 60708
>Category: lib
>Synopsis: printf(3) leaves a positional %F argument untyped, so "%1$F" prints the wrong value
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Sep 10 17:45:00 +0000 2026
>Originator: Showta Ishizaki
>Release: NetBSD 11.0 (the code is the same in -current)
>Organization:
>Environment:
System: NetBSD 11.0 amd64
Architecture: x86_64
Machine: amd64
>Description:
When a format uses positional arguments (n$), vfprintf(3) first walks
the format with __find_arguments() to learn the type of every argument,
and then reads them from a table. That walk, in lib/libc/stdio/
vfwprintf.c, lists the floating-point conversions as
case 'a':
case 'A':
case 'e':
case 'E':
case 'f':
case 'g':
case 'G':
and leaves out F. A double that is only referred to through %F never
gets a type, so its slot in the table stays zero and the conversion
prints a zero:
printf("%1$F", -INFINITY) -> 0.000000
printf("%1$F", 1.5) -> 0.000000
printf("%F", 1.5) -> 1.500000
The same format with %1$f, or with %1$F next to any other conversion of
the same argument, works, because those give the argument its type.
The conversion switch itself already knows F (it sits next to 'f' at
line 1115), so only the type scan is missing it.
abseil's str_format test caught this on NetBSD: it prints "%1$*2$F" and
compares against the C library.
>How-To-Repeat:
#include <stdio.h>
#include <math.h>
int main(void) {
printf("[%1$F]\n", -INFINITY);
printf("[%1$F]\n", 1.5);
printf("[%F]\n", 1.5);
return 0;
}
prints
[0.000000]
[0.000000]
[1.500000]
and the first two should be [-INF] and [1.500000].
>Fix:
Add 'F' to the list in __find_arguments(). The diff is against trunk
and applies to the netbsd-11 file as well.
--- lib/libc/stdio/vfwprintf.c.orig
+++ lib/libc/stdio/vfwprintf.c
@@ -1727,6 +1727,7 @@
case 'e':
case 'E':
case 'f':
+ case 'F':
case 'g':
case 'G':
if (flags & LONGDBL)
Checked by building lib/libc from the 11.0 source sets with this change
and running the program above against the new libc.so.12 through
LD_LIBRARY_PATH: it prints [-INF], [1.500000], [1.500000], and the
system libc still prints the zeros. Not built on -current.
FreeBSD and DragonFly have the same omission in their printf-pos.c and
I am reporting it there separately; OpenBSD's vfprintf.c has the F.
Home |
Main Index |
Thread Index |
Old Index