| | @@ -16,11 +16,11 @@ |
| 16 | 16 | ** if you want a wrapper to interface SQLite with your choice of programming |
| 17 | 17 | ** language. The code for the "sqlite3" command-line shell is also in a |
| 18 | 18 | ** separate file. This file contains only code for the core SQLite library. |
| 19 | 19 | ** |
| 20 | 20 | ** The content in this amalgamation comes from Fossil check-in |
| 21 | | -** 2c605bfb1562d7a3609ad6ffd7446def12f1 with changes in files: |
| 21 | +** 4cb349370daab17123770c814c71872a3e4c with changes in files: |
| 22 | 22 | ** |
| 23 | 23 | ** |
| 24 | 24 | */ |
| 25 | 25 | #ifndef SQLITE_AMALGAMATION |
| 26 | 26 | #define SQLITE_CORE 1 |
| | @@ -467,14 +467,14 @@ |
| 467 | 467 | ** [sqlite3_libversion_number()], [sqlite3_sourceid()], |
| 468 | 468 | ** [sqlite_version()] and [sqlite_source_id()]. |
| 469 | 469 | */ |
| 470 | 470 | #define SQLITE_VERSION "3.54.0" |
| 471 | 471 | #define SQLITE_VERSION_NUMBER 3054000 |
| 472 | | -#define SQLITE_SOURCE_ID "2026-05-30 13:23:25 2c605bfb1562d7a3609ad6ffd7446def12f1ac7084e41b9c6723e998c156501d" |
| 472 | +#define SQLITE_SOURCE_ID "2026-06-08 18:15:27 4cb349370daab17123770c814c71872a3e4c616a3f984569b3d7f97f9c3f5ea0" |
| 473 | 473 | #define SQLITE_SCM_BRANCH "trunk" |
| 474 | 474 | #define SQLITE_SCM_TAGS "" |
| 475 | | -#define SQLITE_SCM_DATETIME "2026-05-30T13:23:25.636Z" |
| 475 | +#define SQLITE_SCM_DATETIME "2026-06-08T18:15:27.790Z" |
| 476 | 476 | |
| 477 | 477 | /* |
| 478 | 478 | ** CAPI3REF: Run-Time Library Version Numbers |
| 479 | 479 | ** KEYWORDS: sqlite3_version sqlite3_sourceid |
| 480 | 480 | ** |
| | @@ -33389,12 +33389,12 @@ |
| 33389 | 33389 | if( flag_alternateform ){ |
| 33390 | 33390 | /* For %#q, do unistr()-style backslash escapes for |
| 33391 | 33391 | ** all control characters, and for backslash itself. |
| 33392 | 33392 | ** For %#Q, do the same but only if there is at least |
| 33393 | 33393 | ** one control character. */ |
| 33394 | | - u32 nBack = 0; |
| 33395 | | - u32 nCtrl = 0; |
| 33394 | + i64 nBack = 0; |
| 33395 | + i64 nCtrl = 0; |
| 33396 | 33396 | for(k=0; k<i; k++){ |
| 33397 | 33397 | if( escarg[k]=='\\' ){ |
| 33398 | 33398 | nBack++; |
| 33399 | 33399 | }else if( ((u8*)escarg)[k]<=0x1f ){ |
| 33400 | 33400 | nCtrl++; |
| | @@ -56926,26 +56926,28 @@ |
| 56926 | 56926 | szBulk = -1024 * (i64)pcache1.nInitPage; |
| 56927 | 56927 | } |
| 56928 | 56928 | if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ |
| 56929 | 56929 | szBulk = pCache->szAlloc*(i64)pCache->nMax; |
| 56930 | 56930 | } |
| 56931 | | - zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 56932 | | - sqlite3EndBenignMalloc(); |
| 56933 | | - if( zBulk ){ |
| 56934 | | - int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| 56935 | | - do{ |
| 56936 | | - PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; |
| 56937 | | - pX->page.pBuf = zBulk; |
| 56938 | | - pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); |
| 56939 | | - assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); |
| 56940 | | - pX->isBulkLocal = 1; |
| 56941 | | - pX->isAnchor = 0; |
| 56942 | | - pX->pNext = pCache->pFree; |
| 56943 | | - pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ |
| 56944 | | - pCache->pFree = pX; |
| 56945 | | - zBulk += pCache->szAlloc; |
| 56946 | | - }while( --nBulk ); |
| 56931 | + if( szBulk>=pCache->szAlloc ){ |
| 56932 | + zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); |
| 56933 | + sqlite3EndBenignMalloc(); |
| 56934 | + if( zBulk ){ |
| 56935 | + int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; |
| 56936 | + do{ |
| 56937 | + PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; |
| 56938 | + pX->page.pBuf = zBulk; |
| 56939 | + pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); |
| 56940 | + assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); |
| 56941 | + pX->isBulkLocal = 1; |
| 56942 | + pX->isAnchor = 0; |
| 56943 | + pX->pNext = pCache->pFree; |
| 56944 | + pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ |
| 56945 | + pCache->pFree = pX; |
| 56946 | + zBulk += pCache->szAlloc; |
| 56947 | + }while( --nBulk ); |
| 56948 | + } |
| 56947 | 56949 | } |
| 56948 | 56950 | return pCache->pFree!=0; |
| 56949 | 56951 | } |
| 56950 | 56952 | |
| 56951 | 56953 | /* |
| | @@ -83086,10 +83088,15 @@ |
| 83086 | 83088 | if( pc+info.nSize>usableSize ){ |
| 83087 | 83089 | checkAppendMsg(pCheck, "Extends off end of page"); |
| 83088 | 83090 | doCoverageCheck = 0; |
| 83089 | 83091 | continue; |
| 83090 | 83092 | } |
| 83093 | + if( info.nPayload && info.pPayload[0]<2 ){ |
| 83094 | + checkAppendMsg(pCheck, "Bad cell header size"); |
| 83095 | + doCoverageCheck = 0; |
| 83096 | + continue; |
| 83097 | + } |
| 83091 | 83098 | |
| 83092 | 83099 | /* Check for integer primary key out of range */ |
| 83093 | 83100 | if( pPage->intKey ){ |
| 83094 | 83101 | if( keyCanBeEqual ? (info.nKey > maxKey) : (info.nKey >= maxKey) ){ |
| 83095 | 83102 | checkAppendMsg(pCheck, "Rowid %lld out of order", info.nKey); |
| | @@ -84596,12 +84603,12 @@ |
| 84596 | 84603 | /* Work-around for GCC bug or bugs: |
| 84597 | 84604 | ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96270 |
| 84598 | 84605 | ** https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114659 |
| 84599 | 84606 | ** The problem appears to be fixed in GCC 15 */ |
| 84600 | 84607 | i64 x; |
| 84601 | | - assert( (MEM_Str&~p->flags)*4==sizeof(x) ); |
| 84602 | | - memcpy(&x, (char*)&p->u, (MEM_Str&~p->flags)*4); |
| 84608 | + assert( (sqlite3Config.bSmallMalloc!=0xee)*8==sizeof(x) ); |
| 84609 | + memcpy(&x, (char*)&p->u.i, (sqlite3Config.bSmallMalloc!=0xee)*8); |
| 84603 | 84610 | p->n = sqlite3Int64ToText(x, zBuf); |
| 84604 | 84611 | #else |
| 84605 | 84612 | p->n = sqlite3Int64ToText(p->u.i, zBuf); |
| 84606 | 84613 | #endif |
| 84607 | 84614 | if( p->flags & MEM_IntReal ){ |
| | @@ -95448,11 +95455,11 @@ |
| 95448 | 95455 | QueryPerformanceCounter(&tm); |
| 95449 | 95456 | return (sqlite3_uint64)tm.QuadPart; |
| 95450 | 95457 | } |
| 95451 | 95458 | |
| 95452 | 95459 | #elif !defined(__STRICT_ANSI__) && defined(__GNUC__) && \ |
| 95453 | | - (defined(i386) || defined(__i386__) || defined(_M_IX86)) |
| 95460 | + (defined(i586) || defined(__i586__) || defined(_M_IX86)) |
| 95454 | 95461 | |
| 95455 | 95462 | __inline__ sqlite_uint64 sqlite3Hwtime(void){ |
| 95456 | 95463 | unsigned int lo, hi; |
| 95457 | 95464 | __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); |
| 95458 | 95465 | return (sqlite_uint64)hi << 32 | lo; |
| | @@ -110164,11 +110171,11 @@ |
| 110164 | 110171 | /* |
| 110165 | 110172 | ** cnt==0 means there was not match. |
| 110166 | 110173 | ** cnt>1 means there were two or more matches. |
| 110167 | 110174 | ** |
| 110168 | 110175 | ** cnt==0 is always an error. cnt>1 is often an error, but might |
| 110169 | | - ** be multiple matches for a NATURAL LEFT JOIN or a LEFT JOIN USING. |
| 110176 | + ** be multiple matches for a NATURAL OUTER JOIN or a OUTER JOIN USING. |
| 110170 | 110177 | */ |
| 110171 | 110178 | assert( pFJMatch==0 || cnt>0 ); |
| 110172 | 110179 | assert( !ExprHasProperty(pExpr, EP_xIsSelect|EP_IntValue) ); |
| 110173 | 110180 | if( cnt!=1 ){ |
| 110174 | 110181 | const char *zErr; |
| | @@ -110247,12 +110254,21 @@ |
| 110247 | 110254 | pExpr->op = eNewExprOp; |
| 110248 | 110255 | lookupname_end: |
| 110249 | 110256 | if( cnt==1 ){ |
| 110250 | 110257 | assert( pNC!=0 ); |
| 110251 | 110258 | #ifndef SQLITE_OMIT_AUTHORIZATION |
| 110252 | | - if( db->xAuth && (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER) ){ |
| 110253 | | - sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); |
| 110259 | + if( db->xAuth ){ |
| 110260 | + if( pFJMatch ){ |
| 110261 | + assert( pExpr->op==TK_FUNCTION ); |
| 110262 | + assert( sqlite3_stricmp(pExpr->u.zToken,"coalesce")==0 ); |
| 110263 | + assert( pExpr->x.pList==pFJMatch ); |
| 110264 | + assert( pFJMatch->nExpr>0 ); |
| 110265 | + pExpr = pFJMatch->a[0].pExpr; |
| 110266 | + } |
| 110267 | + if( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER ){ |
| 110268 | + sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList); |
| 110269 | + } |
| 110254 | 110270 | } |
| 110255 | 110271 | #endif |
| 110256 | 110272 | /* Increment the nRef value on all name contexts from TopNC up to |
| 110257 | 110273 | ** the point where the name matched. */ |
| 110258 | 110274 | for(;;){ |
| | @@ -115930,10 +115946,11 @@ |
| 115930 | 115946 | if( i!=nVector ){ |
| 115931 | 115947 | /* Need to reorder the LHS fields according to aiMap */ |
| 115932 | 115948 | int rLhsOrig = rLhs; |
| 115933 | 115949 | rLhs = sqlite3GetTempRange(pParse, nVector); |
| 115934 | 115950 | for(i=0; i<nVector; i++){ |
| 115951 | + testcase( aiMap[i]!=i ); |
| 115935 | 115952 | sqlite3VdbeAddOp3(v, OP_Copy, rLhsOrig+i, rLhs+aiMap[i], 0); |
| 115936 | 115953 | } |
| 115937 | 115954 | sqlite3ReleaseTempReg(pParse, rLhsOrig); |
| 115938 | 115955 | } |
| 115939 | 115956 | } |
| | @@ -115950,11 +115967,12 @@ |
| 115950 | 115967 | } |
| 115951 | 115968 | for(i=0; i<nVector; i++){ |
| 115952 | 115969 | Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i); |
| 115953 | 115970 | if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error; |
| 115954 | 115971 | if( sqlite3ExprCanBeNull(p) ){ |
| 115955 | | - sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2); |
| 115972 | + testcase( aiMap[i]!=i ); |
| 115973 | + sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2); |
| 115956 | 115974 | VdbeCoverage(v); |
| 115957 | 115975 | } |
| 115958 | 115976 | } |
| 115959 | 115977 | |
| 115960 | 115978 | /* Step 3. The LHS is now known to be non-NULL. Do the binary search |
| | @@ -116024,13 +116042,23 @@ |
| 116024 | 116042 | for(i=0; i<nVector; i++){ |
| 116025 | 116043 | Expr *p; |
| 116026 | 116044 | CollSeq *pColl; |
| 116027 | 116045 | int r3 = sqlite3GetTempReg(pParse); |
| 116028 | 116046 | p = sqlite3VectorFieldSubexpr(pLeft, i); |
| 116029 | | - pColl = sqlite3ExprCollSeq(pParse, p); |
| 116030 | | - sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3); |
| 116031 | | - sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3, |
| 116047 | + if( ExprUseXSelect(pExpr) ){ |
| 116048 | + Expr *pRhs = pExpr->x.pSelect->pEList->a[i].pExpr; |
| 116049 | + pColl = sqlite3BinaryCompareCollSeq(pParse, p, pRhs); |
| 116050 | + }else{ |
| 116051 | + /* If the RHS of the IN(...) expression are scalar expressions, do |
| 116052 | + ** not consider their collation sequences. The documentation says |
| 116053 | + ** "The collating sequence used for expressions of the form "x IN (y, z, |
| 116054 | + ** ...)" is the collating sequence of x.". */ |
| 116055 | + pColl = sqlite3ExprCollSeq(pParse, p); |
| 116056 | + } |
| 116057 | + testcase( aiMap[i]!=i ); |
| 116058 | + sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3); |
| 116059 | + sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3, |
| 116032 | 116060 | (void*)pColl, P4_COLLSEQ); |
| 116033 | 116061 | VdbeCoverage(v); |
| 116034 | 116062 | sqlite3ReleaseTempReg(pParse, r3); |
| 116035 | 116063 | } |
| 116036 | 116064 | sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfNull); |
| | @@ -133231,13 +133259,22 @@ |
| 133231 | 133259 | x.nUsed = 0; |
| 133232 | 133260 | x.apArg = argv+1; |
| 133233 | 133261 | sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]); |
| 133234 | 133262 | str.printfFlags = SQLITE_PRINTF_SQLFUNC; |
| 133235 | 133263 | sqlite3_str_appendf(&str, zFormat, &x); |
| 133236 | | - n = str.nChar; |
| 133237 | | - sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 133238 | | - SQLITE_DYNAMIC); |
| 133264 | + if( str.accError==SQLITE_OK ){ |
| 133265 | + n = str.nChar; |
| 133266 | + sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n, |
| 133267 | + SQLITE_DYNAMIC); |
| 133268 | + }else{ |
| 133269 | + if( str.accError==SQLITE_NOMEM ){ |
| 133270 | + sqlite3_result_error_nomem(context); |
| 133271 | + }else{ |
| 133272 | + sqlite3_result_error_toobig(context); |
| 133273 | + } |
| 133274 | + sqlite3_str_reset(&str); |
| 133275 | + } |
| 133239 | 133276 | } |
| 133240 | 133277 | } |
| 133241 | 133278 | |
| 133242 | 133279 | /* |
| 133243 | 133280 | ** Implementation of the substr() function. |
| | @@ -135867,49 +135904,54 @@ |
| 135867 | 135904 | int iGt; /* Entries at or after a[iGt] are greater than rPivot */ |
| 135868 | 135905 | int i; /* Loop counter */ |
| 135869 | 135906 | double rPivot; /* The pivot value */ |
| 135870 | 135907 | |
| 135871 | 135908 | assert( n>=2 ); |
| 135872 | | - if( a[0]>a[n-1] ){ |
| 135873 | | - SWAP_DOUBLE(a[0],a[n-1]) |
| 135874 | | - } |
| 135875 | | - if( n==2 ) return; |
| 135876 | | - iGt = n-1; |
| 135877 | | - i = n/2; |
| 135878 | | - if( a[0]>a[i] ){ |
| 135879 | | - SWAP_DOUBLE(a[0],a[i]) |
| 135880 | | - }else if( a[i]>a[iGt] ){ |
| 135881 | | - SWAP_DOUBLE(a[i],a[iGt]) |
| 135882 | | - } |
| 135883 | | - if( n==3 ) return; |
| 135884 | | - rPivot = a[i]; |
| 135885 | | - iLt = i = 1; |
| 135886 | | - do{ |
| 135887 | | - if( a[i]<rPivot ){ |
| 135888 | | - if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt]) |
| 135889 | | - iLt++; |
| 135890 | | - i++; |
| 135891 | | - }else if( a[i]>rPivot ){ |
| 135892 | | - do{ |
| 135893 | | - iGt--; |
| 135894 | | - }while( iGt>i && a[iGt]>rPivot ); |
| 135895 | | - SWAP_DOUBLE(a[i],a[iGt]) |
| 135896 | | - }else{ |
| 135897 | | - i++; |
| 135898 | | - } |
| 135899 | | - }while( i<iGt ); |
| 135900 | | - if( iLt>=2 ) percentSort(a, iLt); |
| 135901 | | - if( n-iGt>=2 ) percentSort(a+iGt, n-iGt); |
| 135902 | | - |
| 135903 | | -/* Uncomment for testing */ |
| 135904 | | -#if 0 |
| 135905 | | - for(i=0; i<n-1; i++){ |
| 135906 | | - assert( a[i]<=a[i+1] ); |
| 135907 | | - } |
| 135908 | | -#endif |
| 135909 | | -} |
| 135910 | | - |
| 135909 | + do{ |
| 135910 | + if( a[0]>a[n-1] ){ |
| 135911 | + SWAP_DOUBLE(a[0],a[n-1]) |
| 135912 | + } |
| 135913 | + if( n==2 ) return; |
| 135914 | + iGt = n-1; |
| 135915 | + i = n/2; |
| 135916 | + if( a[0]>a[i] ){ |
| 135917 | + SWAP_DOUBLE(a[0],a[i]) |
| 135918 | + }else if( a[i]>a[iGt] ){ |
| 135919 | + SWAP_DOUBLE(a[i],a[iGt]) |
| 135920 | + } |
| 135921 | + if( n==3 ) return; |
| 135922 | + rPivot = a[i]; |
| 135923 | + iLt = i = 1; |
| 135924 | + do{ |
| 135925 | + if( a[i]<rPivot ){ |
| 135926 | + if( i>iLt ) SWAP_DOUBLE(a[i],a[iLt]) |
| 135927 | + iLt++; |
| 135928 | + i++; |
| 135929 | + }else if( a[i]>rPivot ){ |
| 135930 | + do{ |
| 135931 | + iGt--; |
| 135932 | + }while( iGt>i && a[iGt]>rPivot ); |
| 135933 | + SWAP_DOUBLE(a[i],a[iGt]) |
| 135934 | + }else{ |
| 135935 | + i++; |
| 135936 | + } |
| 135937 | + }while( i<iGt ); |
| 135938 | + |
| 135939 | + /* Recurse on the smaller partition only. The smaller partition |
| 135940 | + ** will hold n/2 or fewer entries, which assures that the stack |
| 135941 | + ** depth will not exceed O(log(n)), even for pathological cases. |
| 135942 | + ** Loop without recursion for the larger partition. */ |
| 135943 | + if( iLt>n/2 ){ |
| 135944 | + if( n-iGt>=2 ) percentSort(a+iGt, n-iGt); |
| 135945 | + n = iLt; |
| 135946 | + }else{ |
| 135947 | + if( iLt>=2 ) percentSort(a, iLt); |
| 135948 | + a += iGt; |
| 135949 | + n -= iGt; |
| 135950 | + } |
| 135951 | + }while( n>=2 ); |
| 135952 | +} |
| 135911 | 135953 | |
| 135912 | 135954 | /* |
| 135913 | 135955 | ** The "inverse" function for percentile(Y,P) is called to remove a |
| 135914 | 135956 | ** row that was previously inserted by "step". |
| 135915 | 135957 | */ |
| | @@ -155479,12 +155521,15 @@ |
| 155479 | 155521 | ** Then, if CheckOnCtx.iJoin indicates that this expression is part of an |
| 155480 | 155522 | ** ON clause from that SrcList (i.e. if iJoin is non-zero), check that it |
| 155481 | 155523 | ** does not refer to a table to the right of CheckOnCtx.iJoin. */ |
| 155482 | 155524 | do { |
| 155483 | 155525 | SrcList *pSrc = pCtx->pSrc; |
| 155526 | + int nSrc = pSrc->nSrc; |
| 155484 | 155527 | int iTab = pExpr->iTable; |
| 155485 | | - if( iTab>=pSrc->a[0].iCursor && iTab<=pSrc->a[pSrc->nSrc-1].iCursor ){ |
| 155528 | + int ii; |
| 155529 | + for(ii=0; ii<nSrc && pSrc->a[ii].iCursor!=iTab; ii++){} |
| 155530 | + if( ii<nSrc ){ |
| 155486 | 155531 | if( pCtx->iJoin && iTab>pCtx->iJoin ){ |
| 155487 | 155532 | sqlite3ErrorMsg(pWalker->pParse, |
| 155488 | 155533 | "%s references tables to its right", |
| 155489 | 155534 | (pCtx->bFuncArg ? "table-function argument" : "ON clause") |
| 155490 | 155535 | ); |
| | @@ -165680,10 +165725,11 @@ |
| 165680 | 165725 | assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); |
| 165681 | 165726 | pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.x.leftColumn, notReady, |
| 165682 | 165727 | WO_EQ|WO_IN|WO_IS, 0); |
| 165683 | 165728 | if( pAlt==0 ) continue; |
| 165684 | 165729 | if( pAlt->wtFlags & (TERM_CODED) ) continue; |
| 165730 | + if( ExprHasProperty(pAlt->pExpr, EP_Collate) ) continue; |
| 165685 | 165731 | if( (pAlt->eOperator & WO_IN) |
| 165686 | 165732 | && ExprUseXSelect(pAlt->pExpr) |
| 165687 | 165733 | && (pAlt->pExpr->x.pSelect->pEList->nExpr>1) |
| 165688 | 165734 | ){ |
| 165689 | 165735 | continue; |
| | @@ -166433,11 +166479,14 @@ |
| 166433 | 166479 | ** Mark term iChild as being a child of term iParent |
| 166434 | 166480 | */ |
| 166435 | 166481 | static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){ |
| 166436 | 166482 | pWC->a[iChild].iParent = iParent; |
| 166437 | 166483 | pWC->a[iChild].truthProb = pWC->a[iParent].truthProb; |
| 166484 | + assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) ); |
| 166438 | 166485 | pWC->a[iParent].nChild++; |
| 166486 | + testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) ); |
| 166487 | + |
| 166439 | 166488 | } |
| 166440 | 166489 | |
| 166441 | 166490 | /* |
| 166442 | 166491 | ** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not |
| 166443 | 166492 | ** a conjunction, then return just pTerm when N==0. If N is exceeds |
| | @@ -166872,21 +166921,22 @@ |
| 166872 | 166921 | ** 1. The SQLITE_Transitive optimization must be enabled |
| 166873 | 166922 | ** 2. Must be either an == or an IS operator |
| 166874 | 166923 | ** 3. Not originating in the ON clause of an OUTER JOIN |
| 166875 | 166924 | ** 4. The operator is not IS or else the query does not contain RIGHT JOIN |
| 166876 | 166925 | ** 5. The affinities of A and B must be compatible |
| 166877 | | -** 6. Both operands use the same collating sequence |
| 166926 | +** 6. Both operands use the same collating sequence, and they must not |
| 166927 | +** use explicit COLLATE clauses. |
| 166878 | 166928 | ** If this routine returns TRUE, that means that the RHS can be substituted |
| 166879 | 166929 | ** for the LHS anyplace else in the WHERE clause where the LHS column occurs. |
| 166880 | 166930 | ** This is an optimization. No harm comes from returning 0. But if 1 is |
| 166881 | 166931 | ** returned when it should not be, then incorrect answers might result. |
| 166882 | 166932 | */ |
| 166883 | 166933 | static int termIsEquivalence(Parse *pParse, Expr *pExpr, SrcList *pSrc){ |
| 166884 | 166934 | char aff1, aff2; |
| 166885 | 166935 | if( !OptimizationEnabled(pParse->db, SQLITE_Transitive) ) return 0; /* (1) */ |
| 166886 | 166936 | if( pExpr->op!=TK_EQ && pExpr->op!=TK_IS ) return 0; /* (2) */ |
| 166887 | | - if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* (3) */ |
| 166937 | + if( ExprHasProperty(pExpr, EP_OuterON|EP_Collate) ) return 0; /* (3) */ |
| 166888 | 166938 | assert( pSrc!=0 ); |
| 166889 | 166939 | if( pExpr->op==TK_IS |
| 166890 | 166940 | && pSrc->nSrc>=2 |
| 166891 | 166941 | && (pSrc->a[0].fg.jointype & JT_LTORJ)!=0 |
| 166892 | 166942 | ){ |
| | @@ -167209,10 +167259,11 @@ |
| 167209 | 167259 | static const u8 ops[] = {TK_GE, TK_LE}; |
| 167210 | 167260 | assert( ExprUseXList(pExpr) ); |
| 167211 | 167261 | pList = pExpr->x.pList; |
| 167212 | 167262 | assert( pList!=0 ); |
| 167213 | 167263 | assert( pList->nExpr==2 ); |
| 167264 | + assert( pWC->a[idxTerm].nChild==0 ); |
| 167214 | 167265 | for(i=0; i<2; i++){ |
| 167215 | 167266 | Expr *pNewExpr; |
| 167216 | 167267 | int idxNew; |
| 167217 | 167268 | pNewExpr = sqlite3PExpr(pParse, ops[i], |
| 167218 | 167269 | sqlite3ExprDup(db, pExpr->pLeft, 0), |
| | @@ -167419,12 +167470,15 @@ |
| 167419 | 167470 | && (pExpr->x.pSelect->pPrior==0 || (pExpr->x.pSelect->selFlags & SF_Values)) |
| 167420 | 167471 | #ifndef SQLITE_OMIT_WINDOWFUNC |
| 167421 | 167472 | && pExpr->x.pSelect->pWin==0 |
| 167422 | 167473 | #endif |
| 167423 | 167474 | && pWC->op==TK_AND |
| 167475 | + && pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild) |
| 167476 | + /* ^-- See bug 2026-06-04T10:00:49Z */ |
| 167424 | 167477 | ){ |
| 167425 | 167478 | int i; |
| 167479 | + assert( pTerm->nChild==0 ); |
| 167426 | 167480 | for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ |
| 167427 | 167481 | int idxNew; |
| 167428 | 167482 | idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE); |
| 167429 | 167483 | pWC->a[idxNew].u.x.iField = i+1; |
| 167430 | 167484 | exprAnalyze(pSrc, pWC, idxNew); |
| | @@ -186978,11 +187032,11 @@ |
| 186978 | 187032 | ** or disables the collection of memory allocation statistics. */ |
| 186979 | 187033 | sqlite3GlobalConfig.bMemstat = va_arg(ap, int); |
| 186980 | 187034 | break; |
| 186981 | 187035 | } |
| 186982 | 187036 | case SQLITE_CONFIG_SMALL_MALLOC: { |
| 186983 | | - sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int); |
| 187037 | + sqlite3GlobalConfig.bSmallMalloc = va_arg(ap, int)!=0; |
| 186984 | 187038 | break; |
| 186985 | 187039 | } |
| 186986 | 187040 | case SQLITE_CONFIG_PAGECACHE: { |
| 186987 | 187041 | /* EVIDENCE-OF: R-18761-36601 There are three arguments to |
| 186988 | 187042 | ** SQLITE_CONFIG_PAGECACHE: A pointer to 8-byte aligned memory (pMem), |
| | @@ -193287,10 +193341,16 @@ |
| 193287 | 193341 | #ifndef SQLITE_CORE |
| 193288 | 193342 | /* # include "sqlite3ext.h" */ |
| 193289 | 193343 | SQLITE_EXTENSION_INIT1 |
| 193290 | 193344 | #endif |
| 193291 | 193345 | |
| 193346 | + |
| 193347 | +/* |
| 193348 | +** Assume any b-tree layer with more levels than this is corrupt. |
| 193349 | +*/ |
| 193350 | +#define FTS3_MAX_BTREE_HEIGHT 48 |
| 193351 | + |
| 193292 | 193352 | typedef struct Fts3HashWrapper Fts3HashWrapper; |
| 193293 | 193353 | struct Fts3HashWrapper { |
| 193294 | 193354 | Fts3Hash hash; /* Hash table */ |
| 193295 | 193355 | int nRef; /* Number of pointers to this object */ |
| 193296 | 193356 | }; |
| | @@ -195003,11 +195063,15 @@ |
| 195003 | 195063 | int iHeight; /* Height of this node in tree */ |
| 195004 | 195064 | |
| 195005 | 195065 | assert( piLeaf || piLeaf2 ); |
| 195006 | 195066 | |
| 195007 | 195067 | fts3GetVarint32(zNode, &iHeight); |
| 195008 | | - rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
| 195068 | + if( iHeight>FTS3_MAX_BTREE_HEIGHT ){ |
| 195069 | + rc = FTS_CORRUPT_VTAB; |
| 195070 | + }else{ |
| 195071 | + rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2); |
| 195072 | + } |
| 195009 | 195073 | assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) ); |
| 195010 | 195074 | |
| 195011 | 195075 | if( rc==SQLITE_OK && iHeight>1 ){ |
| 195012 | 195076 | char *zBlob = 0; /* Blob read from %_segments table */ |
| 195013 | 195077 | int nBlob = 0; /* Size of zBlob in bytes */ |
| | @@ -199532,11 +199596,11 @@ |
| 199532 | 199596 | break; |
| 199533 | 199597 | |
| 199534 | 199598 | /* State 3. The integer just read is a column number. */ |
| 199535 | 199599 | default: assert( eState==3 ); |
| 199536 | 199600 | iCol = (int)v; |
| 199537 | | - if( iCol<1 || iCol>0x3fffffff ){ |
| 199601 | + if( iCol<1 || iCol>(pFts3->nColumn+1) ){ |
| 199538 | 199602 | rc = SQLITE_CORRUPT_VTAB; |
| 199539 | 199603 | break; |
| 199540 | 199604 | } |
| 199541 | 199605 | if( fts3auxGrowStatArray(pCsr, iCol+2) ) return SQLITE_NOMEM; |
| 199542 | 199606 | pCsr->aStat[iCol+1].nDoc++; |
| | @@ -218910,11 +218974,11 @@ |
| 218910 | 218974 | i64 iRowid, |
| 218911 | 218975 | int *piIndex |
| 218912 | 218976 | ){ |
| 218913 | 218977 | int ii; |
| 218914 | 218978 | int nCell = NCELL(pNode); |
| 218915 | | - assert( nCell<200 ); |
| 218979 | + assert( nCell<65536 && nCell>=0 ); |
| 218916 | 218980 | for(ii=0; ii<nCell; ii++){ |
| 218917 | 218981 | if( nodeGetRowid(pRtree, pNode, ii)==iRowid ){ |
| 218918 | 218982 | *piIndex = ii; |
| 218919 | 218983 | return SQLITE_OK; |
| 218920 | 218984 | } |
| | @@ -223953,10 +224017,13 @@ |
| 223953 | 224017 | if( c>=0xc0 ){ \ |
| 223954 | 224018 | c = icuUtf8Trans1[c-0xc0]; \ |
| 223955 | 224019 | while( (*zIn & 0xc0)==0x80 ){ \ |
| 223956 | 224020 | c = (c<<6) + (0x3f & *(zIn++)); \ |
| 223957 | 224021 | } \ |
| 224022 | + if( c<0x80 \ |
| 224023 | + || (c&0xFFFFF800)==0xD800 \ |
| 224024 | + || (c&0xFFFFFFFE)==0xFFFE ){ c = 0xFFFD; } \ |
| 223958 | 224025 | } |
| 223959 | 224026 | |
| 223960 | 224027 | #define SQLITE_ICU_SKIP_UTF8(zIn) \ |
| 223961 | 224028 | assert( *zIn ); \ |
| 223962 | 224029 | if( *(zIn++)>=0xc0 ){ \ |
| | @@ -244051,11 +244118,11 @@ |
| 244051 | 244118 | ){ |
| 244052 | 244119 | HighlightContext ctx; |
| 244053 | 244120 | int rc = SQLITE_OK; /* Return code */ |
| 244054 | 244121 | int iCol; /* 1st argument to snippet() */ |
| 244055 | 244122 | const char *zEllips; /* 4th argument to snippet() */ |
| 244056 | | - int nToken; /* 5th argument to snippet() */ |
| 244123 | + i64 nToken; /* 5th argument to snippet() */ |
| 244057 | 244124 | int nInst = 0; /* Number of instance matches this row */ |
| 244058 | 244125 | int i; /* Used to iterate through instances */ |
| 244059 | 244126 | int nPhrase; /* Number of phrases in query */ |
| 244060 | 244127 | unsigned char *aSeen; /* Array of "seen instance" flags */ |
| 244061 | 244128 | int iBestCol; /* Column containing best snippet */ |
| | @@ -244076,11 +244143,11 @@ |
| 244076 | 244143 | iCol = sqlite3_value_int(apVal[0]); |
| 244077 | 244144 | ctx.zOpen = fts5ValueToText(apVal[1]); |
| 244078 | 244145 | ctx.zClose = fts5ValueToText(apVal[2]); |
| 244079 | 244146 | ctx.iRangeEnd = -1; |
| 244080 | 244147 | zEllips = fts5ValueToText(apVal[3]); |
| 244081 | | - nToken = sqlite3_value_int(apVal[4]); |
| 244148 | + nToken = (int)(MIN( MAX(sqlite3_value_int64(apVal[4]), 0), 64)); |
| 244082 | 244149 | |
| 244083 | 244150 | iBestCol = (iCol>=0 ? iCol : 0); |
| 244084 | 244151 | nPhrase = pApi->xPhraseCount(pFts); |
| 244085 | 244152 | aSeen = sqlite3_malloc64(nPhrase); |
| 244086 | 244153 | if( aSeen==0 ){ |
| | @@ -246792,11 +246859,11 @@ |
| 246792 | 246859 | /* Add an entry to each output position list */ |
| 246793 | 246860 | for(i=0; i<pNear->nPhrase; i++){ |
| 246794 | 246861 | i64 iPos = a[i].reader.iPos; |
| 246795 | 246862 | Fts5PoslistWriter *pWriter = &a[i].writer; |
| 246796 | 246863 | if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){ |
| 246797 | | - sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos); |
| 246864 | + sqlite3Fts5PoslistSafeAppend(a[i].pOut, &pWriter->iPrev, iPos); |
| 246798 | 246865 | } |
| 246799 | 246866 | } |
| 246800 | 246867 | |
| 246801 | 246868 | iAdv = 0; |
| 246802 | 246869 | iMin = a[0].reader.iLookahead; |
| | @@ -251558,19 +251625,20 @@ |
| 251558 | 251625 | assert( pLvl->bEof==0 ); |
| 251559 | 251626 | if( iOff<=pLvl->iFirstOff ){ |
| 251560 | 251627 | pLvl->bEof = 1; |
| 251561 | 251628 | }else{ |
| 251562 | 251629 | u8 *a = pLvl->pData->p; |
| 251630 | + int nn = pLvl->pData->nn; |
| 251563 | 251631 | |
| 251564 | 251632 | pLvl->iOff = 0; |
| 251565 | 251633 | fts5DlidxLvlNext(pLvl); |
| 251566 | 251634 | while( 1 ){ |
| 251567 | 251635 | int nZero = 0; |
| 251568 | 251636 | int ii = pLvl->iOff; |
| 251569 | 251637 | u64 delta = 0; |
| 251570 | 251638 | |
| 251571 | | - while( a[ii]==0 ){ |
| 251639 | + while( ii<nn && a[ii]==0 ){ |
| 251572 | 251640 | nZero++; |
| 251573 | 251641 | ii++; |
| 251574 | 251642 | } |
| 251575 | 251643 | ii += sqlite3Fts5GetVarint(&a[ii], &delta); |
| 251576 | 251644 | |
| | @@ -251985,11 +252053,11 @@ |
| 251985 | 252053 | fts5DataRelease(pIter->pLeaf); |
| 251986 | 252054 | pIter->pLeaf = 0; |
| 251987 | 252055 | while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){ |
| 251988 | 252056 | Fts5Data *pNew; |
| 251989 | 252057 | pIter->iLeafPgno--; |
| 251990 | | - pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID( |
| 252058 | + pNew = fts5LeafRead(p, FTS5_SEGMENT_ROWID( |
| 251991 | 252059 | pIter->pSeg->iSegid, pIter->iLeafPgno |
| 251992 | 252060 | )); |
| 251993 | 252061 | if( pNew ){ |
| 251994 | 252062 | /* iTermLeafOffset may be equal to szLeaf if the term is the last |
| 251995 | 252063 | ** thing on the page - i.e. the first rowid is on the following page. |
| | @@ -253419,12 +253487,11 @@ |
| 253419 | 253487 | } |
| 253420 | 253488 | } |
| 253421 | 253489 | |
| 253422 | 253490 | do { |
| 253423 | 253491 | while( i<nChunk && pChunk[i]!=0x01 ){ |
| 253424 | | - while( pChunk[i] & 0x80 ) i++; |
| 253425 | | - i++; |
| 253492 | + fts5IndexSkipVarint(pChunk, i); |
| 253426 | 253493 | } |
| 253427 | 253494 | if( pCtx->eState ){ |
| 253428 | 253495 | fts5BufferSafeAppendBlob(pCtx->pBuf, &pChunk[iStart], i-iStart); |
| 253429 | 253496 | } |
| 253430 | 253497 | if( i<nChunk ){ |
| | @@ -255163,10 +255230,15 @@ |
| 255163 | 255230 | int iSOP; /* Start-Of-Position-list */ |
| 255164 | 255231 | if( pSeg->iLeafPgno==pSeg->iTermLeafPgno ){ |
| 255165 | 255232 | iStart = pSeg->iTermLeafOffset; |
| 255166 | 255233 | }else{ |
| 255167 | 255234 | iStart = fts5GetU16(&aPg[0]); |
| 255235 | + } |
| 255236 | + if( iStart>nPg ){ |
| 255237 | + FTS5_CORRUPT_IDX(p); |
| 255238 | + sqlite3_free(aIdx); |
| 255239 | + return; |
| 255168 | 255240 | } |
| 255169 | 255241 | |
| 255170 | 255242 | iSOP = iStart + fts5GetVarint(&aPg[iStart], &iDelta); |
| 255171 | 255243 | assert_nc( iSOP<=pSeg->iLeafOffset ); |
| 255172 | 255244 | |
| | @@ -258429,11 +258501,11 @@ |
| 258429 | 258501 | ){ |
| 258430 | 258502 | |
| 258431 | 258503 | /* Check any rowid-less pages that occur before the current leaf. */ |
| 258432 | 258504 | for(iPg=iPrevLeaf+1; iPg<fts5DlidxIterPgno(pDlidx); iPg++){ |
| 258433 | 258505 | iKey = FTS5_SEGMENT_ROWID(iSegid, iPg); |
| 258434 | | - pLeaf = fts5DataRead(p, iKey); |
| 258506 | + pLeaf = fts5LeafRead(p, iKey); |
| 258435 | 258507 | if( pLeaf ){ |
| 258436 | 258508 | if( fts5LeafFirstRowidOff(pLeaf)!=0 ) FTS5_CORRUPT_ROWID(p, iKey); |
| 258437 | 258509 | fts5DataRelease(pLeaf); |
| 258438 | 258510 | } |
| 258439 | 258511 | } |
| | @@ -258440,11 +258512,11 @@ |
| 258440 | 258512 | iPrevLeaf = fts5DlidxIterPgno(pDlidx); |
| 258441 | 258513 | |
| 258442 | 258514 | /* Check that the leaf page indicated by the iterator really does |
| 258443 | 258515 | ** contain the rowid suggested by the same. */ |
| 258444 | 258516 | iKey = FTS5_SEGMENT_ROWID(iSegid, iPrevLeaf); |
| 258445 | | - pLeaf = fts5DataRead(p, iKey); |
| 258517 | + pLeaf = fts5LeafRead(p, iKey); |
| 258446 | 258518 | if( pLeaf ){ |
| 258447 | 258519 | i64 iRowid; |
| 258448 | 258520 | int iRowidOff = fts5LeafFirstRowidOff(pLeaf); |
| 258449 | 258521 | ASSERT_SZLEAF_OK(pLeaf); |
| 258450 | 258522 | if( iRowidOff>=pLeaf->szLeaf ){ |
| | @@ -263040,11 +263112,11 @@ |
| 263040 | 263112 | int nArg, /* Number of args */ |
| 263041 | 263113 | sqlite3_value **apUnused /* Function arguments */ |
| 263042 | 263114 | ){ |
| 263043 | 263115 | assert( nArg==0 ); |
| 263044 | 263116 | UNUSED_PARAM2(nArg, apUnused); |
| 263045 | | - sqlite3_result_text(pCtx, "fts5: 2026-05-30 10:24:03 7487a1c59d3aaea9f8b2569dca76bbccf21948b1e7bd8a1d841e04382db696f4", -1, SQLITE_TRANSIENT); |
| 263117 | + sqlite3_result_text(pCtx, "fts5: 2026-06-08 18:15:27 4cb349370daab17123770c814c71872a3e4c616a3f984569b3d7f97f9c3f5ea0", -1, SQLITE_TRANSIENT); |
| 263046 | 263118 | } |
| 263047 | 263119 | |
| 263048 | 263120 | /* |
| 263049 | 263121 | ** Implementation of fts5_locale(LOCALE, TEXT) function. |
| 263050 | 263122 | ** |
| 263051 | 263123 | |