|
|
113387 |
Subject: [PATCH] Do not allow CREATE TABLE or CREATE VIEW of an object with a name
|
|
|
113387 |
that looks like a shadow table name.
|
|
|
113387 |
|
|
|
113387 |
diff --git a/src/build.c b/src/build.c
|
|
|
113387 |
index 3412670..f273394 100644
|
|
|
113387 |
--- a/src/build.c
|
|
|
113387 |
+++ b/src/build.c
|
|
|
113387 |
@@ -814,6 +814,22 @@ int sqlite3WritableSchema(sqlite3 *db){
|
|
|
113387 |
return (db->flags&(SQLITE_WriteSchema|SQLITE_Defensive))==SQLITE_WriteSchema;
|
|
|
113387 |
}
|
|
|
113387 |
|
|
|
113387 |
+/*
|
|
|
113387 |
+** Return TRUE if shadow tables should be read-only in the current
|
|
|
113387 |
+** context.
|
|
|
113387 |
+*/
|
|
|
113387 |
+int sqlite3ReadOnlyShadowTables(sqlite3 *db){
|
|
|
113387 |
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
113387 |
+ if( (db->flags & SQLITE_Defensive)!=0
|
|
|
113387 |
+ && db->pVtabCtx==0
|
|
|
113387 |
+ && db->nVdbeExec==0
|
|
|
113387 |
+ ){
|
|
|
113387 |
+ return 1;
|
|
|
113387 |
+ }
|
|
|
113387 |
+#endif
|
|
|
113387 |
+ return 0;
|
|
|
113387 |
+}
|
|
|
113387 |
+
|
|
|
113387 |
/*
|
|
|
113387 |
** This routine is used to check if the UTF-8 string zName is a legal
|
|
|
113387 |
** unqualified name for a new schema object (table, index, view or
|
|
|
113387 |
@@ -822,9 +838,10 @@ int sqlite3WritableSchema(sqlite3 *db){
|
|
|
113387 |
** is reserved for internal use.
|
|
|
113387 |
*/
|
|
|
113387 |
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
|
|
|
113387 |
- if( !pParse->db->init.busy && pParse->nested==0
|
|
|
113387 |
+ if(( !pParse->db->init.busy && pParse->nested==0
|
|
|
113387 |
&& sqlite3WritableSchema(pParse->db)==0
|
|
|
113387 |
- && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
|
|
|
113387 |
+ && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ) ||
|
|
|
113387 |
+ (sqlite3ReadOnlyShadowTables(pParse->db) && sqlite3ShadowTableName(pParse->db, zName))){
|
|
|
113387 |
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
|
|
|
113387 |
return SQLITE_ERROR;
|
|
|
113387 |
}
|
|
|
113387 |
@@ -1929,7 +1946,7 @@ int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
|
|
|
113387 |
** zName is temporarily modified while this routine is running, but is
|
|
|
113387 |
** restored to its original value prior to this routine returning.
|
|
|
113387 |
*/
|
|
|
113387 |
-static int isShadowTableName(sqlite3 *db, char *zName){
|
|
|
113387 |
+int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
|
|
|
113387 |
char *zTail; /* Pointer to the last "_" in zName */
|
|
|
113387 |
Table *pTab; /* Table that zName is a shadow of */
|
|
|
113387 |
|
|
|
113387 |
@@ -1942,8 +1959,6 @@ static int isShadowTableName(sqlite3 *db, char *zName){
|
|
|
113387 |
if( !IsVirtual(pTab) ) return 0;
|
|
|
113387 |
return sqlite3IsShadowTableOf(db, pTab, zName);
|
|
|
113387 |
}
|
|
|
113387 |
-#else
|
|
|
113387 |
-# define isShadowTableName(x,y) 0
|
|
|
113387 |
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
|
|
113387 |
|
|
|
113387 |
/*
|
|
|
113387 |
@@ -1985,7 +2000,7 @@ void sqlite3EndTable(
|
|
|
113387 |
p = pParse->pNewTable;
|
|
|
113387 |
if( p==0 ) return;
|
|
|
113387 |
|
|
|
113387 |
- if( pSelect==0 && isShadowTableName(db, p->zName) ){
|
|
|
113387 |
+ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
|
|
|
113387 |
p->tabFlags |= TF_Shadow;
|
|
|
113387 |
}
|
|
|
113387 |
|
|
|
113387 |
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
|
|
|
113387 |
index 60b2ebd..e5ba8a0 100644
|
|
|
113387 |
--- a/src/sqliteInt.h
|
|
|
113387 |
+++ b/src/sqliteInt.h
|
|
|
113387 |
@@ -4408,6 +4408,11 @@ void sqlite3AutoLoadExtensions(sqlite3*);
|
|
|
113387 |
);
|
|
|
113387 |
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
|
|
|
113387 |
#endif
|
|
|
113387 |
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
113387 |
+ int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
|
|
|
113387 |
+#else
|
|
|
113387 |
+# define sqlite3ShadowTableName(A,B) 0
|
|
|
113387 |
+#endif
|
|
|
113387 |
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
|
113387 |
int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
|
|
|
113387 |
#else
|
|
|
113387 |
diff --git a/test/altertab.test b/test/altertab.test
|
|
|
113387 |
index 891b081..0705abc 100644
|
|
|
113387 |
--- a/test/altertab.test
|
|
|
113387 |
+++ b/test/altertab.test
|
|
|
113387 |
@@ -547,13 +547,29 @@ ifcapable fts3 {
|
|
|
113387 |
} {1 {table y1_segments may not be modified}}
|
|
|
113387 |
|
|
|
113387 |
do_catchsql_test 16.20 {
|
|
|
113387 |
- ALTER TABLE y1_segments RENAME TO abc;
|
|
|
113387 |
- } {1 {table y1_segments may not be altered}}
|
|
|
113387 |
-
|
|
|
113387 |
- do_catchsql_test 16.21 {
|
|
|
113387 |
DROP TABLE y1_segments;
|
|
|
113387 |
} {1 {table y1_segments may not be dropped}}
|
|
|
113387 |
|
|
|
113387 |
+ do_catchsql_test 16.20 {
|
|
|
113387 |
+ ALTER TABLE y1_segments RENAME TO abc;
|
|
|
113387 |
+ } {1 {table y1_segments may not be altered}}
|
|
|
113387 |
+ sqlite3_db_config db DEFENSIVE 0
|
|
|
113387 |
+ do_catchsql_test 16.22 {
|
|
|
113387 |
+ ALTER TABLE y1_segments RENAME TO abc;
|
|
|
113387 |
+ } {0 {}}
|
|
|
113387 |
+ sqlite3_db_config db DEFENSIVE 1
|
|
|
113387 |
+ do_catchsql_test 16.23 {
|
|
|
113387 |
+ CREATE TABLE y1_segments AS SELECT * FROM abc;
|
|
|
113387 |
+ } {1 {object name reserved for internal use: y1_segments}}
|
|
|
113387 |
+ do_catchsql_test 16.24 {
|
|
|
113387 |
+ CREATE VIEW y1_segments AS SELECT * FROM abc;
|
|
|
113387 |
+ } {1 {object name reserved for internal use: y1_segments}}
|
|
|
113387 |
+ sqlite3_db_config db DEFENSIVE 0
|
|
|
113387 |
+ do_catchsql_test 16.25 {
|
|
|
113387 |
+ ALTER TABLE abc RENAME TO y1_segments;
|
|
|
113387 |
+ } {0 {}}
|
|
|
113387 |
+ sqlite3_db_config db DEFENSIVE 1
|
|
|
113387 |
+
|
|
|
113387 |
do_execsql_test 16.30 {
|
|
|
113387 |
ALTER TABLE y1 RENAME TO z1;
|
|
|
113387 |
}
|