luci-lib-jsonc: improve handling of integral numeric values
authorJo-Philipp Wich <jo@mein.io>
Wed, 25 Oct 2023 20:35:08 +0000 (22:35 +0200)
committerJo-Philipp Wich <jo@mein.io>
Wed, 25 Oct 2023 20:42:23 +0000 (22:42 +0200)
Properly deal with integral numeric values exceeding the int32_t range
by replacing the cast logic with more fine grained checks:

 - Lua numbers which are integers in the first place are directly converted
   to JSON integers

 - Finite double Lua numbers which are integral are converted to JSON
   integer values

 - All other numeric values are converted to JSON doubles

This should bring the handling of large integral value in line with the
documented behavior of turning non-fractional Lua numbers into JSON
integers.

Fixes: #6647
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
libs/luci-lib-jsonc/src/jsonc.c

index 74839dd4f57cadab356ade396d0645e6bf9ebccb..5abb738f5f912ff3f96947d52f7710b7b9fbe648 100644 (file)
@@ -294,7 +294,7 @@ static bool visited(struct seen **sp, const void *ptr) {
 static struct json_object * _lua_to_json_rec(lua_State *L, int index,
                                              struct seen **seen)
 {
-       lua_Number nd, ni;
+       lua_Number nd;
        struct json_object *obj;
        const char *key;
        int i, max;
@@ -364,10 +364,12 @@ static struct json_object * _lua_to_json_rec(lua_State *L, int index,
                return json_object_new_boolean(lua_toboolean(L, index));
 
        case LUA_TNUMBER:
+               if (lua_isinteger(L, index))
+                       return json_object_new_int64(lua_tointeger(L, index));
+
                nd = lua_tonumber(L, index);
-               ni = lua_tointeger(L, index);
 
-               if (nd == ni)
+               if (isfinite(nd) && trunc(nd) == nd)
                        return json_object_new_int64(nd);
 
                return json_object_new_double(nd);