40 lines
1.4 KiB
Diff
40 lines
1.4 KiB
Diff
# UNDF: UNDF-2026-000000299
|
|
diff --git a/src/trigger.c b/src/trigger.c
|
|
index 4f9068a..5da63ac 100644
|
|
--- a/src/trigger.c
|
|
+++ b/src/trigger.c
|
|
@@ -781,10 +781,33 @@ void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
|
|
static int checkColumnOverlap(IdList *pIdList, ExprList *pEList){
|
|
int e;
|
|
if( pIdList==0 || NEVER(pEList==0) ) return 1;
|
|
+ /* CWE-407 fix: for large column-overlap checks, build a hash set of the
|
|
+ ** trigger's watched-column names (pIdList) so each SET-column lookup is
|
|
+ ** O(1) instead of O(|pIdList|). SQLite's Hash uses a case-insensitive
|
|
+ ** key, matching sqlite3IdListIndex semantics. For small lists the linear
|
|
+ ** scan is kept; on OOM the hash count will be less than nId and we fall
|
|
+ ** back to the linear scan as well. */
|
|
+ if( pIdList->nId>4 && pEList->nExpr>4 ){
|
|
+ Hash h;
|
|
+ int i, found;
|
|
+ sqlite3HashInit(&h);
|
|
+ for(i=0; i<pIdList->nId; i++){
|
|
+ sqlite3HashInsert(&h, pIdList->a[i].zName, pIdList->a[i].zName);
|
|
+ }
|
|
+ if( h.count==pIdList->nId ){
|
|
+ found = 0;
|
|
+ for(e=0; e<pEList->nExpr && !found; e++){
|
|
+ if( sqlite3HashFind(&h, pEList->a[e].zEName) ) found = 1;
|
|
+ }
|
|
+ sqlite3HashClear(&h);
|
|
+ return found;
|
|
+ }
|
|
+ sqlite3HashClear(&h); /* OOM: fall through to linear scan */
|
|
+ }
|
|
for(e=0; e<pEList->nExpr; e++){
|
|
if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
|
|
}
|
|
- return 0;
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|