aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2018-11-03 16:09:59 +0000
committerdrh <drh@noemail.net>2018-11-03 16:09:59 +0000
commita296cda016dfcf81674b04c041637fa0a4f426ac (patch)
treecfd8eb3a5a7162130268f7bbabce562b4026e732 /src
parentc6e519f335af83d8a816b4a0501ebd30f6057548 (diff)
downloadsqlite-a296cda016dfcf81674b04c041637fa0a4f426ac.tar.gz
sqlite-a296cda016dfcf81674b04c041637fa0a4f426ac.zip
Add the SQLITE_DBCONFIG_DEFENSIVE flag.
FossilOrigin-Name: af3f29d49359af2291b1d9e06e0db76fd000fbd24b4ac84d2668a0d1322efd83
Diffstat (limited to 'src')
-rw-r--r--src/btree.c4
-rw-r--r--src/build.c2
-rw-r--r--src/dbpage.c4
-rw-r--r--src/delete.c2
-rw-r--r--src/main.c1
-rw-r--r--src/shell.c.in1
-rw-r--r--src/sqlite.h.in26
-rw-r--r--src/sqliteInt.h1
8 files changed, 37 insertions, 4 deletions
diff --git a/src/btree.c b/src/btree.c
index b4f3d73f6..9b2e43a9f 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -3112,7 +3112,9 @@ static int lockBtree(BtShared *pBt){
pageSize-usableSize);
return rc;
}
- if( (pBt->db->flags & SQLITE_WriteSchema)==0 && nPage>nPageFile ){
+ if( (pBt->db->flags & (SQLITE_WriteSchema|SQLITE_Defensive))==0
+ && nPage>nPageFile
+ ){
rc = SQLITE_CORRUPT_BKPT;
goto page1_init_failed;
}
diff --git a/src/build.c b/src/build.c
index 2b73f4564..da72509da 100644
--- a/src/build.c
+++ b/src/build.c
@@ -806,7 +806,7 @@ int sqlite3TwoPartName(
*/
int sqlite3CheckObjectName(Parse *pParse, const char *zName){
if( !pParse->db->init.busy && pParse->nested==0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && (pParse->db->flags & (SQLITE_WriteSchema|SQLITE_Defensive))==0
&& 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
return SQLITE_ERROR;
diff --git a/src/dbpage.c b/src/dbpage.c
index 5b19abd35..a73ea01bd 100644
--- a/src/dbpage.c
+++ b/src/dbpage.c
@@ -313,6 +313,10 @@ static int dbpageUpdate(
Pager *pPager;
int szPage;
+ if( pTab->db->flags & SQLITE_Defensive ){
+ zErr = "read-only";
+ goto update_fail;
+ }
if( argc==1 ){
zErr = "cannot delete";
goto update_fail;
diff --git a/src/delete.c b/src/delete.c
index 746f6725b..64e7639c1 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -63,7 +63,7 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( ( IsVirtual(pTab)
&& sqlite3GetVTable(pParse->db, pTab)->pMod->pModule->xUpdate==0 )
|| ( (pTab->tabFlags & TF_Readonly)!=0
- && (pParse->db->flags & SQLITE_WriteSchema)==0
+ && (pParse->db->flags & (SQLITE_WriteSchema|SQLITE_Defensive))==0
&& pParse->nested==0 )
){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
diff --git a/src/main.c b/src/main.c
index 8935a19d7..01d8bca86 100644
--- a/src/main.c
+++ b/src/main.c
@@ -835,6 +835,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
{ SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
{ SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP },
{ SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase },
+ { SQLITE_DBCONFIG_DEFENSIVE, SQLITE_Defensive },
};
unsigned int i;
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
diff --git a/src/shell.c.in b/src/shell.c.in
index 4fcd93c01..177a948cb 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -5956,6 +5956,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
{ "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
+ { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
};
int ii, v;
open_db(p, 0);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 9ead2b7aa..18593a644 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -2158,6 +2158,29 @@ struct sqlite3_mem_methods {
** Because resetting a database is destructive and irreversible, the
** process requires the use of this obscure API and multiple steps to help
** ensure that it does not happen by accident.
+**
+** <dt>SQLITE_DBCONFIG_DEFENSIVE</dt>
+** <dd>The SQLITE_DBCONFIG_DEFENSIVE option actives or deactivates the
+** "defensive" flag for a database connection. When the defensive
+** flag is enabled, some obscure features of SQLite are disabled in order
+** to reduce the attack surface. Applications that run untrusted SQL
+** can activate this flag to reduce the risk of zero-day exploits.
+** <p>
+** Features disabled by the defensive flag include:
+** <ul>
+** <li>The [PRAGMA writable_schema=ON] statement.
+** <li>Writes to the [sqlite_dbpage] virtual table.
+** </ul>
+** New restrictions may be added in future releases.
+** <p>
+** To be clear: It should never be possible for hostile SQL to cause
+** arbitrary memory reads, memory leaks, buffer overflows, assertion
+** faults, arbitrary code execution, crashes, or other mischief, regardless
+** of the value of the defensive flag. Any occurrance of these problems
+** is considered a serious bug and will be fixed promptly. It is not
+** necessary to enable the defensive flag in order to make SQLite secure
+** against attack. The defensive flag merely provides an additional layer
+** of defense against unknown vulnerabilities.
** </dd>
** </dl>
*/
@@ -2171,7 +2194,8 @@ struct sqlite3_mem_methods {
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
-#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
+#define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */
+#define SQLITE_DBCONFIG_MAX 1010 /* Largest DBCONFIG */
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 20db52de3..0482db21d 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1540,6 +1540,7 @@ struct sqlite3 {
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
#define SQLITE_LegacyAlter 0x04000000 /* Legacy ALTER TABLE behaviour */
#define SQLITE_NoSchemaError 0x08000000 /* Do not report schema parse errors*/
+#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
/* Flags used only if debugging */
#define HI(X) ((u64)(X)<<32)