aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <>2024-08-20 19:09:59 +0000
committerdrh <>2024-08-20 19:09:59 +0000
commit692c160360c688c4bee3dd13d5293f2c416ad92f (patch)
tree8717f0cd601e571324612d4e170e4777274c54ee /src
parentff176231da8496e9fec72fe147eb60316f9c7f60 (diff)
downloadsqlite-692c160360c688c4bee3dd13d5293f2c416ad92f.tar.gz
sqlite-692c160360c688c4bee3dd13d5293f2c416ad92f.zip
Tighter checking of access constraints on union members in SrcItem.
Improved invariant checking. FossilOrigin-Name: fd72d3400a8fe5747f494eee81654698acee350bb95b9db269e87d857af03492
Diffstat (limited to 'src')
-rw-r--r--src/build.c11
-rw-r--r--src/delete.c2
-rw-r--r--src/fkey.c2
-rw-r--r--src/insert.c1
-rw-r--r--src/select.c4
-rw-r--r--src/sqliteInt.h30
-rw-r--r--src/trigger.c6
7 files changed, 38 insertions, 18 deletions
diff --git a/src/build.c b/src/build.c
index 9cbedf1ec..b2386035d 100644
--- a/src/build.c
+++ b/src/build.c
@@ -501,6 +501,7 @@ Table *sqlite3LocateTableItem(
int iDb = sqlite3SchemaToIndex(pParse->db, p->u4.pSchema);
zDb = pParse->db->aDb[iDb].zDbSName;
}else{
+ assert( !p->fg.isSubquery );
zDb = p->u4.zDatabase;
}
return sqlite3LocateTable(pParse, flags, p->zName, zDb);
@@ -3487,6 +3488,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
assert( isView==0 || isView==LOCATE_VIEW );
@@ -4587,6 +4589,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.isSubquery==0 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
}
@@ -4893,6 +4896,7 @@ SrcList *sqlite3SrcListAppend(
pDatabase = 0;
}
assert( pItem->fg.fixedSchema==0 );
+ assert( pItem->fg.isSubquery==0 );
if( pDatabase ){
pItem->zName = sqlite3NameFromToken(db, pDatabase);
pItem->u4.zDatabase = sqlite3NameFromToken(db, pTable);
@@ -4959,8 +4963,13 @@ void sqlite3SrcListDelete(sqlite3 *db, SrcList *pList){
for(pItem=pList->a, i=0; i<pList->nSrc; i++, pItem++){
/* Check invariants on SrcItem */
+ assert( !pItem->fg.isIndexedBy || !pItem->fg.isTabFunc );
+ assert( !pItem->fg.isCte || !pItem->fg.isIndexedBy );
assert( !pItem->fg.hadSchema || !pItem->fg.isSubquery );
- assert( pItem->fg.hadSchema==0 || pItem->fg.fixedSchema==1 );
+ assert( !pItem->fg.hadSchema || pItem->fg.fixedSchema );
+ assert( !pItem->fg.fixedSchema || !pItem->fg.isSubquery );
+ assert( !pItem->fg.isSubquery || (pItem->u4.pSubq!=0 &&
+ pItem->u4.pSubq->pSelect!=0) );
if( pItem->zName ) sqlite3DbNNFreeNN(db, pItem->zName);
if( pItem->zAlias ) sqlite3DbNNFreeNN(db, pItem->zAlias);
diff --git a/src/delete.c b/src/delete.c
index 1aa67c6a6..1d7ba66a2 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -156,7 +156,7 @@ void sqlite3MaterializeView(
if( pFrom ){
assert( pFrom->nSrc==1 );
pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
- assert( pFrom->a[0].fg.fixedSchema==0 );
+ assert( pFrom->a[0].fg.fixedSchema==0 && pFrom->a[0].fg.isSubquery==0 );
pFrom->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
assert( pFrom->a[0].fg.isUsing==0 );
assert( pFrom->a[0].u3.pOn==0 );
diff --git a/src/fkey.c b/src/fkey.c
index cd1f88502..f1117a884 100644
--- a/src/fkey.c
+++ b/src/fkey.c
@@ -1337,7 +1337,7 @@ static Trigger *fkActionTrigger(
if( pSrc ){
assert( pSrc->nSrc==1 );
pSrc->a[0].zName = sqlite3DbStrDup(db, zFrom);
- assert( pSrc->a[0].fg.fixedSchema==0 );
+ assert( pSrc->a[0].fg.fixedSchema==0 && pSrc->a[0].fg.isSubquery==0 );
pSrc->a[0].u4.zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zDbSName);
}
pSelect = sqlite3SelectNew(pParse,
diff --git a/src/insert.c b/src/insert.c
index 8214cd9c5..d380281be 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -729,6 +729,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
p = &pRet->pSrc->a[0];
p->fg.viaCoroutine = 1;
p->iCursor = -1;
+ assert( !p->fg.isIndexedBy && !p->fg.isTabFunc );
p->u1.nRow = 2;
if( sqlite3SrcItemAttachSubquery(pParse, p, pLeft, 0) ){
pSubq = p->u4.pSubq;
diff --git a/src/select.c b/src/select.c
index 0c10550fa..39955dd60 100644
--- a/src/select.c
+++ b/src/select.c
@@ -4522,6 +4522,7 @@ static int flattenSubquery(
}else{
pSub1 = 0;
}
+ assert( pSubitem->fg.isSubquery==0 );
if( pSubitem->fg.fixedSchema==0 ){
sqlite3DbFree(db, pSubitem->u4.zDatabase);
pSubitem->u4.zDatabase = 0;
@@ -5812,6 +5813,7 @@ static int resolveFromTermToCte(
sqlite3ErrorMsg(pParse, "no such index: \"%s\"", pFrom->u1.zIndexedBy);
return 2;
}
+ assert( !pFrom->fg.isIndexedBy );
pFrom->fg.isCte = 1;
pFrom->u2.pCteUse = pCteUse;
pCteUse->nUse++;
@@ -7728,6 +7730,8 @@ int sqlite3Select(
if( pItem->fg.fixedSchema ){
int iDb = sqlite3SchemaToIndex(pParse->db, pItem->u4.pSchema);
zDb = db->aDb[iDb].zDbSName;
+ }else if( pItem->fg.isSubquery ){
+ zDb = 0;
}else{
zDb = pItem->u4.zDatabase;
}
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index c282023de..9e0faf9cc 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3298,26 +3298,30 @@ struct Subquery {
** In the colUsed field, the high-order bit (bit 63) is set if the table
** contains more than 63 columns and the 64-th or later column is used.
**
-** Intenstive use of "union" helps keep the size of the object small. This
-** has been shown to boost performance due to less time spend initializing
-** fields to zero when a new instance of this object is allocated. The unions
-** also help SrcItem, and hence SrcList and Select, use less memory.
-**
-** Union member validity:
+** Aggressive use of "union" helps keep the size of the object small. This
+** has been shown to boost performance, in addition to saving memory.
+** Access to union elements is gated by the following rules which should
+** always be checked, either by an if-statement or by an assert().
**
+** Field Only access if this is true
+** --------------- -----------------------------------
** u1.zIndexedBy fg.isIndexedBy
** u1.pFuncArg fg.isTabFunc
** u1.nRow !fg.isTabFunc && !fg.isIndexedBy
**
-** u2.pIBIndex fg.isIndexedBy && !fg.isCte
-** u2.pCteUse fg.isCte && !fg.isIndexedBy
+** u2.pIBIndex fg.isIndexedBy
+** u2.pCteUse fg.isCte
**
-** u3.pOn fg.isUsing==0
-** u3.pUsing fg.isUsing==1
+** u3.pOn !fg.isUsing
+** u3.pUsing fg.isUsing
**
-** u4.zDatabase fg.fixedSchema==0 && !fg.isSubquery
-** u4.pSchema fg.fixedSchema==1
+** u4.zDatabase !fg.fixedSchema && !fg.isSubquery
+** u4.pSchema fg.fixedSchema
** u4.pSubq fg.isSubquery
+**
+** See also the sqlite3SrcListDelete() routine for assert() statements that
+** check invariants on the fields of this object, especially the flags
+** inside the fg struct.
*/
struct SrcItem {
char *zName; /* Name of the table */
@@ -3342,7 +3346,7 @@ struct SrcItem {
unsigned isNestedFrom :1; /* pSelect is a SF_NestedFrom subquery */
unsigned rowidUsed :1; /* The ROWID of this table is referenced */
unsigned fixedSchema :1; /* Uses u4.pSchema, not u4.zDatabase */
- unsigned hadSchema :1; /* Has u4.zDatabase before u4.pSchema */
+ unsigned hadSchema :1; /* Had u4.zDatabase before u4.pSchema */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Bitmask colUsed; /* Bit N set if column N used. Details above for N>62 */
diff --git a/src/trigger.c b/src/trigger.c
index 170f094ea..ff2df82cb 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -151,7 +151,9 @@ void sqlite3BeginTrigger(
** To maintain backwards compatibility, ignore the database
** name on pTableName if we are reparsing out of the schema table
*/
- if( db->init.busy && iDb!=1 && ALWAYS(pTableName->a[0].fg.fixedSchema==0) ){
+ if( db->init.busy && iDb!=1 ){
+ assert( pTableName->a[0].fg.fixedSchema==0 );
+ assert( pTableName->a[0].fg.isSubquery==0 );
sqlite3DbFree(db, pTableName->a[0].u4.zDatabase);
pTableName->a[0].u4.zDatabase = 0;
}
@@ -631,7 +633,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName, int noErr){
}
assert( pName->nSrc==1 );
- assert( pName->a[0].fg.fixedSchema==0 );
+ assert( pName->a[0].fg.fixedSchema==0 && pName->a[0].fg.isSubquery==0 );
zDb = pName->a[0].u4.zDatabase;
zName = pName->a[0].zName;
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );