diff options
author | Björn Gustavsson <[email protected]> | 2018-12-12 14:53:40 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2018-12-13 10:20:41 +0100 |
commit | c5bb52143bd28c8ce34e427dbf7f024b6e6a65e1 (patch) | |
tree | a8af26e339a45dbd5d6658d46c119078175c9ae6 /erts/emulator/test | |
parent | 3825199794da28d79b21052a2e69e2335921d55e (diff) | |
download | otp-c5bb52143bd28c8ce34e427dbf7f024b6e6a65e1.tar.gz otp-c5bb52143bd28c8ce34e427dbf7f024b6e6a65e1.tar.bz2 otp-c5bb52143bd28c8ce34e427dbf7f024b6e6a65e1.zip |
Fix reading beyond end of bignum in integer squaring
The multiplication of two bignums is specially optimized when the two
operands have the same address, because squaring can be done more
efficiently than multiplication of two arbitrary integers. That is,
expressions such as `I * I` will be calculated by squaring the value
of `I`.
The optimized function for squaring would read one word beyond the
end of the bignum in the last iteration of a loop. The garbage
value would never be used. In almost all circumstances that would
be harmless. Only if the read word happened to fall on the start
of an unmapped page would the runtime crash. That is unlikely
to happen because most bignums are stored on a process heap, and
since the stack is located at the other end of the block that the
heap is located in, the word beyond the end of bignum is guaranteed
to be readable.
Diffstat (limited to 'erts/emulator/test')
-rw-r--r-- | erts/emulator/test/big_SUITE.erl | 18 |
1 files changed, 17 insertions, 1 deletions
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; |