From 05b79988292cae100e000bea48dcba3e310f7ead Mon Sep 17 00:00:00 2001 From: Lili Zhu Date: Fri, 15 Aug 2025 07:57:39 -0400 Subject: [PATCH] Fix CVE-2025-6965 (RHEL-103830) Resolves: RHEL-103830 Signed-off-by: Lili Zhu --- mingw-sqlite.spec | 96 +++++-- sqlite-3.26.0-CVE-2019-13750.patch | 158 +++++++++++ sqlite-3.26.0-CVE-2019-13751.patch | 22 ++ sqlite-3.26.0-CVE-2019-19603.patch | 124 ++++++++ sqlite-3.26.0-CVE-2019-5827.patch | 442 +++++++++++++++++++++++++++++ sqlite-3.26.0-CVE-2020-13435.patch | 144 ++++++++++ sqlite-3.26.0-CVE-2020-24736.patch | 114 ++++++++ sqlite-3.26.0-CVE-2020-35525.patch | 26 ++ sqlite-3.26.0-CVE-2020-35527.patch | 55 ++++ sqlite-3.26.0-CVE-2022-35737.patch | 31 ++ sqlite-3.34.1-CVE-2023-7104.patch | 42 +++ sqlite-3.34.1-CVE-2025-6965.patch | 95 +++++++ 12 files changed, 1320 insertions(+), 29 deletions(-) create mode 100644 sqlite-3.26.0-CVE-2019-13750.patch create mode 100644 sqlite-3.26.0-CVE-2019-13751.patch create mode 100644 sqlite-3.26.0-CVE-2019-19603.patch create mode 100644 sqlite-3.26.0-CVE-2019-5827.patch create mode 100644 sqlite-3.26.0-CVE-2020-13435.patch create mode 100644 sqlite-3.26.0-CVE-2020-24736.patch create mode 100644 sqlite-3.26.0-CVE-2020-35525.patch create mode 100644 sqlite-3.26.0-CVE-2020-35527.patch create mode 100644 sqlite-3.26.0-CVE-2022-35737.patch create mode 100644 sqlite-3.34.1-CVE-2023-7104.patch create mode 100644 sqlite-3.34.1-CVE-2025-6965.patch diff --git a/mingw-sqlite.spec b/mingw-sqlite.spec index 0e4d9ad..eb90969 100644 --- a/mingw-sqlite.spec +++ b/mingw-sqlite.spec @@ -11,7 +11,7 @@ Name: mingw-%{name1} Version: %{rpmver} -Release: 1%{?dist} +Release: 2%{?dist} Summary: MinGW Windows port of sqlite embeddable SQL database engine License: Public Domain @@ -80,6 +80,25 @@ Patch26: sqlite-3.26.0-CVE-2020-13434.patch # Fix for CVE-2020-15358 # upstream commit: https://www.sqlite.org/src/info/10fa79d00f8091e5 Patch27: sqlite-3.26.0-CVE-2020-15358.patch +Patch28: sqlite-3.26.0-CVE-2019-5827.patch +# Fix for CVE-2019-13750 +Patch29: sqlite-3.26.0-CVE-2019-13750.patch +# Fix for CVE-2019-13751 +Patch30: sqlite-3.26.0-CVE-2019-13751.patch +# Fix for CVE-2019-19603 +Patch31: sqlite-3.26.0-CVE-2019-19603.patch +# Fix for CVE-2020-13435 +Patch34: sqlite-3.26.0-CVE-2020-13435.patch +# Fix for CVE-2020-35527 +Patch35: sqlite-3.26.0-CVE-2020-35527.patch +# Fix for CVE-2020-35525 +Patch36: sqlite-3.26.0-CVE-2020-35525.patch +# Fix for CVE-2022-35737 +Patch37: sqlite-3.26.0-CVE-2022-35737.patch +# Fix for CVE-2020-24736 +Patch38: sqlite-3.26.0-CVE-2020-24736.patch +Patch39: sqlite-3.34.1-CVE-2023-7104.patch +Patch40: sqlite-3.34.1-CVE-2025-6965.patch #end-of-patches-from-RHEL ###################### @@ -203,37 +222,48 @@ This package contains static cross-compiled library %prep %setup -q -n %{name1}-src-%{realver} -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch6 -p1 +%patch -P 1 -p1 +%patch -P 2 -p1 +%patch -P 3 -p1 +%patch -P 4 -p1 +%patch -P 6 -p1 %ifarch %{ix86} -%patch7 -p1 +%patch -P 7 -p1 %endif -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 -%patch11 -p1 -%patch12 -p1 -%patch13 -p1 -%patch14 -p1 -%patch15 -p1 -%patch16 -p1 -%patch17 -p1 -%patch18 -p1 -%patch19 -p1 -%patch20 -p1 -%patch21 -p1 -%patch22 -p1 -%patch23 -p1 -%patch24 -p1 -%patch25 -p1 -%patch26 -p1 -%patch27 -p1 +%patch -P 8 -p1 +%patch -P 9 -p1 +%patch -P 10 -p1 +%patch -P 11 -p1 +%patch -P 12 -p1 +%patch -P 13 -p1 +%patch -P 14 -p1 +%patch -P 15 -p1 +%patch -P 16 -p1 +%patch -P 17 -p1 +%patch -P 18 -p1 +%patch -P 19 -p1 +%patch -P 20 -p1 +%patch -P 21 -p1 +%patch -P 22 -p1 +%patch -P 23 -p1 +%patch -P 24 -p1 +%patch -P 25 -p1 +%patch -P 26 -p1 +%patch -P 27 -p1 +%patch -P 28 -p1 +%patch -P 29 -p1 +%patch -P 30 -p1 +%patch -P 31 -p1 +%patch -P 34 -p1 +%patch -P 35 -p1 +%patch -P 36 -p1 +%patch -P 37 -p1 +%patch -P 38 -p1 +%patch -P 39 -p1 +%patch -P 40 -p1 -%patch1001 -p0 -b .pthread -%patch1002 -p0 -b .cc +%patch -P 1001 -p0 -b .pthread +%patch -P 1002 -p0 -b .cc autoreconf -i --force @@ -317,6 +347,14 @@ find $RPM_BUILD_ROOT -name "*.la" -delete %changelog +* Fri Aug 15 2025 Lili Zhu - 3.26.0.0-2 +- Fix CVE-2019-5827 CVE-2019-13750 CVE-2019-13751 +- Fix CVE-2019-19603 CVE-2020-13435 CVE-2020-35527 +- Fix CVE-2020-35525 CVE-2022-35737 CVE-2020-24736 +- Fix CVE-2023-7104 +- Fix CVE-2025-6965 + Resolves: RHEL-103830 + * Mon Nov 30 2020 Uri Lublin - 3.26.0.0-1 - Rebase to sqlite 3.26.0 diff --git a/sqlite-3.26.0-CVE-2019-13750.patch b/sqlite-3.26.0-CVE-2019-13750.patch new file mode 100644 index 0000000..7b2adab --- /dev/null +++ b/sqlite-3.26.0-CVE-2019-13750.patch @@ -0,0 +1,158 @@ +Subject: [PATCH] In defensive mode, do not allow shadow tables to be renamed + using ALTER TABLE and do not allow shadow tables to be dropped. + +diff --git a/src/alter.c b/src/alter.c +index 0fa24c0..707472a 100644 +--- a/src/alter.c ++++ b/src/alter.c +@@ -28,9 +28,16 @@ + ** + ** Or, if zName is not a system table, zero is returned. + */ +-static int isSystemTable(Parse *pParse, const char *zName){ +- if( 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ +- sqlite3ErrorMsg(pParse, "table %s may not be altered", zName); ++static int isAlterableTable(Parse *pParse, Table *pTab){ ++ if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ || ( (pTab->tabFlags & TF_Shadow) ++ && (pParse->db->flags & SQLITE_Defensive) ++ && pParse->db->nVdbeExec==0 ++ ) ++#endif ++ ){ ++ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName); + return 1; + } + return 0; +@@ -129,7 +136,7 @@ void sqlite3AlterRenameTable( + /* Make sure it is not a system table being altered, or a reserved name + ** that the table is being renamed to. + */ +- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ ++ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ + goto exit_rename_table; + } + if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto +@@ -427,7 +434,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){ + sqlite3ErrorMsg(pParse, "Cannot add a column to a view"); + goto exit_begin_add_column; + } +- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ){ ++ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){ + goto exit_begin_add_column; + } + +@@ -529,7 +536,7 @@ void sqlite3AlterRenameColumn( + if( !pTab ) goto exit_rename_column; + + /* Cannot alter a system table */ +- if( SQLITE_OK!=isSystemTable(pParse, pTab->zName) ) goto exit_rename_column; ++ if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_rename_column; + if( SQLITE_OK!=isRealTable(pParse, pTab) ) goto exit_rename_column; + + /* Which schema holds the table to be altered */ +diff --git a/src/build.c b/src/build.c +index 1dc2614..3412670 100644 +--- a/src/build.c ++++ b/src/build.c +@@ -2661,6 +2661,22 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){ + sqliteViewResetAll(db, iDb); + } + ++/* ++** Return true if it is not allowed to drop the given table ++*/ ++static int tableMayNotBeDropped(Parse *pParse, Table *pTab){ ++ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ ++ if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0; ++ if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0; ++ return 1; ++ } ++ if( pTab->tabFlags & TF_Shadow ){ ++ sqlite3 *db = pParse->db; ++ if( (db->flags & SQLITE_Defensive)!=0 && db->nVdbeExec==0 ) return 1; ++ } ++ return 0; ++} ++ + /* + ** This routine is called to do the work of a DROP TABLE statement. + ** pName is the name of the table to be dropped. +@@ -2730,8 +2746,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){ + } + } + #endif +- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 +- && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){ ++ if( tableMayNotBeDropped(pParse, pTab) ){ + sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); + goto exit_drop_table; + } +diff --git a/test/altertab.test b/test/altertab.test +index a364207..891b081 100644 +--- a/test/altertab.test ++++ b/test/altertab.test +@@ -505,5 +505,62 @@ do_execsql_test 15.5 { + SELECT sql FROM sqlite_master WHERE name = 'y'; + } {{CREATE VIEW y AS SELECT f2 AS f1 FROM x}} + ++#------------------------------------------------------------------------- ++# Test that it is not possible to rename a shadow table in DEFENSIVE mode. ++# ++ifcapable fts3 { ++ proc vtab_command {method args} { ++ switch -- $method { ++ xConnect { ++ if {[info exists ::vtab_connect_sql]} { ++ execsql $::vtab_connect_sql ++ } ++ return "CREATE TABLE t1(a, b, c)" ++ } ++ ++ xBestIndex { ++ set clist [lindex $args 0] ++ if {[llength $clist]!=1} { error "unexpected constraint list" } ++ catch { array unset C } ++ array set C [lindex $clist 0] ++ if {$C(usable)} { ++ return "omit 0 cost 0 rows 1 idxnum 555 idxstr eq!" ++ } else { ++ return "cost 1000000 rows 0 idxnum 0 idxstr scan..." ++ } ++ } ++ } ++ ++ return {} ++ } ++ ++ register_tcl_module db ++ ++ sqlite3_db_config db DEFENSIVE 1 ++ ++ do_execsql_test 16.0 { ++ CREATE VIRTUAL TABLE y1 USING fts3; ++ } ++ ++ do_catchsql_test 16.10 { ++ INSERT INTO y1_segments VALUES(1, X'1234567890'); ++ } {1 {table y1_segments may not be modified}} ++ ++ do_catchsql_test 16.20 { ++ ALTER TABLE y1_segments RENAME TO abc; ++ } {1 {table y1_segments may not be altered}} ++ ++ do_catchsql_test 16.21 { ++ DROP TABLE y1_segments; ++ } {1 {table y1_segments may not be dropped}} ++ ++ do_execsql_test 16.30 { ++ ALTER TABLE y1 RENAME TO z1; ++ } ++ ++ do_execsql_test 16.40 { ++ SELECT * FROM z1_segments; ++ } ++} + + finish_test diff --git a/sqlite-3.26.0-CVE-2019-13751.patch b/sqlite-3.26.0-CVE-2019-13751.patch new file mode 100644 index 0000000..e0e345b --- /dev/null +++ b/sqlite-3.26.0-CVE-2019-13751.patch @@ -0,0 +1,22 @@ +Subject: [PATCH] Further improve detection of corrupt records in fts3 + +--- + ext/fts3/fts3_write.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/fts3/fts3_write.c b/ext/fts3/fts3_write.c +index 5330b4c..0647bd7 100644 +--- a/ext/fts3/fts3_write.c ++++ b/ext/fts3/fts3_write.c +@@ -1376,7 +1376,7 @@ static int fts3SegReaderNext( + pNext += fts3GetVarint32(pNext, &nSuffix); + if( nSuffix<=0 + || (&pReader->aNode[pReader->nNode] - pNext)pReader->nTermAlloc ++ || nPrefix>pReader->nTerm + ){ + return FTS_CORRUPT_VTAB; + } +-- +2.30.2 + diff --git a/sqlite-3.26.0-CVE-2019-19603.patch b/sqlite-3.26.0-CVE-2019-19603.patch new file mode 100644 index 0000000..23402b0 --- /dev/null +++ b/sqlite-3.26.0-CVE-2019-19603.patch @@ -0,0 +1,124 @@ +Subject: [PATCH] Do not allow CREATE TABLE or CREATE VIEW of an object with a name + that looks like a shadow table name. + +diff --git a/src/build.c b/src/build.c +index 3412670..f273394 100644 +--- a/src/build.c ++++ b/src/build.c +@@ -814,6 +814,22 @@ int sqlite3WritableSchema(sqlite3 *db){ + return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema; + } + ++/* ++** Return TRUE if shadow tables should be read-only in the current ++** context. ++*/ ++int sqlite3ReadOnlyShadowTables(sqlite3 *db){ ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ if( (db->flags & SQLITE_Defensive)!=0 ++ && db->pVtabCtx==0 ++ && db->nVdbeExec==0 ++ ){ ++ return 1; ++ } ++#endif ++ return 0; ++} ++ + /* + ** This routine is used to check if the UTF-8 string zName is a legal + ** unqualified name for a new schema object (table, index, view or +@@ -822,9 +838,10 @@ int sqlite3WritableSchema(sqlite3 *db){ + ** is reserved for internal use. + */ + int sqlite3CheckObjectName(Parse *pParse, const char *zName){ +- if( !pParse->db->init.busy && pParse->nested==0 ++ if(( !pParse->db->init.busy && pParse->nested==0 + && sqlite3WritableSchema(pParse->db)==0 +- && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){ ++ && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ) || ++ (sqlite3ReadOnlyShadowTables(pParse->db) && sqlite3ShadowTableName(pParse->db, zName))){ + sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName); + return SQLITE_ERROR; + } +@@ -1929,7 +1946,7 @@ int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){ + ** zName is temporarily modified while this routine is running, but is + ** restored to its original value prior to this routine returning. + */ +-static int isShadowTableName(sqlite3 *db, char *zName){ ++int sqlite3ShadowTableName(sqlite3 *db, const char *zName){ + char *zTail; /* Pointer to the last "_" in zName */ + Table *pTab; /* Table that zName is a shadow of */ + +@@ -1942,8 +1959,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){ + if( !IsVirtual(pTab) ) return 0; + return sqlite3IsShadowTableOf(db, pTab, zName); + } +-#else +-# define isShadowTableName(x,y) 0 + #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ + + /* +@@ -1985,7 +2000,7 @@ void sqlite3EndTable( + p = pParse->pNewTable; + if( p==0 ) return; + +- if( pSelect==0 && isShadowTableName(db, p->zName) ){ ++ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){ + p->tabFlags |= TF_Shadow; + } + +diff --git a/src/sqliteInt.h b/src/sqliteInt.h +index 60b2ebd..e5ba8a0 100644 +--- a/src/sqliteInt.h ++++ b/src/sqliteInt.h +@@ -4408,6 +4408,11 @@ void sqlite3AutoLoadExtensions(sqlite3*); + ); + # define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0) + #endif ++#ifndef SQLITE_OMIT_VIRTUALTABLE ++ int sqlite3ShadowTableName(sqlite3 *db, const char *zName); ++#else ++# define sqlite3ShadowTableName(A,B) 0 ++#endif + #ifndef SQLITE_OMIT_VIRTUALTABLE + int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*); + #else +diff --git a/test/altertab.test b/test/altertab.test +index 891b081..0705abc 100644 +--- a/test/altertab.test ++++ b/test/altertab.test +@@ -547,13 +547,29 @@ ifcapable fts3 { + } {1 {table y1_segments may not be modified}} + + do_catchsql_test 16.20 { +- ALTER TABLE y1_segments RENAME TO abc; +- } {1 {table y1_segments may not be altered}} +- +- do_catchsql_test 16.21 { + DROP TABLE y1_segments; + } {1 {table y1_segments may not be dropped}} + ++ do_catchsql_test 16.20 { ++ ALTER TABLE y1_segments RENAME TO abc; ++ } {1 {table y1_segments may not be altered}} ++ sqlite3_db_config db DEFENSIVE 0 ++ do_catchsql_test 16.22 { ++ ALTER TABLE y1_segments RENAME TO abc; ++ } {0 {}} ++ sqlite3_db_config db DEFENSIVE 1 ++ do_catchsql_test 16.23 { ++ CREATE TABLE y1_segments AS SELECT * FROM abc; ++ } {1 {object name reserved for internal use: y1_segments}} ++ do_catchsql_test 16.24 { ++ CREATE VIEW y1_segments AS SELECT * FROM abc; ++ } {1 {object name reserved for internal use: y1_segments}} ++ sqlite3_db_config db DEFENSIVE 0 ++ do_catchsql_test 16.25 { ++ ALTER TABLE abc RENAME TO y1_segments; ++ } {0 {}} ++ sqlite3_db_config db DEFENSIVE 1 ++ + do_execsql_test 16.30 { + ALTER TABLE y1 RENAME TO z1; + } diff --git a/sqlite-3.26.0-CVE-2019-5827.patch b/sqlite-3.26.0-CVE-2019-5827.patch new file mode 100644 index 0000000..c2a9410 --- /dev/null +++ b/sqlite-3.26.0-CVE-2019-5827.patch @@ -0,0 +1,442 @@ +Subject: [PATCH] Use the 64-bit memory allocator interfaces in extensions, + whenever possible and Enforce the SQLITE_LIMIT_COLUMN limit on virtual tables + +--- + ext/fts3/fts3_snippet.c | 7 ++++--- + ext/fts3/fts3_test.c | 6 +++--- + ext/fts3/fts3_tokenize_vtab.c | 2 +- + ext/fts3/fts3_tokenizer.c | 4 ++-- + ext/fts3/fts3_write.c | 19 ++++++++++--------- + ext/fts5/fts5_tokenize.c | 2 +- + ext/rtree/geopoly.c | 20 ++++++++++---------- + src/build.c | 8 ++++---- + src/expr.c | 2 +- + src/main.c | 2 +- + src/test_fs.c | 2 +- + src/util.c | 2 +- + src/vdbeaux.c | 8 +++++--- + src/vdbesort.c | 4 ++-- + src/vtab.c | 25 +++++++++++++++---------- + 15 files changed, 61 insertions(+), 52 deletions(-) + +diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c +index 5778620..efffff3 100644 +--- a/ext/fts3/fts3_snippet.c ++++ b/ext/fts3/fts3_snippet.c +@@ -130,10 +130,11 @@ struct StrBuffer { + */ + static MatchinfoBuffer *fts3MIBufferNew(int nElem, const char *zMatchinfo){ + MatchinfoBuffer *pRet; +- int nByte = sizeof(u32) * (2*nElem + 1) + sizeof(MatchinfoBuffer); +- int nStr = (int)strlen(zMatchinfo); ++ sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1) ++ + sizeof(MatchinfoBuffer); ++ sqlite3_int64 nStr = strlen(zMatchinfo); + +- pRet = sqlite3_malloc(nByte + nStr+1); ++ pRet = sqlite3_malloc64(nByte + nStr+1); + if( pRet ){ + memset(pRet, 0, nByte); + pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet; +diff --git a/ext/fts3/fts3_test.c b/ext/fts3/fts3_test.c +index a48a556..0b4edcc 100644 +--- a/ext/fts3/fts3_test.c ++++ b/ext/fts3/fts3_test.c +@@ -448,14 +448,14 @@ static int testTokenizerNext( + }else{ + /* Advance to the end of the token */ + const char *pToken = p; +- int nToken; ++ sqlite3_int64 nToken; + while( ppCsr->nBuffer ){ + sqlite3_free(pCsr->aBuffer); +- pCsr->aBuffer = sqlite3_malloc(nToken); ++ pCsr->aBuffer = sqlite3_malloc64(nToken); + } + if( pCsr->aBuffer==0 ){ + rc = SQLITE_NOMEM; +diff --git a/ext/fts3/fts3_tokenize_vtab.c b/ext/fts3/fts3_tokenize_vtab.c +index a3d24bc..5b4085b 100644 +--- a/ext/fts3/fts3_tokenize_vtab.c ++++ b/ext/fts3/fts3_tokenize_vtab.c +@@ -346,7 +346,7 @@ static int fts3tokFilterMethod( + if( idxNum==1 ){ + const char *zByte = (const char *)sqlite3_value_text(apVal[0]); + int nByte = sqlite3_value_bytes(apVal[0]); +- pCsr->zInput = sqlite3_malloc(nByte+1); ++ pCsr->zInput = sqlite3_malloc64(nByte+1); + if( pCsr->zInput==0 ){ + rc = SQLITE_NOMEM; + }else{ +diff --git a/ext/fts3/fts3_tokenizer.c b/ext/fts3/fts3_tokenizer.c +index bfc36af..fe2003e 100644 +--- a/ext/fts3/fts3_tokenizer.c ++++ b/ext/fts3/fts3_tokenizer.c +@@ -194,8 +194,8 @@ int sqlite3Fts3InitTokenizer( + int iArg = 0; + z = &z[n+1]; + while( z0 ){ +- int nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); +- pReader = (Fts3SegReader *)sqlite3_malloc(nByte); ++ sqlite3_int64 nByte; ++ nByte = sizeof(Fts3SegReader) + (nElem+1)*sizeof(Fts3HashElem *); ++ pReader = (Fts3SegReader *)sqlite3_malloc64(nByte); + if( !pReader ){ + rc = SQLITE_NOMEM; + }else{ +@@ -3357,7 +3358,7 @@ static void fts3InsertDocsize( + int rc; /* Result code from subfunctions */ + + if( *pRC ) return; +- pBlob = sqlite3_malloc( 10*p->nColumn ); ++ pBlob = sqlite3_malloc64( 10*(sqlite3_int64)p->nColumn ); + if( pBlob==0 ){ + *pRC = SQLITE_NOMEM; + return; +@@ -3407,7 +3408,7 @@ static void fts3UpdateDocTotals( + const int nStat = p->nColumn+2; + + if( *pRC ) return; +- a = sqlite3_malloc( (sizeof(u32)+10)*nStat ); ++ a = sqlite3_malloc64( (sizeof(u32)+10)*(sqlite3_int64)nStat ); + if( a==0 ){ + *pRC = SQLITE_NOMEM; + return; +@@ -3528,8 +3529,8 @@ static int fts3DoRebuild(Fts3Table *p){ + } + + if( rc==SQLITE_OK ){ +- int nByte = sizeof(u32) * (p->nColumn+1)*3; +- aSz = (u32 *)sqlite3_malloc(nByte); ++ sqlite3_int64 nByte = sizeof(u32) * ((sqlite3_int64)p->nColumn+1)*3; ++ aSz = (u32 *)sqlite3_malloc64(nByte); + if( aSz==0 ){ + rc = SQLITE_NOMEM; + }else{ +@@ -3595,12 +3596,12 @@ static int fts3IncrmergeCsr( + ){ + int rc; /* Return Code */ + sqlite3_stmt *pStmt = 0; /* Statement used to read %_segdir entry */ +- int nByte; /* Bytes allocated at pCsr->apSegment[] */ ++ sqlite3_int64 nByte; /* Bytes allocated at pCsr->apSegment[] */ + + /* Allocate space for the Fts3MultiSegReader.aCsr[] array */ + memset(pCsr, 0, sizeof(*pCsr)); + nByte = sizeof(Fts3SegReader *) * nSeg; +- pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc(nByte); ++ pCsr->apSegment = (Fts3SegReader **)sqlite3_malloc64(nByte); + + if( pCsr->apSegment==0 ){ + rc = SQLITE_NOMEM; +@@ -5591,7 +5592,7 @@ int sqlite3Fts3UpdateMethod( + } + + /* Allocate space to hold the change in document sizes */ +- aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); ++ aSzDel = sqlite3_malloc64(sizeof(aSzDel[0])*((sqlite3_int64)p->nColumn+1)*2); + if( aSzDel==0 ){ + rc = SQLITE_NOMEM; + goto update_out; +diff --git a/ext/fts5/fts5_tokenize.c b/ext/fts5/fts5_tokenize.c +index af2bc22..029efc5 100644 +--- a/ext/fts5/fts5_tokenize.c ++++ b/ext/fts5/fts5_tokenize.c +@@ -363,7 +363,7 @@ static int fts5UnicodeCreate( + + p->bRemoveDiacritic = 1; + p->nFold = 64; +- p->aFold = sqlite3_malloc(p->nFold * sizeof(char)); ++ p->aFold = sqlite3_malloc64(p->nFold * sizeof(char)); + if( p->aFold==0 ){ + rc = SQLITE_NOMEM; + } +diff --git a/ext/rtree/geopoly.c b/ext/rtree/geopoly.c +index f6a31f5..7b97f9b 100644 +--- a/ext/rtree/geopoly.c ++++ b/ext/rtree/geopoly.c +@@ -261,7 +261,7 @@ static GeoPoly *geopolyParseJson(const unsigned char *z, int *pRc){ + GeoPoly *pOut; + int x = 1; + s.nVertex--; /* Remove the redundant vertex at the end */ +- pOut = sqlite3_malloc64( GEOPOLY_SZ(s.nVertex) ); ++ pOut = sqlite3_malloc64( GEOPOLY_SZ((sqlite3_int64)s.nVertex) ); + x = 1; + if( pOut==0 ) goto parse_json_err; + pOut->nVertex = s.nVertex; +@@ -644,7 +644,7 @@ static GeoPoly *geopolyBBox( + if( pRc ) *pRc = SQLITE_OK; + if( aCoord==0 ){ + geopolyBboxFill: +- pOut = sqlite3_realloc(p, GEOPOLY_SZ(4)); ++ pOut = sqlite3_realloc64(p, GEOPOLY_SZ(4)); + if( pOut==0 ){ + sqlite3_free(p); + if( context ) sqlite3_result_error_nomem(context); +@@ -1040,9 +1040,9 @@ static GeoSegment *geopolySortSegmentsByYAndC(GeoSegment *pList){ + ** Determine the overlap between two polygons + */ + static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ +- int nVertex = p1->nVertex + p2->nVertex + 2; ++ sqlite3_int64 nVertex = p1->nVertex + p2->nVertex + 2; + GeoOverlap *p; +- int nByte; ++ sqlite3_int64 nByte; + GeoEvent *pThisEvent; + double rX; + int rc = 0; +@@ -1054,7 +1054,7 @@ static int geopolyOverlap(GeoPoly *p1, GeoPoly *p2){ + nByte = sizeof(GeoEvent)*nVertex*2 + + sizeof(GeoSegment)*nVertex + + sizeof(GeoOverlap); +- p = sqlite3_malloc( nByte ); ++ p = sqlite3_malloc64( nByte ); + if( p==0 ) return -1; + p->aEvent = (GeoEvent*)&p[1]; + p->aSegment = (GeoSegment*)&p->aEvent[nVertex*2]; +@@ -1213,8 +1213,8 @@ static int geopolyInit( + ){ + int rc = SQLITE_OK; + Rtree *pRtree; +- int nDb; /* Length of string argv[1] */ +- int nName; /* Length of string argv[2] */ ++ sqlite3_int64 nDb; /* Length of string argv[1] */ ++ sqlite3_int64 nName; /* Length of string argv[2] */ + sqlite3_str *pSql; + char *zSql; + int ii; +@@ -1222,9 +1222,9 @@ static int geopolyInit( + sqlite3_vtab_config(db, SQLITE_VTAB_CONSTRAINT_SUPPORT, 1); + + /* Allocate the sqlite3_vtab structure */ +- nDb = (int)strlen(argv[1]); +- nName = (int)strlen(argv[2]); +- pRtree = (Rtree *)sqlite3_malloc(sizeof(Rtree)+nDb+nName+2); ++ nDb = strlen(argv[1]); ++ nName = strlen(argv[2]); ++ pRtree = (Rtree *)sqlite3_malloc64(sizeof(Rtree)+nDb+nName+2); + if( !pRtree ){ + return SQLITE_NOMEM; + } +diff --git a/src/build.c b/src/build.c +index afe4171..1dc2614 100644 +--- a/src/build.c ++++ b/src/build.c +@@ -3760,9 +3760,9 @@ void *sqlite3ArrayAllocate( + int *pIdx /* Write the index of a new slot here */ + ){ + char *z; +- int n = *pnEntry; ++ sqlite3_int64 n = *pnEntry; + if( (n & (n-1))==0 ){ +- int sz = (n==0) ? 1 : 2*n; ++ sqlite3_int64 sz = (n==0) ? 1 : 2*n; + void *pNew = sqlite3DbRealloc(db, pArray, sz*szEntry); + if( pNew==0 ){ + *pIdx = -1; +@@ -3870,7 +3870,7 @@ SrcList *sqlite3SrcListEnlarge( + /* Allocate additional space if needed */ + if( (u32)pSrc->nSrc+nExtra>pSrc->nAlloc ){ + SrcList *pNew; +- int nAlloc = pSrc->nSrc*2+nExtra; ++ sqlite3_int64 nAlloc = 2*(sqlite3_int64)pSrc->nSrc+nExtra; + int nGot; + pNew = sqlite3DbRealloc(db, pSrc, + sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) ); +@@ -4612,7 +4612,7 @@ With *sqlite3WithAdd( + } + + if( pWith ){ +- int nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); ++ sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte); + pNew = sqlite3DbRealloc(db, pWith, nByte); + }else{ + pNew = sqlite3DbMallocZero(db, sizeof(*pWith)); +diff --git a/src/expr.c b/src/expr.c +index 5f98f76..d64b8eb 100644 +--- a/src/expr.c ++++ b/src/expr.c +@@ -1547,7 +1547,7 @@ ExprList *sqlite3ExprListAppend( + }else if( (pList->nExpr & (pList->nExpr-1))==0 ){ + ExprList *pNew; + pNew = sqlite3DbRealloc(db, pList, +- sizeof(*pList)+(2*pList->nExpr - 1)*sizeof(pList->a[0])); ++ sizeof(*pList)+(2*(sqlite3_int64)pList->nExpr-1)*sizeof(pList->a[0])); + if( pNew==0 ){ + goto no_mem; + } +diff --git a/src/main.c b/src/main.c +index 46c8346..434b898 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -698,7 +698,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ + pStart = 0; + }else if( pBuf==0 ){ + sqlite3BeginBenignMalloc(); +- pStart = sqlite3Malloc( sz*cnt ); /* IMP: R-61949-35727 */ ++ pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */ + sqlite3EndBenignMalloc(); + if( pStart ) cnt = sqlite3MallocSize(pStart)/sz; + }else{ +diff --git a/src/test_fs.c b/src/test_fs.c +index 8192beb..1feea46 100644 +--- a/src/test_fs.c ++++ b/src/test_fs.c +@@ -744,7 +744,7 @@ static int fsColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ + fstat(fd, &sbuf); + + if( sbuf.st_size>=pCur->nAlloc ){ +- int nNew = sbuf.st_size*2; ++ sqlite3_int64 nNew = sbuf.st_size*2; + char *zNew; + if( nNew<1024 ) nNew = 1024; + +diff --git a/src/util.c b/src/util.c +index 96b0b14..7f2b977 100644 +--- a/src/util.c ++++ b/src/util.c +@@ -1572,7 +1572,7 @@ VList *sqlite3VListAdd( + assert( pIn==0 || pIn[0]>=3 ); /* Verify ok to add new elements */ + if( pIn==0 || pIn[1]+nInt > pIn[0] ){ + /* Enlarge the allocation */ +- int nAlloc = (pIn ? pIn[0]*2 : 10) + nInt; ++ sqlite3_int64 nAlloc = (pIn ? 2*(sqlite3_int64)pIn[0] : 10) + nInt; + VList *pOut = sqlite3DbRealloc(db, pIn, nAlloc*sizeof(int)); + if( pOut==0 ) return pIn; + if( pIn==0 ) pOut[1] = 2; +diff --git a/src/vdbeaux.c b/src/vdbeaux.c +index b74141b..ffc5d0b 100644 +--- a/src/vdbeaux.c ++++ b/src/vdbeaux.c +@@ -125,9 +125,11 @@ static int growOpArray(Vdbe *v, int nOp){ + ** operation (without SQLITE_TEST_REALLOC_STRESS) is to double the current + ** size of the op array or add 1KB of space, whichever is smaller. */ + #ifdef SQLITE_TEST_REALLOC_STRESS +- int nNew = (p->nOpAlloc>=512 ? p->nOpAlloc*2 : p->nOpAlloc+nOp); ++ sqlite3_int64 nNew = (p->nOpAlloc>=512 ? 2*(sqlite3_int64)p->nOpAlloc ++ : (sqlite3_int64)p->nOpAlloc+nOp); + #else +- int nNew = (p->nOpAlloc ? p->nOpAlloc*2 : (int)(1024/sizeof(Op))); ++ sqlite3_int64 nNew = (p->nOpAlloc ? 2*(sqlite3_int64)p->nOpAlloc ++ : (sqlite3_int64)1024/sizeof(Op)); + UNUSED_PARAMETER(nOp); + #endif + +@@ -875,7 +877,7 @@ void sqlite3VdbeScanStatus( + LogEst nEst, /* Estimated number of output rows */ + const char *zName /* Name of table or index being scanned */ + ){ +- int nByte = (p->nScan+1) * sizeof(ScanStatus); ++ sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus); + ScanStatus *aNew; + aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); + if( aNew ){ +diff --git a/src/vdbesort.c b/src/vdbesort.c +index b30bc4e..d84a411 100644 +--- a/src/vdbesort.c ++++ b/src/vdbesort.c +@@ -537,7 +537,7 @@ static int vdbePmaReadBlob( + /* Extend the p->aAlloc[] allocation if required. */ + if( p->nAllocnAlloc*2); ++ sqlite3_int64 nNew = MAX(128, 2*(sqlite3_int64)p->nAlloc); + while( nByte>nNew ) nNew = nNew*2; + aNew = sqlite3Realloc(p->aAlloc, nNew); + if( !aNew ) return SQLITE_NOMEM_BKPT; +@@ -1829,7 +1829,7 @@ int sqlite3VdbeSorterWrite( + if( nMin>pSorter->nMemory ){ + u8 *aNew; + int iListOff = (u8*)pSorter->list.pList - pSorter->list.aMemory; +- int nNew = pSorter->nMemory * 2; ++ sqlite3_int64 nNew = 2 * (sqlite3_int64)pSorter->nMemory; + while( nNew < nMin ) nNew = nNew*2; + if( nNew > pSorter->mxPmaSize ) nNew = pSorter->mxPmaSize; + if( nNew < nMin ) nNew = nMin; +diff --git a/src/vtab.c b/src/vtab.c +index 1b8d283..41c6093 100644 +--- a/src/vtab.c ++++ b/src/vtab.c +@@ -302,9 +302,13 @@ void sqlite3VtabClear(sqlite3 *db, Table *p){ + ** string will be freed automatically when the table is + ** deleted. + */ +-static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ +- int nBytes = sizeof(char *)*(2+pTable->nModuleArg); ++static void addModuleArgument(Parse *pParse, Table *pTable, char *zArg){ ++ sqlite3_int64 nBytes = sizeof(char *)*(2+pTable->nModuleArg); + char **azModuleArg; ++ sqlite3 *db = pParse->db; ++ if( pTable->nModuleArg+3>=db->aLimit[SQLITE_LIMIT_COLUMN] ){ ++ sqlite3ErrorMsg(pParse, "too many columns on %s", pTable->zName); ++ } + azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); + if( azModuleArg==0 ){ + sqlite3DbFree(db, zArg); +@@ -339,9 +343,9 @@ void sqlite3VtabBeginParse( + db = pParse->db; + + assert( pTable->nModuleArg==0 ); +- addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); +- addModuleArgument(db, pTable, 0); +- addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); ++ addModuleArgument(pParse, pTable, sqlite3NameFromToken(db, pModuleName)); ++ addModuleArgument(pParse, pTable, 0); ++ addModuleArgument(pParse, pTable, sqlite3DbStrDup(db, pTable->zName)); + assert( (pParse->sNameToken.z==pName2->z && pName2->z!=0) + || (pParse->sNameToken.z==pName1->z && pName2->z==0) + ); +@@ -374,7 +378,7 @@ static void addArgumentToVtab(Parse *pParse){ + const char *z = (const char*)pParse->sArg.z; + int n = pParse->sArg.n; + sqlite3 *db = pParse->db; +- addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); ++ addModuleArgument(pParse, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); + } + } + +@@ -663,7 +667,8 @@ static int growVTrans(sqlite3 *db){ + /* Grow the sqlite3.aVTrans array if required */ + if( (db->nVTrans%ARRAY_INCR)==0 ){ + VTable **aVTrans; +- int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); ++ sqlite3_int64 nBytes = sizeof(sqlite3_vtab*)* ++ ((sqlite3_int64)db->nVTrans + ARRAY_INCR); + aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); + if( !aVTrans ){ + return SQLITE_NOMEM_BKPT; +@@ -1157,9 +1162,9 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ + pTab->pSchema = db->aDb[0].pSchema; + assert( pTab->nModuleArg==0 ); + pTab->iPKey = -1; +- addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); +- addModuleArgument(db, pTab, 0); +- addModuleArgument(db, pTab, sqlite3DbStrDup(db, pTab->zName)); ++ addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); ++ addModuleArgument(pParse, pTab, 0); ++ addModuleArgument(pParse, pTab, sqlite3DbStrDup(db, pTab->zName)); + rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr); + if( rc ){ + sqlite3ErrorMsg(pParse, "%s", zErr); +-- +2.30.2 + diff --git a/sqlite-3.26.0-CVE-2020-13435.patch b/sqlite-3.26.0-CVE-2020-13435.patch new file mode 100644 index 0000000..8a88771 --- /dev/null +++ b/sqlite-3.26.0-CVE-2020-13435.patch @@ -0,0 +1,144 @@ +Subject: [PATCH] When rewriting a query for window functions, if the rewrite +changes the depth of TK_AGG_FUNCTION nodes, be sure to adjust the Expr.op2 +field appropriately. + +diff --git a/src/resolve.c b/src/resolve.c +index cdcf4d9..c47f6bb 100644 +--- a/src/resolve.c ++++ b/src/resolve.c +@@ -24,6 +24,8 @@ + ** + ** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..) + ** is a helper function - a callback for the tree walker. ++** ++** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c + */ + static int incrAggDepth(Walker *pWalker, Expr *pExpr){ + if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n; +diff --git a/src/select.c b/src/select.c +index a6d1757..6f5570c 100644 +--- a/src/select.c ++++ b/src/select.c +@@ -1961,7 +1961,7 @@ int sqlite3ColumnsFromExprList( + assert( pColExpr!=0 ); + } + assert( pColExpr->op!=TK_AGG_COLUMN ); +- if( pColExpr->op==TK_COLUMN ){ ++ if( pColExpr->op==TK_COLUMN && pColExpr->y.pTab ){ + /* For columns use the column name name */ + int iCol = pColExpr->iColumn; + Table *pTab = pColExpr->y.pTab; +diff --git a/src/sqliteInt.h b/src/sqliteInt.h +index 1cf6937..ea9a7ae 100644 +--- a/src/sqliteInt.h ++++ b/src/sqliteInt.h +@@ -3579,6 +3579,8 @@ void sqlite3WindowUpdate(Parse*, Window*, Window*, FuncDef*); + Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p); + Window *sqlite3WindowListDup(sqlite3 *db, Window *p); + void sqlite3WindowFunctions(void); ++int sqlite3WalkerDepthIncrease(Walker*,Select*); ++void sqlite3WalkerDepthDecrease(Walker*,Select*); + #else + # define sqlite3WindowDelete(a,b) + # define sqlite3WindowFunctions() +diff --git a/src/walker.c b/src/walker.c +index c31d94f..8cd3b65 100644 +--- a/src/walker.c ++++ b/src/walker.c +@@ -165,3 +165,16 @@ int sqlite3WalkSelect(Walker *pWalker, Select *p){ + }while( p!=0 ); + return WRC_Continue; + } ++ ++/* Increase the walkerDepth when entering a subquery, and ++** descrease when leaving the subquery. ++*/ ++int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){ ++ UNUSED_PARAMETER(pSelect); ++ pWalker->walkerDepth++; ++ return WRC_Continue; ++} ++void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){ ++ UNUSED_PARAMETER(pSelect); ++ pWalker->walkerDepth--; ++} +\ No newline at end of file +diff --git a/src/window.c b/src/window.c +index c65eadd..48d8090 100644 +--- a/src/window.c ++++ b/src/window.c +@@ -738,6 +738,23 @@ static ExprList *exprListAppendList( + return pList; + } + ++/* ++** When rewriting a query, if the new subquery in the FROM clause ++** contains TK_AGG_FUNCTION nodes that refer to an outer query, ++** then we have to increase the Expr->op2 values of those nodes ++** due to the extra subquery layer that was added. ++** ++** See also the incrAggDepth() routine in resolve.c ++*/ ++static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){ ++ if( pExpr->op==TK_AGG_FUNCTION ++ && pExpr->op2>=pWalker->walkerDepth ++ ){ ++ pExpr->op2++; ++ } ++ return WRC_Continue; ++} ++ + /* + ** If the SELECT statement passed as the second argument does not invoke + ** any SQL window functions, this function is a no-op. Otherwise, it +@@ -827,14 +844,24 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){ + p->pSrc = sqlite3SrcListAppend(db, 0, 0, 0); + assert( p->pSrc || db->mallocFailed ); + if( p->pSrc ){ ++ Table *pTab2; ++ Walker w; + p->pSrc->a[0].pSelect = pSub; + sqlite3SrcListAssignCursors(pParse, p->pSrc); +- if( sqlite3ExpandSubquery(pParse, &p->pSrc->a[0]) ){ ++ pTab2 = sqlite3ResultSetOfSelect(pParse, pSub); ++ if( pTab2==0 ){ + rc = SQLITE_NOMEM; + }else{ + pSub->selFlags |= SF_Expanded; + p->selFlags &= ~SF_Aggregate; + sqlite3SelectPrep(pParse, pSub, 0); ++ pTab2->tabFlags |= TF_Ephemeral; ++ p->pSrc->a[0].pTab = pTab2; ++ memset(&w, 0, sizeof(w)); ++ w.xExprCallback = sqlite3WindowExtraAggFuncDepth; ++ w.xSelectCallback = sqlite3WalkerDepthIncrease; ++ w.xSelectCallback2 = sqlite3WalkerDepthDecrease; ++ sqlite3WalkSelect(&w, pSub); + } + + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr); +diff --git a/test/window1.test b/test/window1.test +index a8399a8..13ecc32 100644 +--- a/test/window1.test ++++ b/test/window1.test +@@ -594,4 +594,20 @@ do_execsql_test 13.5 { + } { + } + ++# 2020-05-23 ++# ticket 7a5279a25c57adf1 ++# ++reset_db ++do_execsql_test 53.0 { ++ CREATE TABLE a(c UNIQUE); ++ INSERT INTO a VALUES(4),(0),(9),(-9); ++ SELECT a.c ++ FROM a ++ JOIN a AS b ON a.c=4 ++ JOIN a AS e ON a.c=e.c ++ WHERE a.c=(SELECT (SELECT coalesce(lead(2) OVER(),0) + sum(d.c)) ++ FROM a AS d ++ WHERE a.c); ++} {4 4 4 4} ++ + finish_test diff --git a/sqlite-3.26.0-CVE-2020-24736.patch b/sqlite-3.26.0-CVE-2020-24736.patch new file mode 100644 index 0000000..38c1930 --- /dev/null +++ b/sqlite-3.26.0-CVE-2020-24736.patch @@ -0,0 +1,114 @@ +From f030b376820102ff6cda49565c8b8173b2d44606 Mon Sep 17 00:00:00 2001 +From: dan +Date: Fri, 22 Feb 2019 19:24:16 +0000 +Subject: [PATCH] Internally, remove all references to a Window object that + belongs to an expression in an ORDER BY clause if that expression is + converted to an alias of a result-set expression. Fix for [4feb3159c6]. + +FossilOrigin-Name: 579b66eaa0816561c6e47ea116b46f229188f0fc84c1173bfe0d21df2dff9a9a +--- + src/resolve.c | 49 ++++++++++++++++++++++++++++++++++------------- + test/window1.test | 20 +++++++++++++++++++ + 2 files changed, 56 insertions(+), 13 deletions(-) + +diff --git a/src/resolve.c b/src/resolve.c +index 9410bc020..fd2cf539a 100644 +--- a/src/resolve.c ++++ b/src/resolve.c +@@ -1243,6 +1243,38 @@ int sqlite3ResolveOrderGroupBy( + return 0; + } + ++#ifndef SQLITE_OMIT_WINDOWFUNC ++/* ++** Walker callback for resolveRemoveWindows(). ++*/ ++static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){ ++ if( ExprHasProperty(pExpr, EP_WinFunc) ){ ++ Window **pp; ++ for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ ++ if( *pp==pExpr->y.pWin ){ ++ *pp = (*pp)->pNextWin; ++ break; ++ } ++ } ++ } ++ return WRC_Continue; ++} ++ ++/* ++** Remove any Window objects owned by the expression pExpr from the ++** Select.pWin list of Select object pSelect. ++*/ ++static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){ ++ Walker sWalker; ++ memset(&sWalker, 0, sizeof(Walker)); ++ sWalker.xExprCallback = resolveRemoveWindowsCb; ++ sWalker.u.pSelect = pSelect; ++ sqlite3WalkExpr(&sWalker, pExpr); ++} ++#else ++# define resolveRemoveWindows(x,y) ++#endif ++ + /* + ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect. + ** The Name context of the SELECT statement is pNC. zType is either +@@ -1309,19 +1341,10 @@ static int resolveOrderGroupBy( + } + for(j=0; jpEList->nExpr; j++){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ +-#ifndef SQLITE_OMIT_WINDOWFUNC +- if( ExprHasProperty(pE, EP_WinFunc) ){ +- /* Since this window function is being changed into a reference +- ** to the same window function the result set, remove the instance +- ** of this window function from the Select.pWin list. */ +- Window **pp; +- for(pp=&pSelect->pWin; *pp; pp=&(*pp)->pNextWin){ +- if( *pp==pE->y.pWin ){ +- *pp = (*pp)->pNextWin; +- } +- } +- } +-#endif ++ /* Since this expresion is being changed into a reference ++ ** to an identical expression in the result set, remove all Window ++ ** objects belonging to the expression from the Select.pWin list. */ ++ resolveRemoveWindows(pSelect, pE); + pItem->u.x.iOrderByCol = j+1; + } + } +diff --git a/test/window1.test b/test/window1.test +index 2c504205e..b3073985b 100644 +--- a/test/window1.test ++++ b/test/window1.test +@@ -594,6 +594,26 @@ + } { + } + ++#------------------------------------------------------------------------- ++do_execsql_test 17.0 { ++ CREATE TABLE t8(a); ++ INSERT INTO t8 VALUES(1), (2), (3); ++} ++ ++do_execsql_test 17.1 { ++ SELECT +sum(0) OVER () ORDER BY +sum(0) OVER (); ++} {0} ++ ++do_execsql_test 17.2 { ++ select +sum(a) OVER () FROM t8 ORDER BY +sum(a) OVER () DESC; ++} {6 6 6} ++ ++do_execsql_test 17.3 { ++ SELECT 10+sum(a) OVER (ORDER BY a) ++ FROM t8 ++ ORDER BY 10+sum(a) OVER (ORDER BY a) DESC; ++} {16 13 11} ++ + # 2020-05-23 + # ticket 7a5279a25c57adf1 + # +-- +2.39.2 + diff --git a/sqlite-3.26.0-CVE-2020-35525.patch b/sqlite-3.26.0-CVE-2020-35525.patch new file mode 100644 index 0000000..34d4dc6 --- /dev/null +++ b/sqlite-3.26.0-CVE-2020-35525.patch @@ -0,0 +1,26 @@ +From 5f69512404cd2e5153ddf90ea277fbba6dd58ab7 Mon Sep 17 00:00:00 2001 +From: drh +Date: Thu, 20 Feb 2020 14:08:51 +0000 +Subject: [PATCH] Early-out on the INTERSECT query processing following an + error. + +FossilOrigin-Name: a67cf5b7d37d5b1484be32092635faafd8f76e5881898cd9435517c4b287d663 +--- + src/select.c | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +diff --git a/src/select.c b/src/select.c +index c60ff2700..b3ae9f415 100644 +--- a/src/select.c ++++ b/src/select.c +@@ -2775,6 +2775,7 @@ static int multiSelect( + /* Generate code to take the intersection of the two temporary + ** tables. + */ ++ if( rc ) break; + assert( p->pEList ); + iBreak = sqlite3VdbeMakeLabel(v); + iCont = sqlite3VdbeMakeLabel(v); +-- +2.37.3 + diff --git a/sqlite-3.26.0-CVE-2020-35527.patch b/sqlite-3.26.0-CVE-2020-35527.patch new file mode 100644 index 0000000..6912457 --- /dev/null +++ b/sqlite-3.26.0-CVE-2020-35527.patch @@ -0,0 +1,55 @@ +From 0990c415f65d2556a5e4122cbe5727d500411aeb Mon Sep 17 00:00:00 2001 +From: drh +Date: Sun, 23 Feb 2020 17:34:45 +0000 +Subject: [PATCH] Fix a problem with ALTER TABLE for views that have a nested + FROM clause. Ticket [f50af3e8a565776b]. + +FossilOrigin-Name: c431b3fd8fd0f6a6974bba3e9366b0430ec003d570e7ce70ceefbcff5fe4b6fa +--- + src/select.c | 2 +- + test/altertab.test | 17 +++++++++++++++++ + 4 files changed, 18 insertions(+), 1 deletions(-) + +diff --git a/src/select.c b/src/select.c +index c60ff2700..fe0229ca8 100644 +--- a/src/select.c ++++ b/src/select.c +@@ -5046,7 +5046,7 @@ static int selectExpander(Walker *pWalker, Select *p){ + pNew = sqlite3ExprListAppend(pParse, pNew, pExpr); + sqlite3TokenInit(&sColname, zColname); + sqlite3ExprListSetName(pParse, pNew, &sColname, 0); +- if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){ ++ if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT){ + struct ExprList_item *pX = &pNew->a[pNew->nExpr-1]; + if( pSub ){ + pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan); + +diff --git a/test/altertab.test b/test/altertab.test +index a3642070e..520502c3d 100644 +--- a/test/altertab.test ++++ b/test/altertab.test +@@ -578,5 +578,21 @@ ifcapable fts3 { + SELECT * FROM z1_segments; + } + } ++# 2020-02-23 ticket f50af3e8a565776b ++reset_db ++do_execsql_test 19.100 { ++ CREATE TABLE t1(x); ++ CREATE VIEW t2 AS SELECT 1 FROM t1, (t1 AS a0, t1); ++ ALTER TABLE t1 RENAME TO t3; ++ SELECT sql FROM sqlite_master; ++} {{CREATE TABLE "t3"(x)} {CREATE VIEW t2 AS SELECT 1 FROM "t3", ("t3" AS a0, "t3")}} ++do_execsql_test 19.110 { ++ INSERT INTO t3(x) VALUES(123); ++ SELECT * FROM t2; ++} {1} ++do_execsql_test 19.120 { ++ INSERT INTO t3(x) VALUES('xyz'); ++ SELECT * FROM t2; ++} {1 1 1 1 1 1 1 1} + + finish_test +-- +2.37.3 + diff --git a/sqlite-3.26.0-CVE-2022-35737.patch b/sqlite-3.26.0-CVE-2022-35737.patch new file mode 100644 index 0000000..963e119 --- /dev/null +++ b/sqlite-3.26.0-CVE-2022-35737.patch @@ -0,0 +1,31 @@ +From 077e17b59a98eb8839ecfef661e7305fdb3e898d Mon Sep 17 00:00:00 2001 +From: drh <> +Date: Mon, 18 Jul 2022 15:02:00 +0000 +Subject: [PATCH] Increase the size of loop variables in the printf() + implementation to avoid harmless compiler warnings. + +FossilOrigin-Name: aab790a16e1bdff78759f9c9ae87a2559ba82dd34ef3dedfb66035a0db7067a7 +--- + manifest | 12 ++++++------ + manifest.uuid | 2 +- + src/printf.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/printf.c b/src/printf.c +index f0bfa5327..3602e1fcb 100644 +--- a/src/printf.c ++++ b/src/printf.c +@@ -803,8 +803,8 @@ void sqlite3_str_vappendf( + case etSQLESCAPE: /* %q: Escape ' characters */ + case etSQLESCAPE2: /* %Q: Escape ' and enclose in '...' */ + case etSQLESCAPE3: { /* %w: Escape " characters */ +- int i, j, k, n, isnull; +- int needQuote; ++ i64 i, j, k, n; ++ int needQuote, isnull; + char ch; + char q = ((xtype==etSQLESCAPE3)?'"':'\''); /* Quote character */ + char *escarg; +-- +2.38.1 + diff --git a/sqlite-3.34.1-CVE-2023-7104.patch b/sqlite-3.34.1-CVE-2023-7104.patch new file mode 100644 index 0000000..6b9c1b7 --- /dev/null +++ b/sqlite-3.34.1-CVE-2023-7104.patch @@ -0,0 +1,42 @@ +From 09f1652f36c5c4e8a6a640ce887f9ea0f48a7958 Mon Sep 17 00:00:00 2001 +From: dan +Date: Thu, 7 Sep 2023 13:53:09 +0000 +Subject: [PATCH] Fix a buffer overread in the sessions extension that could + occur when processing a corrupt changeset. + +FossilOrigin-Name: 0e4e7a05c4204b47a324d67e18e76d2a98e26b2723d19d5c655ec9fd2e41f4b7 + +diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c +index 9f862f2465..0491549231 100644 +--- a/ext/session/sqlite3session.c ++++ b/ext/session/sqlite3session.c +@@ -2811,15 +2811,19 @@ static int sessionReadRecord( + } + } + if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ +- sqlite3_int64 v = sessionGetI64(aVal); +- if( eType==SQLITE_INTEGER ){ +- sqlite3VdbeMemSetInt64(apOut[i], v); ++ if( (pIn->nData-pIn->iNext)<8 ){ ++ rc = SQLITE_CORRUPT_BKPT; + }else{ +- double d; +- memcpy(&d, &v, 8); +- sqlite3VdbeMemSetDouble(apOut[i], d); ++ sqlite3_int64 v = sessionGetI64(aVal); ++ if( eType==SQLITE_INTEGER ){ ++ sqlite3VdbeMemSetInt64(apOut[i], v); ++ }else{ ++ double d; ++ memcpy(&d, &v, 8); ++ sqlite3VdbeMemSetDouble(apOut[i], d); ++ } ++ pIn->iNext += 8; + } +- pIn->iNext += 8; + } + } + } +-- +2.43.0 + diff --git a/sqlite-3.34.1-CVE-2025-6965.patch b/sqlite-3.34.1-CVE-2025-6965.patch new file mode 100644 index 0000000..2be7498 --- /dev/null +++ b/sqlite-3.34.1-CVE-2025-6965.patch @@ -0,0 +1,95 @@ +From d9ca6e7b0d2e93dc5510baac4b92c9b6d217f9e5 Mon Sep 17 00:00:00 2001 +From: Ales Nezbeda +Date: Wed, 16 Jul 2025 23:59:02 +0200 +Subject: [PATCH] Fixes CVE-2025-6965 + +--- + src/expr.c | 19 ++++++++++++++++++- + src/sqliteInt.h | 8 ++++++++ + 2 files changed, 26 insertions(+), 1 deletion(-) + +diff --git a/src/expr.c b/src/expr.c +index 791e61e..946ed9b 100644 +--- a/src/expr.c ++++ b/src/expr.c +@@ -5136,6 +5136,11 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + ** is not an entry there already. + */ + int k; ++ ++ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; ++ ++ assert( mxTerm <= SMXV(i16) ); ++ + pCol = pAggInfo->aCol; + for(k=0; knColumn; k++, pCol++){ + if( pCol->iTable==pExpr->iTable && +@@ -5146,6 +5151,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + if( (k>=pAggInfo->nColumn) + && (k = addAggInfoColumn(pParse->db, pAggInfo))>=0 + ){ ++ if( k>mxTerm ){ ++ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); ++ k = mxTerm; ++ } + pCol = &pAggInfo->aCol[k]; + pCol->pTab = pExpr->y.pTab; + pCol->iTable = pExpr->iTable; +@@ -5179,6 +5188,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + ExprSetVVAProperty(pExpr, EP_NoReduce); + pExpr->pAggInfo = pAggInfo; + pExpr->op = TK_AGG_COLUMN; ++ assert( k <= SMXV(pExpr->iAgg) ); + pExpr->iAgg = (i16)k; + break; + } /* endif pExpr->iTable==pItem->iCursor */ +@@ -5194,12 +5204,18 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + ** function that is already in the pAggInfo structure + */ + struct AggInfo_func *pItem = pAggInfo->aFunc; ++ int mxTerm = pParse->db->aLimit[SQLITE_LIMIT_COLUMN]; ++ assert( mxTerm <= SMXV(i16) ); + for(i=0; inFunc; i++, pItem++){ + if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){ + break; + } + } +- if( i>=pAggInfo->nFunc ){ ++ if( i>mxTerm ){ ++ sqlite3ErrorMsg(pParse, "more than %d aggregate terms", mxTerm); ++ i = mxTerm; ++ assert( inFunc ); ++ }else if( i>=pAggInfo->nFunc ){ + /* pExpr is original. Make a new entry in pAggInfo->aFunc[] + */ + u8 enc = ENC(pParse->db); +@@ -5224,6 +5240,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ + */ + assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + ExprSetVVAProperty(pExpr, EP_NoReduce); ++ assert( i <= SMXV(pExpr->iAgg) ); + pExpr->iAgg = (i16)i; + pExpr->pAggInfo = pAggInfo; + return WRC_Prune; +diff --git a/src/sqliteInt.h b/src/sqliteInt.h +index d13c715..a509330 100644 +--- a/src/sqliteInt.h ++++ b/src/sqliteInt.h +@@ -868,6 +868,14 @@ typedef INT16_TYPE LogEst; + #define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32)) + #define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64) + ++/* ++** Macro SMXV(n) return the maximum value that can be held in variable n, ++** assuming n is a signed integer type. UMXV(n) is similar for unsigned ++** integer types. ++*/ ++#define SMXV(n) ((((i64)1)<<(sizeof(n)*8-1))-1) ++#define UMXV(n) ((((i64)1)<<(sizeof(n)*8))-1) ++ + /* + ** Round up a number to the next larger multiple of 8. This is used + ** to force 8-byte alignment on 64-bit architectures. +-- +2.50.0 +