aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/test/big_SUITE.erl
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2018-12-12 14:53:40 +0100
committerBjörn Gustavsson <[email protected]>2018-12-13 10:20:41 +0100
commitc5bb52143bd28c8ce34e427dbf7f024b6e6a65e1 (patch)
treea8af26e339a45dbd5d6658d46c119078175c9ae6 /erts/emulator/test/big_SUITE.erl
parent3825199794da28d79b21052a2e69e2335921d55e (diff)
downloadotp-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/big_SUITE.erl')
-rw-r--r--erts/emulator/test/big_SUITE.erl18
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;