# HG changeset patch # User jbe # Date 1406678484 -7200 # Node ID a686ed2ce96764fb557e2256eece89bf3bc2c1f4 # Parent ca27aae3f1a189bc0536da8eecefbc9bcbaab4be Protect json.import(...) against Lua stack overflows (or integer overflows) due to too many nested levels diff -r ca27aae3f1a1 -r a686ed2ce967 libraries/json/json.c --- a/libraries/json/json.c Wed Jul 30 01:47:01 2014 +0200 +++ b/libraries/json/json.c Wed Jul 30 02:01:24 2014 +0200 @@ -3,6 +3,8 @@ #include #include +#define JSON_MAXDEPTH 100 + #define JSON_REGENT static char #define JSON_REGREF void * @@ -118,8 +120,6 @@ // if a JSON object is not expected here, then return an error: if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE) goto json_import_syntax_error; - // consume input character: - pos++; // create JSON object on stack: lua_newtable(L); // set metatable of JSON object: @@ -131,18 +131,14 @@ lua_pushvalue(L, -2); lua_pushvalue(L, -2); lua_rawset(L, json_import_shadowtbl_idx); - // increment level: - level++; // expect object key (or end of object) and continue with loop: mode = JSON_STATE_OBJECT_KEY; - goto json_import_loop; + goto json_import_open; // new JSON array: case '[': // if a JSON array is not expected here, then return an error: if (mode != JSON_STATE_VALUE && mode != JSON_STATE_OBJECT_VALUE && mode != JSON_STATE_ARRAY_VALUE) goto json_import_syntax_error; - // consume input character: - pos++; // create JSON array on stack: lua_newtable(L); // set metatable of JSON array: @@ -156,10 +152,24 @@ lua_rawset(L, json_import_shadowtbl_idx); // add nil as key (needed to keep stack balance) and as magic to detect arrays: lua_pushnil(L); + // expect array value (or end of array) and continue with loop: + mode = JSON_STATE_ARRAY_VALUE; + // continue with common code for opening JSON object and JSON array: + // commn code for opening JSON object or JSON array: + json_import_open: + // limit nested levels: + if (level >= JSON_MAXDEPTH) { + lua_pushnil(L); + lua_pushliteral(L, "Too many nested JSON levels"); + return 2; + } + // additional buffer overflow protection: + if (!lua_checkstack(L, LUA_MINSTACK)) + return luaL_error(L, "Caught stack overflow in JSON import function (too many nested levels and stack size too small)"); // increment level: level++; - // expect array value (or end of array) and continue with loop: - mode = JSON_STATE_ARRAY_VALUE; + // consume input character: + pos++; goto json_import_loop; // end of JSON object: case '}':