Index | Thread | Search

From:
蟹澤翔太 <zakinko@snowrabbit.org>
Subject:
Re: printf(3): "%#.0o" of 0 prints nothing instead of "0"
To:
Theo de Raadt <deraadt@openbsd.org>
Cc:
tech@openbsd.org
Date:
Mon, 14 Sep 2026 19:50:18 +0900

Download raw body.

Thread
Thanks for the quick reply.  Of the three you named, the kernel copy
has the same bug; the other two don't.

sys/kern/subr_prf.c (kprintf) is not shrunk in this respect -- it has
the same code as libc, the "if (_uquad != 0 || prec != 0)" test with
the octal leading-0 step inside it, so "%#.0o" of 0 prints nothing
there too.  Diff below.

sys/lib/libsa/printf.c (bootblocks) is shrunk past where it matters:
no precision and no # handling for octal, so "%#.0o" can't reach the
bug -- the flag is ignored and it prints the digits.

libexec/ld.so/util.c (_dl_printf) is the same: no precision, no #,
nothing to fix.

I only looked at those three, not the whole tree.

I built GENERIC.MP with the diff -- it compiles clean.  Pulling the
octal block out of subr_prf.c into a small harness, the stock code
prints [] for "%#.0o" of 0 and the patched code prints [0]; "%#.0o" of
8 -> [010], "%.0o" of 0 -> [], and "%#o" of 0 -> [0] are unchanged
either way.  Same one-line change I made in libc, built on 7.9 and
checked the same way.

Index: sys/kern/subr_prf.c
===================================================================
--- sys/kern/subr_prf.c.orig
+++ sys/kern/subr_prf.c
@@ -960,7 +960,8 @@
 			 *	-- ANSI X3J11
 			 */
 			cp = buf + KPRINTF_BUFSIZE;
-			if (_uquad != 0 || prec != 0) {
+			if (_uquad != 0 || prec != 0 ||
+			    (flags & ALT && base == OCT)) {
 				/*
 				 * Unsigned mod is hard, and unsigned mod
 				 * by a constant is easier than that by

> 2026/09/11 10:13、Theo de Raadt <deraadt@openbsd.org>のメール:
> 
> Please check for other clones of printf in the tree.  There is one
> in kernel, one in bootblocks, one in ld.so.  There may be others.
> These have all been shrunk, but maybe it matters.