aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam
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/beam
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/beam')
-rw-r--r--erts/emulator/beam/big.c12
1 files changed, 5 insertions, 7 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);