diff options
author | Björn-Egil Dahlberg <[email protected]> | 2016-06-13 11:12:04 +0200 |
---|---|---|
committer | Björn-Egil Dahlberg <[email protected]> | 2016-06-13 11:12:04 +0200 |
commit | d71195359ad79134b9333d4467d2748d49e8b018 (patch) | |
tree | fe4b8b4f875a656682a1546a7a7e99c31b0312ad | |
parent | 261866ff36c80942c8cf309ac6603b36127d5673 (diff) | |
parent | e2263999247487be70049b0c05223dd54c5a1681 (diff) | |
download | otp-d71195359ad79134b9333d4467d2748d49e8b018.tar.gz otp-d71195359ad79134b9333d4467d2748d49e8b018.tar.bz2 otp-d71195359ad79134b9333d4467d2748d49e8b018.zip |
Merge branch 'egil/erl_interface/fix-decode-longlong/ERL-158/OTP-13666'
* egil/erl_interface/fix-decode-longlong/ERL-158/OTP-13666:
Fix decoding of LLONG_MIN in erl_decode
-rw-r--r-- | lib/erl_interface/src/legacy/erl_marshal.c | 40 |
1 files changed, 26 insertions, 14 deletions
diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c index 3c212bf177..2bdf5f2134 100644 --- a/lib/erl_interface/src/legacy/erl_marshal.c +++ b/lib/erl_interface/src/legacy/erl_marshal.c @@ -767,6 +767,13 @@ static ETERM *erl_decode_it(unsigned char **ext) ((*ext)[2]) << 8 |((*ext)[3]); *ext += 4; big_cont: + +#ifdef _MSC_VER +#define MAX_TO_NEGATE 0x8000000000000000Ui64 +#else +#define MAX_TO_NEGATE 0x8000000000000000ULL +#endif + sign = *(*ext)++; if (arity > 8) goto big_truncate; @@ -803,23 +810,28 @@ static ETERM *erl_decode_it(unsigned char **ext) *ext += arity; return ep; } else { - /* Fits in a long long */ - int x; - long long l = 0LL; + /* Fits in a signed long long */ + int x; + unsigned long long l = 0LL; + long long sl; - for(x = 0 ; x < arity ; x++) { - l |= ((long long)(*ext)[x]) << ((long long)(8*x)); - } - if (sign) { - l = -l; - if (l > 0) goto big_truncate; - } + for(x = 0 ; x < arity ; x++) { + l |= ((unsigned long long)(*ext)[x]) << ((unsigned long long)(8*x)); + } - ERL_TYPE(ep) = ERL_LONGLONG; - ep->uval.llval.i = l; - *ext += arity; - return ep; + sl = (long long)l; + + if (sign && l != MAX_TO_NEGATE) { + sl = -sl; + if (sl > 0) goto big_truncate; + } + + ERL_TYPE(ep) = ERL_LONGLONG; + ep->uval.llval.i = sl; + *ext += arity; + return ep; } +#undef MAX_TO_NEGATE big_truncate: /* truncate to: (+/-) 1 */ #ifdef DEBUG |