summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2025-05-16 19:59:40 -0700
committerKaz Kylheku <kaz@kylheku.com>2025-05-16 19:59:40 -0700
commitae09800483c3a5df8d31e400b7a3be87a9dc5814 (patch)
tree806f0dbe4e0411a7def5c1604ad9b94dacb9f4b2
parent410116deffa838061b8380f4d794a1b0ed12dbee (diff)
downloadtxr-ae09800483c3a5df8d31e400b7a3be87a9dc5814.tar.gz
txr-ae09800483c3a5df8d31e400b7a3be87a9dc5814.tar.bz2
txr-ae09800483c3a5df8d31e400b7a3be87a9dc5814.zip
arith: logtrunc: issues with short-circuiting to zero.
* arith.c (logtrunc): Firstly, the correct condition for trivially returning zero is bits <= 0, not bits < 0. Secondly, we don't want to do this upfront. In the case we have a struct with user-defined arithmetic, the method must be called. It might return a different kind of zero.
-rw-r--r--arith.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/arith.c b/arith.c
index ad7e3e69..a0d2ee10 100644
--- a/arith.c
+++ b/arith.c
@@ -3867,21 +3867,20 @@ bad:
val logtrunc(val a, val bits)
{
val self = logtrunc_s;
- cnum an, bn;
- val b;
const cnum num_mask = (NUM_MAX << 1) | 1;
if (!fixnump(bits))
goto bad2;
- bn = c_n(bits);
-
- if (bn < 0)
- return zero;
switch (type(a)) {
mp_err mpe;
+ cnum an, bn;
+ val b;
case NUM:
+ bn = c_n(bits);
+ if (bn <= 0)
+ return zero;
an = c_n(a);
if (bn <= NUM_BIT) {
cnum mask = num_mask >> (NUM_BIT - bn);
@@ -3890,6 +3889,9 @@ val logtrunc(val a, val bits)
a = bignum(an);
/* fallthrough */
case BGNUM:
+ bn = c_n(bits);
+ if (bn <= 0)
+ return zero;
b = make_ubignum();
if ((mpe = mp_trunc(mp(a), mp(b), bn)) != MP_OKAY)
do_mp_error(self, mpe);