Blob Blame History Raw
From 454bea87cff4ff3cd2fd9ae34a3718dd200ce0fb Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Sun, 17 Mar 2019 11:34:04 +0530
Subject: [PATCH 69/72] Guard against undefined behaviour when casting from
 float to unsigned

Only range (-1.0, UINT64_MAX) can be safely converted to unsigned
directly, and (-INT64_MAX,INT_64_MAX) through a cast to int64_t first.
The remaining range is undefined.

TODO: Do the same for JIT as well as for float to other ranges.
---
 src/lj_obj.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/lj_obj.h b/src/lj_obj.h
index c7e4742..4ff5944 100644
--- a/src/lj_obj.h
+++ b/src/lj_obj.h
@@ -944,12 +944,18 @@ static LJ_AINLINE int32_t lj_num2bit(lua_Number n)
 
 static LJ_AINLINE uint64_t lj_num2u64(lua_Number n)
 {
+  /* Undefined behaviour. This is deliberately not a full check because we
+     don't want to slow down compliant code. */
+  lua_assert(n >= -9223372036854775809.0);
 #ifdef _MSC_VER
   if (n >= 9223372036854775808.0)  /* They think it's a feature. */
     return (uint64_t)(int64_t)(n - 18446744073709551616.0);
   else
 #endif
-    return (uint64_t)n;
+    if (n > -1.0)
+      return (uint64_t)n;
+    else
+      return (uint64_t)(int64_t)n;
 }
 
 static LJ_AINLINE int32_t numberVint(cTValue *o)
-- 
2.20.1