aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2016-07-08 16:41:22 +0200
committerSverker Eriksson <[email protected]>2016-07-08 16:41:22 +0200
commit3585c1e6832083acbfc130c0aafc8f2db2f3f706 (patch)
tree5e2e73ae6b662c3d33a20928875461260c023159
parent0573efbc18fc20f8646cf3ff64d2affd06e03cb8 (diff)
downloadotp-3585c1e6832083acbfc130c0aafc8f2db2f3f706.tar.gz
otp-3585c1e6832083acbfc130c0aafc8f2db2f3f706.tar.bz2
otp-3585c1e6832083acbfc130c0aafc8f2db2f3f706.zip
erts: Fix GC overrun bug in 'bsl' op with small Op1
Symptom: VM abort "Overrun stack and heap" Problem: The temporary bignum created in buffer tmp_big[] will be part of the GC initiated by TestHeapPreserve, but its size is not included which can cause the GC to overflow if very unlucky. Solution: Do not include tmp_big in the GC.
-rw-r--r--erts/emulator/beam/beam_emu.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/erts/emulator/beam/beam_emu.c b/erts/emulator/beam/beam_emu.c
index 4716460a6b..c6258287c4 100644
--- a/erts/emulator/beam/beam_emu.c
+++ b/erts/emulator/beam/beam_emu.c
@@ -3032,6 +3032,7 @@ do { \
if (i == 0) {
StoreBifResult(4, Op1);
}
+ ires = big_size(Op1);
goto big_shift;
}
} else if (is_big(Op2)) {
@@ -3047,7 +3048,6 @@ do { \
OpCase(i_bsl_jIssd):
GetArg2(2, Op1, Op2);
-
do_bsl:
if (is_small(Op2)) {
i = signed_val(Op2);
@@ -3073,16 +3073,12 @@ do { \
StoreBifResult(4, Op1);
}
}
- Op1 = small_to_big(ires, tmp_big);
-#ifdef TAG_LITERAL_PTR
- Op1 |= TAG_LITERAL_PTR;
-#endif
+ ires = 1; /* big_size(small_to_big(Op1)) */
big_shift:
if (i > 0) { /* Left shift. */
- ires = big_size(Op1) + (i / D_EXP);
+ ires += (i / D_EXP);
} else { /* Right shift. */
- ires = big_size(Op1);
if (ires <= (-i / D_EXP))
ires = 3; /* ??? */
else
@@ -3101,6 +3097,9 @@ do { \
goto lb_Cl_error;
}
TestHeapPreserve(ires+1, Arg(1), Op1);
+ if (is_small(Op1)) {
+ Op1 = small_to_big(signed_val(Op1), tmp_big);
+ }
bigp = HTOP;
Op1 = big_lshift(Op1, i, bigp);
if (is_big(Op1)) {
@@ -3123,6 +3122,7 @@ do { \
if (i == 0) {
StoreBifResult(4, Op1);
}
+ ires = big_size(Op1);
goto big_shift;
}
} else if (is_big(Op2)) {