NetBSD Problem Report #56937
From kre@munnari.OZ.AU Fri Jul 22 13:13:48 2022
Return-Path: <kre@munnari.OZ.AU>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id CA5911A9239
for <gnats-bugs@gnats.NetBSD.org>; Fri, 22 Jul 2022 13:13:48 +0000 (UTC)
Message-Id: <202207221045.26MAjDmB002514@jacaranda.noi.kre.to>
Date: Fri, 22 Jul 2022 17:45:13 +0700 (+07)
From: kre@munnari.OZ.AU
Reply-To:
To: gnats-bugs@NetBSD.org
Subject: printf(3) long double %a formatting is broken
X-Send-Pr-Version: 3.95
>Number: 56937
>Category: lib
>Synopsis: printf(3) long double %a formatting is broken
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: lib-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Fri Jul 22 13:15:00 +0000 2022
>Originator: kre@munnari.OZ.AU
>Release: NetBSD 9.99.99
>Organization:
>Environment:
System: NetBSD jacaranda.noi.kre.to 9.99.99 NetBSD 9.99.99 (JACARANDA:1.1-20220718) #0: Tue Jul 19 03:35:07 +07 2022 kre@jacaranda.noi.kre.to:/usr/obj/testing/kernels/amd64/JACARANDA amd64
Architecture: x86_64
Machine: amd64
>Description:
When printf(3) is asked to print a long double (flost) in %a format
(eg: printf("%La", (long double)1.0); ) It includes a bit set in the
result that should not be there.
>How-To-Repeat:
You can write code easily to test this (I did), but a simple way
is to install (of not already done) any version (well, recentish)
of bash ans use its builtin printf(1) - bash uses long double for
floats in its arithmetic
jacaranda$ printf %a\\n 1
0x8.8p-3
jacaranda$ /usr/bin/printf %a\\n 1
0x1p+0
The first of those is from bash, and is clearly nonsense, no
matter how you express it, the floating point representation
of 1 has (at most) 1 bit set (in its mantissa), not two.
The second is NetBSD's printf, which uses regular double for
its floats, and is correct.
Note that the difference between 0x8p-3 and 0x1p+0 is
irrelevant - either is acceptable (those values represent the
same thing).
Similarly, from bash:
jacaranda$ printf '%a ' 1.5 1.25 1.125 1.0625 ; printf \\n
0x8.cp-3 0x8.ap-3 0x8.9p-3 0x8.88p-3
Those values should all have 2 bits set, not the 3 shown.
And they do when it is just a double being printed:
jacaranda$ /usr/bin/printf '%a ' 1.5 1.25 1.125 1.0625 ; printf \\n
0x1.8p+0 0x1.4p+0 0x1.2p+0 0x1.1p+0
You can repeat all of this using a simple C program, to demonstrate
that the problem is not internal to bash somewhere (which is
what I first assumed).
The internal format difference between double and long double
should not be altering the representation (in this form) of any
of these values, the extra precision or range is not relevant.
All the other conversions (%e %f %g) seem fine, as does parsing
floats in any of the formats they're allowed - including converting
0xX.XXXp[+-]N into float/double/long double.
>Fix:
I spent some time hunting in src/lib/libc/gdtoa/hdtoa.c
which is where I think the problem occurs, but ...
(It doesn't help that I don't know either IEEE or x87
floating point representations almost at all).
(Contact us)
$NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.