|
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
|