|
|
Message-ID: <20260805075236.3509669-1-matthias.goergens@gmail.com>
Date: Wed, 5 Aug 2026 15:52:36 +0800
From: Matthias Goergens <matthias.goergens@...il.com>
To: musl@...ts.openwall.com
Cc: Matthias Goergens <matthias.goergens@...il.com>
Subject: [PATCH] stdio: reserve leading limb for floating-point rounding
In the negative-exponent path of floating-point formatting, a value
just below one can round up to one. The logical layout then starts at
big[0], so propagating the final rounding carry would form and
dereference a pointer one element before the array. One reachable case
is printf("%.0Lf", nextafterl(1.0L, 0.0L)).
Reserve one physical leading limb and start the negative-exponent
layout at big+1, leaving big[0] for the single rounding carry. The
carry cannot need a second new limb: insertion increments a zero limb
to one and terminates. The positive-exponent layout is computed from
the enlarged array end, so its distances to both array ends are
unchanged and all logical pointer differences used by formatting are
preserved.
Formatted output is unchanged: the 62,304-case corpus and the extrema
matrices are byte-identical before and after, on all three musl
long-double representations (x87 64-bit mantissa, 53-bit, and
binary128).
---
src/stdio/vfprintf.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c
index 514a44dd..bfbcf094 100644
--- a/src/stdio/vfprintf.c
+++ b/src/stdio/vfprintf.c
@@ -182,11 +182,12 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps)
{
int max_mant_dig = (ps==BIGLPRE) ? LDBL_MANT_DIG : DBL_MANT_DIG;
int max_exp = (ps==BIGLPRE) ? LDBL_MAX_EXP : DBL_MAX_EXP;
- /* One slot for 29 bits left of radix point, a slot for every 29-21=8
- * bits right of the radix point, and one final zero slot. */
+ /* One slot for a rounding carry, one for 29 bits left of radix point,
+ * a slot for every 29-21=8 bits right of the radix point, and one final
+ * zero slot. */
int max_mant_slots = 1 + (max_mant_dig-29+7)/8 + 1;
int max_exp_slots = (max_exp+max_mant_dig+28+8)/9;
- int bufsize = max_mant_slots + max_exp_slots;
+ int bufsize = 1 + max_mant_slots + max_exp_slots;
uint32_t big[bufsize];
uint32_t *a, *d, *r, *z;
int e2=0, e, i, j, l;
@@ -267,7 +268,7 @@ static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t, int ps)
if (y) y *= 0x1p28, e2-=28;
- if (e2<0) a=r=z=big;
+ if (e2<0) a=r=z=big+1;
else a=r=z=big+sizeof(big)/sizeof(*big) - max_mant_slots - 1;
do {
--
2.55.0
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.