From a61d7840ba2d79df8cb73d8c864a99d0eb06d580 Mon Sep 17 00:00:00 2001 From: Thibault Charbonnier Date: Fri, 16 Dec 2016 18:27:49 -0800 Subject: bugfix: preserve 'empty_array_mt' behavior upon multiple loadings of the module. Prior to this fix, when the module would be loaded several times (by-passing `package.loaded`), the `lua_cjson_new` function would override the `empty_array_mt` table in the registry with a new one. Comparison for equality between those tables would then fail, and the behavior would be broken. This was discovered after loading `cjson` *and* `cjson.safe` in the same application, resulting in two calls to `lua_cjson_new`. Signed-off-by: Yichun Zhang (agentzh) --- lua_cjson.c | 17 ++++++++++++++--- tests/agentzh.t | 28 ++++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/lua_cjson.c b/lua_cjson.c index 3a77644..1695979 100644 --- a/lua_cjson.c +++ b/lua_cjson.c @@ -1401,10 +1401,21 @@ static int lua_cjson_new(lua_State *l) /* Initialise number conversions */ fpconv_init(); - /* Create empty array metatable */ + /* Test if empty array metatable is in registry */ lua_pushlightuserdata(l, &json_empty_array); - lua_newtable(l); - lua_rawset(l, LUA_REGISTRYINDEX); + lua_rawget(l, LUA_REGISTRYINDEX); + if (lua_isnil(l, -1)) { + /* Create empty array metatable. + * + * If multiple calls to lua_cjson_new() are made, + * this prevents overriding the table at the given + * registry's index with a new one. + */ + lua_pop(l, 1); + lua_pushlightuserdata(l, &json_empty_array); + lua_newtable(l); + lua_rawset(l, LUA_REGISTRYINDEX); + } /* cjson module table */ lua_newtable(l); diff --git a/tests/agentzh.t b/tests/agentzh.t index e76f910..3b0ecf1 100644 --- a/tests/agentzh.t +++ b/tests/agentzh.t @@ -113,7 +113,31 @@ print(cjson.encode(data)) -=== TEST 9: & in JSON +=== TEST 9: multiple calls to lua_cjson_new (1/2) +--- lua +local cjson = require "cjson" +package.loaded["cjson"] = nil +require "cjson" +local arr = setmetatable({}, cjson.empty_array_mt) +print(cjson.encode(arr)) +--- out +[] + + + +=== TEST 10: multiple calls to lua_cjson_new (2/2) +--- lua +local cjson = require "cjson.safe" +-- load another cjson instance (not in package.loaded) +require "cjson" +local arr = setmetatable({}, cjson.empty_array_mt) +print(cjson.encode(arr)) +--- out +[] + + + +=== TEST 11: & in JSON --- lua local cjson = require "cjson" local a="[\"a=1&b=2\"]" @@ -124,7 +148,7 @@ print(cjson.encode(b)) -=== TEST 10: default and max precision +=== TEST 12: default and max precision --- lua local math = require "math" local cjson = require "cjson" -- cgit v1.2.3-55-g6feb