aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2016-06-13 11:12:04 +0200
committerBjörn-Egil Dahlberg <[email protected]>2016-06-13 11:12:04 +0200
commitd71195359ad79134b9333d4467d2748d49e8b018 (patch)
treefe4b8b4f875a656682a1546a7a7e99c31b0312ad /lib
parent261866ff36c80942c8cf309ac6603b36127d5673 (diff)
parente2263999247487be70049b0c05223dd54c5a1681 (diff)
downloadotp-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
Diffstat (limited to 'lib')
-rw-r--r--lib/erl_interface/src/legacy/erl_marshal.c40
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