diff options
-rw-r--r-- | lua_cjson.c | 98 | ||||
-rw-r--r-- | manual.txt | 26 |
2 files changed, 89 insertions, 35 deletions
diff --git a/lua_cjson.c b/lua_cjson.c index 344cb43..bdfa7d4 100644 --- a/lua_cjson.c +++ b/lua_cjson.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <assert.h> | 39 | #include <assert.h> |
40 | #include <string.h> | 40 | #include <string.h> |
41 | #include <math.h> | 41 | #include <math.h> |
42 | #include <limits.h> | ||
42 | #include <lua.h> | 43 | #include <lua.h> |
43 | #include <lauxlib.h> | 44 | #include <lauxlib.h> |
44 | 45 | ||
@@ -61,7 +62,8 @@ | |||
61 | #define DEFAULT_SPARSE_CONVERT 0 | 62 | #define DEFAULT_SPARSE_CONVERT 0 |
62 | #define DEFAULT_SPARSE_RATIO 2 | 63 | #define DEFAULT_SPARSE_RATIO 2 |
63 | #define DEFAULT_SPARSE_SAFE 10 | 64 | #define DEFAULT_SPARSE_SAFE 10 |
64 | #define DEFAULT_MAX_DEPTH 20 | 65 | #define DEFAULT_ENCODE_MAX_DEPTH 20 |
66 | #define DEFAULT_DECODE_MAX_DEPTH 20 | ||
65 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 | 67 | #define DEFAULT_ENCODE_REFUSE_BADNUM 1 |
66 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 | 68 | #define DEFAULT_DECODE_REFUSE_BADNUM 0 |
67 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 | 69 | #define DEFAULT_ENCODE_KEEP_BUFFER 1 |
@@ -120,9 +122,11 @@ typedef struct { | |||
120 | int encode_sparse_safe; | 122 | int encode_sparse_safe; |
121 | int encode_max_depth; | 123 | int encode_max_depth; |
122 | int encode_refuse_badnum; | 124 | int encode_refuse_badnum; |
123 | int decode_refuse_badnum; | ||
124 | int encode_keep_buffer; | ||
125 | int encode_number_precision; | 125 | int encode_number_precision; |
126 | int encode_keep_buffer; | ||
127 | |||
128 | int decode_refuse_badnum; | ||
129 | int decode_max_depth; | ||
126 | } json_config_t; | 130 | } json_config_t; |
127 | 131 | ||
128 | typedef struct { | 132 | typedef struct { |
@@ -130,6 +134,7 @@ typedef struct { | |||
130 | const char *ptr; | 134 | const char *ptr; |
131 | strbuf_t *tmp; /* Temporary storage for strings */ | 135 | strbuf_t *tmp; /* Temporary storage for strings */ |
132 | json_config_t *cfg; | 136 | json_config_t *cfg; |
137 | int current_depth; | ||
133 | } json_parse_t; | 138 | } json_parse_t; |
134 | 139 | ||
135 | typedef struct { | 140 | typedef struct { |
@@ -234,46 +239,50 @@ static int json_cfg_encode_sparse_array(lua_State *l) | |||
234 | return 3; | 239 | return 3; |
235 | } | 240 | } |
236 | 241 | ||
237 | /* Configures the maximum number of nested arrays/objects allowed when | 242 | /* Process integer options for configuration functions */ |
238 | * encoding */ | 243 | static int json_integer_option(lua_State *l, int *setting, int min, int max) |
239 | static int json_cfg_encode_max_depth(lua_State *l) | ||
240 | { | 244 | { |
241 | json_config_t *cfg; | 245 | char errmsg[64]; |
242 | int depth; | 246 | int value; |
243 | 247 | ||
244 | json_verify_arg_count(l, 1); | 248 | json_verify_arg_count(l, 1); |
245 | cfg = json_fetch_config(l); | ||
246 | 249 | ||
247 | if (lua_gettop(l)) { | 250 | if (lua_gettop(l)) { |
248 | depth = luaL_checkinteger(l, 1); | 251 | value = luaL_checkinteger(l, 1); |
249 | luaL_argcheck(l, depth > 0, 1, "expected positive integer"); | 252 | snprintf(errmsg, sizeof(errmsg), "expected integer between %d and %d", min, max); |
250 | cfg->encode_max_depth = depth; | 253 | luaL_argcheck(l, min <= value && value <= max, 1, errmsg); |
254 | *setting = value; | ||
251 | } | 255 | } |
252 | 256 | ||
253 | lua_pushinteger(l, cfg->encode_max_depth); | 257 | lua_pushinteger(l, *setting); |
254 | 258 | ||
255 | return 1; | 259 | return 1; |
256 | } | 260 | } |
257 | 261 | ||
258 | /* Configures number precision when converting doubles to text */ | 262 | /* Configures the maximum number of nested arrays/objects allowed when |
259 | static int json_cfg_encode_number_precision(lua_State *l) | 263 | * encoding */ |
264 | static int json_cfg_encode_max_depth(lua_State *l) | ||
260 | { | 265 | { |
261 | json_config_t *cfg; | 266 | json_config_t *cfg = json_fetch_config(l); |
262 | int precision; | ||
263 | 267 | ||
264 | json_verify_arg_count(l, 1); | 268 | return json_integer_option(l, &cfg->encode_max_depth, 1, INT_MAX); |
265 | cfg = json_fetch_config(l); | 269 | } |
266 | 270 | ||
267 | if (lua_gettop(l)) { | 271 | /* Configures the maximum number of nested arrays/objects allowed when |
268 | precision = luaL_checkinteger(l, 1); | 272 | * encoding */ |
269 | luaL_argcheck(l, 1 <= precision && precision <= 14, 1, | 273 | static int json_cfg_decode_max_depth(lua_State *l) |
270 | "expected integer between 1 and 14"); | 274 | { |
271 | cfg->encode_number_precision = precision; | 275 | json_config_t *cfg = json_fetch_config(l); |
272 | } | ||
273 | 276 | ||
274 | lua_pushinteger(l, cfg->encode_number_precision); | 277 | return json_integer_option(l, &cfg->decode_max_depth, 1, INT_MAX); |
278 | } | ||
275 | 279 | ||
276 | return 1; | 280 | /* Configures number precision when converting doubles to text */ |
281 | static int json_cfg_encode_number_precision(lua_State *l) | ||
282 | { | ||
283 | json_config_t *cfg = json_fetch_config(l); | ||
284 | |||
285 | return json_integer_option(l, &cfg->encode_number_precision, 1, 14); | ||
277 | } | 286 | } |
278 | 287 | ||
279 | /* Configures JSON encoding buffer persistence */ | 288 | /* Configures JSON encoding buffer persistence */ |
@@ -387,7 +396,8 @@ static void json_create_config(lua_State *l) | |||
387 | cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT; | 396 | cfg->encode_sparse_convert = DEFAULT_SPARSE_CONVERT; |
388 | cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO; | 397 | cfg->encode_sparse_ratio = DEFAULT_SPARSE_RATIO; |
389 | cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE; | 398 | cfg->encode_sparse_safe = DEFAULT_SPARSE_SAFE; |
390 | cfg->encode_max_depth = DEFAULT_MAX_DEPTH; | 399 | cfg->encode_max_depth = DEFAULT_ENCODE_MAX_DEPTH; |
400 | cfg->decode_max_depth = DEFAULT_DECODE_MAX_DEPTH; | ||
391 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; | 401 | cfg->encode_refuse_badnum = DEFAULT_ENCODE_REFUSE_BADNUM; |
392 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; | 402 | cfg->decode_refuse_badnum = DEFAULT_DECODE_REFUSE_BADNUM; |
393 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; | 403 | cfg->encode_keep_buffer = DEFAULT_ENCODE_KEEP_BUFFER; |
@@ -1094,10 +1104,19 @@ static void json_throw_parse_error(lua_State *l, json_parse_t *json, | |||
1094 | exp, found, token->index + 1); | 1104 | exp, found, token->index + 1); |
1095 | } | 1105 | } |
1096 | 1106 | ||
1097 | static void json_decode_checkstack(lua_State *l, json_parse_t *json, int n) | 1107 | static inline void json_decode_ascend(json_parse_t *json) |
1098 | { | 1108 | { |
1099 | if (lua_checkstack(l, n)) | 1109 | json->current_depth--; |
1110 | } | ||
1111 | |||
1112 | static void json_decode_descend(lua_State *l, json_parse_t *json, int slots) | ||
1113 | { | ||
1114 | json->current_depth++; | ||
1115 | |||
1116 | if (json->current_depth <= json->cfg->decode_max_depth && | ||
1117 | lua_checkstack(l, slots)) { | ||
1100 | return; | 1118 | return; |
1119 | } | ||
1101 | 1120 | ||
1102 | strbuf_free(json->tmp); | 1121 | strbuf_free(json->tmp); |
1103 | luaL_error(l, "Too many nested data structures"); | 1122 | luaL_error(l, "Too many nested data structures"); |
@@ -1109,7 +1128,7 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json) | |||
1109 | 1128 | ||
1110 | /* 3 slots required: | 1129 | /* 3 slots required: |
1111 | * .., table, key, value */ | 1130 | * .., table, key, value */ |
1112 | json_decode_checkstack(l, json, 3); | 1131 | json_decode_descend(l, json, 3); |
1113 | 1132 | ||
1114 | lua_newtable(l); | 1133 | lua_newtable(l); |
1115 | 1134 | ||
@@ -1117,6 +1136,7 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json) | |||
1117 | 1136 | ||
1118 | /* Handle empty objects */ | 1137 | /* Handle empty objects */ |
1119 | if (token.type == T_OBJ_END) { | 1138 | if (token.type == T_OBJ_END) { |
1139 | json_decode_ascend(json); | ||
1120 | return; | 1140 | return; |
1121 | } | 1141 | } |
1122 | 1142 | ||
@@ -1140,8 +1160,10 @@ static void json_parse_object_context(lua_State *l, json_parse_t *json) | |||
1140 | 1160 | ||
1141 | json_next_token(json, &token); | 1161 | json_next_token(json, &token); |
1142 | 1162 | ||
1143 | if (token.type == T_OBJ_END) | 1163 | if (token.type == T_OBJ_END) { |
1164 | json_decode_ascend(json); | ||
1144 | return; | 1165 | return; |
1166 | } | ||
1145 | 1167 | ||
1146 | if (token.type != T_COMMA) | 1168 | if (token.type != T_COMMA) |
1147 | json_throw_parse_error(l, json, "comma or object end", &token); | 1169 | json_throw_parse_error(l, json, "comma or object end", &token); |
@@ -1158,15 +1180,17 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json) | |||
1158 | 1180 | ||
1159 | /* 2 slots required: | 1181 | /* 2 slots required: |
1160 | * .., table, value */ | 1182 | * .., table, value */ |
1161 | json_decode_checkstack(l, json, 2); | 1183 | json_decode_descend(l, json, 2); |
1162 | 1184 | ||
1163 | lua_newtable(l); | 1185 | lua_newtable(l); |
1164 | 1186 | ||
1165 | json_next_token(json, &token); | 1187 | json_next_token(json, &token); |
1166 | 1188 | ||
1167 | /* Handle empty arrays */ | 1189 | /* Handle empty arrays */ |
1168 | if (token.type == T_ARR_END) | 1190 | if (token.type == T_ARR_END) { |
1191 | json_decode_ascend(json); | ||
1169 | return; | 1192 | return; |
1193 | } | ||
1170 | 1194 | ||
1171 | for (i = 1; ; i++) { | 1195 | for (i = 1; ; i++) { |
1172 | json_process_value(l, json, &token); | 1196 | json_process_value(l, json, &token); |
@@ -1174,8 +1198,10 @@ static void json_parse_array_context(lua_State *l, json_parse_t *json) | |||
1174 | 1198 | ||
1175 | json_next_token(json, &token); | 1199 | json_next_token(json, &token); |
1176 | 1200 | ||
1177 | if (token.type == T_ARR_END) | 1201 | if (token.type == T_ARR_END) { |
1202 | json_decode_ascend(json); | ||
1178 | return; | 1203 | return; |
1204 | } | ||
1179 | 1205 | ||
1180 | if (token.type != T_COMMA) | 1206 | if (token.type != T_COMMA) |
1181 | json_throw_parse_error(l, json, "comma or array end", &token); | 1207 | json_throw_parse_error(l, json, "comma or array end", &token); |
@@ -1221,6 +1247,7 @@ static void lua_json_decode(lua_State *l, const char *json_text, int json_len) | |||
1221 | json_token_t token; | 1247 | json_token_t token; |
1222 | 1248 | ||
1223 | json.cfg = json_fetch_config(l); | 1249 | json.cfg = json_fetch_config(l); |
1250 | json.current_depth = 0; | ||
1224 | json.data = json_text; | 1251 | json.data = json_text; |
1225 | json.ptr = json.data; | 1252 | json.ptr = json.data; |
1226 | 1253 | ||
@@ -1292,6 +1319,7 @@ static int lua_cjson_new(lua_State *l) | |||
1292 | { "decode", json_decode }, | 1319 | { "decode", json_decode }, |
1293 | { "encode_sparse_array", json_cfg_encode_sparse_array }, | 1320 | { "encode_sparse_array", json_cfg_encode_sparse_array }, |
1294 | { "encode_max_depth", json_cfg_encode_max_depth }, | 1321 | { "encode_max_depth", json_cfg_encode_max_depth }, |
1322 | { "decode_max_depth", json_cfg_decode_max_depth }, | ||
1295 | { "encode_number_precision", json_cfg_encode_number_precision }, | 1323 | { "encode_number_precision", json_cfg_encode_number_precision }, |
1296 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, | 1324 | { "encode_keep_buffer", json_cfg_encode_keep_buffer }, |
1297 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, | 1325 | { "refuse_invalid_numbers", json_cfg_refuse_invalid_numbers }, |
@@ -158,6 +158,7 @@ setting = cjson.refuse_invalid_numbers([setting]) | |||
158 | depth = cjson.encode_max_depth([depth]) | 158 | depth = cjson.encode_max_depth([depth]) |
159 | convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]]) | 159 | convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]]) |
160 | keep = cjson.encode_keep_buffer([keep]) | 160 | keep = cjson.encode_keep_buffer([keep]) |
161 | depth = cjson.decode_max_depth([depth]) | ||
161 | ------------ | 162 | ------------ |
162 | 163 | ||
163 | 164 | ||
@@ -239,6 +240,31 @@ numeric key will be stored as a Lua +string+. Any code assuming type | |||
239 | +number+ may break. | 240 | +number+ may break. |
240 | 241 | ||
241 | 242 | ||
243 | [[decode_max_depth]] | ||
244 | decode_max_depth | ||
245 | ~~~~~~~~~~~~~~~~ | ||
246 | |||
247 | [source,lua] | ||
248 | ------------ | ||
249 | depth = cjson.decode_max_depth([depth]) | ||
250 | -- "depth" must be a positive integer | ||
251 | ------------ | ||
252 | |||
253 | By default, Lua CJSON will reject JSON with arrays and/or objects | ||
254 | nested more than 20 deep. | ||
255 | |||
256 | This setting is only changed when an argument is provided. The current | ||
257 | setting is always returned. | ||
258 | |||
259 | When the maximum array/object depth is exceeded Lua CJSON will throw | ||
260 | an error. An error may be thrown before the depth limit is hit if Lua | ||
261 | is unable to allocate more objects on the Lua stack. | ||
262 | |||
263 | This check prevents unnecessarily complicated JSON from slowing down | ||
264 | the application, or crashing the application due to lack of process | ||
265 | stack space. | ||
266 | |||
267 | |||
242 | encode | 268 | encode |
243 | ~~~~~~ | 269 | ~~~~~~ |
244 | 270 | ||