aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLukas Larsson <[email protected]>2014-11-05 15:27:14 +0100
committerLukas Larsson <[email protected]>2014-11-05 15:27:14 +0100
commit0d18bf3268379df2b91e165a835426db77f015e3 (patch)
tree0f7adb74cf5ee963b95b4581b2c6f82ea039fd5c
parent0c23d76c650e3dca4935aaca2f2ea88b0e9a52ff (diff)
parent7513bb7670cf7081c4b70e240f99f9424b612f0b (diff)
downloadotp-0d18bf3268379df2b91e165a835426db77f015e3.tar.gz
otp-0d18bf3268379df2b91e165a835426db77f015e3.tar.bz2
otp-0d18bf3268379df2b91e165a835426db77f015e3.zip
Merge branch 'maint'
* maint: erts: Fix ub in list_to_integer and bignum div
-rw-r--r--erts/emulator/beam/bif.c8
-rw-r--r--erts/emulator/beam/big.c7
2 files changed, 8 insertions, 7 deletions
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 059f9f6c2c..49996e7f0b 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -2868,6 +2868,7 @@ static int do_list_to_integer(Process *p, Eterm orig_list,
Eterm *integer, Eterm *rest)
{
Sint i = 0;
+ Uint ui = 0;
int skip = 0;
int neg = 0;
int n = 0;
@@ -2921,8 +2922,8 @@ static int do_list_to_integer(Process *p, Eterm orig_list,
unsigned_val(CAR(list_val(lst))) > '9') {
break;
}
- i = i * 10;
- i = i + unsigned_val(CAR(list_val(lst))) - '0';
+ ui = ui * 10;
+ ui = ui + unsigned_val(CAR(list_val(lst))) - '0';
n++;
lst = CDR(list_val(lst));
if (is_nil(lst)) {
@@ -2946,7 +2947,8 @@ static int do_list_to_integer(Process *p, Eterm orig_list,
*/
if (n <= SMALL_DIGITS) { /* It must be small */
- if (neg) i = -i;
+ if (neg) i = -(Sint)ui;
+ else i = (Sint)ui;
res = make_small(i);
} else {
lg2 = (n+1)*230/69+1;
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index a8710dd910..de7d370938 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -274,10 +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))); \
+ /* If needed to avoid undefined behaviour */ \
+ if (_s) _un32 = (_a1 << _s) | ((_a0>>(D_EXP-_s)) & (-_s >> (D_EXP-1))); \
+ else _un32 = _a1; \
_un10 = _a0 << _s; \
_un1 = _un10 >> H_EXP; \
_un0 = _un10 & LO_MASK; \