From 454bea87cff4ff3cd2fd9ae34a3718dd200ce0fb Mon Sep 17 00:00:00 2001 From: Siddhesh Poyarekar 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