Blame otp-0010-Fix-decoding-of-LLONG_MIN-in-erl_decode.patch

Peter Lemenkov 35d916
From: =?UTF-8?q?Bj=C3=B6rn-Egil=20Dahlberg?= <egil@erlang.org>
Peter Lemenkov 35d916
Date: Fri, 10 Jun 2016 16:40:38 +0200
Peter Lemenkov 35d916
Subject: [PATCH] Fix decoding of LLONG_MIN in erl_decode
Peter Lemenkov 35d916
Peter Lemenkov 35d916
Reported-by: Peter Lemenkov
Peter Lemenkov 35d916
Peter Lemenkov 35d916
diff --git a/lib/erl_interface/src/legacy/erl_marshal.c b/lib/erl_interface/src/legacy/erl_marshal.c
Peter Lemenkov 35d916
index a4216c9..6a1b573 100644
Peter Lemenkov 35d916
--- a/lib/erl_interface/src/legacy/erl_marshal.c
Peter Lemenkov 35d916
+++ b/lib/erl_interface/src/legacy/erl_marshal.c
Peter Lemenkov 35d916
@@ -727,6 +727,13 @@ static ETERM *erl_decode_it(unsigned char **ext)
Peter Lemenkov 35d916
 	    ((*ext)[2]) << 8 |((*ext)[3]); 
Peter Lemenkov 35d916
 	*ext += 4;
Peter Lemenkov 35d916
     big_cont:
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
+#ifdef _MSC_VER
Peter Lemenkov 35d916
+#define MAX_TO_NEGATE 0x8000000000000000Ui64
Peter Lemenkov 35d916
+#else
Peter Lemenkov 35d916
+#define MAX_TO_NEGATE 0x8000000000000000ULL
Peter Lemenkov 35d916
+#endif
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
 	sign = *(*ext)++; 
Peter Lemenkov 35d916
 	if (arity > 8)             
Peter Lemenkov 35d916
 	    goto big_truncate;
Peter Lemenkov 35d916
@@ -763,23 +770,28 @@ static ETERM *erl_decode_it(unsigned char **ext)
Peter Lemenkov 35d916
 	    *ext += arity;
Peter Lemenkov 35d916
 	    return ep;
Peter Lemenkov 35d916
 	} else {
Peter Lemenkov 35d916
-	    /* Fits in a long long */
Peter Lemenkov 35d916
-	    int x;
Peter Lemenkov 35d916
-	    long long l = 0LL;
Peter Lemenkov 35d916
-
Peter Lemenkov 35d916
-	    for(x = 0 ; x < arity ; x++) {
Peter Lemenkov 35d916
-		l |= ((long long)(*ext)[x]) << ((long long)(8*x));
Peter Lemenkov 35d916
-	    }
Peter Lemenkov 35d916
-	    if (sign) {
Peter Lemenkov 35d916
-		l = -l;
Peter Lemenkov 35d916
-		if (l > 0) goto big_truncate;
Peter Lemenkov 35d916
-	    }
Peter Lemenkov 35d916
-
Peter Lemenkov 35d916
-	    ERL_TYPE(ep) = ERL_LONGLONG;
Peter Lemenkov 35d916
-	    ep->uval.llval.i = l;
Peter Lemenkov 35d916
-	    *ext += arity;
Peter Lemenkov 35d916
-	    return ep;
Peter Lemenkov 35d916
+            /* Fits in a signed long long */
Peter Lemenkov 35d916
+            int x;
Peter Lemenkov 35d916
+            unsigned long long l = 0LL;
Peter Lemenkov 35d916
+            long long sl;
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
+            for(x = 0 ; x < arity ; x++) {
Peter Lemenkov 35d916
+                l |= ((unsigned long long)(*ext)[x]) << ((unsigned long long)(8*x));
Peter Lemenkov 35d916
+            }
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
+            sl = (long long)l;
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
+            if (sign && l != MAX_TO_NEGATE) {
Peter Lemenkov 35d916
+                sl = -sl;
Peter Lemenkov 35d916
+                if (sl > 0) goto big_truncate;
Peter Lemenkov 35d916
+            }
Peter Lemenkov 35d916
+
Peter Lemenkov 35d916
+            ERL_TYPE(ep) = ERL_LONGLONG;
Peter Lemenkov 35d916
+            ep->uval.llval.i = sl;
Peter Lemenkov 35d916
+            *ext += arity;
Peter Lemenkov 35d916
+            return ep;
Peter Lemenkov 35d916
 	}
Peter Lemenkov 35d916
+#undef MAX_TO_NEGATE
Peter Lemenkov 35d916
     big_truncate: 
Peter Lemenkov 35d916
 	/* truncate to: (+/-) 1 */
Peter Lemenkov 35d916
 #ifdef DEBUG