Skip to content

Commit 720f6d0

Browse files
committed
Safe shift
Signed-off-by: Davide Bettio <davide@uninstall.it>
1 parent 72067e3 commit 720f6d0

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

src/libAtomVM/bif.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,8 +1523,9 @@ static inline int32_t int32_bsr(int32_t n, unsigned int rshift)
15231523
static inline bool int32_bsl_overflow(int32_t n, unsigned int lshift, int32_t *out)
15241524
{
15251525
//
1526-
if ((n != 0) && (lshift > 64)) {
1527-
return true;
1526+
if ((n != 0) && (lshift > 32)) {
1527+
*out = 0;
1528+
return (n != 0);
15281529
}
15291530
//
15301531

@@ -1533,6 +1534,14 @@ static inline bool int32_bsl_overflow(int32_t n, unsigned int lshift, int32_t *o
15331534
int32_t check = int32_bsr(res, lshift);
15341535
return check != n;
15351536
}
1537+
1538+
static inline int32_t int32_bsr_safe(int32_t n, unsigned int rshift)
1539+
{
1540+
if (rshift > 32) {
1541+
return n < 0 ? -1 : 0;
1542+
}
1543+
return int32_bsr(n, rshift);
1544+
}
15361545
#endif
15371546

15381547
static inline int64_t int64_bsr(int64_t n, unsigned int rshift)
@@ -1543,8 +1552,9 @@ static inline int64_t int64_bsr(int64_t n, unsigned int rshift)
15431552
static inline bool int64_bsl_overflow(int64_t n, unsigned int lshift, int64_t *out)
15441553
{
15451554
//
1546-
if ((n != 0) && (lshift > 64)) {
1547-
return true;
1555+
if (lshift > 64) {
1556+
*out = 0;
1557+
return (n != 0);
15481558
}
15491559
//
15501560

@@ -1554,6 +1564,14 @@ static inline bool int64_bsl_overflow(int64_t n, unsigned int lshift, int64_t *o
15541564
return check != n;
15551565
}
15561566

1567+
static inline int64_t int64_bsr_safe(int64_t n, unsigned int rshift)
1568+
{
1569+
if (rshift > 64) {
1570+
return n < 0 ? -1 : 0;
1571+
}
1572+
return int64_bsr(n, rshift);
1573+
}
1574+
15571575
term bif_erlang_bsl_2(Context *ctx, uint32_t fail_label, int live, term arg1, term arg2)
15581576
{
15591577
if (LIKELY(term_is_any_integer(arg1) && term_is_any_integer(arg2))) {
@@ -1610,7 +1628,7 @@ term bif_erlang_bsr_2(Context *ctx, uint32_t fail_label, int live, term arg1, te
16101628

16111629
if (arg1_size <= BOXED_TERMS_REQUIRED_FOR_INT64) {
16121630
uint64_t a = (uint64_t) term_maybe_unbox_int64(arg1);
1613-
int64_t result = (int64_t) (a >> b); //FIX THIS
1631+
int64_t result = int64_bsr_safe(a, b);
16141632

16151633
#if BOXED_TERMS_REQUIRED_FOR_INT64 > 1
16161634
return make_maybe_boxed_int64(ctx, fail_label, live, result);

0 commit comments

Comments
 (0)