diff options
author | Björn Gustavsson <[email protected]> | 2018-12-13 10:22:36 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2018-12-13 10:22:36 +0100 |
commit | 2bf2b7009905a880f514621e8912508055df437e (patch) | |
tree | a8af26e339a45dbd5d6658d46c119078175c9ae6 /erts | |
parent | 3825199794da28d79b21052a2e69e2335921d55e (diff) | |
parent | c5bb52143bd28c8ce34e427dbf7f024b6e6a65e1 (diff) | |
download | otp-2bf2b7009905a880f514621e8912508055df437e.tar.gz otp-2bf2b7009905a880f514621e8912508055df437e.tar.bz2 otp-2bf2b7009905a880f514621e8912508055df437e.zip |
Merge pull request #2051 from bjorng/bjorn/erts/bignum/OTP-15484
Fix reading beyond end of bignum in integer squaring
Diffstat (limited to 'erts')
-rw-r--r-- | erts/emulator/beam/big.c | 12 | ||||
-rw-r--r-- | erts/emulator/test/big_SUITE.erl | 18 |
2 files changed, 22 insertions, 8 deletions
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c index 84338769e0..dac9574fa5 100644 --- a/erts/emulator/beam/big.c +++ b/erts/emulator/beam/big.c @@ -668,27 +668,25 @@ static dsize_t I_mul(ErtsDigit* x, dsize_t xl, ErtsDigit* y, dsize_t yl, ErtsDig static dsize_t I_sqr(ErtsDigit* x, dsize_t xl, ErtsDigit* r) { - ErtsDigit d_next = *x; ErtsDigit d; ErtsDigit* r0 = r; ErtsDigit* s = r; if ((r + xl) == x) /* "Inline" operation */ *x = 0; - x++; while(xl--) { - ErtsDigit* y = x; + ErtsDigit* y; ErtsDigit y_0 = 0, y_1 = 0, y_2 = 0, y_3 = 0; ErtsDigit b0, b1; ErtsDigit z0, z1, z2; ErtsDigit t; dsize_t y_l = xl; - + + d = *x; + x++; + y = x; s = r; - d = d_next; - d_next = *x; - x++; DMUL(d, d, b1, b0); DSUMc(*s, b0, y_3, t); diff --git a/erts/emulator/test/big_SUITE.erl b/erts/emulator/test/big_SUITE.erl index 0a42b09903..5b602dd4dc 100644 --- a/erts/emulator/test/big_SUITE.erl +++ b/erts/emulator/test/big_SUITE.erl @@ -168,7 +168,11 @@ eval({op,_,Op,A0,B0}, LFH) -> Res = eval_op(Op, A, B), erlang:garbage_collect(), Res; -eval({integer,_,I}, _) -> I; +eval({integer,_,I}, _) -> + %% "Parasitic" ("symbiotic"?) test of squaring all numbers + %% found in the test data. + test_squaring(I), + I; eval({call,_,{atom,_,Local},Args0}, LFH) -> Args = eval_list(Args0, LFH), LFH(Local, Args). @@ -192,6 +196,18 @@ eval_op('bxor', A, B) -> A bxor B; eval_op('bsl', A, B) -> A bsl B; eval_op('bsr', A, B) -> A bsr B. +test_squaring(I) -> + %% Multiplying an integer by itself is specially optimized, so we + %% should take special care to test squaring. The optimization + %% will kick in when the two operands have the same address. + Sqr = I * I, + + %% This expression will be multiplied in the usual way, because + %% the the two operands for '*' are stored at different addresses. + Sqr = I * ((I + id(1)) - id(1)), + + ok. + %% Built in test functions fac(0) -> 1; |