Limit the depth of recursion for valid JSON in the JSON1 extension in order

to avoid using excess stack space in the recursive descent parser.
Fix for ticket [981329adeef51011052667a9].

FossilOrigin-Name: 1f68c184596912d742b50b1ca38252a9e783aacf121619a27b17a7ae9f6df041
This commit is contained in:
drh 2017-04-11 18:55:05 +00:00
parent e97c9ff49a
commit ff6d50e973
4 changed files with 49 additions and 8 deletions

View File

@ -90,6 +90,7 @@ static const char jsonIsSpace[] = {
** but the definitions need to be repeated for separate compilation. */
typedef sqlite3_uint64 u64;
typedef unsigned int u32;
typedef unsigned short int u16;
typedef unsigned char u8;
#endif
@ -169,8 +170,18 @@ struct JsonParse {
u32 *aUp; /* Index of parent of each node */
u8 oom; /* Set to true if out of memory */
u8 nErr; /* Number of errors seen */
u16 iDepth; /* Nesting depth */
};
/*
** Maximum nesting depth of JSON for this implementation.
**
** This limit is needed to avoid a stack overflow in the recursive
** descent parser. A depth of 2000 is far deeper than any sane JSON
** should go.
*/
#define JSON_MAX_DEPTH 2000
/**************************************************************************
** Utility routines for dealing with JsonString objects
**************************************************************************/
@ -735,8 +746,10 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( iThis<0 ) return -1;
for(j=i+1;;j++){
while( safe_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
if( x<0 ){
pParse->iDepth--;
if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1;
return -1;
}
@ -749,6 +762,7 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( z[j]!=':' ) return -1;
j++;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
if( x<0 ) return -1;
j = x;
while( safe_isspace(z[j]) ){ j++; }
@ -765,7 +779,9 @@ static int jsonParseValue(JsonParse *pParse, u32 i){
if( iThis<0 ) return -1;
for(j=i+1;;j++){
while( safe_isspace(z[j]) ){ j++; }
if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1;
x = jsonParseValue(pParse, j);
pParse->iDepth--;
if( x<0 ){
if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1;
return -1;
@ -885,6 +901,7 @@ static int jsonParse(
i = jsonParseValue(pParse, 0);
if( pParse->oom ) i = -1;
if( i>0 ){
assert( pParse->iDepth==0 );
while( safe_isspace(zJson[i]) ) i++;
if( zJson[i] ) i = -1;
}

View File

@ -1,5 +1,5 @@
C Smaller\sand\sfaster\simplementation\sof\sexprMightBeIndexed().
D 2017-04-11T18:06:48.387
C Limit\sthe\sdepth\sof\srecursion\sfor\svalid\sJSON\sin\sthe\sJSON1\sextension\sin\sorder\nto\savoid\susing\sexcess\sstack\sspace\sin\sthe\srecursive\sdescent\sparser.\nFix\sfor\sticket\s[981329adeef51011052667a9].
D 2017-04-11T18:55:05.542
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
@ -218,7 +218,7 @@ F ext/misc/eval.c f971962e92ebb8b0a4e6b62949463ee454d88fa2
F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
F ext/misc/json1.c 70d49f69ce61e54a83a29e425e704ca3e7e42e6bd9a7cf3c112d0ad995f6560b
F ext/misc/json1.c 18d80526c34e3eab8adf6a86f7e45b873c19b33d341e76993590a3fca9aefa14
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
@ -911,7 +911,7 @@ F test/journal3.test ff8af941f9e06161d3db1b46bb9f965ff0e7f307
F test/jrnlmode.test 7864d59cf7f6e552b9b99ba0f38acd167edc10fa
F test/jrnlmode2.test 81610545a4e6ed239ea8fa661891893385e23a1d
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
F test/json101.test c0897616f32d95431f37fd291cb78742181980ac
F test/json101.test 9e68ac5c7cb3fabe22677d919ca025f80f27dde37f4e760b43f9720179ee466c
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
@ -1571,7 +1571,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 4143650c4ce32289d2301cdfc69bb10877246420f656bed122886f6803fc956a
R 1aa45dcbe6873a793fc57d44af855002
P 76cd611d41465fcec61c21520d55172cb236530f38386b7d4a5544ba87de2353
R 4121191f9cbabfb85c1e92872e6e98a5
U drh
Z c24847878c6bf2e9fe8bedbea41e582e
Z 8a8f0ee4e24e0270c8727f53d830c8c6

View File

@ -1 +1 @@
76cd611d41465fcec61c21520d55172cb236530f38386b7d4a5544ba87de2353
1f68c184596912d742b50b1ca38252a9e783aacf121619a27b17a7ae9f6df041

View File

@ -688,5 +688,29 @@ do_execsql_test json-10.95 {
SELECT json_valid('" \~ "');
} {0}
#--------------------------------------------------------------------------
# 2017-04-11. https://www.sqlite.org/src/info/981329adeef51011
# Stack overflow on deeply nested JSON.
#
# The following tests confirm that deeply nested JSON is considered invalid.
#
do_execsql_test json-11.0 {
/* Shallow enough to be parsed */
SELECT json_valid(printf('%.2000c0%.2000c','[',']'));
} {1}
do_execsql_test json-11.1 {
/* Too deep by one */
SELECT json_valid(printf('%.2001c0%.2001c','[',']'));
} {0}
do_execsql_test json-11.2 {
/* Shallow enough to be parsed { */
SELECT json_valid(replace(printf('%.2000c0%.2000c','[','}'),'[','{"a":'));
/* } */
} {1}
do_execsql_test json-11.3 {
/* Too deep by one { */
SELECT json_valid(replace(printf('%.2001c0%.2001c','[','}'),'[','{"a":'));
/* } */
} {0}
finish_test