11/******************************************************************************
22** This file is an amalgamation of many separate C source files from SQLite
3- ** version 3.53.3 . By combining all the individual C code files into this
3+ ** version 3.53.4 . By combining all the individual C code files into this
44** single large file, the entire code can be compiled as a single translation
55** unit. This allows many compilers to do optimizations that would not be
66** possible if the files were compiled separately. Performance improvements
1818** separate file. This file contains only code for the core SQLite library.
1919**
2020** The content in this amalgamation comes from Fossil check-in
21- ** d4c0e51e4aeb96955b99185ab9cde75c339e with changes in files:
21+ ** bf7c7f30031888f4e796e429ab3978879485 with changes in files:
2222**
2323**
2424*/
@@ -467,12 +467,12 @@ extern "C" {
467467** [sqlite3_libversion_number()], [sqlite3_sourceid()],
468468** [sqlite_version()] and [sqlite_source_id()].
469469*/
470- #define SQLITE_VERSION "3.53.3 "
471- #define SQLITE_VERSION_NUMBER 3053003
472- #define SQLITE_SOURCE_ID "2026-06-26 20:14:12 d4c0e51e4aeb96955b99185ab9cde75c339e2c29c3f3f12428d364a10d782c62 "
470+ #define SQLITE_VERSION "3.53.4 "
471+ #define SQLITE_VERSION_NUMBER 3053004
472+ #define SQLITE_SOURCE_ID "2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc "
473473#define SQLITE_SCM_BRANCH "branch-3.53"
474- #define SQLITE_SCM_TAGS "release version-3.53.3 "
475- #define SQLITE_SCM_DATETIME "2026-06-26T20:14:12.354Z "
474+ #define SQLITE_SCM_TAGS "release version-3.53.4 "
475+ #define SQLITE_SCM_DATETIME "2026-07-24T19:02:57.525Z "
476476
477477/*
478478** CAPI3REF: Run-Time Library Version Numbers
@@ -27591,7 +27591,7 @@ SQLITE_PRIVATE int sqlite3OsCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p
2759127591 }else{
2759227592 double r;
2759327593 rc = pVfs->xCurrentTime(pVfs, &r);
27594- *pTimeOut = (sqlite3_int64) (r*86400000.0);
27594+ *pTimeOut = sqlite3RealToI64 (r*86400000.0);
2759527595 }
2759627596 return rc;
2759727597}
@@ -60969,7 +60969,7 @@ static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
6096960969 cksum -= zOut[u];
6097060970 }
6097160971 }
60972- if( rc!=SQLITE_OK || cksum ){
60972+ if( rc!=SQLITE_OK || cksum || zOut[0]==0 ){
6097360973 /* If the checksum doesn't add up, then one or more of the disk sectors
6097460974 ** containing the super-journal filename is corrupted. This means
6097560975 ** definitely roll back, so just return SQLITE_OK and report a (nul)
@@ -111437,11 +111437,20 @@ static SQLITE_NOINLINE void resolveSetExprSubtypeArg(ExprList *pList){
111437111437 nn = pList ? pList->nExpr : 0;
111438111438 for(ii=0; ii<nn; ii++){
111439111439 Expr *pExpr = pList->a[ii].pExpr;
111440- ExprSetProperty(pExpr, EP_SubtArg);
111441- if( pExpr->op==TK_SELECT ){
111442- assert( ExprUseXSelect(pExpr) );
111443- assert( pExpr->x.pSelect!=0 );
111444- resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
111440+ while( 1 /*exit-by-break*/ ){
111441+ ExprSetProperty(pExpr, EP_SubtArg);
111442+ if( pExpr->op==TK_SELECT ){
111443+ assert( ExprUseXSelect(pExpr) );
111444+ assert( pExpr->x.pSelect!=0 );
111445+ resolveSetExprSubtypeArg(pExpr->x.pSelect->pEList);
111446+ break;
111447+ }
111448+ if( pExpr->op==TK_UPLUS ){
111449+ pExpr = pExpr->pLeft;
111450+ assert( pExpr!=0 );
111451+ }else{
111452+ break;
111453+ }
111445111454 }
111446111455 }
111447111456}
@@ -176954,7 +176963,7 @@ static void nth_valueStepFunc(
176954176963 break;
176955176964 case SQLITE_FLOAT: {
176956176965 double fVal = sqlite3_value_double(apArg[1]);
176957- if( ((i64) fVal)!=fVal ) goto error_out;
176966+ if( sqlite3RealToI64( fVal)!=fVal ) goto error_out;
176958176967 iVal = (i64)fVal;
176959176968 break;
176960176969 }
@@ -210776,8 +210785,8 @@ static int fts3StringAppend(
210776210785 ** to grow the buffer until so that it is big enough to accommodate the
210777210786 ** appended data.
210778210787 */
210779- if( pStr->n+nAppend+1>=pStr->nAlloc ){
210780- sqlite3_int64 nAlloc = pStr->nAlloc+(sqlite3_int64 )nAppend+100;
210788+ if( (i64) pStr->n+(i64) nAppend+1>=(i64) pStr->nAlloc ){
210789+ i64 nAlloc = pStr->nAlloc+(i64 )nAppend+100;
210781210790 char *zNew = sqlite3_realloc64(pStr->z, nAlloc);
210782210791 if( !zNew ){
210783210792 return SQLITE_NOMEM;
@@ -214981,7 +214990,8 @@ static u32 jsonTranslateBlobToText(
214981214990 if( sz==0 ) goto malformed_jsonb;
214982214991 if( zIn[0]=='-' ){
214983214992 jsonAppendChar(pOut, '-');
214984- k++;
214993+ if( sz<=1 ) goto malformed_jsonb;
214994+ k = 1;
214985214995 }
214986214996 if( zIn[k]=='.' ){
214987214997 jsonAppendChar(pOut, '0');
@@ -217945,7 +217955,9 @@ static int jsonSkipLabel(JsonEachCursor *p){
217945217955 if( p->eType==JSONB_OBJECT ){
217946217956 u32 sz = 0;
217947217957 u32 n = jsonbPayloadSize(&p->sParse, p->i, &sz);
217948- return p->i + n + sz;
217958+ sz += p->i + n;
217959+ if( sz >= p->sParse.nBlob ) sz = p->i;
217960+ return sz;
217949217961 }else{
217950217962 return p->i;
217951217963 }
@@ -226906,8 +226918,8 @@ static int rbuDeltaApply(
226906226918 int lenDelta, /* Length of the delta */
226907226919 char *zOut /* Write the output into this preallocated buffer */
226908226920){
226909- unsigned int limit;
226910- unsigned int total = 0;
226921+ sqlite3_uint64 limit;
226922+ sqlite3_uint64 total = 0;
226911226923#if RBU_ENABLE_DELTA_CKSUM
226912226924 char *zOrigOut = zOut;
226913226925#endif
@@ -226917,16 +226929,16 @@ static int rbuDeltaApply(
226917226929 /* ERROR: size integer not terminated by "\n" */
226918226930 return -1;
226919226931 }
226920- zDelta++; lenDelta--;
226921- while( *zDelta && lenDelta>0 ){
226932+ zDelta++; lenDelta--; /* Skip the \n */
226933+ while( lenDelta>0 && zDelta[0] ){
226922226934 unsigned int cnt, ofst;
226923226935 cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
226924226936 if( lenDelta<=0 ) return -1;
226925226937 switch( zDelta[0] ){
226926226938 case '@': {
226927226939 zDelta++; lenDelta--;
226928226940 ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
226929- if( lenDelta>0 || zDelta[0]!=',' ){
226941+ if( lenDelta>0 && zDelta[0]!=',' ){
226930226942 /* ERROR: copy command not terminated by ',' */
226931226943 return -1;
226932226944 }
@@ -226951,7 +226963,7 @@ static int rbuDeltaApply(
226951226963 /* ERROR: insert command gives an output larger than predicted */
226952226964 return -1;
226953226965 }
226954- if( (i64) cnt>(i64) lenDelta ){
226966+ if( cnt>lenDelta ){
226955226967 /* ERROR: insert count exceeds size of delta */
226956226968 return -1;
226957226969 }
@@ -228964,13 +228976,13 @@ static int rbuGetUpdateStmt(
228964228976 char *zUpdate = 0;
228965228977
228966228978 pUp->zMask = (char*)&pUp[1];
228967- memcpy(pUp->zMask, zMask, pIter->nTblCol);
228968228979 pUp->pNext = pIter->pRbuUpdate;
228969228980 pIter->pRbuUpdate = pUp;
228970228981
228971228982 if( zSet ){
228972228983 const char *zPrefix = "";
228973-
228984+ assert( p->rc==SQLITE_OK );
228985+ memcpy(pUp->zMask, zMask, pIter->nTblCol);
228974228986 if( pIter->eType!=RBU_PK_VTAB ) zPrefix = "rbu_imp_";
228975228987 zUpdate = sqlite3_mprintf("UPDATE \"%s%w\" SET %s WHERE %s",
228976228988 zPrefix, pIter->zTbl, zSet, zWhere
@@ -229060,6 +229072,9 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
229060229072
229061229073 case RBU_STATE_ROW:
229062229074 pRet->nRow = sqlite3_column_int(pStmt, 1);
229075+ if( pRet->nRow<0 ){
229076+ rc = SQLITE_CORRUPT;
229077+ }
229063229078 break;
229064229079
229065229080 case RBU_STATE_PROGRESS:
@@ -240296,7 +240311,12 @@ static int sessionChangesetToHash(
240296240311
240297240312 pIter->in.bNoDiscard = 1;
240298240313 while( SQLITE_ROW==(sessionChangesetNext(pIter, &aRec, &nRec, 0)) ){
240299- rc = sessionOneChangeIterToHash(pGrp, pIter, bRebase);
240314+ if( bRebase && pIter->bPatchset ){
240315+ /* A patchset may not be used as a rebase */
240316+ rc = SQLITE_ERROR;
240317+ }else{
240318+ rc = sessionOneChangeIterToHash(pGrp, pIter, bRebase);
240319+ }
240300240320 if( rc!=SQLITE_OK ) break;
240301240321 }
240302240322
@@ -240673,13 +240693,14 @@ static void sessionAppendPartialUpdate(
240673240693 int i;
240674240694 u8 *a1 = aRec;
240675240695 u8 *a2 = aChange;
240696+ u8 *a2Eof = &a2[nChange];
240676240697
240677240698 *pOut++ = SQLITE_UPDATE;
240678240699 *pOut++ = pIter->bIndirect;
240679240700 for(i=0; i<pIter->nCol; i++){
240680240701 int n1 = sessionSerialLen(a1);
240681- int n2 = sessionSerialLen(a2);
240682- if( pIter->abPK[i] || a2[0]==0 ){
240702+ int n2 = (a2>=a2Eof) ? 0 : sessionSerialLen(a2);
240703+ if( n2<=0 || pIter->abPK[i] || a2[0]==0 ){
240683240704 if( !pIter->abPK[i] && a1[0] ) bData = 1;
240684240705 memcpy(pOut, a1, n1);
240685240706 pOut += n1;
@@ -240880,8 +240901,8 @@ SQLITE_API int sqlite3rebaser_configure(
240880240901 sqlite3_rebaser *p,
240881240902 int nRebase, const void *pRebase
240882240903){
240883- sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
240884240904 int rc; /* Return code */
240905+ sqlite3_changeset_iter *pIter = 0; /* Iterator opened on pData/nData */
240885240906 rc = sqlite3changeset_start(&pIter, nRebase, (void*)pRebase);
240886240907 if( rc==SQLITE_OK ){
240887240908 rc = sessionChangesetToHash(pIter, &p->grp, 1);
@@ -251701,6 +251722,7 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
251701251722 pRet = (Fts5Data*)sqlite3_malloc64(nAlloc);
251702251723 if( pRet ){
251703251724 pRet->nn = nByte;
251725+ pRet->szLeaf = 0;
251704251726 aOut = pRet->p = (u8*)pRet + szData;
251705251727 }else{
251706251728 rc = SQLITE_NOMEM;
@@ -251713,10 +251735,8 @@ static Fts5Data *fts5DataRead(Fts5Index *p, i64 iRowid){
251713251735 sqlite3_free(pRet);
251714251736 pRet = 0;
251715251737 }else{
251716- /* TODO1: Fix this */
251717251738 pRet->p[nByte] = 0x00;
251718251739 pRet->p[nByte+1] = 0x00;
251719- pRet->szLeaf = fts5GetU16(&pRet->p[2]);
251720251740 }
251721251741 }
251722251742 p->rc = rc;
@@ -251737,9 +251757,17 @@ static void fts5DataRelease(Fts5Data *pData){
251737251757 sqlite3_free(pData);
251738251758}
251739251759
251760+ /*
251761+ ** Read a leaf-page record. This is similar to fts5DataRead(), except that
251762+ ** it fills in the Fts5Data.szLeaf value before returning.
251763+ */
251740251764static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
251741251765 Fts5Data *pRet = fts5DataRead(p, iRowid);
251742251766 if( pRet ){
251767+ assert( pRet->szLeaf==0 );
251768+ if( pRet->nn>=4 ){
251769+ pRet->szLeaf = fts5GetU16(&pRet->p[2]);
251770+ }
251743251771 if( pRet->szLeaf<4 || pRet->szLeaf>pRet->nn ){
251744251772 FTS5_CORRUPT_ROWID(p, iRowid);
251745251773 fts5DataRelease(pRet);
@@ -253649,6 +253677,10 @@ static void fts5SegIterNextInit(
253649253677
253650253678 pIter->iPgidxOff = pIter->pLeaf->szLeaf;
253651253679 pIter->iPgidxOff += fts5GetVarint32(&a[pIter->iPgidxOff], iTermOff);
253680+ if( iTermOff > pIter->pLeaf->szLeaf ){
253681+ p->rc = FTS5_CORRUPT;
253682+ return;
253683+ }
253652253684 pIter->iLeafOffset = iTermOff;
253653253685 fts5SegIterLoadTerm(p, pIter, 0);
253654253686 fts5SegIterLoadNPos(p, pIter);
@@ -255975,15 +256007,15 @@ static void fts5SecureDeleteOverflow(
255975256007 int iNext = 0;
255976256008 u8 *aPg = 0;
255977256009
255978- pLeaf = fts5DataRead (p, iRowid);
256010+ pLeaf = fts5LeafRead (p, iRowid);
255979256011 if( pLeaf==0 ) break;
255980256012 aPg = pLeaf->p;
255981256013
255982256014 iNext = fts5GetU16(&aPg[0]);
255983256015 if( iNext!=0 ){
255984256016 *pbLastInDoclist = 0;
255985256017 }
255986- if( iNext==0 && pLeaf->szLeaf!= pLeaf->nn ){
256018+ if( iNext==0 && pLeaf->szLeaf< pLeaf->nn ){
255987256019 fts5GetVarint32(&aPg[pLeaf->szLeaf], iNext);
255988256020 }
255989256021
@@ -256270,15 +256302,15 @@ static void fts5DoSecureDelete(
256270256302 /* The entry being removed may be the only position list in
256271256303 ** its doclist. */
256272256304 for(iPgno=pSeg->iLeafPgno-1; iPgno>pSeg->iTermLeafPgno; iPgno-- ){
256273- Fts5Data *pPg = fts5DataRead (p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
256305+ Fts5Data *pPg = fts5LeafRead (p, FTS5_SEGMENT_ROWID(iSegid, iPgno));
256274256306 int bEmpty = (pPg && pPg->nn==4);
256275256307 fts5DataRelease(pPg);
256276256308 if( bEmpty==0 ) break;
256277256309 }
256278256310
256279256311 if( iPgno==pSeg->iTermLeafPgno ){
256280256312 i64 iId = FTS5_SEGMENT_ROWID(iSegid, pSeg->iTermLeafPgno);
256281- Fts5Data *pTerm = fts5DataRead (p, iId);
256313+ Fts5Data *pTerm = fts5LeafRead (p, iId);
256282256314 if( pTerm && pTerm->szLeaf==pSeg->iTermLeafOffset ){
256283256315 u8 *aTermIdx = &pTerm->p[pTerm->szLeaf];
256284256316 int nTermIdx = pTerm->nn - pTerm->szLeaf;
@@ -259230,7 +259262,7 @@ static void fts5IndexIntegrityCheckEmpty(
259230259262 /* Now check that the iter.nEmpty leaves following the current leaf
259231259263 ** (a) exist and (b) contain no terms. */
259232259264 for(i=iFirst; p->rc==SQLITE_OK && i<=iLast; i++){
259233- Fts5Data *pLeaf = fts5DataRead (p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
259265+ Fts5Data *pLeaf = fts5LeafRead (p, FTS5_SEGMENT_ROWID(pSeg->iSegid, i));
259234259266 if( pLeaf ){
259235259267 if( !fts5LeafIsTermless(pLeaf)
259236259268 || (i>=iNoRowid && 0!=fts5LeafFirstRowidOff(pLeaf))
@@ -259358,7 +259390,7 @@ static void fts5IndexIntegrityCheckSegment(
259358259390 FTS5_CORRUPT_ROWID(p, iRow);
259359259391 }else{
259360259392 iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
259361- if( iOff+nTerm>pLeaf->szLeaf ){
259393+ if( (i64) iOff+(i64) nTerm>(i64) pLeaf->szLeaf ){
259362259394 FTS5_CORRUPT_ROWID(p, iRow);
259363259395 }else{
259364259396 res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
@@ -263086,19 +263118,23 @@ static int fts5ApiPhraseFirstColumn(
263086263118
263087263119 if( pConfig->eDetail==FTS5_DETAIL_COLUMNS ){
263088263120 Fts5Sorter *pSorter = pCsr->pSorter;
263089- int n;
263090- if( pSorter ){
263091- int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
263092- n = pSorter->aIdx[iPhrase] - i1;
263093- pIter->a = &pSorter->aPoslist[i1];
263121+ if( iPhrase<0 || iPhrase>=sqlite3Fts5ExprPhraseCount(pCsr->pExpr) ){
263122+ rc = SQLITE_RANGE;
263094263123 }else{
263095- rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
263096- }
263097- if( rc==SQLITE_OK ){
263098- assert( pIter->a || n==0 );
263099- pIter->b = (pIter->a ? &pIter->a[n] : 0);
263100- *piCol = 0;
263101- fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
263124+ int n;
263125+ if( pSorter ){
263126+ int i1 = (iPhrase==0 ? 0 : pSorter->aIdx[iPhrase-1]);
263127+ n = pSorter->aIdx[iPhrase] - i1;
263128+ pIter->a = &pSorter->aPoslist[i1];
263129+ }else{
263130+ rc = sqlite3Fts5ExprPhraseCollist(pCsr->pExpr, iPhrase, &pIter->a, &n);
263131+ }
263132+ if( rc==SQLITE_OK ){
263133+ assert( pIter->a || n==0 );
263134+ pIter->b = (pIter->a ? &pIter->a[n] : 0);
263135+ *piCol = 0;
263136+ fts5ApiPhraseNextColumn(pCtx, pIter, piCol);
263137+ }
263102263138 }
263103263139 }else{
263104263140 int n;
@@ -264006,7 +264042,7 @@ static void fts5SourceIdFunc(
264006264042){
264007264043 assert( nArg==0 );
264008264044 UNUSED_PARAM2(nArg, apUnused);
264009- sqlite3_result_text(pCtx, "fts5: 2026-06-26 20:14:12 d4c0e51e4aeb96955b99185ab9cde75c339e2c29c3f3f12428d364a10d782c62 ", -1, SQLITE_TRANSIENT);
264045+ sqlite3_result_text(pCtx, "fts5: 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc ", -1, SQLITE_TRANSIENT);
264010264046}
264011264047
264012264048/*
0 commit comments