aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/big.c
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-08-14 09:44:29 +0200
committerLukas Larsson <[email protected]>2014-08-14 09:44:29 +0200
commit9de7cc7f881b5df18d0a26f7d37af164bc0c390e (patch)
treeb72c97468a188307915f707f0d2133f719719f0d /erts/emulator/beam/big.c
parent8fe6c462ec8e20ab2ad14b0c1addf1030ada0e54 (diff)
parent9d3c22934491afe85fbcf8543ae43fb2eb1ab387 (diff)
downloadotp-9de7cc7f881b5df18d0a26f7d37af164bc0c390e.tar.gz
otp-9de7cc7f881b5df18d0a26f7d37af164bc0c390e.tar.bz2
otp-9de7cc7f881b5df18d0a26f7d37af164bc0c390e.zip
Merge branch 'lukas/erts/fix_neg_of_int64_min/OTP-12097' into maint
* lukas/erts/fix_neg_of_int64_min/OTP-12097: erts: Fix neg int overflow when sint is min size
Diffstat (limited to 'erts/emulator/beam/big.c')
-rw-r--r--erts/emulator/beam/big.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 4d087bf967..e62caa6b22 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -274,6 +274,9 @@
_b = _b << _s; \
_vn1 = _b >> H_EXP; \
_vn0 = _b & LO_MASK; \
+ /* Sometimes _s is 0 which triggers undefined behaviour for the \
+ (_a0>>(D_EXP-_s)) shift, but this is ok because the \
+ & -s will make it all to 0 later anyways. */ \
_un32 = (_a1 << _s) | ((_a0>>(D_EXP-_s)) & (-_s >> (D_EXP-1))); \
_un10 = _a0 << _s; \
_un1 = _un10 >> H_EXP; \
@@ -1542,21 +1545,24 @@ Eterm erts_uint64_to_big(Uint64 x, Eterm **hpp)
Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp)
{
Eterm *hp = *hpp;
+ Uint64 ux;
int neg;
- if (x >= 0)
+ if (x >= 0) {
neg = 0;
+ ux = x;
+ }
else {
neg = 1;
- x = -x;
+ ux = -(Uint64)x;
}
#if defined(ARCH_32) || HALFWORD_HEAP
- if (x >= (((Uint64) 1) << 32)) {
+ if (ux >= (((Uint64) 1) << 32)) {
if (neg)
*hp = make_neg_bignum_header(2);
else
*hp = make_pos_bignum_header(2);
- BIG_DIGIT(hp, 0) = (Uint) (x & ((Uint) 0xffffffff));
- BIG_DIGIT(hp, 1) = (Uint) ((x >> 32) & ((Uint) 0xffffffff));
+ BIG_DIGIT(hp, 0) = (Uint) (ux & ((Uint) 0xffffffff));
+ BIG_DIGIT(hp, 1) = (Uint) ((ux >> 32) & ((Uint) 0xffffffff));
*hpp += 3;
}
else
@@ -1566,7 +1572,7 @@ Eterm erts_sint64_to_big(Sint64 x, Eterm **hpp)
*hp = make_neg_bignum_header(1);
else
*hp = make_pos_bignum_header(1);
- BIG_DIGIT(hp, 0) = (Uint) x;
+ BIG_DIGIT(hp, 0) = (Uint) ux;
*hpp += 2;
}
return make_big(hp);