mirror of
https://github.com/sqlite/sqlite.git
synced 2025-12-24 14:17:58 +03:00
Do a better job of providing bug compatibility with SQLite 3.44.0. See
[forum:/forumpost/07e206fcd6|forum thread 07e206fcd6] for background. FossilOrigin-Name: 614d061b32c3bdf4825323d6f8e8a98624e4eeeb96dd442d8e365527122ed3bc
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
||||
C Update\sto\scomments\sin\ssqlite3session.h.
|
||||
D 2025-04-19T20:08:04.182
|
||||
C Do\sa\sbetter\sjob\sof\sproviding\sbug\scompatibility\swith\sSQLite\s3.44.0.\s\sSee\n[forum:/forumpost/07e206fcd6|forum\sthread\s07e206fcd6]\sfor\sbackground.
|
||||
D 2025-04-21T19:53:12.406
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -746,7 +746,7 @@ F src/hash.h 46b92795a95bfefb210f52f0c316e9d7cdbcdd7e7fcfb0d8be796d3a5767cddf
|
||||
F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c d05934dfab2c5c0c480fc6fd2038f11215661de08ea6ff38d2563216bd555c1b
|
||||
F src/json.c d0e1c62a9689018fe5876b1a1eb574e4ab7a40e0928e0e5adda8b3860c70e1b8
|
||||
F src/json.c d13d5e29d18b1b711d832cab48f48fab6705747abbac0ab65953c06eba74c99d
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
|
||||
F src/main.c 07f78d917ffcdf327982840cfd8e855fd000527a2ea5ace372ce4febcbd0bf97
|
||||
@@ -2216,8 +2216,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 00313d15270b36fce44f7784c97ddc42517e23c209c1ccc4d814ef06b11528c0
|
||||
R 8e876785cd8a9f724c2edd8d86d424db
|
||||
U dan
|
||||
Z ad6897ab80a5e3b64556d94fd097e39b
|
||||
P ea9acb5573f4d71a314e4467d30477a1d01c8db648985750a42b3c047f404c9c
|
||||
R ead9acfd8b581f4510534b8b584f9293
|
||||
U drh
|
||||
Z dd601f105d2c079fb81118dbb59f331e
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
@@ -1 +1 @@
|
||||
ea9acb5573f4d71a314e4467d30477a1d01c8db648985750a42b3c047f404c9c
|
||||
614d061b32c3bdf4825323d6f8e8a98624e4eeeb96dd442d8e365527122ed3bc
|
||||
|
||||
109
src/json.c
109
src/json.c
@@ -398,7 +398,7 @@ struct JsonParse {
|
||||
** Forward references
|
||||
**************************************************************************/
|
||||
static void jsonReturnStringAsBlob(JsonString*);
|
||||
static int jsonFuncArgMightBeBinary(sqlite3_value *pJson);
|
||||
static int jsonArgIsJsonb(sqlite3_value *pJson, JsonParse *p);
|
||||
static u32 jsonTranslateBlobToText(const JsonParse*,u32,JsonString*);
|
||||
static void jsonReturnParse(sqlite3_context*,JsonParse*);
|
||||
static JsonParse *jsonParseFuncArg(sqlite3_context*,sqlite3_value*,u32);
|
||||
@@ -816,11 +816,9 @@ static void jsonAppendSqlValue(
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if( jsonFuncArgMightBeBinary(pValue) ){
|
||||
JsonParse px;
|
||||
memset(&px, 0, sizeof(px));
|
||||
px.aBlob = (u8*)sqlite3_value_blob(pValue);
|
||||
px.nBlob = sqlite3_value_bytes(pValue);
|
||||
JsonParse px;
|
||||
memset(&px, 0, sizeof(px));
|
||||
if( jsonArgIsJsonb(pValue, &px) ){
|
||||
jsonTranslateBlobToText(&px, 0, p);
|
||||
}else if( p->eErr==0 ){
|
||||
sqlite3_result_error(p->pCtx, "JSON cannot hold BLOB values", -1);
|
||||
@@ -1396,7 +1394,7 @@ static u32 jsonbValidityCheck(
|
||||
case JSONB_INT5: {
|
||||
if( sz<3 ) return i+1;
|
||||
j = i+n;
|
||||
if( z[j]=='-' ){
|
||||
if( z[j]=='-' || z[j]=='+' ){
|
||||
if( sz<4 ) return i+1;
|
||||
j++;
|
||||
}
|
||||
@@ -2494,33 +2492,6 @@ static u32 jsonTranslateBlobToPrettyText(
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/* Return true if the input pJson
|
||||
**
|
||||
** For performance reasons, this routine does not do a detailed check of the
|
||||
** input BLOB to ensure that it is well-formed. Hence, false positives are
|
||||
** possible. False negatives should never occur, however.
|
||||
*/
|
||||
static int jsonFuncArgMightBeBinary(sqlite3_value *pJson){
|
||||
u32 sz, n;
|
||||
const u8 *aBlob;
|
||||
int nBlob;
|
||||
JsonParse s;
|
||||
if( sqlite3_value_type(pJson)!=SQLITE_BLOB ) return 0;
|
||||
aBlob = sqlite3_value_blob(pJson);
|
||||
nBlob = sqlite3_value_bytes(pJson);
|
||||
if( nBlob<1 ) return 0;
|
||||
if( NEVER(aBlob==0) || (aBlob[0] & 0x0f)>JSONB_OBJECT ) return 0;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.aBlob = (u8*)aBlob;
|
||||
s.nBlob = nBlob;
|
||||
n = jsonbPayloadSize(&s, 0, &sz);
|
||||
if( n==0 ) return 0;
|
||||
if( sz+n!=(u32)nBlob ) return 0;
|
||||
if( (aBlob[0] & 0x0f)<=JSONB_FALSE && sz>0 ) return 0;
|
||||
return sz+n==(u32)nBlob;
|
||||
}
|
||||
|
||||
/*
|
||||
** Given that a JSONB_ARRAY object starts at offset i, return
|
||||
** the number of entries in that array.
|
||||
@@ -3348,10 +3319,7 @@ static int jsonFunctionArgToBlob(
|
||||
return 0;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
if( jsonFuncArgMightBeBinary(pArg) ){
|
||||
pParse->aBlob = (u8*)sqlite3_value_blob(pArg);
|
||||
pParse->nBlob = sqlite3_value_bytes(pArg);
|
||||
}else{
|
||||
if( !jsonArgIsJsonb(pArg, pParse) ){
|
||||
sqlite3_result_error(ctx, "JSON cannot hold BLOB values", -1);
|
||||
return 1;
|
||||
}
|
||||
@@ -3502,27 +3470,43 @@ jsonInsertIntoBlob_patherror:
|
||||
/*
|
||||
** If pArg is a blob that seems like a JSONB blob, then initialize
|
||||
** p to point to that JSONB and return TRUE. If pArg does not seem like
|
||||
** a JSONB blob, then return FALSE;
|
||||
** a JSONB blob, then return FALSE.
|
||||
**
|
||||
** This routine is only called if it is already known that pArg is a
|
||||
** blob. The only open question is whether or not the blob appears
|
||||
** to be a JSONB blob.
|
||||
** For small BLOBs (having no more than 7 bytes of payload) a full
|
||||
** validity check is done. So for small BLOBs this routine only returns
|
||||
** true if the value is guaranteed to be a valid JSONB. For larger BLOBs
|
||||
** (8 byte or more of payload) only the size of the outermost element is
|
||||
** checked to verify that the BLOB is superficially valid JSONB.
|
||||
**
|
||||
** A full JSONB validation is done on smaller BLOBs because those BLOBs might
|
||||
** also be text JSON that has been incorrectly cast into a BLOB.
|
||||
** (See tag-20240123-a and https://sqlite.org/forum/forumpost/012136abd5)
|
||||
** If the BLOB is 9 bytes are larger, then it is not possible for the
|
||||
** superficial size check done here to pass if the input is really text
|
||||
** JSON so we do not need to look deeper in that case.
|
||||
**
|
||||
** Why we only need to do full JSONB validation for smaller BLOBs:
|
||||
**
|
||||
** The first byte of valid JSON text must be one of: '{', '[', '"', ' ', '\n',
|
||||
** '\r', '\t', '-', or a digit '0' through '9'. Of these, only a subset
|
||||
** can also be the first byte of JSONB: '{', '[', '\n', '\t', and digits '3'
|
||||
** through '9'. In every one of those cases, the payload size is 7 bytes
|
||||
** or less. So if we do full JSONB validation for every BLOB where the
|
||||
** payload is less than 7 bytes, we will never get a false positive for
|
||||
** JSONB on an input that is really text JSON.
|
||||
*/
|
||||
static int jsonArgIsJsonb(sqlite3_value *pArg, JsonParse *p){
|
||||
u32 n, sz = 0;
|
||||
if( sqlite3_value_type(pArg)!=SQLITE_BLOB ) return 0;
|
||||
p->aBlob = (u8*)sqlite3_value_blob(pArg);
|
||||
p->nBlob = (u32)sqlite3_value_bytes(pArg);
|
||||
if( p->nBlob==0 ){
|
||||
p->aBlob = 0;
|
||||
return 0;
|
||||
}
|
||||
if( NEVER(p->aBlob==0) ){
|
||||
return 0;
|
||||
}
|
||||
if( (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
|
||||
if( p->nBlob>0
|
||||
&& ALWAYS(p->aBlob!=0)
|
||||
&& (p->aBlob[0] & 0x0f)<=JSONB_OBJECT
|
||||
&& (n = jsonbPayloadSize(p, 0, &sz))>0
|
||||
&& sz+n==p->nBlob
|
||||
&& ((p->aBlob[0] & 0x0f)>JSONB_FALSE || sz==0)
|
||||
&& (sz>7 || (sz&1)==0 || jsonbValidityCheck(p, 0, p->nBlob, 1)==0)
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
@@ -4615,21 +4599,17 @@ static void jsonValidFunc(
|
||||
return;
|
||||
}
|
||||
case SQLITE_BLOB: {
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
if( flags & 0x04 ){
|
||||
JsonParse py;
|
||||
memset(&py, 0, sizeof(py));
|
||||
if( jsonArgIsJsonb(argv[0], &py) ){
|
||||
if( (flags & 0x04)!=0 || py.nBlob<=7 ){
|
||||
/* Superficial checking only - accomplished by the
|
||||
** jsonFuncArgMightBeBinary() call above. */
|
||||
** jsonArgIsJsonb() call above. */
|
||||
res = 1;
|
||||
}else if( flags & 0x08 ){
|
||||
/* Strict checking. Check by translating BLOB->TEXT->BLOB. If
|
||||
** no errors occur, call that a "strict check". */
|
||||
JsonParse px;
|
||||
u32 iErr;
|
||||
memset(&px, 0, sizeof(px));
|
||||
px.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
px.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
iErr = jsonbValidityCheck(&px, 0, px.nBlob, 1);
|
||||
res = iErr==0;
|
||||
res = 0==jsonbValidityCheck(&py, 0, py.nBlob, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4687,9 +4667,7 @@ static void jsonErrorFunc(
|
||||
UNUSED_PARAMETER(argc);
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.db = sqlite3_context_db_handle(ctx);
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
s.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
s.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
if( jsonArgIsJsonb(argv[0], &s) ){
|
||||
iErrPos = (i64)jsonbValidityCheck(&s, 0, s.nBlob, 1);
|
||||
}else{
|
||||
s.zJson = (char*)sqlite3_value_text(argv[0]);
|
||||
@@ -5374,9 +5352,8 @@ static int jsonEachFilter(
|
||||
memset(&p->sParse, 0, sizeof(p->sParse));
|
||||
p->sParse.nJPRef = 1;
|
||||
p->sParse.db = p->db;
|
||||
if( jsonFuncArgMightBeBinary(argv[0]) ){
|
||||
p->sParse.nBlob = sqlite3_value_bytes(argv[0]);
|
||||
p->sParse.aBlob = (u8*)sqlite3_value_blob(argv[0]);
|
||||
if( jsonArgIsJsonb(argv[0], &p->sParse) ){
|
||||
/* We have JSONB */
|
||||
}else{
|
||||
p->sParse.zJson = (char*)sqlite3_value_text(argv[0]);
|
||||
p->sParse.nJson = sqlite3_value_bytes(argv[0]);
|
||||
|
||||
Reference in New Issue
Block a user