Report the correct authorization context in the authorization callback

when coding an INSTEAD OF trigger on an update or delete. (CVS 936)

FossilOrigin-Name: 67746833fc8de3afff80db413bd63a362bb28218
This commit is contained in:
drh 2003-04-25 17:52:11 +00:00
parent 2e6d11bc07
commit 85e2096fb6
8 changed files with 169 additions and 34 deletions

View File

@ -1,5 +1,5 @@
C Add\stests\sto\sinsure\sVACUUM\sworks\sin\sthe\spresence\sof\sI/O\serrors.\s\sFix\ssome\nproblems\sthat\scame\sto\slight\sby\sthese\stests.\s(CVS\s935)
D 2003-04-25T15:37:58
C Report\sthe\scorrect\sauthorization\scontext\sin\sthe\sauthorization\scallback\nwhen\scoding\san\sINSTEAD\sOF\strigger\son\san\supdate\sor\sdelete.\s(CVS\s936)
D 2003-04-25T17:52:11
F Makefile.in 004acec253ecdde985c8ecd5b7c9accdb210378f
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@ -20,13 +20,13 @@ F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183
F src/auth.c a4afd27964fb9f661147115790c8ae2ee230ebcc
F src/auth.c 3be3c7434592117f049703966b940e0b07088ae2
F src/btree.c 077d75aee4ed63f3628698611ba43c87097d458d
F src/btree.h 23c50e00709de16a5dce1fcea9c0429cc955ff0e
F src/btree_rb.c 8e00e40be264716e1929987878672e55d9e0e76d
F src/build.c d5a26baeffa5bc49b4b7009a7723c6ab7e1b02d9
F src/copy.c 44b13fd4d2444fb53bff8a5ecee1c5f6f86a8263
F src/delete.c 23d33fd8967c6cc492943bbecea93be6491edc6a
F src/delete.c 0f7c26aaebc417ad66a2a1099e59cc4056512c31
F src/encode.c faf03741efe921755ec371cf4a6984536de00042
F src/expr.c 46e2bb93abd6c70e67c8cdc5d92fdcd0b95498f3
F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605
@ -47,7 +47,7 @@ F src/select.c dfc13cb62ba658c4463179713c40ee25a062b2ba
F src/shell.c e0b3da1f44a2cc72daf41a4559b1c5f0545944a5
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in eec06462cba262c0ee03f38462a18a4bc66dda4e
F src/sqliteInt.h 5d15d1dea3f0c497a78c6a123eec5b4b92811c1c
F src/sqliteInt.h 0c7474068c37a5aad715810c8190266edcbd4f4c
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c 9e25f98f1765afa0716144ef57abda75c88f688d
F src/test1.c 4484806861a3099670188a09e12f858ec65aa56c
@ -55,8 +55,8 @@ F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e
F src/tokenize.c 067d1a477a94af7712ca74e09aaa6bd0f7299527
F src/trigger.c e763f4015c96e06b694184ead5754985c1dfdae0
F src/update.c b7fa7c427b74aee6db56ecfa09e5e151e6f9fa6a
F src/trigger.c 62d1e1b837a98f1fa7511c77977d51c8516ddb65
F src/update.c f40376ed2e092a7040c6fc6fa0add59fad5c5e76
F src/util.c 87635cfdfffa056a8d3147719357aa442374f78c
F src/vacuum.c 14ac3073203fa021e01ffe33db56968ad79a8344
F src/vdbe.c 48098080d2b5d35d4cc28ac2a4855c7730f6ee7b
@ -64,7 +64,7 @@ F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
F src/where.c f632cd30f013163484a4d60c249d36fe31f5be12
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test b311c83e370e6b22b79a8279317039440ce64862
F test/auth.test d25a76f21494b61483787caa7b28c713bc7c7c7f
F test/auth.test dee78be1f4f920bd6b15c4c947ce4d01bfe2826d
F test/bigfile.test 1cd8256d4619c39bea48147d344f348823e78678
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/btree.test 1e3463c7838e7e71bbf37c9c6e45beee9c8975ba
@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P c3b1f84dfce13b2523c9923e4270577862ca0595
R 40330553c4eb619fb11602a7f62ead1c
P 8d3e879349fc9523c72cb46111e0058b57ce9341
R fbd9cacc0c39e890456b02e579584ea3
U drh
Z 09a1f9c6aa9e8c12d787618e6052f340
Z d170dde2366e1aeda159869f0f0e19bb

