aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua_cjson.c98
-rw-r--r--manual.txt26
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
128typedef struct { 132typedef 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
135typedef struct { 140typedef 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 */ 243static int json_integer_option(lua_State *l, int *setting, int min, int max)
239static 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
259static int json_cfg_encode_number_precision(lua_State *l) 263 * encoding */
264static 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, 273static 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 */
281static 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
1097static void json_decode_checkstack(lua_State *l, json_parse_t *json, int n) 1107static inline void json_decode_ascend(json_parse_t *json)
1098{ 1108{
1099 if (lua_checkstack(l, n)) 1109 json->current_depth--;
1110}
1111
1112static 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 },
diff --git a/manual.txt b/manual.txt
index 99681cc..13454be 100644
--- a/manual.txt
+++ b/manual.txt
@@ -158,6 +158,7 @@ setting = cjson.refuse_invalid_numbers([setting])
158depth = cjson.encode_max_depth([depth]) 158depth = cjson.encode_max_depth([depth])
159convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]]) 159convert, ratio, safe = cjson.encode_sparse_array([convert[, ratio[, safe]]])
160keep = cjson.encode_keep_buffer([keep]) 160keep = cjson.encode_keep_buffer([keep])
161depth = 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]]
244decode_max_depth
245~~~~~~~~~~~~~~~~
246
247[source,lua]
248------------
249depth = cjson.decode_max_depth([depth])
250-- "depth" must be a positive integer
251------------
252
253By default, Lua CJSON will reject JSON with arrays and/or objects
254nested more than 20 deep.
255
256This setting is only changed when an argument is provided. The current
257setting is always returned.
258
259When the maximum array/object depth is exceeded Lua CJSON will throw
260an error. An error may be thrown before the depth limit is hit if Lua
261is unable to allocate more objects on the Lua stack.
262
263This check prevents unnecessarily complicated JSON from slowing down
264the application, or crashing the application due to lack of process
265stack space.
266
267
242encode 268encode
243~~~~~~ 269~~~~~~
244 270