sqlite/SOURCES/sqlite-3.26.0-CVE-2019-19645.patch
2021-09-10 04:51:57 +00:00

113 lines
3.8 KiB
Diff

Subject: [PATCH] Avoid infinite recursion in the ALTER TABLE code when a view
contains an unused CTE that references, directly or indirectly, the view itself.
diff --git a/src/alter.c b/src/alter.c
index 707472a..132c821 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -796,6 +796,7 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
+ if( p->selFlags & SF_View ) return WRC_Prune;
UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(p);
return WRC_Continue;
@@ -1258,8 +1259,9 @@ static void renameColumnFunc(
if( sParse.pNewTable ){
Select *pSelect = sParse.pNewTable->pSelect;
if( pSelect ){
+ pSelect->selFlags &= ~SF_View;
sParse.rc = SQLITE_OK;
- sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
+ sqlite3SelectPrep(&sParse, pSelect, 0);
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
if( rc==SQLITE_OK ){
sqlite3WalkSelect(&sWalker, pSelect);
@@ -1368,6 +1370,7 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
+ if( pSelect->selFlags & SF_View ) return WRC_Prune;
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
@@ -1442,10 +1445,13 @@ static void renameTableFunc(
if( pTab->pSelect ){
if( isLegacy==0 ){
+ Select *pSelect = pTab->pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = &sParse;
+ assert( pSelect->selFlags & SF_View );
+ pSelect->selFlags &= ~SF_View;
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
if( sParse.nErr ) rc = sParse.rc;
sqlite3WalkSelect(&sWalker, pTab->pSelect);
diff --git a/src/build.c b/src/build.c
index f273394..7d73893 100644
--- a/src/build.c
+++ b/src/build.c
@@ -2266,6 +2266,7 @@ void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
+ pSelect->selFlags |= SF_View;
if( IN_RENAME_OBJECT ){
p->pSelect = pSelect;
pSelect = 0;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index e5ba8a0..1cf6937 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -2875,6 +2875,7 @@ struct Select {
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
+#define SF_View 0x0200000 /* SELECT statement is a view */
/*
** The results of a SELECT can be distributed in several ways, as defined
diff --git a/test/altertab2.test b/test/altertab2.test
index 2102e02..f2fa5ee 100644
--- a/test/altertab2.test
+++ b/test/altertab2.test
@@ -106,4 +106,35 @@ do_catchsql_test 3.2 {
ALTER TABLE v0 RENAME TO t3 ;
} {1 {error in view v2: view v2 is circularly defined}}
+#------------------------------------------------------------------------
+#
+reset_db
+do_execsql_test 4.1 {
+ CREATE TABLE t1(a);
+ CREATE VIEW v2(b) AS SELECT * FROM v2;
+}
+
+do_catchsql_test 4.2 {
+ ALTER TABLE t1 RENAME TO t4;
+} {1 {error in view v2: view v2 is circularly defined}}
+
+do_execsql_test 4.3 {
+ DROP VIEW v2;
+ CREATE VIEW v2(b) AS WITH t3 AS (SELECT b FROM v2) SELECT * FROM t3;
+}
+
+breakpoint
+do_catchsql_test 4.4 {
+ ALTER TABLE t1 RENAME TO t4;
+} {1 {error in view v2: view v2 is circularly defined}}
+
+do_execsql_test 4.5 {
+ DROP VIEW v2;
+ CREATE VIEW v2(b) AS WITH t3 AS (SELECT b FROM v2) VALUES(1);
+}
+
+do_catchsql_test 4.6 {
+ ALTER TABLE t1 RENAME TO t4;
+} {0 {}}
+
finish_test