diff options
author | Lukas Larsson <[email protected]> | 2014-11-05 15:27:14 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2014-11-05 15:27:14 +0100 |
commit | 0d18bf3268379df2b91e165a835426db77f015e3 (patch) | |
tree | 0f7adb74cf5ee963b95b4581b2c6f82ea039fd5c | |
parent | 0c23d76c650e3dca4935aaca2f2ea88b0e9a52ff (diff) | |
parent | 7513bb7670cf7081c4b70e240f99f9424b612f0b (diff) | |
download | otp-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.c | 8 | ||||
-rw-r--r-- | erts/emulator/beam/big.c | 7 |
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; \ |