From 50be59058117b07c2d3082175bb05a6dc7e2dfa9 Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Fri, 19 Nov 2021 11:57:58 -0800 Subject: [PATCH] Use pre-defined standard integer max/mins in INTCHECK This makes the code easier to read. --- upb/bindings/lua/upb.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/upb/bindings/lua/upb.c b/upb/bindings/lua/upb.c index 2b476592e0..02cfbb395c 100644 --- a/upb/bindings/lua/upb.c +++ b/upb/bindings/lua/upb.c @@ -181,7 +181,7 @@ const char *lupb_checkstring(lua_State *L, int narg, size_t *len) { /* Unlike luaL_checkinteger, these do not implicitly convert from string or * round an existing double value. We allow floating-point input, but only if * the actual value is integral. */ -#define INTCHECK(type, ctype, min, max_bits) \ +#define INTCHECK(type, ctype, min, max) \ ctype lupb_check##type(lua_State *L, int narg) { \ double n; \ if (lua_isinteger(L, narg)) { \ @@ -192,9 +192,17 @@ const char *lupb_checkstring(lua_State *L, int narg, size_t *len) { luaL_checktype(L, narg, LUA_TNUMBER); \ n = lua_tonumber(L, narg); \ \ - /* Check this double has no fractional part and remains in bounds. */ \ + /* Check this double has no fractional part and remains in bounds. \ + * Consider INT64_MIN and INT64_MAX: \ + * 1. INT64_MIN -(2^63) is a power of 2, so this converts to a double. \ + * 2. INT64_MAX (2^63 - 1) is not a power of 2, and conversion of \ + * out-of-range integer values to a double can lead to undefined behavior. \ + * On some compilers, this conversion can return 0, but it also can return \ + * the max value. To deal with this, we can first divide by 2 to prevent \ + * the overflow, multiply it back, and add 1 to find the true limit. */ \ double i; \ - if ((modf(n, &i) != 0.0) || n < min || n >= ldexp(1, max_bits)) { \ + double max_value = (((double) max / 2) * 2) + 1; \ + if ((modf(n, &i) != 0.0) || n < min || n >= max_value) { \ luaL_error(L, "number %f was not an integer or out of range for " #type, \ n); \ } \ @@ -207,10 +215,10 @@ const char *lupb_checkstring(lua_State *L, int narg, size_t *len) { lua_pushnumber(L, val); \ } -INTCHECK(int64, int64_t, INT64_MIN, 63) -INTCHECK(int32, int32_t, INT32_MIN, 31) -INTCHECK(uint64, uint64_t, 0, 64) -INTCHECK(uint32, uint32_t, 0, 32) +INTCHECK(int64, int64_t, INT64_MIN, INT64_MAX) +INTCHECK(int32, int32_t, INT32_MIN, INT32_MAX) +INTCHECK(uint64, uint64_t, 0, UINT64_MAX) +INTCHECK(uint32, uint32_t, 0, UINT32_MAX) double lupb_checkdouble(lua_State *L, int narg) { /* If we were being really hard-nosed here, we'd check whether the input was