Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpx/lua-cjson.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Pulford <mark@kyne.com.au>2012-02-01 18:03:58 +0400
committerMark Pulford <mark@kyne.com.au>2012-03-04 12:24:36 +0400
commit95cbf2012ef273b13a494a2c66cef61c334d442f (patch)
treeb9ec33c975dc34a1b5d04a5817613848abc33412
parent60e14dbb2b03f2b6d7336a777e017f5787296988 (diff)
Add cjson.safe module to suppress exceptions
Add cjson.safe module to suppress exceptions during JSON conversions.
-rw-r--r--lua_cjson.c58
-rw-r--r--manual.txt34
-rwxr-xr-xtests/test.lua14
3 files changed, 94 insertions, 12 deletions
diff --git a/lua_cjson.c b/lua_cjson.c
index 498c686..afa5266 100644
--- a/lua_cjson.c
+++ b/lua_cjson.c
@@ -1310,6 +1310,35 @@ static void luaL_setfuncs (lua_State *l, const luaL_Reg *reg, int nup)
}
#endif
+/* Call target function in protected mode with all supplied args.
+ * Assumes target function only returns a single non-nil value.
+ * Convert and return thrown errors as: nil, "error message" */
+static int json_protect_conversion(lua_State *l)
+{
+ int err;
+
+ /* Deliberately throw an error for invalid arguments */
+ luaL_argcheck(l, lua_gettop(l) == 1, 1, "expected 1 argument");
+
+ /* pcall() the function stored as upvalue(1) */
+ lua_pushvalue(l, lua_upvalueindex(1));
+ lua_insert(l, 1);
+ err = lua_pcall(l, 1, 1, 0);
+ if (!err)
+ return 1;
+
+ if (err == LUA_ERRRUN) {
+ lua_pushnil(l);
+ lua_insert(l, -2);
+ return 2;
+ }
+
+ /* Since we are not using a custom error handler, the only remaining
+ * errors are memory related */
+ return luaL_error(l, "Memory allocation error in CJSON protected call");
+}
+
+/* Return cjson module table */
static int lua_cjson_new(lua_State *l)
{
luaL_Reg reg[] = {
@@ -1349,6 +1378,27 @@ static int lua_cjson_new(lua_State *l)
return 1;
}
+/* Return cjson.safe module table */
+static int lua_cjson_safe_new(lua_State *l)
+{
+ const char *func[] = { "decode", "encode", NULL };
+ int i;
+
+ lua_cjson_new(l);
+
+ /* Fix new() method */
+ lua_pushcfunction(l, lua_cjson_safe_new);
+ lua_setfield(l, -2, "new");
+
+ for (i = 0; func[i]; i++) {
+ lua_getfield(l, -1, func[i]);
+ lua_pushcclosure(l, json_protect_conversion, 1);
+ lua_setfield(l, -2, func[i]);
+ }
+
+ return 1;
+}
+
int luaopen_cjson(lua_State *l)
{
lua_cjson_new(l);
@@ -1363,5 +1413,13 @@ int luaopen_cjson(lua_State *l)
return 1;
}
+int luaopen_cjson_safe(lua_State *l)
+{
+ lua_cjson_safe_new(l);
+
+ /* Return cjson.safe table */
+ return 1;
+}
+
/* vi:ai et sw=4 ts=4:
*/
diff --git a/manual.txt b/manual.txt
index 9833c58..afd9528 100644
--- a/manual.txt
+++ b/manual.txt
@@ -173,6 +173,7 @@ Synopsis
-- Module instantiation
local cjson = require "cjson"
local cjson2 = cjson.new()
+local cjson_safe = require "cjson.safe"
-- Translate Lua value to/from JSON
text = cjson.encode(value)
@@ -195,11 +196,20 @@ Module Instantiation
------------
local cjson = require "cjson"
local cjson2 = cjson.new()
+local cjson_safe = require "cjson.safe"
------------
Import Lua CJSON via the Lua +require+ function. Lua CJSON does not
-register a global module table with the default
-<<build_options,build options>>.
+register a global module table.
+
+The +cjson+ module will throw an error during JSON conversion if any
+invalid data is encountered. Refer to <<cjson_encode,+cjson.encode+>>
+and <<cjson_decode,+cjson.decode+>> for details.
+
+The +cjson.safe+ module behaves identically to the +cjson+ module,
+except when errors are encountered during JSON conversion. On error, the
++cjson_safe.encode+ and +cjson_safe.decode+ functions will return
++nil+ followed by the error message.
+cjson.new+ can be used to instantiate an independent copy of the Lua
CJSON module. The new module has a separate persistent encoding buffer,
@@ -276,8 +286,8 @@ setting = cjson.decode_invalid_numbers([setting])
-- "setting" must be a boolean. Default: true.
------------
-Lua CJSON may throw an error when trying to decode numbers not supported
-by the JSON specification. _Invalid numbers_ are defined as:
+Lua CJSON may generate an error when trying to decode numbers not
+supported by the JSON specification. _Invalid numbers_ are defined as:
- infinity
- not-a-number (NaN)
@@ -303,13 +313,13 @@ depth = cjson.decode_max_depth([depth])
-- "depth" must be a positive integer. Default: 1000.
------------
-Lua CJSON will throw an error when parsing deeply nested JSON once the
-maximum array/object depth has been exceeded. This check prevents
+Lua CJSON will generate an error when parsing deeply nested JSON once
+the maximum array/object depth has been exceeded. This check prevents
unnecessarily complicated JSON from slowing down the application, or
crashing the application due to lack of process stack space.
-An error may be thrown before the depth limit is hit if Lua is unable to
-allocate more objects on the Lua stack.
+An error may be generated before the depth limit is hit if Lua is unable
+to allocate more objects on the Lua stack.
By default, Lua CJSON will reject JSON with arrays and/or objects nested
more than 1000 levels deep.
@@ -424,7 +434,7 @@ setting = cjson.encode_invalid_numbers([setting])
-- "setting" must a boolean or "null". Default: false.
------------
-Lua CJSON may throw an error when encoding floating point numbers not
+Lua CJSON may generate an error when encoding floating point numbers not
supported by the JSON specification (_invalid numbers_):
- infinity
@@ -476,11 +486,11 @@ depth = cjson.encode_max_depth([depth])
-- "depth" must be a positive integer. Default: 1000.
------------
-Once the maximum table depth has been exceeded Lua CJSON will throw an
-error. This prevents a deeply nested or recursive data structure from
+Once the maximum table depth has been exceeded Lua CJSON will generate
+an error. This prevents a deeply nested or recursive data structure from
crashing the application.
-By default, Lua CJSON will throw an error when trying to encode data
+By default, Lua CJSON will generate an error when trying to encode data
structures with more than 1000 nested tables.
The current setting is always returned, and is only updated when an
diff --git a/tests/test.lua b/tests/test.lua
index ac6419a..96b47ff 100755
--- a/tests/test.lua
+++ b/tests/test.lua
@@ -7,6 +7,7 @@
-- Note: The output of this script is easier to read with "less -S"
local json = require "cjson"
+local json_safe = require "cjson.safe"
local util = require "cjson.util"
local function gen_raw_octets()
@@ -386,6 +387,19 @@ local cjson_tests = {
{ "Check encode_sparse_array()",
function (...) return json.encode_sparse_array(...) end, { },
true, { false, 2, 10 } },
+
+ { "Encode (safe) simple value",
+ json_safe.encode, { true },
+ true, { "true" } },
+ { "Encode (safe) argument validation [throw error]",
+ json_safe.encode, { "arg1", "arg2" },
+ false, { "bad argument #1 to '?' (expected 1 argument)" } },
+ { "Decode (safe) error generation",
+ json_safe.decode, { "Oops" },
+ true, { nil, "Expected value but found invalid token at character 1" } },
+ { "Decode (safe) error generation after new()",
+ function(...) return json_safe.new().decode(...) end, { "Oops" },
+ true, { nil, "Expected value but found invalid token at character 1" } },
}
print(("==> Testing Lua CJSON version %s\n"):format(json._VERSION))