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;