aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2003-01-12 18:02:16 +0000
committerdrh <drh@noemail.net>2003-01-12 18:02:16 +0000
commited6c8671b342e9b3793e2603e7f098ba4fc092a4 (patch)
tree1243d500342286b978543d20e5c88264cedfa2e5 /src
parent49f0936ec79dcbdbd80134151658615726643fa1 (diff)
downloadsqlite-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.c29
-rw-r--r--src/delete.c6
-rw-r--r--src/expr.c7
-rw-r--r--src/insert.c3
-rw-r--r--src/main.c3
-rw-r--r--src/pager.c3
-rw-r--r--src/select.c3
-rw-r--r--src/sqlite.h.in34
-rw-r--r--src/sqliteInt.h25
-rw-r--r--src/test1.c103
-rw-r--r--src/trigger.c15
-rw-r--r--src/update.c12
-rw-r--r--src/util.c20
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){