aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2014-01-22 16:24:48 +0100
committerSverker Eriksson <[email protected]>2014-01-22 16:24:48 +0100
commitaf0227d7591bde8927ea95c93cbadee6b812b1d9 (patch)
tree023db83bb756fa0991ecd7e7e50b40a098e31726
parent1b904fd1fcec000efb33446859e75872dc00ef2b (diff)
downloadotp-af0227d7591bde8927ea95c93cbadee6b812b1d9.tar.gz
otp-af0227d7591bde8927ea95c93cbadee6b812b1d9.tar.bz2
otp-af0227d7591bde8927ea95c93cbadee6b812b1d9.zip
erts: Fix crash when comparing very large floats with integers
big_buf was one word too short on 32-bit emulators causing memory corruption. Seems like this did not cause a problem before the ESTACK memory layout was changed in 172ebf11dc455e22b87f.
-rw-r--r--erts/emulator/beam/big.c3
-rw-r--r--erts/emulator/beam/big.h4
-rw-r--r--erts/emulator/beam/utils.c5
3 files changed, 7 insertions, 5 deletions
diff --git a/erts/emulator/beam/big.c b/erts/emulator/beam/big.c
index 4343c6cb4c..41a041eba6 100644
--- a/erts/emulator/beam/big.c
+++ b/erts/emulator/beam/big.c
@@ -1607,7 +1607,7 @@ big_to_double(Wterm x, double* resp)
* HALFWORD: Return relative term with 'heap' as base.
*/
Eterm
-double_to_big(double x, Eterm *heap)
+double_to_big(double x, Eterm *heap, Uint hsz)
{
int is_negative;
int ds;
@@ -1638,6 +1638,7 @@ double_to_big(double x, Eterm *heap)
res = make_big_rel(hp, heap);
xp = (ErtsDigit*) (hp + 1);
+ ASSERT(ds < hsz);
for (i = ds - 1; i >= 0; i--) {
ErtsDigit d;
diff --git a/erts/emulator/beam/big.h b/erts/emulator/beam/big.h
index 1a7b14170f..d80111822e 100644
--- a/erts/emulator/beam/big.h
+++ b/erts/emulator/beam/big.h
@@ -1,7 +1,7 @@
/*
* %CopyrightBegin%
*
- * Copyright Ericsson AB 1996-2013. All Rights Reserved.
+ * Copyright Ericsson AB 1996-2014. All Rights Reserved.
*
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
@@ -141,7 +141,7 @@ Eterm big_lshift(Eterm, Sint, Eterm*);
int big_comp (Wterm, Wterm);
int big_ucomp (Eterm, Eterm);
int big_to_double(Wterm x, double* resp);
-Eterm double_to_big(double, Eterm*);
+Eterm double_to_big(double, Eterm*, Uint hsz);
Eterm small_to_big(Sint, Eterm*);
Eterm uint_to_big(Uint, Eterm*);
Eterm uword_to_big(UWord, Eterm*);
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index 86bb5fd3ad..e0776cf67d 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -2688,7 +2688,6 @@ tailrecur_ne:
{
FloatDef f1, f2;
Eterm big;
- Eterm big_buf[32];
#if HALFWORD_HEAP
Wterm aw = is_immed(a) ? a : rterm2wterm(a,a_base);
Wterm bw = is_immed(b) ? b : rterm2wterm(b,b_base);
@@ -2699,6 +2698,8 @@ tailrecur_ne:
#define MAX_LOSSLESS_FLOAT ((double)((1LL << 53) - 2))
#define MIN_LOSSLESS_FLOAT ((double)(((1LL << 53) - 2)*-1))
#define BIG_ARITY_FLOAT_MAX (1024 / D_EXP) /* arity of max float as a bignum */
+ Eterm big_buf[BIG_NEED_SIZE(BIG_ARITY_FLOAT_MAX)];
+
b_tag = tag_val_def(bw);
switch(_NUMBER_CODE(a_tag, b_tag)) {
@@ -2761,7 +2762,7 @@ tailrecur_ne:
j = float_comp(f1.fd, f2.fd);
}
} else {
- big = double_to_big(f2.fd, big_buf);
+ big = double_to_big(f2.fd, big_buf, sizeof(big_buf)/sizeof(Eterm));
j = big_comp(aw, rterm2wterm(big,big_buf));
}
if (_NUMBER_CODE(a_tag, b_tag) == FLOAT_BIG) {