From de93a78d3002ee72bb1c7e3a629d67e19623a4ae Mon Sep 17 00:00:00 2001 From: lijunlong Date: Wed, 22 Feb 2023 11:28:15 +0800 Subject: feature: Add option to skip invalid value types. Co-authored-by: Jesper Lundgren --- .travis.yml | 4 +-- lua-cjson-2.1.0.10-1.rockspec | 60 ------------------------------------------- lua-cjson-2.1.0.11-1.rockspec | 60 +++++++++++++++++++++++++++++++++++++++++++ lua_cjson.c | 59 ++++++++++++++++++++++++++++++++---------- strbuf.h | 6 +++++ tests/agentzh.t | 26 +++++++++++++++++++ 6 files changed, 139 insertions(+), 76 deletions(-) delete mode 100644 lua-cjson-2.1.0.10-1.rockspec create mode 100644 lua-cjson-2.1.0.11-1.rockspec diff --git a/.travis.yml b/.travis.yml index b07f3dc..91f73ff 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,8 +46,8 @@ install: - cd .. script: - - cppcheck -i ./luajit2 -i --force --error-exitcode=1 --enable=warning . > build.log 2>&1 || (cat build.log && exit 1) - - sh runtests.sh + - cppcheck -i ./luajit2 --force --error-exitcode=1 --enable=warning . > build.log 2>&1 || (cat build.log && exit 1) + - bash runtests.sh - make - prove -Itests tests - TEST_LUA_USE_VALGRIND=1 prove -Itests tests > build.log 2>&1; export e=$? diff --git a/lua-cjson-2.1.0.10-1.rockspec b/lua-cjson-2.1.0.10-1.rockspec deleted file mode 100644 index 9ed4272..0000000 --- a/lua-cjson-2.1.0.10-1.rockspec +++ /dev/null @@ -1,60 +0,0 @@ -package = "lua-cjson" -version = "2.1.0.11-1" - -source = { - url = "git+https://github.com/openresty/lua-cjson", - tag = "2.1.0.11", -} - -description = { - summary = "A fast JSON encoding/parsing module", - detailed = [[ - The Lua CJSON module provides JSON support for Lua. It features: - - Fast, standards compliant encoding/parsing routines - - Full support for JSON with UTF-8, including decoding surrogate pairs - - Optional run-time support for common exceptions to the JSON specification - (infinity, NaN,..) - - No dependencies on other libraries - ]], - homepage = "http://www.kyne.com.au/~mark/software/lua-cjson.php", - license = "MIT" -} - -dependencies = { - "lua >= 5.1" -} - -build = { - type = "builtin", - modules = { - cjson = { - sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" }, - defines = { --- LuaRocks does not support platform specific configuration for Solaris. --- Uncomment the line below on Solaris platforms if required. --- "USE_INTERNAL_ISINF" - } - }, - ["cjson.safe"] = { - sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" } - } - }, - install = { - lua = { - ["cjson.util"] = "lua/cjson/util.lua" - }, - bin = { - json2lua = "lua/json2lua.lua", - lua2json = "lua/lua2json.lua" - } - }, - -- Override default build options (per platform) - platforms = { - win32 = { modules = { cjson = { defines = { - "DISABLE_INVALID_NUMBERS", "USE_INTERNAL_ISINF" - } } } } - }, - copy_directories = { "tests" } -} - --- vi:ai et sw=4 ts=4: diff --git a/lua-cjson-2.1.0.11-1.rockspec b/lua-cjson-2.1.0.11-1.rockspec new file mode 100644 index 0000000..9ed4272 --- /dev/null +++ b/lua-cjson-2.1.0.11-1.rockspec @@ -0,0 +1,60 @@ +package = "lua-cjson" +version = "2.1.0.11-1" + +source = { + url = "git+https://github.com/openresty/lua-cjson", + tag = "2.1.0.11", +} + +description = { + summary = "A fast JSON encoding/parsing module", + detailed = [[ + The Lua CJSON module provides JSON support for Lua. It features: + - Fast, standards compliant encoding/parsing routines + - Full support for JSON with UTF-8, including decoding surrogate pairs + - Optional run-time support for common exceptions to the JSON specification + (infinity, NaN,..) + - No dependencies on other libraries + ]], + homepage = "http://www.kyne.com.au/~mark/software/lua-cjson.php", + license = "MIT" +} + +dependencies = { + "lua >= 5.1" +} + +build = { + type = "builtin", + modules = { + cjson = { + sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" }, + defines = { +-- LuaRocks does not support platform specific configuration for Solaris. +-- Uncomment the line below on Solaris platforms if required. +-- "USE_INTERNAL_ISINF" + } + }, + ["cjson.safe"] = { + sources = { "lua_cjson.c", "strbuf.c", "fpconv.c" } + } + }, + install = { + lua = { + ["cjson.util"] = "lua/cjson/util.lua" + }, + bin = { + json2lua = "lua/json2lua.lua", + lua2json = "lua/lua2json.lua" + } + }, + -- Override default build options (per platform) + platforms = { + win32 = { modules = { cjson = { defines = { + "DISABLE_INVALID_NUMBERS", "USE_INTERNAL_ISINF" + } } } } + }, + copy_directories = { "tests" } +} + +-- vi:ai et sw=4 ts=4: diff --git a/lua_cjson.c b/lua_cjson.c index 94b0b46..42672de 100644 --- a/lua_cjson.c +++ b/lua_cjson.c @@ -82,6 +82,7 @@ #define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 1 #define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0 #define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1 +#define DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES 0 #ifdef DISABLE_INVALID_NUMBERS #undef DEFAULT_DECODE_INVALID_NUMBERS @@ -165,6 +166,7 @@ typedef struct { int decode_invalid_numbers; int decode_max_depth; int decode_array_with_array_mt; + int encode_skip_unsupported_value_types; } json_config_t; typedef struct { @@ -356,6 +358,16 @@ static int json_cfg_decode_array_with_array_mt(lua_State *l) return 1; } +/* Configure how to treat invalid types */ +static int json_cfg_encode_skip_unsupported_value_types(lua_State *l) +{ + json_config_t *cfg = json_arg_init(l, 1); + + json_enum_option(l, 1, &cfg->encode_skip_unsupported_value_types, NULL, 1); + + return 1; +} + /* Configures JSON encoding buffer persistence */ static int json_cfg_encode_keep_buffer(lua_State *l) { @@ -463,6 +475,7 @@ static void json_create_config(lua_State *l) cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT; cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT; cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH; + cfg->encode_skip_unsupported_value_types = DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES; #if DEFAULT_ENCODE_KEEP_BUFFER > 0 strbuf_init(&cfg->encode_buf, 0); @@ -627,7 +640,7 @@ static void json_check_encode_depth(lua_State *l, json_config_t *cfg, current_depth); } -static void json_append_data(lua_State *l, json_config_t *cfg, +static int json_append_data(lua_State *l, json_config_t *cfg, int current_depth, strbuf_t *json); /* json_append_array args: @@ -637,19 +650,24 @@ static void json_append_data(lua_State *l, json_config_t *cfg, static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth, strbuf_t *json, int array_length) { - int comma, i; + int comma, i, json_pos, err; strbuf_append_char(json, '['); comma = 0; for (i = 1; i <= array_length; i++) { - if (comma) + json_pos = strbuf_length(json); + if (comma++ > 0) strbuf_append_char(json, ','); - else - comma = 1; lua_rawgeti(l, -1, i); - json_append_data(l, cfg, current_depth, json); + err = json_append_data(l, cfg, current_depth, json); + if (err) { + strbuf_set_length(json, json_pos); + if (comma == 1) { + comma = 0; + } + } lua_pop(l, 1); } @@ -697,7 +715,7 @@ static void json_append_number(lua_State *l, json_config_t *cfg, static void json_append_object(lua_State *l, json_config_t *cfg, int current_depth, strbuf_t *json) { - int comma, keytype; + int comma, keytype, json_pos, err; /* Object */ strbuf_append_char(json, '{'); @@ -706,10 +724,9 @@ static void json_append_object(lua_State *l, json_config_t *cfg, /* table, startkey */ comma = 0; while (lua_next(l, -2) != 0) { - if (comma) + json_pos = strbuf_length(json); + if (comma++ > 0) strbuf_append_char(json, ','); - else - comma = 1; /* table, key, value */ keytype = lua_type(l, -2); @@ -727,7 +744,14 @@ static void json_append_object(lua_State *l, json_config_t *cfg, } /* table, key, value */ - json_append_data(l, cfg, current_depth, json); + err = json_append_data(l, cfg, current_depth, json); + if (err) { + strbuf_set_length(json, json_pos); + if (comma == 1) { + comma = 0; + } + } + lua_pop(l, 1); /* table, key */ } @@ -735,8 +759,8 @@ static void json_append_object(lua_State *l, json_config_t *cfg, strbuf_append_char(json, '}'); } -/* Serialise Lua data into JSON string. */ -static void json_append_data(lua_State *l, json_config_t *cfg, +/* Serialise Lua data into JSON string. Return 1 if error an error happened, else 0 */ +static int json_append_data(lua_State *l, json_config_t *cfg, int current_depth, strbuf_t *json) { int len; @@ -807,9 +831,15 @@ static void json_append_data(lua_State *l, json_config_t *cfg, default: /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, * and LUA_TLIGHTUSERDATA) cannot be serialised */ - json_encode_exception(l, cfg, json, -1, "type not supported"); + if (cfg->encode_skip_unsupported_value_types) { + return 1; + } else { + json_encode_exception(l, cfg, json, -1, "type not supported"); + } + /* never returns */ } + return 0; } static int json_encode(lua_State *l) @@ -1479,6 +1509,7 @@ static int lua_cjson_new(lua_State *l) { "encode_invalid_numbers", json_cfg_encode_invalid_numbers }, { "decode_invalid_numbers", json_cfg_decode_invalid_numbers }, { "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash }, + { "encode_skip_unsupported_value_types", json_cfg_encode_skip_unsupported_value_types }, { "new", lua_cjson_new }, { NULL, NULL } }; diff --git a/strbuf.h b/strbuf.h index 5df0b7b..a98ee22 100644 --- a/strbuf.h +++ b/strbuf.h @@ -70,6 +70,7 @@ static char *strbuf_string(strbuf_t *s, int *len); static void strbuf_ensure_empty_length(strbuf_t *s, int len); static char *strbuf_empty_ptr(strbuf_t *s); static void strbuf_extend_length(strbuf_t *s, int len); +static void strbuf_set_length(strbuf_t *s, int len); /* Update */ extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...); @@ -108,6 +109,11 @@ static inline char *strbuf_empty_ptr(strbuf_t *s) return s->buf + s->length; } +static inline void strbuf_set_length(strbuf_t *s, int len) +{ + s->length = len; +} + static inline void strbuf_extend_length(strbuf_t *s, int len) { s->length += len; diff --git a/tests/agentzh.t b/tests/agentzh.t index 2e7c8ce..552630a 100644 --- a/tests/agentzh.t +++ b/tests/agentzh.t @@ -306,3 +306,29 @@ print(b) {"test":"http:\/\/google.com\/google"} {"test":"http://google.com/google"} {"test":"http:\/\/google.com\/google"} + + + +=== TEST 22: disable error on invalid type +--- lua +local cjson = require "cjson" +local f = function (x) return 2*x end +local res, err = pcall(cjson.encode, f) +print(err) +local t = {f = f, valid = "valid"} +local res, err = pcall(cjson.encode, t) +print(err) +local arr = {"one", "two", f, "three"} +local res, err = pcall(cjson.encode, arr) +print(err) +cjson.encode_skip_unsupported_value_types(true) +print(cjson.encode(f)) +print(cjson.encode(t)) +print(cjson.encode(arr)) +--- out +Cannot serialise function: type not supported +Cannot serialise function: type not supported +Cannot serialise function: type not supported + +{"valid":"valid"} +["one","two","three"] -- cgit v1.2.3-55-g6feb