aboutsummaryrefslogtreecommitdiff
path: root/ext/misc/json1.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2017-04-11 18:55:05 +0000
committerdrh <drh@noemail.net>2017-04-11 18:55:05 +0000
commitff6d50e973f597c1ab3ead0ea7d553d41b608a8d (patch)
treea63e74bdc4b935ac43608a15523e8ae49bbf5993 /ext/misc/json1.c
parente97c9ff49adaa4906f935f2e52e355110c806218 (diff)
downloadsqlite-ff6d50e973f597c1ab3ead0ea7d553d41b608a8d.tar.gz
sqlite-ff6d50e973f597c1ab3ead0ea7d553d41b608a8d.zip
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
Diffstat (limited to 'ext/misc/json1.c')
-rw-r--r--ext/misc/json1.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/ext/misc/json1.c b/ext/misc/json1.c
index 0d1b9a464..486eaa428 100644
--- a/ext/misc/json1.c
+++ b/ext/misc/json1.c
@@ -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;
}