From: drh <> Date: Sun, 3 Dec 2023 23:30:59 +0000 (+0000) Subject: Avoid problems when the path argument to json_tree() contains embedded U+0000 X-Git-Tag: version-3.45.0~116^2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=16e8a5b2f35450711d9c8bac8326ca79718d86e0;p=thirdparty%2Fsqlite.git Avoid problems when the path argument to json_tree() contains embedded U+0000 characters. FossilOrigin-Name: 9f055091af01a5dddba1a7e9868ad030c8f206237e1569215cb161e53e54aa71 --- diff --git a/manifest b/manifest index 31e68565bc..fb3e811b9c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Ensure\sthat\sOOM\sconditions\sin\sthe\sgeneration\sof\sthe\s"bad\sJSON\spath"\serror\nmessage\sresult\sin\san\sSQLITE_NOMEM\serror. -D 2023-12-03T20:11:35.681 +C Avoid\sproblems\swhen\sthe\spath\sargument\sto\sjson_tree()\scontains\sembedded\sU+0000\ncharacters. +D 2023-12-03T23:30:59.212 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -688,7 +688,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276 -F src/json.c 6d92343776fe32e9d703d6e13c1d1883d75e1fd17e081159dd257b21a859f5f9 +F src/json.c 6ac93a6cc3cbfa8be1b4058c7aa335ede339a36b65be5fdde0593bd428ee74cc F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9 @@ -2145,8 +2145,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4d6a9a217df6792b41766b774fb0c0553b45f9104c26a0955bf4a30862d7d7bf -R 1defa3c713a22ae4567d6d3fb033b34d +P aa0e02b5c26a2ef3d6216a0ed8bc01382be43173485f898cb63f2a8c559f2e74 +R 04d47333f96a5f7bc80310aa6a2b6c34 U drh -Z e3833547911441ddc3c3cd95bc32393c +Z 051e2555795818c726068d0b4b3820ce # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c9937a03fa..a0e2cc933f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -aa0e02b5c26a2ef3d6216a0ed8bc01382be43173485f898cb63f2a8c559f2e74 \ No newline at end of file +9f055091af01a5dddba1a7e9868ad030c8f206237e1569215cb161e53e54aa71 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 9fcfd3e10f..f7e1591ad2 100644 --- a/src/json.c +++ b/src/json.c @@ -3082,59 +3082,6 @@ static void jsonbTest2( ** Scalar SQL function implementations ****************************************************************************/ -/* SQL Function: jsonb(JSON) -** -** Convert the input argument into JSONB (the SQLite binary encoding of -** JSON). -** -** If the input is TEXT, or NUMERIC, try to parse it as JSON. If the fails, -** raise an error. Otherwise, return the resulting BLOB value. -** -** If the input is a BLOB, check to see if the input is a plausible -** JSONB. If it is, return it unchanged. Raise an error if it is not. -** Note that there could be internal inconsistencies in the BLOB - this -** routine does not do a full byte-for-byte validity check of the -** JSON blob. -** -** If the input is NULL, return NULL. -*/ -static void jsonbFunc( - sqlite3_context *ctx, - int argc, - sqlite3_value **argv -){ - JsonParse *pParse; - int nJson; - const char *zJson; - JsonParse x; - UNUSED_PARAMETER(argc); - - if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ - /* No-op */ - }else if( jsonFuncArgMightBeBinary(argv[0]) ){ - sqlite3_result_value(ctx, argv[0]); - }else{ - zJson = (const char*)sqlite3_value_text(argv[0]); - if( zJson==0 ) return; - nJson = sqlite3_value_bytes(argv[0]); - pParse = &x; - memset(&x, 0, sizeof(x)); - x.zJson = (char*)zJson; - x.nJson = nJson; - if( jsonConvertTextToBlob(pParse, ctx) ){ - sqlite3_result_error(ctx, "malformed JSON", -1); - }else{ - assert( pParse->nBlobAlloc>0 ); - assert( !pParse->bReadOnly ); - sqlite3_result_blob(ctx, pParse->aBlob, pParse->nBlob, sqlite3_free); - pParse->aBlob = 0; - pParse->nBlob = 0; - pParse->nBlobAlloc = 0; - } - jsonParseReset(pParse); - } -} - /* ** Implementation of the json_quote(VALUE) function. Return a JSON value ** corresponding to the SQL value input. Mostly this means putting @@ -3271,9 +3218,10 @@ static void jsonExtractFunc( for(i=1; ipCtx = ctx; z = (const char*)sqlite3_value_text(argv[0]); - n = (u32)sqlite3_value_bytes(argv[0]); + n = z ? sqlite3Strlen30(z) : 0; jsonAppendString(pStr, z, n); jsonAppendChar(pStr, ':'); jsonAppendSqlValue(pStr, argv[1]); @@ -4462,15 +4410,16 @@ static int jsonEachPathLength(JsonEachCursor *p){ if( p->iRowid==0 && p->bRecursive && n>1 ){ if( p->path.zBuf[n-1]==']' ){ do{ - n--; assert( n>0 ); + n--; }while( p->path.zBuf[n]!='[' ); }else{ u32 sz = 0; jsonbPayloadSize(&p->sParse, p->i, &sz); if( p->path.zBuf[n-1]=='"' ) sz += 2; + assert( szpath.zBuf[n]!='.' ){ + while( p->path.zBuf[n]!='.' && ALWAYS(n>0) ){ n--; assert( n>0 ); } @@ -4666,11 +4615,15 @@ static int jsonEachFilter( if( idxNum==0 ) return SQLITE_OK; memset(&p->sParse, 0, sizeof(p->sParse)); p->sParse.nJPRef = 1; - if( jsonFuncArgMightBeBinary(argv[0]) ){ - p->sParse.nBlob = sqlite3_value_bytes(argv[0]); - p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); - if( p->sParse.aBlob==0 ){ - return SQLITE_NOMEM; + if( sqlite3_value_type(argv[0])==SQLITE_BLOB ){ + if( jsonFuncArgMightBeBinary(argv[0]) ){ + p->sParse.nBlob = sqlite3_value_bytes(argv[0]); + p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]); + if( p->sParse.aBlob==0 ){ + return SQLITE_NOMEM; + } + }else{ + goto json_each_malformed_input; } }else{ p->sParse.zJson = (char*)sqlite3_value_text(argv[0]); @@ -4683,10 +4636,7 @@ static int jsonEachFilter( if( p->sParse.oom ){ return SQLITE_NOMEM; } - sqlite3_free(cur->pVtab->zErrMsg); - cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); - jsonEachCursorReset(p); - return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; + goto json_each_malformed_input; } } if( idxNum==3 ){ @@ -4698,7 +4648,7 @@ static int jsonEachFilter( jsonEachCursorReset(p); return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } - p->nRoot = sqlite3_value_bytes(argv[1]); + p->nRoot = sqlite3Strlen30(zRoot); if( zRoot[1]==0 ){ i = p->i = 0; p->eType = 0; @@ -4747,6 +4697,12 @@ static int jsonEachFilter( p->aParent[0].iValue = i; } return SQLITE_OK; + +json_each_malformed_input: + sqlite3_free(cur->pVtab->zErrMsg); + cur->pVtab->zErrMsg = sqlite3_mprintf("malformed JSON"); + jsonEachCursorReset(p); + return cur->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM; } /* The methods of the json_each virtual table */ @@ -4822,7 +4778,7 @@ void sqlite3RegisterJsonFunctions(void){ /* Number of arguments ---, | | | | ,--- Flags */ /* | | | | | | */ JFUNCTION(json, 1,1,1, 0,0,0, jsonRemoveFunc), - JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonbFunc), + JFUNCTION(jsonb, 1,1,0, 0,1,0, jsonRemoveFunc), JFUNCTION(json_array, -1,0,1, 1,0,0, jsonArrayFunc), JFUNCTION(jsonb_array, -1,0,1, 1,1,0, jsonArrayFunc), JFUNCTION(json_array_length, 1,1,0, 0,0,0, jsonArrayLengthFunc),