diff options
author | drh <drh@noemail.net> | 2003-01-12 18:02:16 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2003-01-12 18:02:16 +0000 |
commit | ed6c8671b342e9b3793e2603e7f098ba4fc092a4 (patch) | |
tree | 1243d500342286b978543d20e5c88264cedfa2e5 /src | |
parent | 49f0936ec79dcbdbd80134151658615726643fa1 (diff) | |
download | sqlite-ed6c8671b342e9b3793e2603e7f098ba4fc092a4.tar.gz sqlite-ed6c8671b342e9b3793e2603e7f098ba4fc092a4.zip |
Initial check-in of the code for the new sqlite_set_authorizer() API function.
The code is mostly untested at this point. (CVS 827)
FossilOrigin-Name: 52d5007f64d0af5286b2a0e1f0b9e53c86bece3f
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 29 | ||||
-rw-r--r-- | src/delete.c | 6 | ||||
-rw-r--r-- | src/expr.c | 7 | ||||
-rw-r--r-- | src/insert.c | 3 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/pager.c | 3 | ||||
-rw-r--r-- | src/select.c | 3 | ||||
-rw-r--r-- | src/sqlite.h.in | 34 | ||||
-rw-r--r-- | src/sqliteInt.h | 25 | ||||
-rw-r--r-- | src/test1.c | 103 | ||||
-rw-r--r-- | src/trigger.c | 15 | ||||
-rw-r--r-- | src/update.c | 12 | ||||
-rw-r--r-- | src/util.c | 20 |
13 files changed, 246 insertions, 17 deletions
diff --git a/src/build.c b/src/build.c index 30457c7ba..b13755215 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.119 2003/01/11 13:30:57 drh Exp $ +** $Id: build.c,v 1.120 2003/01/12 18:02:17 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -325,6 +325,9 @@ void sqliteStartTable(Parse *pParse, Token *pStart, Token *pName, int isTemp){ pParse->sFirstToken = *pStart; zName = sqliteTableNameFromToken(pName); if( zName==0 ) return; + if( sqliteAuthInsert(pParse, SCHEMA_TABLE(isTemp), 1) ){ + return; + } /* Before trying to create a temporary table, make sure the Btree for ** holding temporary tables is open. @@ -894,7 +897,7 @@ void sqliteCreateView( sqliteStartTable(pParse, pBegin, pName, isTemp); p = pParse->pNewTable; - if( p==0 ){ + if( p==0 || pParse->nErr ){ sqliteSelectDelete(pSelect); return; } @@ -1069,6 +1072,9 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ if( pParse->nErr || sqlite_malloc_failed ) return; pTable = sqliteTableFromToken(pParse, pName); if( pTable==0 ) return; + if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pTable->isTemp), 1) ){ + return; + } if( pTable->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTable->zName, " may not be dropped", 0); @@ -1087,6 +1093,9 @@ void sqliteDropTable(Parse *pParse, Token *pName, int isView){ pParse->nErr++; return; } + if( sqliteAuthDelete(pParse, pTable->zName, 1) ){ + return; + } /* Generate code to remove the table from the master table ** on disk. @@ -1365,6 +1374,9 @@ void sqliteCreateIndex( pParse->nErr++; goto exit_create_index; } + if( sqliteAuthInsert(pParse, SCHEMA_TABLE(pTab->isTemp), 1) ){ + goto exit_create_index; + } /* If this index is created while re-reading the schema from sqlite_master ** but the table associated with this index is a temporary table, it can @@ -1626,6 +1638,9 @@ void sqliteDropIndex(Parse *pParse, Token *pName){ pParse->nErr++; return; } + if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pIndex->pTable->isTemp), 1) ){ + return; + } /* Generate code to remove the index and from the master table */ v = sqliteGetVdbe(pParse); @@ -1822,6 +1837,12 @@ void sqliteCopy( pTab = sqliteTableNameToTable(pParse, zTab); sqliteFree(zTab); if( pTab==0 ) goto copy_cleanup; + if( sqliteAuthInsert(pParse, zTab, 0) ){ + goto copy_cleanup; + } + if( sqliteAuthCommand(pParse, "COPY", zTab) ){ + goto copy_cleanup; + } v = sqliteGetVdbe(pParse); if( v ){ int openOp; @@ -1904,6 +1925,7 @@ void sqliteBeginTransaction(Parse *pParse, int onError){ if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; + if( sqliteAuthCommand(pParse, "BEGIN", "") ) return; if( db->flags & SQLITE_InTrans ){ pParse->nErr++; sqliteSetString(&pParse->zErrMsg, "cannot start a transaction " @@ -1923,6 +1945,7 @@ void sqliteCommitTransaction(Parse *pParse){ if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; + if( sqliteAuthCommand(pParse, "COMMIT", "") ) return; if( (db->flags & SQLITE_InTrans)==0 ){ pParse->nErr++; sqliteSetString(&pParse->zErrMsg, @@ -1943,6 +1966,7 @@ void sqliteRollbackTransaction(Parse *pParse){ if( pParse==0 || (db=pParse->db)==0 || db->pBe==0 ) return; if( pParse->nErr || sqlite_malloc_failed ) return; + if( sqliteAuthCommand(pParse, "ROLLBACK", "") ) return; if( (db->flags & SQLITE_InTrans)==0 ){ pParse->nErr++; sqliteSetString(&pParse->zErrMsg, @@ -2051,6 +2075,7 @@ void sqlitePragma(Parse *pParse, Token *pLeft, Token *pRight, int minusFlag){ zRight = sqliteStrNDup(pRight->z, pRight->n); sqliteDequote(zRight); } + if( sqliteAuthCommand(pParse, "PRAGMA", zLeft) ) return; /* ** PRAGMA default_cache_size diff --git a/src/delete.c b/src/delete.c index bfcf2e4e2..5c5582433 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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.43 2003/01/11 13:30:57 drh Exp $ +** $Id: delete.c,v 1.44 2003/01/12 18:02:18 drh Exp $ */ #include "sqliteInt.h" @@ -88,7 +88,8 @@ void sqliteDeleteFrom( int row_triggers_exist = 0; int oldIdx = -1; - if( pParse->nErr || sqlite_malloc_failed ){ + if( pParse->nErr || sqlite_malloc_failed + || sqliteAuthCommand(pParse,"DELETE",0) ){ pTabList = 0; goto delete_from_cleanup; } @@ -125,6 +126,7 @@ void sqliteDeleteFrom( assert( pTabList->nSrc==1 ); pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a view */ + if( sqliteAuthDelete(pParse, pTab->zName, 0) ) goto delete_from_cleanup; /* Allocate a cursor used to store the old.* data for a trigger. */ diff --git a/src/expr.c b/src/expr.c index 21c2c0308..5fcfd8833 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.83 2002/10/31 00:09:40 drh Exp $ +** $Id: expr.c,v 1.84 2003/01/12 18:02:18 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -430,6 +430,7 @@ int sqliteExprResolveIds( case TK_ID: { int cnt = 0; /* Number of matches */ int i; /* Loop counter */ + int rc; /* Return code */ char *z; assert( pExpr->token.z ); z = sqliteStrNDup(pExpr->token.z, pExpr->token.n); @@ -488,6 +489,9 @@ int sqliteExprResolveIds( pParse->nErr++; return 1; } + if( pExpr->op==TK_COLUMN ){ + sqliteAuthRead(pParse, pExpr, pTabList, base); + } break; } @@ -595,6 +599,7 @@ int sqliteExprResolveIds( sqliteExprDelete(pRight); pExpr->pRight = 0; pExpr->op = TK_COLUMN; + sqliteAuthRead(pParse, pExpr, pTabList, base); break; } diff --git a/src/insert.c b/src/insert.c index d03fff701..5dc8882d3 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.68 2003/01/11 13:30:58 drh Exp $ +** $Id: insert.c,v 1.69 2003/01/12 18:02:18 drh Exp $ */ #include "sqliteInt.h" @@ -114,6 +114,7 @@ void sqliteInsert( int newIdx = -1; if( pParse->nErr || sqlite_malloc_failed ) goto insert_cleanup; + if( sqliteAuthCommand(pParse, "INSERT", 0) ) goto insert_cleanup; db = pParse->db; /* Locate the table into which we will be inserting new information. diff --git a/src/main.c b/src/main.c index b8be0dc5b..2c602103a 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.105 2002/12/02 04:25:21 drh Exp $ +** $Id: main.c,v 1.106 2003/01/12 18:02:18 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -689,6 +689,7 @@ const char *sqlite_error_string(int rc){ case SQLITE_MISMATCH: z = "datatype mismatch"; break; case SQLITE_MISUSE: z = "library routine called out of sequence";break; case SQLITE_NOLFS: z = "kernel lacks large file support"; break; + case SQLITE_AUTH: z = "authorization denied"; break; default: z = "unknown error"; break; } return z; diff --git a/src/pager.c b/src/pager.c index fb28913f1..8b618ab3b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.66 2003/01/11 13:30:58 drh Exp $ +** @(#) $Id: pager.c,v 1.67 2003/01/12 18:02:18 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -1050,6 +1050,7 @@ int sqlitepager_get(Pager *pPager, Pgno pgno, void **ppPage){ } pPg->pgno = pgno; if( pPager->aInJournal && (int)pgno<=pPager->origDbSize ){ + sqliteCheckMemory(pPager->aInJournal, pgno/8); pPg->inJournal = (pPager->aInJournal[pgno/8] & (1<<(pgno&7)))!=0; }else{ pPg->inJournal = 0; diff --git a/src/select.c b/src/select.c index 129a4edd5..fe90eccc5 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.119 2003/01/11 14:19:52 drh Exp $ +** $Id: select.c,v 1.120 2003/01/12 18:02:18 drh Exp $ */ #include "sqliteInt.h" @@ -1781,6 +1781,7 @@ int sqliteSelect( int rc = 1; /* Value to return from this function */ if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1; + if( sqliteAuthCommand(pParse, "SELECT", 0) ) return 1; /* If there is are a sequence of queries, do the earlier ones first. */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 8f9a6c83e..985f255a5 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.35 2002/11/09 00:33:17 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.36 2003/01/12 18:02:18 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -163,6 +163,7 @@ int sqlite_exec( #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ +#define SQLITE_AUTH 23 /* Authorization denied */ /* ** Each entry in an SQLite table has a unique integer key. (The key is @@ -499,6 +500,37 @@ void *sqlite_aggregate_context(sqlite_func*, int nBytes); int sqlite_aggregate_count(sqlite_func*); /* +** This routine registers a callback with the SQLite library. The +** callback is invoked for every attempt to access a column of a table +** in the database. The callback returns SQLITE_OK if access is allowed, +** SQLITE_DENY if the entire SQL statement should be aborted with an error +** and SQLITE_IGNORE if the column should be treated as a NULL value. +*/ +int sqlite_set_authorizer( + sqlite*, + int (*xAuth)(void*,int,const char*,const char*), + void* +); + +/* +** The second parameter to the access authorization function above will +** be one of these values: +*/ +#define SQLITE_READ_COLUMN 1 /* Is it OK to read the specified column? */ +#define SQLITE_WRITE_COLUMN 2 /* Is it OK to update the specified column? */ +#define SQLITE_DELETE_ROW 3 /* Is it OK to delete a row from the table? */ +#define SQLITE_INSERT_ROW 4 /* Is it OK to insert a new row in the table? */ +#define SQLITE_COMMAND 5 /* Is it OK to execute a particular command? */ + +/* +** The return value of the authorization function should be one of the +** following constants: +*/ +/* #define SQLITE_OK 0 // Allow access (This is actually defined above) */ +#define SQLITE_DENY 1 /* Abort the SQL statement with an error */ +#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */ + +/* ** Attempt to open the file named in the argument as the auxiliary database ** file. The auxiliary database file is used to store TEMP tables. But ** by using this API, it is possible to trick SQLite into opening two diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5a4c7dc41..b757a8320 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.152 2003/01/11 13:30:58 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.153 2003/01/12 18:02:18 drh Exp $ */ #include "config.h" #include "sqlite.h" @@ -155,6 +155,11 @@ extern int sqlite_iMallocFail; /* Fail sqliteMalloc() after this many calls */ #define TEMP_MASTER_NAME "sqlite_temp_master" /* +** The name of the schema table. +*/ +#define SCHEMA_TABLE(x) (x?TEMP_MASTER_NAME:MASTER_NAME) + +/* ** A convenience macro that returns the number of elements in ** an array. */ @@ -220,6 +225,10 @@ struct sqlite { int magic; /* Magic number for detect library misuse */ int nChange; /* Number of rows changed */ int recursionDepth; /* Number of nested calls to sqlite_exec() */ +#ifndef SQLITE_OMIT_AUTHORIZATION + int (*xAuth)(void*,int,const char*,const char*); /* Access Auth function */ + void *pAuthArg; /* 1st argument to the access auth function */ +#endif }; /* @@ -899,6 +908,7 @@ void sqliteRealToSortable(double r, char *); void *sqliteRealloc_(void*,int,char*,int); char *sqliteStrDup_(const char*,char*,int); char *sqliteStrNDup_(const char*, int,char*,int); + void sqliteCheckMemory(void*,int); #else void *sqliteMalloc(int); void *sqliteMallocRaw(int); @@ -906,6 +916,7 @@ void sqliteRealToSortable(double r, char *); void *sqliteRealloc(void*,int); char *sqliteStrDup(const char*); char *sqliteStrNDup(const char*, int); +# define sqliteCheckMemory(a,b) #endif void sqliteSetString(char **, const char *, ...); void sqliteSetNString(char **, ...); @@ -1022,3 +1033,15 @@ void sqliteDeleteTrigger(Trigger*); int sqliteJoinType(Parse*, Token*, Token*, Token*); void sqliteCreateForeignKey(Parse*, IdList*, Token*, IdList*, int); void sqliteDeferForeignKey(Parse*, int); +#ifndef SQLITE_OMIT_AUTHORIZATION + void sqliteAuthRead(Parse*,Expr*,SrcList*,int); + int sqliteAuthDelete(Parse*,const char*, int); + int sqliteAuthInsert(Parse*,const char*, int); + int sqliteAuthCommand(Parse*,const char*,const char*); +#else +# define sqliteAuthRead(a,b,c,d) +# define sqliteAuthDelete(a,b,c) SQLITE_OK +# define sqliteAuthInsert(a,b,c) SQLITE_OK +# define sqliteAuthWrite(a,b,c) SQLITE_OK +# define sqliteAuthCommand(a,b,c) SQLITE_OK +#endif diff --git a/src/test1.c b/src/test1.c index 90498b123..92f186ef6 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.14 2003/01/11 14:19:52 drh Exp $ +** $Id: test1.c,v 1.15 2003/01/12 18:02:19 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -559,6 +559,104 @@ static int sqlite_datatypes( return TCL_OK; } +#ifndef SQLITE_OMIT_AUTHORIZATION +/* +** Information used by the authentication function. +*/ +typedef struct AuthInfo AuthInfo; +struct AuthInfo { + Tcl_Interp *interp; /* Interpreter to use */ + int nCmd; /* Number of characters in zCmd[] */ + char zCmd[500]; /* Command to invoke */ +}; + +/* +** We create a single static authenticator. This won't work in a +** multi-threaded environment, but the test fixture is not multithreaded. +** And be making it static, we don't have to worry about deallocating +** after a test in order to void memory leaks. +*/ +static AuthInfo authInfo; + +/* +** This is the authentication function. It appends the authentication +** type code and the two arguments to zCmd[] then invokes the result +** on the interpreter. The reply is examined to determine if the +** authentication fails or succeeds. +*/ +static int auth_callback( + void *NotUsed, + int code, + const char *zArg1, + const char *zArg2 +){ + char *zCode; + Tcl_DString str; + int rc; + const char *zReply; + switch( code ){ + case SQLITE_READ_COLUMN: zCode="SQLITE_READ_COLUMN"; break; + case SQLITE_WRITE_COLUMN: zCode="SQLITE_WRITE_COLUMN"; break; + case SQLITE_INSERT_ROW: zCode="SQLITE_INSERT_ROW"; break; + case SQLITE_DELETE_ROW: zCode="SQLITE_DELETE_ROW"; break; + case SQLITE_COMMAND: zCode="SQLITE_COMMAND"; break; + default: zCode="unknown code"; break; + } + Tcl_DStringInit(&str); + Tcl_DStringAppend(&str, authInfo.zCmd, -1); + Tcl_DStringAppendElement(&str, zCode); + Tcl_DStringAppendElement(&str, zArg1); + Tcl_DStringAppendElement(&str, zArg2 ? zArg2 : ""); + rc = Tcl_GlobalEval(authInfo.interp, Tcl_DStringValue(&str)); + Tcl_DStringFree(&str); + zReply = Tcl_GetStringResult(authInfo.interp); + if( strcmp(zReply,"SQLITE_OK")==0 ){ + rc = SQLITE_OK; + }else if( strcmp(zReply,"SQLITE_DENY")==0 ){ + rc = SQLITE_DENY; + }else if( strcmp(zReply,"SQLITE_IGNORE")==0 ){ + rc = SQLITE_IGNORE; + }else{ + rc = 999; + } + return rc; +} + +/* +** This routine creates a new authenticator. It fills in the zCmd[] +** field of the authentication function state variable and then registers +** the authentication function with the SQLite library. +*/ +static int test_set_authorizer( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + char **argv /* Text of each argument */ +){ + sqlite *db; + char *zCmd; + if( argc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " DB CALLBACK\"", 0); + return TCL_ERROR; + } + db = (sqlite*)strtol(argv[1], 0, 0); + zCmd = argv[2]; + if( zCmd[0]==0 ){ + sqlite_set_authorizer(db, 0, 0); + return TCL_OK; + } + if( strlen(zCmd)>sizeof(authInfo.zCmd) ){ + Tcl_AppendResult(interp, "command too big", 0); + return TCL_ERROR; + } + authInfo.interp = interp; + authInfo.nCmd = strlen(zCmd); + strcpy(authInfo.zCmd, zCmd); + sqlite_set_authorizer(db, auth_callback, 0); + return TCL_OK; +} +#endif /* SQLITE_OMIT_AUTHORIZATION */ /* ** Register commands with the TCL interpreter. @@ -582,6 +680,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_datatypes", (Tcl_CmdProc*)sqlite_datatypes }, +#ifndef SQLITE_OMIT_AUTHORIZATION + { "sqlite_set_authorizer", (Tcl_CmdProc*)test_set_authorizer }, +#endif #ifdef MEMORY_DEBUG { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail }, { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat }, diff --git a/src/trigger.c b/src/trigger.c index 222d09de0..079a4c2f8 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -50,6 +50,8 @@ void sqliteCreateTrigger( Trigger *nt; Table *tab; + if( sqliteAuthCommand(pParse, "CREATE", "TRIGGER") ) goto trigger_cleanup; + /* Check that: ** 1. the trigger name does not already exist. ** 2. the table (or view) does exist. @@ -102,6 +104,9 @@ void sqliteCreateTrigger( " trigger on table: ", -1, pTableName->z, pTableName->n, 0); goto trigger_cleanup; } + if( sqliteAuthInsert(pParse, SCHEMA_TABLE(tab->isTemp), 1) ){ + goto trigger_cleanup; + } } if (tr_tm == TK_INSTEAD){ @@ -337,6 +342,7 @@ void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){ Table *pTable; Vdbe *v; + if( sqliteAuthCommand(pParse, "DROP", "TRIGGER") ) return; zName = sqliteStrNDup(pName->z, pName->n); /* ensure that the trigger being dropped exists */ @@ -347,13 +353,18 @@ void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){ sqliteFree(zName); return; } + pTable = sqliteFindTable(pParse->db, pTrigger->table); + assert(pTable); + if( sqliteAuthDelete(pParse, SCHEMA_TABLE(pTable->isTemp), 1) ){ + sqliteFree(zName); + return; + } + /* * If this is not an "explain", then delete the trigger structure. */ if( !pParse->explain ){ - pTable = sqliteFindTable(pParse->db, pTrigger->table); - assert(pTable); if( pTable->pTrigger == pTrigger ){ pTable->pTrigger = pTrigger->pNext; }else{ diff --git a/src/update.c b/src/update.c index 29a4197f9..7ddecaca1 100644 --- a/src/update.c +++ b/src/update.c @@ -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.51 2003/01/11 13:30:58 drh Exp $ +** $Id: update.c,v 1.52 2003/01/12 18:02:19 drh Exp $ */ #include "sqliteInt.h" @@ -53,6 +53,7 @@ void sqliteUpdate( int oldIdx = -1; /* index of trigger "old" temp table */ if( pParse->nErr || sqlite_malloc_failed ) goto update_cleanup; + if( sqliteAuthCommand(pParse, "UPDATE", 0) ) goto update_cleanup; db = pParse->db; /* Check for the special case of a VIEW with one or more ON UPDATE triggers @@ -110,7 +111,9 @@ void sqliteUpdate( /* Resolve the column names in all the expressions in both the ** WHERE clause and in the new values. Also find the column index - ** for each column to be updated in the pChanges array. + ** 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) ){ @@ -144,6 +147,11 @@ void sqliteUpdate( pParse->nErr++; goto update_cleanup; } +#ifndef SQLITE_OMIT_AUTHORIZATION + if( sqliteAuthWrite(pParse, pTab, j)==SQLITE_IGNORE ){ + aXRef[j] = -1; + } +#endif } /* Allocate memory for the array apIdx[] and fill it with pointers to every diff --git a/src/util.c b/src/util.c index 3d47bbaf6..7e4e72f58 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.54 2003/01/02 14:43:57 drh Exp $ +** $Id: util.c,v 1.55 2003/01/12 18:02:19 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> @@ -85,6 +85,24 @@ void *sqliteMalloc_(int n, int bZero, char *zFile, int line){ } /* +** Check to see if the given pointer was obtained from sqliteMalloc() +** and is able to hold at least N bytes. Raise an exception if this +** is not the case. +** +** This routine is used for testing purposes only. +*/ +void sqliteCheckMemory(void *p, int N){ + int *pi = p; + int n, k; + pi -= 2; + assert( pi[0]==0xdead1122 ); + n = pi[1]; + assert( N>=0 && N<n ); + k = (n+sizeof(int)-1)/sizeof(int); + assert( pi[k+2]==0xdead3344 ); +} + +/* ** Free memory previously obtained from sqliteMalloc() */ void sqliteFree_(void *p, char *zFile, int line){ |