diff options
author | Sverker Eriksson <[email protected]> | 2014-01-22 16:24:48 +0100 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2014-01-22 16:24:48 +0100 |
commit | af0227d7591bde8927ea95c93cbadee6b812b1d9 (patch) | |
tree | 023db83bb756fa0991ecd7e7e50b40a098e31726 | |
parent | 1b904fd1fcec000efb33446859e75872dc00ef2b (diff) | |
download | otp-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.c | 3 | ||||
-rw-r--r-- | erts/emulator/beam/big.h | 4 | ||||
-rw-r--r-- | erts/emulator/beam/utils.c | 5 |
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) { |