View File

@ -1 +1 @@
8d3e879349fc9523c72cb46111e0058b57ce9341
67746833fc8de3afff80db413bd63a362bb28218

View File

@ -14,7 +14,7 @@
** systems that do not need this facility may omit it by recompiling
** the library with -DSQLITE_OMIT_AUTHORIZATION=1
**
** $Id: auth.c,v 1.7 2003/04/24 01:45:04 drh Exp $
** $Id: auth.c,v 1.8 2003/04/25 17:52:11 drh Exp $
*/
#include "sqliteInt.h"
@ -173,4 +173,32 @@ int sqliteAuthCheck(
return rc;
}
/*
** Push an authorization context. After this routine is called, the
** zArg3 argument to authorization callbacks will be zContext until
** popped. Or if pParse==0, this routine is a no-op.
*/
void sqliteAuthContextPush(
Parse *pParse,
AuthContext *pContext,
const char *zContext
){
pContext->pParse = pParse;
if( pParse ){
pContext->zAuthContext = pParse->zAuthContext;
pParse->zAuthContext = zContext;
}
}
/*
** Pop an authorization context that was previously pushed
** by sqliteAuthContextPush
*/
void sqliteAuthContextPop(AuthContext *pContext){
if( pContext->pParse ){
pContext->pParse->zAuthContext = pContext->zAuthContext;
pContext->pParse = 0;
}
}
#endif /* SQLITE_OMIT_AUTHORIZATION */

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.54 2003/04/24 01:45:04 drh Exp $
** $Id: delete.c,v 1.55 2003/04/25 17:52:11 drh Exp $
*/
#include "sqliteInt.h"
@ -68,12 +68,14 @@ void sqliteDeleteFrom(
int base; /* Index of the first available table cursor */
sqlite *db; /* Main database structure */
int isView; /* True if attempting to delete from a view */
AuthContext sContext; /* Authorization context */
int row_triggers_exist = 0; /* True if any triggers exist */
int before_triggers; /* True if there are BEFORE triggers */
int after_triggers; /* True if there are AFTER triggers */
int oldIdx = -1; /* Cursor for the OLD table of AFTER triggers */
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ){
pTabList = 0;
goto delete_from_cleanup;
@ -127,6 +129,12 @@ void sqliteDeleteFrom(
}
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
@ -303,6 +311,7 @@ void sqliteDeleteFrom(
}
delete_from_cleanup:
sqliteAuthContextPop(&sContext);
sqliteSrcListDelete(pTabList);
sqliteExprDelete(pWhere);
return;

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.180 2003/04/24 01:45:04 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.181 2003/04/25 17:52:11 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
@ -219,6 +219,7 @@ typedef struct TriggerStep TriggerStep;
typedef struct TriggerStack TriggerStack;
typedef struct FKey FKey;
typedef struct Db Db;
typedef struct AuthContext AuthContext;
/*
** Each database file to be accessed by the system is an instance
@ -834,6 +835,15 @@ struct Parse {
TriggerStack *trigStack; /* Trigger actions being coded */
};
/*
** An instance of the following structure can be declared on a stack and used
** to save the Parse.zAuthContext value so that it can be restored later.
*/
struct AuthContext {
const char *zAuthContext; /* Put saved Parse.zAuthContext here */
Parse *pParse; /* The Parse structure */
};
/*
* Each trigger present in the database schema is stored as an instance of
* struct Trigger.
@ -1111,9 +1121,13 @@ void sqliteDeferForeignKey(Parse*, int);
#ifndef SQLITE_OMIT_AUTHORIZATION
void sqliteAuthRead(Parse*,Expr*,SrcList*,int);
int sqliteAuthCheck(Parse*,int, const char*, const char*, const char*);
void sqliteAuthContextPush(Parse*, AuthContext*, const char*);
void sqliteAuthContextPop(AuthContext*);
#else
# define sqliteAuthRead(a,b,c,d)
# define sqliteAuthCheck(a,b,c,d) SQLITE_OK
# define sqliteAuthContextPush(a,b,c)
# define sqliteAuthContextPop(a)
#endif
void sqliteAttach(Parse*, Token*, Token*);
void sqliteDetach(Parse*, Token*);

View File

@ -661,7 +661,7 @@ int sqliteCodeRowTrigger(
int endTrigger;
SrcList dummyTablist;
Expr * whenExpr;
const char *zSavedAuthContext;
AuthContext sContext;
dummyTablist.nSrc = 0;
@ -673,8 +673,7 @@ int sqliteCodeRowTrigger(
pTriggerStack->pNext = pParse->trigStack;
pTriggerStack->ignoreJump = ignoreJump;
pParse->trigStack = pTriggerStack;
zSavedAuthContext = pParse->zAuthContext;
pParse->zAuthContext = pTrigger->name;
sqliteAuthContextPush(pParse, &sContext, pTrigger->name);
/* code the WHEN clause */
endTrigger = sqliteVdbeMakeLabel(pParse->pVdbe);
@ -692,7 +691,7 @@ int sqliteCodeRowTrigger(
/* Pop the entry off the trigger stack */
pParse->trigStack = pParse->trigStack->pNext;
pParse->zAuthContext = zSavedAuthContext;
sqliteAuthContextPop(&sContext);
sqliteFree(pTriggerStack);
sqliteVdbeResolveLabel(pParse->pVdbe, endTrigger);

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.63 2003/04/24 01:45:05 drh Exp $
** $Id: update.c,v 1.64 2003/04/25 17:52:11 drh Exp $
*/
#include "sqliteInt.h"
@ -49,6 +49,7 @@ void sqliteUpdate(
Expr *pRecnoExpr; /* Expression defining the new record number */
int openAll; /* True if all indices need to be opened */
int isView; /* Trying to update a view */
AuthContext sContext; /* The authorization context */
int before_triggers; /* True if there are any BEFORE triggers */
int after_triggers; /* True if there are any AFTER triggers */
@ -57,6 +58,7 @@ void sqliteUpdate(
int newIdx = -1; /* index of trigger "new" temp table */
int oldIdx = -1; /* index of trigger "old" temp table */
sContext.pParse = 0;
if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup;
db = pParse->db;
assert( pTabList->nSrc==1 );
@ -74,8 +76,10 @@ void sqliteUpdate(
if( sqliteIsReadOnly(pParse, pTab, before_triggers) ){
goto update_cleanup;
}
if( isView && sqliteViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
if( isView ){
if( sqliteViewGetColumnNames(pParse, pTab) ){
goto update_cleanup;
}
}
aXRef = sqliteMalloc( sizeof(int) * pTab->nCol );
if( aXRef==0 ) goto update_cleanup;
@ -99,20 +103,12 @@ void sqliteUpdate(
pParse->nTab++;
}
/* Resolve the column names in all the expressions in both the
** WHERE clause and in the new values. Also find the column index
/* Resolve the column names in all the expressions of the
** of the UPDATE statement. Also find the column index
** for each column to be updated in the pChanges array. For each
** column to be updated, make sure we have authorization to change
** that column.
*/
if( pWhere ){
if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto update_cleanup;
}
}
chngRecno = 0;
for(i=0; i<pChanges->nExpr; i++){
if( sqliteExprResolveIds(pParse, base, pTabList, 0, pChanges->a[i].pExpr) ){
@ -185,6 +181,24 @@ void sqliteUpdate(
}
}
/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
if( pWhere ){
if( sqliteExprResolveIds(pParse, base, pTabList, 0, pWhere) ){
goto update_cleanup;
}
if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
goto update_cleanup;
}
}
/* Start the view context
*/
if( isView ){
sqliteAuthContextPush(pParse, &sContext, pTab->zName);
}
/* Begin generating code.
*/
v = sqliteGetVdbe(pParse);
@ -195,7 +209,8 @@ void sqliteUpdate(
** a temporary table.
*/
if( isView ){
Select *pView = sqliteSelectDup(pTab->pSelect);
Select *pView;
pView = sqliteSelectDup(pTab->pSelect);
sqliteSelect(pParse, pView, SRT_TempTable, base, 0, 0, 0);
sqliteSelectDelete(pView);
}
@ -422,6 +437,7 @@ void sqliteUpdate(
}
update_cleanup:
sqliteAuthContextPop(&sContext);
sqliteFree(apIdx);
sqliteFree(aXRef);
sqliteSrcListDelete(pTabList);

View File

@ -12,7 +12,7 @@
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: auth.test,v 1.8 2003/04/22 20:30:40 drh Exp $
# $Id: auth.test,v 1.9 2003/04/25 17:52:11 drh Exp $
#
set testdir [file dirname $argv0]
@ -1714,5 +1714,74 @@ do_test auth-3.2 {
}
} {12 112 2 2 {} {} 8 108 8 8 {} {}}
# Make sure the names of views and triggers are passed on on arg4.
#
do_test auth-4.1 {
proc auth {code arg1 arg2 arg3 arg4} {
lappend ::authargs $code $arg1 $arg2 $arg3 $arg4
return SQLITE_OK
}
set authargs {}
execsql {
UPDATE t2 SET a=a+1;
}
set authargs
} [list \
SQLITE_READ t2 a main {} \
SQLITE_UPDATE t2 a main {} \
SQLITE_INSERT tx {} main r1 \
SQLITE_READ t2 a main r1 \
SQLITE_READ t2 a main r1 \
SQLITE_READ t2 b main r1 \
SQLITE_READ t2 b main r1 \
SQLITE_READ t2 c main r1 \
SQLITE_READ t2 c main r1]
do_test auth-4.2 {
execsql {
CREATE VIEW v1 AS SELECT a+b AS x FROM t2;
CREATE TABLE v1chng(x1,x2);
CREATE TRIGGER r2 INSTEAD OF UPDATE ON v1 BEGIN
INSERT INTO v1chng VALUES(OLD.x,NEW.x);
END;
SELECT * FROM v1;
}
} {115 117}
do_test auth-4.3 {
set authargs {}
execsql {
UPDATE v1 SET x=1 WHERE x=117
}
set authargs
} [list \
SQLITE_UPDATE v1 x main {} \
SQLITE_READ v1 x main {} \
SQLITE_SELECT {} {} {} v1 \
SQLITE_READ t2 a main v1 \
SQLITE_READ t2 b main v1 \
SQLITE_INSERT v1chng {} main r2 \
SQLITE_READ v1 x main r2 \
SQLITE_READ v1 x main r2]
do_test auth-4.4 {
execsql {
CREATE TRIGGER r3 INSTEAD OF DELETE ON v1 BEGIN
INSERT INTO v1chng VALUES(OLD.x,NULL);
END;
SELECT * FROM v1;
}
} {115 117}
do_test auth-4.5 {
set authargs {}
execsql {
DELETE FROM v1 WHERE x=117
}
set authargs
} [list \
SQLITE_DELETE v1 {} main {} \
SQLITE_READ v1 x main {} \
SQLITE_SELECT {} {} {} v1 \
SQLITE_READ t2 a main v1 \
SQLITE_READ t2 b main v1 \
SQLITE_INSERT v1chng {} main r3 \
SQLITE_READ v1 x main r3]
finish_test