diff options
author | lijunlong <lijunlong@openresty.com> | 2023-02-22 11:28:15 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-22 11:28:15 +0800 |
commit | de93a78d3002ee72bb1c7e3a629d67e19623a4ae (patch) | |
tree | fddd9ba083aae1c3f58868e313aa0540885951b8 | |
parent | 1dff61d9bf390372124c13443e0131a96383f5bc (diff) | |
download | lua-cjson-de93a78d3002ee72bb1c7e3a629d67e19623a4ae.tar.gz lua-cjson-de93a78d3002ee72bb1c7e3a629d67e19623a4ae.tar.bz2 lua-cjson-de93a78d3002ee72bb1c7e3a629d67e19623a4ae.zip |
feature: Add option to skip invalid value types.
Co-authored-by: Jesper Lundgren <jesperlundgren@exosite.com>
-rw-r--r-- | .travis.yml | 4 | ||||
-rw-r--r-- | lua-cjson-2.1.0.11-1.rockspec (renamed from lua-cjson-2.1.0.10-1.rockspec) | 0 | ||||
-rw-r--r-- | lua_cjson.c | 59 | ||||
-rw-r--r-- | strbuf.h | 6 | ||||
-rw-r--r-- | tests/agentzh.t | 26 |
5 files changed, 79 insertions, 16 deletions
diff --git a/.travis.yml b/.travis.yml index b07f3dc..91f73ff 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -46,8 +46,8 @@ install: | |||
46 | - cd .. | 46 | - cd .. |
47 | 47 | ||
48 | script: | 48 | script: |
49 | - cppcheck -i ./luajit2 -i --force --error-exitcode=1 --enable=warning . > build.log 2>&1 || (cat build.log && exit 1) | 49 | - cppcheck -i ./luajit2 --force --error-exitcode=1 --enable=warning . > build.log 2>&1 || (cat build.log && exit 1) |
50 | - sh runtests.sh | 50 | - bash runtests.sh |
51 | - make | 51 | - make |
52 | - prove -Itests tests | 52 | - prove -Itests tests |
53 | - TEST_LUA_USE_VALGRIND=1 prove -Itests tests > build.log 2>&1; export e=$? | 53 | - 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.11-1.rockspec index 9ed4272..9ed4272 100644 --- a/lua-cjson-2.1.0.10-1.rockspec +++ b/lua-cjson-2.1.0.11-1.rockspec | |||
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 @@ | |||
82 | #define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 1 | 82 | #define DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT 1 |
83 | #define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0 | 83 | #define DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT 0 |
84 | #define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1 | 84 | #define DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH 1 |
85 | #define DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES 0 | ||
85 | 86 | ||
86 | #ifdef DISABLE_INVALID_NUMBERS | 87 | #ifdef DISABLE_INVALID_NUMBERS |
87 | #undef DEFAULT_DECODE_INVALID_NUMBERS | 88 | #undef DEFAULT_DECODE_INVALID_NUMBERS |
@@ -165,6 +166,7 @@ typedef struct { | |||
165 | int decode_invalid_numbers; | 166 | int decode_invalid_numbers; |
166 | int decode_max_depth; | 167 | int decode_max_depth; |
167 | int decode_array_with_array_mt; | 168 | int decode_array_with_array_mt; |
169 | int encode_skip_unsupported_value_types; | ||
168 | } json_config_t; | 170 | } json_config_t; |
169 | 171 | ||
170 | typedef struct { | 172 | typedef struct { |
@@ -356,6 +358,16 @@ static int json_cfg_decode_array_with_array_mt(lua_State *l) | |||
356 | return 1; | 358 | return 1; |
357 | } | 359 | } |
358 | 360 | ||
361 | /* Configure how to treat invalid types */ | ||
362 | static int json_cfg_encode_skip_unsupported_value_types(lua_State *l) | ||
363 | { | ||
364 | json_config_t *cfg = json_arg_init(l, 1); | ||
365 | |||
366 | json_enum_option(l, 1, &cfg->encode_skip_unsupported_value_types, NULL, 1); | ||
367 | |||
368 | return 1; | ||
369 | } | ||
370 | |||
359 | /* Configures JSON encoding buffer persistence */ | 371 | /* Configures JSON encoding buffer persistence */ |
360 | static int json_cfg_encode_keep_buffer(lua_State *l) | 372 | static int json_cfg_encode_keep_buffer(lua_State *l) |
361 | { | 373 | { |
@@ -463,6 +475,7 @@ static void json_create_config(lua_State *l) | |||
463 | cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT; | 475 | cfg->encode_empty_table_as_object = DEFAULT_ENCODE_EMPTY_TABLE_AS_OBJECT; |
464 | cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT; | 476 | cfg->decode_array_with_array_mt = DEFAULT_DECODE_ARRAY_WITH_ARRAY_MT; |
465 | cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH; | 477 | cfg->encode_escape_forward_slash = DEFAULT_ENCODE_ESCAPE_FORWARD_SLASH; |
478 | cfg->encode_skip_unsupported_value_types = DEFAULT_ENCODE_SKIP_UNSUPPORTED_VALUE_TYPES; | ||
466 | 479 | ||
467 | #if DEFAULT_ENCODE_KEEP_BUFFER > 0 | 480 | #if DEFAULT_ENCODE_KEEP_BUFFER > 0 |
468 | strbuf_init(&cfg->encode_buf, 0); | 481 | strbuf_init(&cfg->encode_buf, 0); |
@@ -627,7 +640,7 @@ static void json_check_encode_depth(lua_State *l, json_config_t *cfg, | |||
627 | current_depth); | 640 | current_depth); |
628 | } | 641 | } |
629 | 642 | ||
630 | static void json_append_data(lua_State *l, json_config_t *cfg, | 643 | static int json_append_data(lua_State *l, json_config_t *cfg, |
631 | int current_depth, strbuf_t *json); | 644 | int current_depth, strbuf_t *json); |
632 | 645 | ||
633 | /* json_append_array args: | 646 | /* json_append_array args: |
@@ -637,19 +650,24 @@ static void json_append_data(lua_State *l, json_config_t *cfg, | |||
637 | static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth, | 650 | static void json_append_array(lua_State *l, json_config_t *cfg, int current_depth, |
638 | strbuf_t *json, int array_length) | 651 | strbuf_t *json, int array_length) |
639 | { | 652 | { |
640 | int comma, i; | 653 | int comma, i, json_pos, err; |
641 | 654 | ||
642 | strbuf_append_char(json, '['); | 655 | strbuf_append_char(json, '['); |
643 | 656 | ||
644 | comma = 0; | 657 | comma = 0; |
645 | for (i = 1; i <= array_length; i++) { | 658 | for (i = 1; i <= array_length; i++) { |
646 | if (comma) | 659 | json_pos = strbuf_length(json); |
660 | if (comma++ > 0) | ||
647 | strbuf_append_char(json, ','); | 661 | strbuf_append_char(json, ','); |
648 | else | ||
649 | comma = 1; | ||
650 | 662 | ||
651 | lua_rawgeti(l, -1, i); | 663 | lua_rawgeti(l, -1, i); |
652 | json_append_data(l, cfg, current_depth, json); | 664 | err = json_append_data(l, cfg, current_depth, json); |
665 | if (err) { | ||
666 | strbuf_set_length(json, json_pos); | ||
667 | if (comma == 1) { | ||
668 | comma = 0; | ||
669 | } | ||
670 | } | ||
653 | lua_pop(l, 1); | 671 | lua_pop(l, 1); |
654 | } | 672 | } |
655 | 673 | ||
@@ -697,7 +715,7 @@ static void json_append_number(lua_State *l, json_config_t *cfg, | |||
697 | static void json_append_object(lua_State *l, json_config_t *cfg, | 715 | static void json_append_object(lua_State *l, json_config_t *cfg, |
698 | int current_depth, strbuf_t *json) | 716 | int current_depth, strbuf_t *json) |
699 | { | 717 | { |
700 | int comma, keytype; | 718 | int comma, keytype, json_pos, err; |
701 | 719 | ||
702 | /* Object */ | 720 | /* Object */ |
703 | strbuf_append_char(json, '{'); | 721 | strbuf_append_char(json, '{'); |
@@ -706,10 +724,9 @@ static void json_append_object(lua_State *l, json_config_t *cfg, | |||
706 | /* table, startkey */ | 724 | /* table, startkey */ |
707 | comma = 0; | 725 | comma = 0; |
708 | while (lua_next(l, -2) != 0) { | 726 | while (lua_next(l, -2) != 0) { |
709 | if (comma) | 727 | json_pos = strbuf_length(json); |
728 | if (comma++ > 0) | ||
710 | strbuf_append_char(json, ','); | 729 | strbuf_append_char(json, ','); |
711 | else | ||
712 | comma = 1; | ||
713 | 730 | ||
714 | /* table, key, value */ | 731 | /* table, key, value */ |
715 | keytype = lua_type(l, -2); | 732 | keytype = lua_type(l, -2); |
@@ -727,7 +744,14 @@ static void json_append_object(lua_State *l, json_config_t *cfg, | |||
727 | } | 744 | } |
728 | 745 | ||
729 | /* table, key, value */ | 746 | /* table, key, value */ |
730 | json_append_data(l, cfg, current_depth, json); | 747 | err = json_append_data(l, cfg, current_depth, json); |
748 | if (err) { | ||
749 | strbuf_set_length(json, json_pos); | ||
750 | if (comma == 1) { | ||
751 | comma = 0; | ||
752 | } | ||
753 | } | ||
754 | |||
731 | lua_pop(l, 1); | 755 | lua_pop(l, 1); |
732 | /* table, key */ | 756 | /* table, key */ |
733 | } | 757 | } |
@@ -735,8 +759,8 @@ static void json_append_object(lua_State *l, json_config_t *cfg, | |||
735 | strbuf_append_char(json, '}'); | 759 | strbuf_append_char(json, '}'); |
736 | } | 760 | } |
737 | 761 | ||
738 | /* Serialise Lua data into JSON string. */ | 762 | /* Serialise Lua data into JSON string. Return 1 if error an error happened, else 0 */ |
739 | static void json_append_data(lua_State *l, json_config_t *cfg, | 763 | static int json_append_data(lua_State *l, json_config_t *cfg, |
740 | int current_depth, strbuf_t *json) | 764 | int current_depth, strbuf_t *json) |
741 | { | 765 | { |
742 | int len; | 766 | int len; |
@@ -807,9 +831,15 @@ static void json_append_data(lua_State *l, json_config_t *cfg, | |||
807 | default: | 831 | default: |
808 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, | 832 | /* Remaining types (LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, |
809 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ | 833 | * and LUA_TLIGHTUSERDATA) cannot be serialised */ |
810 | json_encode_exception(l, cfg, json, -1, "type not supported"); | 834 | if (cfg->encode_skip_unsupported_value_types) { |
835 | return 1; | ||
836 | } else { | ||
837 | json_encode_exception(l, cfg, json, -1, "type not supported"); | ||
838 | } | ||
839 | |||
811 | /* never returns */ | 840 | /* never returns */ |
812 | } | 841 | } |
842 | return 0; | ||
813 | } | 843 | } |
814 | 844 | ||
815 | static int json_encode(lua_State *l) | 845 | static int json_encode(lua_State *l) |
@@ -1479,6 +1509,7 @@ static int lua_cjson_new(lua_State *l) | |||
1479 | { "encode_invalid_numbers", json_cfg_encode_invalid_numbers }, | 1509 | { "encode_invalid_numbers", json_cfg_encode_invalid_numbers }, |
1480 | { "decode_invalid_numbers", json_cfg_decode_invalid_numbers }, | 1510 | { "decode_invalid_numbers", json_cfg_decode_invalid_numbers }, |
1481 | { "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash }, | 1511 | { "encode_escape_forward_slash", json_cfg_encode_escape_forward_slash }, |
1512 | { "encode_skip_unsupported_value_types", json_cfg_encode_skip_unsupported_value_types }, | ||
1482 | { "new", lua_cjson_new }, | 1513 | { "new", lua_cjson_new }, |
1483 | { NULL, NULL } | 1514 | { NULL, NULL } |
1484 | }; | 1515 | }; |
@@ -70,6 +70,7 @@ static char *strbuf_string(strbuf_t *s, int *len); | |||
70 | static void strbuf_ensure_empty_length(strbuf_t *s, int len); | 70 | static void strbuf_ensure_empty_length(strbuf_t *s, int len); |
71 | static char *strbuf_empty_ptr(strbuf_t *s); | 71 | static char *strbuf_empty_ptr(strbuf_t *s); |
72 | static void strbuf_extend_length(strbuf_t *s, int len); | 72 | static void strbuf_extend_length(strbuf_t *s, int len); |
73 | static void strbuf_set_length(strbuf_t *s, int len); | ||
73 | 74 | ||
74 | /* Update */ | 75 | /* Update */ |
75 | extern void strbuf_append_fmt(strbuf_t *s, int len, const char *fmt, ...); | 76 | 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) | |||
108 | return s->buf + s->length; | 109 | return s->buf + s->length; |
109 | } | 110 | } |
110 | 111 | ||
112 | static inline void strbuf_set_length(strbuf_t *s, int len) | ||
113 | { | ||
114 | s->length = len; | ||
115 | } | ||
116 | |||
111 | static inline void strbuf_extend_length(strbuf_t *s, int len) | 117 | static inline void strbuf_extend_length(strbuf_t *s, int len) |
112 | { | 118 | { |
113 | s->length += len; | 119 | 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) | |||
306 | {"test":"http:\/\/google.com\/google"} | 306 | {"test":"http:\/\/google.com\/google"} |
307 | {"test":"http://google.com/google"} | 307 | {"test":"http://google.com/google"} |
308 | {"test":"http:\/\/google.com\/google"} | 308 | {"test":"http:\/\/google.com\/google"} |
309 | |||
310 | |||
311 | |||
312 | === TEST 22: disable error on invalid type | ||
313 | --- lua | ||
314 | local cjson = require "cjson" | ||
315 | local f = function (x) return 2*x end | ||
316 | local res, err = pcall(cjson.encode, f) | ||
317 | print(err) | ||
318 | local t = {f = f, valid = "valid"} | ||
319 | local res, err = pcall(cjson.encode, t) | ||
320 | print(err) | ||
321 | local arr = {"one", "two", f, "three"} | ||
322 | local res, err = pcall(cjson.encode, arr) | ||
323 | print(err) | ||
324 | cjson.encode_skip_unsupported_value_types(true) | ||
325 | print(cjson.encode(f)) | ||
326 | print(cjson.encode(t)) | ||
327 | print(cjson.encode(arr)) | ||
328 | --- out | ||
329 | Cannot serialise function: type not supported | ||
330 | Cannot serialise function: type not supported | ||
331 | Cannot serialise function: type not supported | ||
332 | |||
333 | {"valid":"valid"} | ||
334 | ["one","two","three"] | ||