From ce46e0eb11ea5a518034d8a8415bd1d50da6dba5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 14:01:38 +0000 Subject: [PATCH 01/10] Work toward enhanced functionality for json_valid() with deep checking of the JSONB (second argument has bit 0x08). FossilOrigin-Name: c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770 --- manifest | 15 +++-- manifest.uuid | 2 +- src/json.c | 149 ++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 136 insertions(+), 30 deletions(-) diff --git a/manifest b/manifest index f1e356acec..0ee7bf7d35 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\spotential\suse\sof\suninitialized\svalue\sin\sjson_valid()\swith\s2nd\nargument\sof\s8. -D 2023-12-11T02:39:11.053 +C Work\stoward\senhanced\sfunctionality\sfor\sjson_valid()\swith\sdeep\schecking\nof\sthe\sJSONB\s(second\sargument\shas\sbit\s0x08). +D 2023-12-11T14:01:38.458 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 022548736478f10bec4f2766f2c9fe1cc25c06b14cabb0ca64b4a1beb83fbf16 +F src/json.c 683a85f8b35a79c817b05723cee14ce7281a9f76e78d64950cfb50be10caf6d0 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9 @@ -2153,8 +2153,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 1503cba6d17e9bade7a5c103ddd23241ff4741f9a2e3032ffe2987af243dae65 -R 10c5202c73d5a29cc977b618b1930c91 +P fa102036fe46eeb71b7df3e265be1935ae5c78e0b939b08841bcfb8abadbc77a +R d66c4373e6cbfb5a424f82330e7184cd +T *branch * jsonb-valid +T *sym-jsonb-valid * +T -sym-trunk * U drh -Z 03628577bea44fb563932e72818a5e19 +Z 18d49697fdb46dc3745b2a8b7db33d7b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c4f83fcd22..b365e86e8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa102036fe46eeb71b7df3e265be1935ae5c78e0b939b08841bcfb8abadbc77a \ No newline at end of file +c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 71a1b789a4..ab69f33ce0 100644 --- a/src/json.c +++ b/src/json.c @@ -3869,6 +3869,128 @@ json_type_done: jsonParseFree(p); } +/* +** Check a single element of the JSONB in pParse for validity. +** +** The element to be checked starts at offset i and must end at on the +** last byte before iEnd. +** +** Return 0 if everything is correct. Return the 1-based byte offset of the +** error if a problem is detected. (In other words, if the error is at offset +** 0, return 1). +*/ +static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ + u32 n, sz, j, k; + const u8 *z; + u8 x; + if( iDepth>JSON_MAX_DEPTH ) return i+1; + sz = 0; + n = jsonbPayloadSize(pParse, i, &sz); + if( n==0 ) return i+1; + if( i+n+sz!=iEnd ) return i+1; + z = pParse->aBlob; + x = z[i] & 0x0f; + switch( x ){ + case JSONB_NULL: + case JSONB_TRUE: + case JSONB_FALSE: { + return n+sz==1 ? 0 : i+1; + } + default: { + return i+1; + } + case JSONB_INT: { + if( sz<1 ) return i+1; + j = i+n; + if( z[j]=='-' ){ + j++; + if( sz<2 ) return j; + } + k = i+n+sz; + while( jk ) return j+1; + sub = jsonbValidityCheck(pParse, j, k, iDepth+1); + if( sub ) return sub; + j += n + sz; + } + assert( j==k ); + return 0; + } + case JSONB_OBJECT: { + u32 cnt = 0; + u32 sub; + j = i+n; + k = j+sz; + while( jk ) return j+1; + if( (cnt & 1)==0 ){ + x = z[j] & 0x0f; + if( xJSONB_TEXTRAW ) return j+1; + } + sub = jsonbValidityCheck(pParse, j, k, iDepth+1); + if( sub ) return sub; + cnt++; + j += n + sz; + } + assert( j==k ); + if( (cnt & 1)!=0 ) return j+1; + return 0; + } + } +} + /* ** json_valid(JSON) ** json_valid(JSON, FLAGS) @@ -3954,38 +4076,19 @@ static void jsonValidFunc( case SQLITE_BLOB: { if( (flags & 0x0c)!=0 && jsonFuncArgMightBeBinary(argv[0]) ){ if( flags & 0x04 ){ - /* Superficial checking only - accomplisehd by the + /* Superficial checking only - accomplished by the ** jsonFuncArgMightBeBinary() call above. */ res = 1; }else{ /* Strict checking. Check by translating BLOB->TEXT->BLOB. If ** no errors occur, call that a "strict check". */ JsonParse px; - JsonString sx; - u8 oom = 0; + u32 iErr; memset(&px, 0, sizeof(px)); px.aBlob = (u8*)sqlite3_value_blob(argv[0]); px.nBlob = sqlite3_value_bytes(argv[0]); - jsonStringInit(&sx, 0); - jsonXlateBlobToText(&px, 0, &sx); - jsonParseReset(&px); - if( sx.eErr & JSTRING_OOM ) oom = 1; - if( sx.eErr==0 ){ - memset(&px, 0, sizeof(px)); - jsonStringTerminate(&sx); - px.zJson = sx.zBuf; - px.nJson = sx.nUsed; - if( jsonXlateTextToBlob(&px, 0)==px.nJson ){ - res = 1; - } - oom |= px.oom; - jsonParseReset(&px); - } - jsonStringReset(&sx); - if( oom ){ - sqlite3_result_error_nomem(ctx); - return; - } + iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1); + res = iErr==0; } } break; From 7d2eaae83e46ef5f41419bdd4934f7ed4217529b Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 17:03:12 +0000 Subject: [PATCH 02/10] Add SQLITE_TESTCTRL_VALIDATE_JSONB, which if enabled under SQLITE_DEBUG causes cross-checking of generate JSONB. FossilOrigin-Name: b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8 --- manifest | 25 ++--- manifest.uuid | 2 +- src/global.c | 3 + src/json.c | 288 ++++++++++++++++++++++++++++-------------------- src/main.c | 13 +++ src/shell.c.in | 7 ++ src/sqlite.h.in | 1 + src/sqliteInt.h | 3 + 8 files changed, 205 insertions(+), 137 deletions(-) diff --git a/manifest b/manifest index 0ee7bf7d35..2b659538e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Work\stoward\senhanced\sfunctionality\sfor\sjson_valid()\swith\sdeep\schecking\nof\sthe\sJSONB\s(second\sargument\shas\sbit\s0x08). -D 2023-12-11T14:01:38.458 +C Add\sSQLITE_TESTCTRL_VALIDATE_JSONB,\swhich\sif\senabled\sunder\sSQLITE_DEBUG\scauses\ncross-checking\sof\sgenerate\sJSONB. +D 2023-12-11T17:03:12.559 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -690,16 +690,16 @@ F src/expr.c 05278def9c186b5875d6903ea26148c7461b9ce0344f0fd7be9a0dfea0a4538a F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43 -F src/global.c 29f56a330ed9d1b5cd9b79ac0ca36f97ac3afc730ff8bfa987b0db9e559d684d +F src/global.c c32438e08249ca9440cccff110283bc93b65d05320c8b162e492e8aef865d15c F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 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 683a85f8b35a79c817b05723cee14ce7281a9f76e78d64950cfb50be10caf6d0 +F src/json.c ea4b13e85f81a61d0331cec790e55648785864f31eba51a74b7190e895a37ac5 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 -F src/main.c 1b89f3de98d1b59fec5bac1d66d6ece21f703821b8eaa0d53d9604c35309f6f9 +F src/main.c f8bfeb360386291b1f5b9ab216ab8d8655bdb52c977bc8287db3fbfd3f8a2611 F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 @@ -737,11 +737,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 9f55c9f3307b9888f62abe709eec245e98ff217bd14c044f93d72810bb7dc445 -F src/shell.c.in 9b6c3e641de45651ad0b5e9c26cd2f72efabee28179a5315d15c54239515ee3a -F src/sqlite.h.in d93a4821d2f792467a60f7dc81268d1bb8634f40c31694ef254cab4f9921f96a +F src/shell.c.in 64feb9fdb6829f7643b4e64e83f3b6261331474c4876abb8ebe70cfd33f25086 +F src/sqlite.h.in d6dee6231a2b248f6f2453bf9832a51694d90578f096bcfe49414c2d0211b6eb F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h 39b6fe0652c763d8ff6bd0a2427c009e5abe05fb70f5a0cb145a34bcc614fb90 +F src/sqliteInt.h f34c338e2c34e4f0795f8110ecb64ad90252306c7b3f0587ad6cf82f68e7c401 F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2153,11 +2153,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 fa102036fe46eeb71b7df3e265be1935ae5c78e0b939b08841bcfb8abadbc77a -R d66c4373e6cbfb5a424f82330e7184cd -T *branch * jsonb-valid -T *sym-jsonb-valid * -T -sym-trunk * +P c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770 +R c7157327882c9dc5aa9e50e7e992741a U drh -Z 18d49697fdb46dc3745b2a8b7db33d7b +Z 3bfa19b437a7164afac8549d2bca446e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index b365e86e8e..a11be5a493 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770 \ No newline at end of file +b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8 \ No newline at end of file diff --git a/src/global.c b/src/global.c index 60cd13e2ab..5db5565bf9 100644 --- a/src/global.c +++ b/src/global.c @@ -244,6 +244,9 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 0, /* bSmallMalloc */ 1, /* bExtraSchemaChecks */ sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ +#ifdef SQLITE_DEBUG + 0, /* bJsonbValidate */ +#endif 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */ diff --git a/src/json.c b/src/json.c index ab69f33ce0..f800dc931b 100644 --- a/src/json.c +++ b/src/json.c @@ -336,6 +336,7 @@ static u32 jsonXlateBlobToText(const JsonParse*,u32,JsonString*); static void jsonReturnParse(sqlite3_context*,JsonParse*); static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); static void jsonParseFree(JsonParse*); +static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); /************************************************************************** ** Utility routines for dealing with JsonCache objects @@ -1228,6 +1229,166 @@ static int jsonIs4HexB(const char *z, int *pOp){ return 1; } + +/* +** Check a single element of the JSONB in pParse for validity. +** +** The element to be checked starts at offset i and must end at on the +** last byte before iEnd. +** +** Return 0 if everything is correct. Return the 1-based byte offset of the +** error if a problem is detected. (In other words, if the error is at offset +** 0, return 1). +*/ +static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ + u32 n, sz, j, k; + const u8 *z; + u8 x; + if( iDepth>JSON_MAX_DEPTH ) return i+1; + sz = 0; + n = jsonbPayloadSize(pParse, i, &sz); + if( n==0 ) return i+1; + if( i+n+sz!=iEnd ) return i+1; + z = pParse->aBlob; + x = z[i] & 0x0f; + switch( x ){ + case JSONB_NULL: + case JSONB_TRUE: + case JSONB_FALSE: { + return n+sz==1 ? 0 : i+1; + } + default: { + return i+1; + } + case JSONB_INT: { + if( sz<1 ) return i+1; + j = i+n; + if( z[j]=='-' ){ + j++; + if( sz<2 ) return j; + } + k = i+n+sz; + while( jk ) return i+1; + if( z[j+1]!='.' ) return i+1; + j += 2; + seen = 1; + } + for(; j0 ) return i+1; + if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ + return i+1; + } + seen = 1; + continue; + } + if( z[j]=='e' || z[j]=='E' ){ + if( seen==2 ) return i+1; + if( j==k-1 ) return i+1; + if( z[j+1]=='+' || z[j+1]=='-' ){ + j++; + if( j==k-1 ) return i+1; + } + seen = 2; + continue; + } + return i+1; + } + return 0; + } + case JSONB_TEXT: { + return 0; + } + case JSONB_TEXTJ: + case JSONB_TEXT5: { + return 0; + } + case JSONB_TEXTRAW: { + return 0; + } + case JSONB_ARRAY: { + u32 sub; + j = i+n; + k = j+sz; + while( jk ) return j+1; + sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); + if( sub ) return sub; + j += n + sz; + } + assert( j==k ); + return 0; + } + case JSONB_OBJECT: { + u32 cnt = 0; + u32 sub; + j = i+n; + k = j+sz; + while( jk ) return j+1; + if( (cnt & 1)==0 ){ + x = z[j] & 0x0f; + if( xJSONB_TEXTRAW ) return j+1; + } + sub = jsonbValidityCheck(pParse, j, j+n+sz, iDepth+1); + if( sub ) return sub; + cnt++; + j += n + sz; + } + assert( j==k ); + if( (cnt & 1)!=0 ) return j+1; + return 0; + } + } +} + /* ** Translate a single element of JSON text at pParse->zJson[i] into ** its equivalent binary JSONB representation. Append the translation into @@ -1713,7 +1874,12 @@ static int jsonConvertTextToBlob( i = jsonXlateTextToBlob(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ +#ifdef SQLITE_DEBUG assert( pParse->iDepth==0 ); + if( sqlite3Config.bJsonbValidate ){ + assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 ); + } +#endif while( jsonIsspace(zJson[i]) ) i++; if( zJson[i] ){ i += json5Whitespace(&zJson[i]); @@ -3869,128 +4035,6 @@ json_type_done: jsonParseFree(p); } -/* -** Check a single element of the JSONB in pParse for validity. -** -** The element to be checked starts at offset i and must end at on the -** last byte before iEnd. -** -** Return 0 if everything is correct. Return the 1-based byte offset of the -** error if a problem is detected. (In other words, if the error is at offset -** 0, return 1). -*/ -static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ - u32 n, sz, j, k; - const u8 *z; - u8 x; - if( iDepth>JSON_MAX_DEPTH ) return i+1; - sz = 0; - n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ) return i+1; - if( i+n+sz!=iEnd ) return i+1; - z = pParse->aBlob; - x = z[i] & 0x0f; - switch( x ){ - case JSONB_NULL: - case JSONB_TRUE: - case JSONB_FALSE: { - return n+sz==1 ? 0 : i+1; - } - default: { - return i+1; - } - case JSONB_INT: { - if( sz<1 ) return i+1; - j = i+n; - if( z[j]=='-' ){ - j++; - if( sz<2 ) return j; - } - k = i+n+sz; - while( jk ) return j+1; - sub = jsonbValidityCheck(pParse, j, k, iDepth+1); - if( sub ) return sub; - j += n + sz; - } - assert( j==k ); - return 0; - } - case JSONB_OBJECT: { - u32 cnt = 0; - u32 sub; - j = i+n; - k = j+sz; - while( jk ) return j+1; - if( (cnt & 1)==0 ){ - x = z[j] & 0x0f; - if( xJSONB_TEXTRAW ) return j+1; - } - sub = jsonbValidityCheck(pParse, j, k, iDepth+1); - if( sub ) return sub; - cnt++; - j += n + sz; - } - assert( j==k ); - if( (cnt & 1)!=0 ) return j+1; - return 0; - } - } -} - /* ** json_valid(JSON) ** json_valid(JSON, FLAGS) diff --git a/src/main.c b/src/main.c index 6acfdc325d..553e3dc2d8 100644 --- a/src/main.c +++ b/src/main.c @@ -4659,6 +4659,19 @@ int sqlite3_test_control(int op, ...){ break; } #endif + + /* sqlite3_test_control(SQLITE_TESTCTRL_VALIDATE_JSONB, (u8)trueFalse); + ** + ** Activate or deactivate validation of JSONB that is generated from + ** text. Off by default, as the validation is slow. Validation is + ** only available if compiled using SQLITE_DEBUG. + */ + case SQLITE_TESTCTRL_VALIDATE_JSONB: { +#if defined(SQLITE_DEBUG) + sqlite3Config.bJsonbValidate = (u8)(va_arg(ap, int)&0xff); +#endif + break; + } } va_end(ap); #endif /* SQLITE_UNTESTABLE */ diff --git a/src/shell.c.in b/src/shell.c.in index 6d1312d0f8..af7b1b6cfc 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -10770,6 +10770,7 @@ static int do_meta_command(char *zLine, ShellState *p){ {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"}, + {"validate_jsonb", SQLITE_TESTCTRL_VALIDATE_JSONB,0, "BOOLEAN" }, }; int testctrl = -1; int iCtrl = -1; @@ -10974,6 +10975,12 @@ static int do_meta_command(char *zLine, ShellState *p){ isOk = 3; } break; + case SQLITE_TESTCTRL_VALIDATE_JSONB: + if( nArg==3 ){ + sqlite3_test_control(testctrl, booleanValue(azArg[2])); + isOk = 3; + } + break; } } if( isOk==0 && iCtrl>=0 ){ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index ce32b85b18..84af1c54e6 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8300,6 +8300,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ +#define SQLITE_TESTCTRL_VALIDATE_JSONB 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index a0d5962005..f2846ca6d4 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4177,6 +4177,9 @@ struct Sqlite3Config { u8 bSmallMalloc; /* Avoid large memory allocations if true */ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ u8 bUseLongDouble; /* Make use of long double */ +#ifdef SQLITE_DEBUG + u8 bJsonbValidate; /* Double-check JSONB parsing */ +#endif int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ From ba5505657f94d5eb6bb7f0bd294e0c0b35b50dae Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 19:00:44 +0000 Subject: [PATCH 03/10] Rename the new test-control to SQLITE_TESTCTRL_JSON_SELFCHECK. Make it so that the current value of the setting can be interrogated. FossilOrigin-Name: 7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d --- manifest | 22 +++++++++++----------- manifest.uuid | 2 +- src/global.c | 2 +- src/json.c | 2 +- src/main.c | 15 ++++++++++++--- src/shell.c.in | 12 ++++++++---- src/sqlite.h.in | 2 +- src/sqliteInt.h | 2 +- 8 files changed, 36 insertions(+), 23 deletions(-) diff --git a/manifest b/manifest index 2b659538e1..f0bb7f952c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sSQLITE_TESTCTRL_VALIDATE_JSONB,\swhich\sif\senabled\sunder\sSQLITE_DEBUG\scauses\ncross-checking\sof\sgenerate\sJSONB. -D 2023-12-11T17:03:12.559 +C Rename\sthe\snew\stest-control\sto\sSQLITE_TESTCTRL_JSON_SELFCHECK.\s\sMake\sit\sso\nthat\sthe\scurrent\svalue\sof\sthe\ssetting\scan\sbe\sinterrogated. +D 2023-12-11T19:00:44.322 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -690,16 +690,16 @@ F src/expr.c 05278def9c186b5875d6903ea26148c7461b9ce0344f0fd7be9a0dfea0a4538a F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c a47610f0a5c6cb0ad79f8fcef039c01833dec0c751bb695f28dc0ec6a4c3ba00 F src/func.c 472f6dcfa39cf54f89a6aec76c79c225fb880a6c14469c15d361331662b9bf43 -F src/global.c c32438e08249ca9440cccff110283bc93b65d05320c8b162e492e8aef865d15c +F src/global.c 765a0656d6cbf043cb272ff0ae38f39cc46713539ffe6793258ed3eb4b188b52 F src/hash.c 9ee4269fb1d6632a6fecfb9479c93a1f29271bddbbaf215dd60420bcb80c7220 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 ea4b13e85f81a61d0331cec790e55648785864f31eba51a74b7190e895a37ac5 +F src/json.c 484486f07aa17757c2277f4d3eac4b6ea174532ad27cd68288ed35b0e546bd15 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 -F src/main.c f8bfeb360386291b1f5b9ab216ab8d8655bdb52c977bc8287db3fbfd3f8a2611 +F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 F src/malloc.c f016922435dc7d1f1f5083a03338a3e91f8c67ce2c5bdcfa4cdef62e612f5fcc F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2 @@ -737,11 +737,11 @@ F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c F src/resolve.c d017bad7ba8e778617701a0e986fdeb393d67d6afa84fb28ef4e8b8ad2acf916 F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97 F src/select.c 9f55c9f3307b9888f62abe709eec245e98ff217bd14c044f93d72810bb7dc445 -F src/shell.c.in 64feb9fdb6829f7643b4e64e83f3b6261331474c4876abb8ebe70cfd33f25086 -F src/sqlite.h.in d6dee6231a2b248f6f2453bf9832a51694d90578f096bcfe49414c2d0211b6eb +F src/shell.c.in 0cd2ef4b3c814dded5436625ab664d9a973cbc4266a1768e3aa4cbf11bb41eca +F src/sqlite.h.in adcc7dbfeea1e69d6d487139a7e90db8a48fe998f3f5bb0f85c683e6a6fa68ca F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54 -F src/sqliteInt.h f34c338e2c34e4f0795f8110ecb64ad90252306c7b3f0587ad6cf82f68e7c401 +F src/sqliteInt.h 615524fff083abf9353aa4a3a8adca2d32b3e61e014e62b1a5335c454a386783 F src/sqliteLimit.h 33b1c9baba578d34efe7dfdb43193b366111cdf41476b1e82699e14c11ee1fb6 F src/status.c 160c445d7d28c984a0eae38c144f6419311ed3eace59b44ac6dafc20db4af749 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2153,8 +2153,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 c370d573198b151767f04e91bf8baa4ae0076751ae468c5709742a0b0ed16770 -R c7157327882c9dc5aa9e50e7e992741a +P b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8 +R 2937e9cc9e961c36660161b1501df048 U drh -Z 3bfa19b437a7164afac8549d2bca446e +Z a13ee25229a871327250064e3f63946b # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a11be5a493..d68fb2986c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8 \ No newline at end of file +7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d \ No newline at end of file diff --git a/src/global.c b/src/global.c index 5db5565bf9..7f27d91d15 100644 --- a/src/global.c +++ b/src/global.c @@ -245,7 +245,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = { 1, /* bExtraSchemaChecks */ sizeof(LONGDOUBLE_TYPE)>8, /* bUseLongDouble */ #ifdef SQLITE_DEBUG - 0, /* bJsonbValidate */ + 0, /* bJsonSelfcheck */ #endif 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ diff --git a/src/json.c b/src/json.c index f800dc931b..407705c017 100644 --- a/src/json.c +++ b/src/json.c @@ -1876,7 +1876,7 @@ static int jsonConvertTextToBlob( if( i>0 ){ #ifdef SQLITE_DEBUG assert( pParse->iDepth==0 ); - if( sqlite3Config.bJsonbValidate ){ + if( sqlite3Config.bJsonSelfcheck ){ assert( jsonbValidityCheck(pParse, 0, pParse->nBlob, 0)==0 ); } #endif diff --git a/src/main.c b/src/main.c index 553e3dc2d8..50572ef87f 100644 --- a/src/main.c +++ b/src/main.c @@ -4660,15 +4660,24 @@ int sqlite3_test_control(int op, ...){ } #endif - /* sqlite3_test_control(SQLITE_TESTCTRL_VALIDATE_JSONB, (u8)trueFalse); + /* sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &onOff); ** ** Activate or deactivate validation of JSONB that is generated from ** text. Off by default, as the validation is slow. Validation is ** only available if compiled using SQLITE_DEBUG. + ** + ** If onOff is initially 1, then turn it on. If onOff is initially + ** off, turn it off. If onOff is initially -1, then change onOff + ** to be the current setting. */ - case SQLITE_TESTCTRL_VALIDATE_JSONB: { + case SQLITE_TESTCTRL_JSON_SELFCHECK: { #if defined(SQLITE_DEBUG) - sqlite3Config.bJsonbValidate = (u8)(va_arg(ap, int)&0xff); + int *pOnOff = va_arg(ap, int*); + if( *pOnOff<0 ){ + *pOnOff = sqlite3Config.bJsonSelfcheck; + }else{ + sqlite3Config.bJsonSelfcheck = (u8)((*pOnOff)&0xff); + } #endif break; } diff --git a/src/shell.c.in b/src/shell.c.in index af7b1b6cfc..35ed0cb5c4 100644 --- a/src/shell.c.in +++ b/src/shell.c.in @@ -10756,6 +10756,7 @@ static int do_meta_command(char *zLine, ShellState *p){ {"fk_no_action", SQLITE_TESTCTRL_FK_NO_ACTION, 0, "BOOLEAN" }, {"imposter", SQLITE_TESTCTRL_IMPOSTER,1,"SCHEMA ON/OFF ROOTPAGE"}, {"internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS,0,"" }, + {"json_selfcheck", SQLITE_TESTCTRL_JSON_SELFCHECK ,0,"BOOLEAN" }, {"localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,0,"BOOLEAN" }, {"never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT,1, "BOOLEAN" }, {"optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS,0,"DISABLE-MASK" }, @@ -10770,7 +10771,6 @@ static int do_meta_command(char *zLine, ShellState *p){ {"sorter_mmap", SQLITE_TESTCTRL_SORTER_MMAP, 0, "NMAX" }, {"tune", SQLITE_TESTCTRL_TUNE, 1, "ID VALUE" }, {"uselongdouble", SQLITE_TESTCTRL_USELONGDOUBLE,0,"?BOOLEAN|\"default\"?"}, - {"validate_jsonb", SQLITE_TESTCTRL_VALIDATE_JSONB,0, "BOOLEAN" }, }; int testctrl = -1; int iCtrl = -1; @@ -10975,11 +10975,15 @@ static int do_meta_command(char *zLine, ShellState *p){ isOk = 3; } break; - case SQLITE_TESTCTRL_VALIDATE_JSONB: - if( nArg==3 ){ - sqlite3_test_control(testctrl, booleanValue(azArg[2])); + case SQLITE_TESTCTRL_JSON_SELFCHECK: + if( nArg==2 ){ + rc2 = -1; + isOk = 1; + }else{ + rc2 = booleanValue(azArg[2]); isOk = 3; } + sqlite3_test_control(testctrl, &rc2); break; } } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 84af1c54e6..1f53438142 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8300,7 +8300,7 @@ int sqlite3_test_control(int op, ...); #define SQLITE_TESTCTRL_ASSERT 12 #define SQLITE_TESTCTRL_ALWAYS 13 #define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */ -#define SQLITE_TESTCTRL_VALIDATE_JSONB 14 +#define SQLITE_TESTCTRL_JSON_SELFCHECK 14 #define SQLITE_TESTCTRL_OPTIMIZATIONS 15 #define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */ #define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f2846ca6d4..83226b5750 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4178,7 +4178,7 @@ struct Sqlite3Config { u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */ u8 bUseLongDouble; /* Make use of long double */ #ifdef SQLITE_DEBUG - u8 bJsonbValidate; /* Double-check JSONB parsing */ + u8 bJsonSelfcheck; /* Double-check JSON parsing */ #endif int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ From 74456595595d753a6b6f3f42a0505f347064d129 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 19:21:06 +0000 Subject: [PATCH 04/10] Activate JSON_SELFCHECK within fuzzcheck. FossilOrigin-Name: 4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/fuzzcheck.c | 2 ++ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index f0bb7f952c..770abb234a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rename\sthe\snew\stest-control\sto\sSQLITE_TESTCTRL_JSON_SELFCHECK.\s\sMake\sit\sso\nthat\sthe\scurrent\svalue\sof\sthe\ssetting\scan\sbe\sinterrogated. -D 2023-12-11T19:00:44.322 +C Activate\sJSON_SELFCHECK\swithin\sfuzzcheck. +D 2023-12-11T19:21:06.298 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1229,7 +1229,7 @@ F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634 F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830 F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2 -F test/fuzzcheck.c 69b8549e112fb815931a8c14c7955a0c407ae91a79356eecb82458384f2cb989 +F test/fuzzcheck.c 442b0b02146bb905c47c4ee1388949e7fd9d27acf22d9535e9abf216e582b956 F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517 F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba @@ -2153,8 +2153,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 b410a4db74a650003539ffaaea18519d5159b504daac47db6a4874b730f40ac8 -R 2937e9cc9e961c36660161b1501df048 +P 7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d +R 73f673c74c17eaf64270ba7fabaefbeb U drh -Z a13ee25229a871327250064e3f63946b +Z 036937c49ad3c44a290e0f1c7a504e81 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index d68fb2986c..c7f1e82f00 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d \ No newline at end of file +4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5 \ No newline at end of file diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c index 23200a5f03..d71335510d 100644 --- a/test/fuzzcheck.c +++ b/test/fuzzcheck.c @@ -1267,6 +1267,8 @@ int runCombinedDbSqlInput( } sqlite3_limit(cx.db, SQLITE_LIMIT_LIKE_PATTERN_LENGTH, 100); sqlite3_hard_heap_limit64(heapLimit); + rc = 1; + sqlite3_test_control(SQLITE_TESTCTRL_JSON_SELFCHECK, &rc); if( nDb>=20 && aDb[18]==2 && aDb[19]==2 ){ aDb[18] = aDb[19] = 1; From 001caa714fc29ca13aa86605aa2c18a47f875430 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 20:19:10 +0000 Subject: [PATCH 05/10] json_valid(*,8) allows minus-signs on hexadecimal literals. FossilOrigin-Name: c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 4 ++++ 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 770abb234a..29dc28440b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Activate\sJSON_SELFCHECK\swithin\sfuzzcheck. -D 2023-12-11T19:21:06.298 +C json_valid(*,8)\sallows\sminus-signs\son\shexadecimal\sliterals. +D 2023-12-11T20:19:10.982 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 484486f07aa17757c2277f4d3eac4b6ea174532ad27cd68288ed35b0e546bd15 +F src/json.c d0c018e1d9dba58c09518b15b4d0a1847bc8be7f7f050524618b486c8e286db8 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 7aff1d9a4cb17ecd5abab21ab032f35a78741dd641ddd8cbcc85fc4a81a0707d -R 73f673c74c17eaf64270ba7fabaefbeb +P 4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5 +R a882161352f3e912beb8ce222b601993 U drh -Z 036937c49ad3c44a290e0f1c7a504e81 +Z 09da734bc01fda75ed726fff4da7e465 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c7f1e82f00..c1e7de9ccc 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5 \ No newline at end of file +c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 407705c017..b735987734 100644 --- a/src/json.c +++ b/src/json.c @@ -1280,6 +1280,10 @@ static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ case JSONB_INT5: { if( sz<3 ) return i+1; j = i+n; + if( z[j]=='-' ){ + if( sz<4 ) return i+1; + j++; + } if( z[j]!='0' ) return j+1; if( z[j+1]!='x' && z[j+1]!='X' ) return j+2; j += 2; From 5a890b4ed2b0f5732fa370dfbae295aa41748e0b Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 20:44:21 +0000 Subject: [PATCH 06/10] json_error_position() now uses jsonValidityCheck() to find the approximate position of an error in a JSONB blob. FossilOrigin-Name: c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 14 ++++---------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 29dc28440b..2e4f529d17 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C json_valid(*,8)\sallows\sminus-signs\son\shexadecimal\sliterals. -D 2023-12-11T20:19:10.982 +C json_error_position()\snow\suses\sjsonValidityCheck()\sto\sfind\sthe\sapproximate\nposition\sof\san\serror\sin\sa\sJSONB\sblob. +D 2023-12-11T20:44:21.543 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 d0c018e1d9dba58c09518b15b4d0a1847bc8be7f7f050524618b486c8e286db8 +F src/json.c 191626c46afe3325a01c1a77b7aef6b10b8dc8a76c38757adeca89e51a4248db F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 4d14e733bb521aed65e98533969d2303738232ae87dab70fdf7962e6513195f5 -R a882161352f3e912beb8ce222b601993 +P c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350 +R 3b1676d0420fc714545bd48a8af4a295 U drh -Z 09da734bc01fda75ed726fff4da7e465 +Z 901bf4bbda4e9c3a1530e623c45e3a19 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index c1e7de9ccc..825ac56d41 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350 \ No newline at end of file +c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8 \ No newline at end of file diff --git a/src/json.c b/src/json.c index b735987734..fd741f696d 100644 --- a/src/json.c +++ b/src/json.c @@ -4170,9 +4170,9 @@ static void jsonValidFunc( ** ** If the argument is NULL, return NULL ** -** If the argument is BLOB, do a fast validity check and return non-zero -** if the check fails. The returned value does not indicate where in the -** BLOB the error occurs. +** If the argument is BLOB, do a full validity check and return non-zero +** if the check fails. The return value is the approximate 1-based offset +** to the byte of the element that contains the first error. ** ** Otherwise interpret the argument is TEXT (even if it is numeric) and ** return the 1-based character position for where the parser first recognized @@ -4191,15 +4191,9 @@ static void jsonErrorFunc( UNUSED_PARAMETER(argc); memset(&s, 0, sizeof(s)); if( jsonFuncArgMightBeBinary(argv[0]) ){ - JsonString out; - jsonStringInit(&out, 0); s.aBlob = (u8*)sqlite3_value_blob(argv[0]); s.nBlob = sqlite3_value_bytes(argv[0]); - jsonXlateBlobToText(&s, 0, &out); - if( out.eErr ){ - iErrPos = (out.eErr & JSTRING_MALFORMED)!=0 ? 1 : -1; - } - jsonStringReset(&out); + iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 0); }else{ s.zJson = (char*)sqlite3_value_text(argv[0]); if( s.zJson==0 ) return; /* NULL input or OOM */ From ad6bc61804547bab9e358809a9281a2facdbadd8 Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 11 Dec 2023 21:00:55 +0000 Subject: [PATCH 07/10] The json_error_position() function now reports an approximate byte offset to the problem in a JSONB if there is a problem. FossilOrigin-Name: 80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 30 +++++++++++++++++------------- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/manifest b/manifest index 2e4f529d17..ada03e02f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C json_error_position()\snow\suses\sjsonValidityCheck()\sto\sfind\sthe\sapproximate\nposition\sof\san\serror\sin\sa\sJSONB\sblob. -D 2023-12-11T20:44:21.543 +C The\sjson_error_position()\sfunction\snow\sreports\san\sapproximate\sbyte\soffset\nto\sthe\sproblem\sin\sa\sJSONB\sif\sthere\sis\sa\sproblem. +D 2023-12-11T21:00:55.202 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 191626c46afe3325a01c1a77b7aef6b10b8dc8a76c38757adeca89e51a4248db +F src/json.c 387dd9d7d63bac1e0068d66e8b40d86e1e2f0edc6930da28c67584c7a5a32872 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 c0d7f4520d839a268b3fd2474d0897a9832aa608bd6238b3e287fabecf07a350 -R 3b1676d0420fc714545bd48a8af4a295 +P c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8 +R eef20549bb0818034c7a80cb1490f371 U drh -Z 901bf4bbda4e9c3a1530e623c45e3a19 +Z 99dd825f602cc4286df6f3fcbe1570d6 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 825ac56d41..07345f0192 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8 \ No newline at end of file +80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd \ No newline at end of file diff --git a/src/json.c b/src/json.c index fd741f696d..31367fe544 100644 --- a/src/json.c +++ b/src/json.c @@ -1240,7 +1240,12 @@ static int jsonIs4HexB(const char *z, int *pOp){ ** error if a problem is detected. (In other words, if the error is at offset ** 0, return 1). */ -static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ +static u32 jsonbValidityCheck( + const JsonParse *pParse, /* Input JSONB. Only aBlob and nBlob are used */ + u32 i, /* Start of element as pParse->aBlob[i] */ + u32 iEnd, /* One more than the last byte of the element */ + u32 iDepth /* Current nesting depth */ +){ u32 n, sz, j, k; const u8 *z; u8 x; @@ -1265,7 +1270,7 @@ static u32 jsonbValidityCheck(JsonParse *pParse, u32 i, u32 iEnd, u32 iDepth){ j = i+n; if( z[j]=='-' ){ j++; - if( sz<2 ) return j; + if( sz<2 ) return i+1; } k = i+n+sz; while( jk ) return i+1; - if( z[j+1]!='.' ) return i+1; - j += 2; - seen = 1; + if( j+3>k ) return j+1; + if( z[j+1]!='.' && z[j+1]!='e' && z[j+1]!='E' ) return j+1; + j++; } for(; j0 ) return i+1; if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ - return i+1; + return j+1; } seen = 1; continue; } if( z[j]=='e' || z[j]=='E' ){ - if( seen==2 ) return i+1; - if( j==k-1 ) return i+1; + if( seen==2 ) return j+1; + if( j==k-1 ) return j+1; if( z[j+1]=='+' || z[j+1]=='-' ){ j++; - if( j==k-1 ) return i+1; + if( j==k-1 ) return j+1; } seen = 2; continue; } - return i+1; + return j+1; } return 0; } From cc1a39fd247cf90af0ae59304206faf7ecb61819 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 12 Dec 2023 02:31:12 +0000 Subject: [PATCH 08/10] Validity checking of text nodes in JSONB. FossilOrigin-Name: fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 41 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index ada03e02f1..91ba64c3dd 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C The\sjson_error_position()\sfunction\snow\sreports\san\sapproximate\sbyte\soffset\nto\sthe\sproblem\sin\sa\sJSONB\sif\sthere\sis\sa\sproblem. -D 2023-12-11T21:00:55.202 +C Validity\schecking\sof\stext\snodes\sin\sJSONB. +D 2023-12-12T02:31:12.655 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 387dd9d7d63bac1e0068d66e8b40d86e1e2f0edc6930da28c67584c7a5a32872 +F src/json.c 34f829db190ae485926855da651d349eedb35fa56010266e14c0b094f536c9f5 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 c3d60cf7028a333b825d5b89516945a73e0c158ac81d8bcc117d21bfd98602c8 -R eef20549bb0818034c7a80cb1490f371 +P 80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd +R 8ac47232b4f02631d44b831db0790bc1 U drh -Z 99dd825f602cc4286df6f3fcbe1570d6 +Z 8178cefe916c4486a65df71a751de097 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 07345f0192..208d3cd26d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd \ No newline at end of file +fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e \ No newline at end of file diff --git a/src/json.c b/src/json.c index 31367fe544..17ebc769cc 100644 --- a/src/json.c +++ b/src/json.c @@ -176,7 +176,9 @@ static const char jsonSpaces[] = "\011\012\015\040"; /* ** Characters that are special to JSON. Control characters, -** '"' and '\\'. +** '"' and '\\' and '\''. Actually, '\'' is not special to +** canonical JSON, but it is special in JSON-5, so we include +** it in the set of special characters. */ static const char jsonIsOk[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -337,6 +339,7 @@ static void jsonReturnParse(sqlite3_context*,JsonParse*); static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32); static void jsonParseFree(JsonParse*); static u32 jsonbPayloadSize(const JsonParse*, u32, u32*); +static u32 jsonUnescapeOneChar(const char*, u32, u32*); /************************************************************************** ** Utility routines for dealing with JsonCache objects @@ -1346,10 +1349,42 @@ static u32 jsonbValidityCheck( return 0; } case JSONB_TEXT: { + j = i+n; + k = j+sz; + while( j=k ){ + return j+1; + }else if( strchr("\"\\/bfnrt",z[j+1])!=0 ){ + j++; + }else if( z[j+1]=='u' ){ + if( j+5>=k ) return j+1; + if( !jsonIs4Hex((const char*)&z[j+2]) ) return j+1; + j++; + }else if( x!=JSONB_TEXT5 ){ + return j+1; + }else{ + u32 c = 0; + u32 szC = jsonUnescapeOneChar((const char*)&z[j], k-j, &c); + if( c==0xfffd ) return j+1; + j += szC - 1; + } + } + j++; + } return 0; } case JSONB_TEXTRAW: { @@ -1625,6 +1660,8 @@ json_parse_restart: /* Control characters are not allowed in strings */ pParse->iErr = j; return -1; + }else if( c=='"' ){ + opcode = JSONB_TEXT5; } j++; } @@ -2084,13 +2121,13 @@ static u32 jsonXlateBlobToText( } break; } + case JSONB_TEXT: case JSONB_TEXTJ: { jsonAppendChar(pOut, '"'); jsonAppendRaw(pOut, (const char*)&pParse->aBlob[i+n], sz); jsonAppendChar(pOut, '"'); break; } - case JSONB_TEXT: case JSONB_TEXT5: { const char *zIn; u32 k; From 87399a56db384f4ebf188652132ef0f29cd57b75 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 12 Dec 2023 14:33:52 +0000 Subject: [PATCH 09/10] Improvements to JSONB validation - catch more cases where the input does not conform to spec. FossilOrigin-Name: be1864eac4eb75cc30bf98f73092c8608467f4bd956240df6a0cbea9f1e09e85 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 12 +++++++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/manifest b/manifest index 91ba64c3dd..2e875799d2 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Validity\schecking\sof\stext\snodes\sin\sJSONB. -D 2023-12-12T02:31:12.655 +C Improvements\sto\sJSONB\svalidation\s-\scatch\smore\scases\swhere\sthe\sinput\sdoes\nnot\sconform\sto\sspec. +D 2023-12-12T14:33:52.419 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 34f829db190ae485926855da651d349eedb35fa56010266e14c0b094f536c9f5 +F src/json.c 6fc223a6cf1f475dfe72376018615ed85a1415b57121571ad65747f8b845b57f F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 80d5d94dff6a2d2557039be3d7d47c1a6003c4b98defe0bd411acfeb963ad5dd -R 8ac47232b4f02631d44b831db0790bc1 +P fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e +R 06eab0897027e01e7643ca8237160284 U drh -Z 8178cefe916c4486a65df71a751de097 +Z fe2966c205a693292efc9fe6aaf9e427 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 208d3cd26d..8f1ff9f03a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e \ No newline at end of file +be1864eac4eb75cc30bf98f73092c8608467f4bd956240df6a0cbea9f1e09e85 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 17ebc769cc..5487f04022 100644 --- a/src/json.c +++ b/src/json.c @@ -1265,9 +1265,6 @@ static u32 jsonbValidityCheck( case JSONB_FALSE: { return n+sz==1 ? 0 : i+1; } - default: { - return i+1; - } case JSONB_INT: { if( sz<1 ) return i+1; j = i+n; @@ -1316,6 +1313,7 @@ static u32 jsonbValidityCheck( if( sz<3 ) return i+1; } if( z[j]=='.' ){ + if( x==JSONB_FLOAT ) return j+1; if( !sqlite3Isdigit(z[j+1]) ) return j+1; j += 2; seen = 1; @@ -1327,7 +1325,7 @@ static u32 jsonbValidityCheck( for(; j0 ) return i+1; + if( seen>0 ) return j+1; if( x==JSONB_FLOAT && (j==k-1 || !sqlite3Isdigit(z[j+1])) ){ return j+1; } @@ -1346,6 +1344,7 @@ static u32 jsonbValidityCheck( } return j+1; } + if( seen==0 ) return i+1; return 0; } case JSONB_TEXT: { @@ -1429,6 +1428,9 @@ static u32 jsonbValidityCheck( if( (cnt & 1)!=0 ) return j+1; return 0; } + default: { + return i+1; + } } } @@ -4234,7 +4236,7 @@ static void jsonErrorFunc( if( jsonFuncArgMightBeBinary(argv[0]) ){ s.aBlob = (u8*)sqlite3_value_blob(argv[0]); s.nBlob = sqlite3_value_bytes(argv[0]); - iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 0); + iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1); }else{ s.zJson = (char*)sqlite3_value_text(argv[0]); if( s.zJson==0 ) return; /* NULL input or OOM */ From 78e636bba65e57b364263418bdde2417752bd9fc Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 12 Dec 2023 17:13:10 +0000 Subject: [PATCH 10/10] Add NEVER to two unreachable branches in JSON. FossilOrigin-Name: c96ebb086feb89341565cc52b970ae7799ce1327fe1ad4fc790f1b0dcaa6e229 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/json.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 2e875799d2..2ef2ef6944 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improvements\sto\sJSONB\svalidation\s-\scatch\smore\scases\swhere\sthe\sinput\sdoes\nnot\sconform\sto\sspec. -D 2023-12-12T14:33:52.419 +C Add\sNEVER\sto\stwo\sunreachable\sbranches\sin\sJSON. +D 2023-12-12T17:13:10.122 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,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 6fc223a6cf1f475dfe72376018615ed85a1415b57121571ad65747f8b845b57f +F src/json.c cd270629b4b99d065522b45c3d2b5185491b1ab3544843c6f780aa50755d54dc F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36 F src/main.c ce714ee501122c76eb2e69b292bebe443aba611fc3b88e6786eb910285515fe4 @@ -2153,8 +2153,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 fa5160687c2f970d407e8af73c246f7cd806bb4ce35f29a79ac534a8646a6c8e -R 06eab0897027e01e7643ca8237160284 +P be1864eac4eb75cc30bf98f73092c8608467f4bd956240df6a0cbea9f1e09e85 +R 6e221a94cd5525fe9f8a7e94ea467b60 U drh -Z fe2966c205a693292efc9fe6aaf9e427 +Z 2ea9e875faf360824d045f495f8867aa # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8f1ff9f03a..838b8ad2ba 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -be1864eac4eb75cc30bf98f73092c8608467f4bd956240df6a0cbea9f1e09e85 \ No newline at end of file +c96ebb086feb89341565cc52b970ae7799ce1327fe1ad4fc790f1b0dcaa6e229 \ No newline at end of file diff --git a/src/json.c b/src/json.c index 5487f04022..e94cac6d52 100644 --- a/src/json.c +++ b/src/json.c @@ -1255,8 +1255,8 @@ static u32 jsonbValidityCheck( if( iDepth>JSON_MAX_DEPTH ) return i+1; sz = 0; n = jsonbPayloadSize(pParse, i, &sz); - if( n==0 ) return i+1; - if( i+n+sz!=iEnd ) return i+1; + if( NEVER(n==0) ) return i+1; /* Checked by caller */ + if( NEVER(i+n+sz!=iEnd) ) return i+1; /* Checked by caller */ z = pParse->aBlob; x = z[i] & 0x0f; switch( x ){