Skip to content

Commit

Permalink
fix: quickjs-wasm-sys: properly handle shifts by 32 in libbf.c
Browse files Browse the repository at this point in the history
As reported upstream in bellard/quickjs#131:
shifting by `(LIMB_BITS - shift)` when `LIMB_BITS == 32` and `shift == 0`
produces wrong results on 32-bit targets.

This fix replaces all occurences of `(LIMB_BITS - shift)` with
calls to the existing helpers: `shld()` and `shrd`, which are
moved to the beginning of the file so that they are defined
before their new usages.

The helpers properly handle the cases when `shift` is zero.

Fixes issue 556
  • Loading branch information
ulan committed Dec 1, 2023
1 parent f3d6b6f commit 984b8d1
Showing 1 changed file with 22 additions and 23 deletions.
45 changes: 22 additions & 23 deletions crates/quickjs-wasm-sys/quickjs/libbf.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,22 @@ static inline slimb_t sat_add(slimb_t a, slimb_t b)
return r;
}

static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
{
if (shift != 0)
low = (low >> shift) | (high << (LIMB_BITS - shift));
return low;
}

static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
{
if (shift != 0)
return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
else
return a1;
}


#define malloc(s) malloc_is_forbidden(s)
#define free(p) free_is_forbidden(p)
#define realloc(p, s) realloc_is_forbidden(p, s)
Expand Down Expand Up @@ -236,7 +252,7 @@ int bf_set_ui(bf_t *r, uint64_t a)
a1 = a >> 32;
shift = clz(a1);
r->tab[0] = a0 << shift;
r->tab[1] = (a1 << shift) | (a0 >> (LIMB_BITS - shift));
r->tab[1] = shld(a1, a0, shift);
r->expn = 2 * LIMB_BITS - shift;
}
#endif
Expand Down Expand Up @@ -613,7 +629,7 @@ int bf_normalize_and_round(bf_t *r, limb_t prec1, bf_flags_t flags)
v = 0;
for(i = 0; i < l; i++) {
a = r->tab[i];
r->tab[i] = (a << shift) | (v >> (LIMB_BITS - shift));
r->tab[i] = shld(a, v, shift);
v = a;
}
r->expn -= shift;
Expand Down Expand Up @@ -1120,7 +1136,7 @@ static limb_t mp_shr(limb_t *tab_r, const limb_t *tab, mp_size_t n,
l = high;
for(i = n - 1; i >= 0; i--) {
a = tab[i];
tab_r[i] = (a >> shift) | (l << (LIMB_BITS - shift));
tab_r[i] = shrd(a, l, shift);
l = a;
}
return l & (((limb_t)1 << shift) - 1);
Expand Down Expand Up @@ -5392,21 +5408,6 @@ int bf_acos(bf_t *r, const bf_t *a, limb_t prec, bf_flags_t flags)

#endif /* LIMB_BITS != 64 */

static inline __maybe_unused limb_t shrd(limb_t low, limb_t high, long shift)
{
if (shift != 0)
low = (low >> shift) | (high << (LIMB_BITS - shift));
return low;
}

static inline __maybe_unused limb_t shld(limb_t a1, limb_t a0, long shift)
{
if (shift != 0)
return (a1 << shift) | (a0 >> (LIMB_BITS - shift));
else
return a1;
}

#if LIMB_DIGITS == 19

/* WARNING: hardcoded for b = 1e19. It is assumed that:
Expand Down Expand Up @@ -5766,7 +5767,7 @@ limb_t mp_div1_dec(limb_t *tabr, const limb_t *taba, mp_size_t na,
for(i = na - 1; i >= 0; i--) {
muldq(t1, t0, r, base);
adddq(t1, t0, 0, taba[i]);
t1 = (t1 << shift) | (t0 >> (LIMB_BITS - shift));
t1 = shld(t1, t0, shift);
t0 <<= shift;
q = udiv1norm(&r, t1, t0, b, b_inv);
r >>= shift;
Expand Down Expand Up @@ -8133,8 +8134,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
carry[j - (n_limb1 + 1)] = u[j];
} else {
for(j = n_limb1; j < nb_mods - 1; j++) {
carry[j - n_limb1] = (u[j] >> shift) |
(u[j + 1] << (LIMB_BITS - shift));
carry[j - n_limb1] = shrd(u[j], u[j + 1], shift);
}
carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
}
Expand Down Expand Up @@ -8234,8 +8234,7 @@ static no_inline void ntt_to_limb(BFNTTState *s, limb_t *tabr, limb_t r_len,
carry[j - (n_limb1 + 1)] = u[j];
} else {
for(j = n_limb1; j < nb_mods - 1; j++) {
carry[j - n_limb1] = (u[j] >> shift) |
(u[j + 1] << (LIMB_BITS - shift));
carry[j - n_limb1] = shrd(u[j], u[j + 1], shift);
}
carry[nb_mods - 1 - n_limb1] = u[nb_mods - 1] >> shift;
}
Expand Down

0 comments on commit 984b8d1

Please sign in to comment.