aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn-Egil Dahlberg <[email protected]>2016-06-10 16:40:38 +0200
committerBjörn-Egil Dahlberg <[email protected]>2016-06-13 11:10:16 +0200
commite2263999247487be70049b0c05223dd54c5a1681 (patch)
treea542e89441416a71f59587436ae527cf38457742
parent78eeb8b231791c23c40ea6c653ef2962bc52ba6f (diff)
downloadotp-e2263999247487be70049b0c05223dd54c5a1681.tar.gz
otp-e2263999247487be70049b0c05223dd54c5a1681.tar.bz2
otp-e2263999247487be70049b0c05223dd54c5a1681.zip
Fix decoding of LLONG_MIN in erl_decode
Reported-by: Peter Lemenkov
-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