diff options
author | drh <> | 2024-08-20 19:09:59 +0000 |
---|---|---|
committer | drh <> | 2024-08-20 19:09:59 +0000 |
commit | 692c160360c688c4bee3dd13d5293f2c416ad92f (patch) | |
tree | 8717f0cd601e571324612d4e170e4777274c54ee /src | |
parent | ff176231da8496e9fec72fe147eb60316f9c7f60 (diff) | |
download | sqlite-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.c | 11 | ||||
-rw-r--r-- | src/delete.c | 2 | ||||
-rw-r--r-- | src/fkey.c | 2 | ||||
-rw-r--r-- | src/insert.c | 1 | ||||
-rw-r--r-- | src/select.c | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 30 | ||||
-rw-r--r-- | src/trigger.c | 6 |
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) ); |