]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Validate the type, name, and tbl_name fields of the sqlite_master table when
authordrh <drh@noemail.net>
Fri, 17 Jan 2020 15:24:13 +0000 (15:24 +0000)
committerdrh <drh@noemail.net>
Fri, 17 Jan 2020 15:24:13 +0000 (15:24 +0000)
loading the schema, unless writable_schema is engaged.

FossilOrigin-Name: 3d13fbf248e6bcb997c301530ee834c6f1fc21add7f46b673d0f63e986c60680

12 files changed:
manifest
manifest.uuid
src/alter.c
src/build.c
src/prepare.c
src/sqliteInt.h
src/trigger.c
src/vdbe.c
test/corruptL.test
test/corruptM.test [new file with mode: 0644]
test/dbfuzz001.test
test/fts3corrupt4.test

index 9f48875b95c14d7cae7feeb7567a455d0765f5c8..87411b8a72d5306c2066de4a205d085e69839ecd 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sallow\sshadow\stables\sto\sbe\sdropped\sin\sdefensive\smode.
-D 2020-01-17T14:56:11.132
+C Validate\sthe\stype,\sname,\sand\stbl_name\sfields\sof\sthe\ssqlite_master\stable\swhen\nloading\sthe\sschema,\sunless\swritable_schema\sis\sengaged.
+D 2020-01-17T15:24:13.730
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -452,7 +452,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
 F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
-F src/alter.c 25f54387121a0c5fd0f49b299f4070c81af8f26a84edaae6de679c4e4b71b1ff
+F src/alter.c 00814c584a2792dcb41004b4fbedda35dc16bc2295b0a2c0995e04ecc27244a4
 F src/analyze.c 58db66344a5c58dcabb57f26696f6f2993956c830446da40b444051d2fdaf644
 F src/attach.c 78e986baee90cb7b83fb9eafa79c22581a8ada14030fd633b0683c95cf11213c
 F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
@@ -462,7 +462,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c 958939f608e351a36756e3749596472baa0e5aae54eebd14e6beffe7a68aafc7
 F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89
 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
-F src/build.c 6a2e4b5b4b3aa714ceb6b6bf985c1d99fd16032184b721f302724024c5e6ee5b
+F src/build.c 66af916c1c755b475f17a8c69ef550effd4750ad9be168b0a1a6d274635411dd
 F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
@@ -513,7 +513,7 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c be64b2f3908a7f97c56c963676eb12f0d6254c95b28cdc1d73a186eff213219d
 F src/pragma.c af67dedaad8bafe9a5f9adcec32a0da6dd118617dd8220ad1d118f5a6bf83a02
 F src/pragma.h a776bb9c915207e9d1117b5754743ddf1bf6a39cc092a4a44e74e6cb5fab1177
-F src/prepare.c 78027c6231fbb19ca186a5f5f0c0a1375d9c2cec0655273f9bd90d9ff74a34b3
+F src/prepare.c f739feb4cf0dfe22b5729c3610c80e2261c816731c7884641552e12aa9f7346d
 F src/printf.c 67f79227273a9009d86a017619717c3f554f50b371294526da59faa6014ed2cd
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 567888ee3faec14dae06519b4306201771058364a37560186a3e0e755ebc4cb8
@@ -523,7 +523,7 @@ F src/shell.c.in c1986496062f9dba4ed5b70db06b5e0f32e1954cdcfab0b30372c6c18679681
 F src/sqlite.h.in 59f5e145b8d7a915ca29c6bf4a1f00e3112c1605c9ac5c627c45060110332ba2
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 9ecc93b8493bd20c0c07d52e2ac0ed8bab9b549c7f7955b59869597b650dd8b5
-F src/sqliteInt.h d229b6a5f70fe6c57d2f91f0edc60a9c4437397b4a5b59fd72fe9eb3b94d3437
+F src/sqliteInt.h 6013f8633a448ea08c8540ba3260ae6082817ea1fb230d54d74534d4d394df73
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -584,13 +584,13 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c d3615f0cbe4db5949503bf5916f3cd4fa5de855d5b4ef560f3b6dd5629423a1e
 F src/treeview.c 56724725c62a0d0f408f7c257475dc33309198afee36a1d18be1bc268b09055e
-F src/trigger.c bb034c08eca111e66a19cda045903a12547c1be2294b5570d794b869d9c44a73
+F src/trigger.c 132009e29dc8099e2cbabc67b5608f03487e61d5dc4b1c5c98187ef703326e2c
 F src/update.c 0b973357d88092140531e07ff641139c26fb4380b0b9f5ed98c5f7691b4604d1
 F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
 F src/utf.c 2f0fac345c7660d5c5bd3df9e9d8d33d4c27f366bcfb09e07443064d751a0507
 F src/util.c e12939405e77906d06ab0b78c5f513dcd2b7cec2fbb553877b0abfece6067141
 F src/vacuum.c 72690ccb6877a88f8473a893cf9f6d7592236f3eebfebfa840b19c708acde574
-F src/vdbe.c 711ef421b3bb3db3b2476067b2dc3c71ef5844d9b1a723026578f89f6da621e8
+F src/vdbe.c 63db3831dfa1ddcfe1c9ed4e88561427cb78614f1883593d9abb30d715229dd6
 F src/vdbe.h 712bca562eaed1c25506b9faf9680bdc75fc42e2f4a1cd518d883fa79c7a4237
 F src/vdbeInt.h 2c12704db9740c8e899786ecfc7a5797a9d067563496eb1b6ed03c592d7b8d90
 F src/vdbeapi.c 2ddd60f4a351f15ee98d841e346af16111ad59dfa4d25d2dd4012e9875bf7d92
@@ -762,7 +762,8 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
 F test/corruptI.test a17bbf54fdde78d43cf3cc34b0057719fd4a173a3d824285b67dc5257c064c7b
 F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
 F test/corruptK.test 5b4212fe346699831c5ad559a62c54e11c0611bdde1ea8423a091f9c01aa32af
-F test/corruptL.test a569f3cece872a1f21568bd5378f55ce5c365c50845a06fae65a2721cce62264
+F test/corruptL.test 18e62c39f41bd2ad861ab031728503409fec16213b13c3cb60ad39fd4c0b43b5
+F test/corruptM.test 04a4061b1979283851953217e411187be79e50f5e5e3ef340c3f8e564173aae1
 F test/cost.test 51f4fcaae6e78ad5a57096831259ed6c760e2ac6876836e91c00030fad385b34
 F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
 F test/countofview.test e17d6e6688cf74f22783c9ec6e788c0790ee4fbbaee713affd00b1ac0bb39b86
@@ -787,7 +788,7 @@ F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68
 F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
 F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
 F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
-F test/dbfuzz001.test e32d14465f1c77712896fda6a1ccc0f037b481c191c1696a9c44f6c9e4964faf
+F test/dbfuzz001.test 42aad1dcef6219fbee86a9b7d08832c9bbb2e41508f6f128ae91745927276292
 F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
 F test/dbfuzz2.c 6c355cf70c4a308b1b84a11a65282bcac5b4038db77de5cfc8ad080ef371f109
 F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
@@ -923,7 +924,7 @@ F test/fts3conf.test c84bbaec81281c1788aa545ac6e78a6bd6cde2bdbbce2da261690e3659f
 F test/fts3corrupt.test 46b9ddda7f6588fd5a5b1f4bb4fc0618dc45010e7dddb8a3a188baf3197177ae
 F test/fts3corrupt2.test bf55c3fa0b0dc8ea1c0fe5543623bd27714585da6a129038fd6999fe3b0d25f3
 F test/fts3corrupt3.test 0d5b69a0998b4adf868cc301fc78f3d0707745f1d984ce044c205cdb764b491f
-F test/fts3corrupt4.test 9fe1c500ea7a45605dd62dfea83c09ff692a981ff4234280713701097eac8299
+F test/fts3corrupt4.test 926564a11038db245539a9a158085b2b7ca157694d050937aa5cf2d46979c6e2
 F test/fts3cov.test cb932743da52a1c79a1ab8983e26c8121cf02263d6ff16e1f642e6f9b8348338
 F test/fts3d.test 2bd8c97bcb9975f2334147173b4872505b6a41359a4f9068960a36afe07a679f
 F test/fts3defer.test f4c20e4c7153d20a98ee49ee5f3faef624fefc9a067f8d8d629db380c4d9f1de
@@ -1818,8 +1819,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P be4269c624b30dd744f80448558b650b505e04c7748386bb461158f5b1823680
-Q +70390bbca49e706649ca5b7c031f0baf416fc38798c17e5f3b73746b3e66e3b5
-R add24c14dc00ee37846bfc57868ae717
+P ad1f760f164c819eac24597dd621586933c8ca77f79efd2e4773f5599e089c5e
+Q +724f4df9ccc2b683f7091a3f7a8c20ee210f44d7a610cd1b4c49da1c274add08
+R dca847b9ecccaa71c64d4a1b4d2ddb68
 U drh
-Z fd9f5bc320eec6288a9772fd21e90b8a
+Z 54c6427e345328d9cbde0765658ffd7c
index 19107767c89aac5ad1ffa20e602e9c10cfde0109..27d5caa1115878cce6e99436e033ba22542a29ab 100644 (file)
@@ -1 +1 @@
-ad1f760f164c819eac24597dd621586933c8ca77f79efd2e4773f5599e089c5e
\ No newline at end of file
+3d13fbf248e6bcb997c301530ee834c6f1fc21add7f46b673d0f63e986c60680
\ No newline at end of file
index d71074795b707576f63de5d3c45f00d1d0c677f7..5d910bb985e478ad3e0612d03564d90822a499d3 100644 (file)
@@ -136,8 +136,8 @@ void sqlite3AlterRenameTable(
   if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
     goto exit_rename_table;
   }
-  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
-    exit_rename_table;
+  if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
+    goto exit_rename_table;
   }
 
 #ifndef SQLITE_OMIT_VIEW
index 1ece5cd2762c2acb01fa6cf9e67ee066dcdcd89d..c16f6032a05c689bd5667db554ba6e2e21f42613 100644 (file)
@@ -825,13 +825,38 @@ int sqlite3WritableSchema(sqlite3 *db){
 ** trigger). All names are legal except those that begin with the string
 ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
 ** is reserved for internal use.
+**
+** When parsing the sqlite_master table, this routine also checks to
+** make sure the "type", "name", and "tbl_name" columns are consistent
+** with the SQL.
 */
-int sqlite3CheckObjectName(Parse *pParse, const char *zName){
-  if( !pParse->db->init.busy && pParse->nested==0 
-          && sqlite3WritableSchema(pParse->db)==0
-          && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
-    sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
-    return SQLITE_ERROR;
+int sqlite3CheckObjectName(
+  Parse *pParse,            /* Parsing context */
+  const char *zName,        /* Name of the object to check */
+  const char *zType,        /* Type of this object */
+  const char *zTblName      /* Parent table name for triggers and indexes */
+){
+  sqlite3 *db = pParse->db;
+  if( sqlite3WritableSchema(db) || db->init.imposterTable ){
+    /* Skip these error checks for writable_schema=ON */
+    return SQLITE_OK;
+  }
+  if( db->init.busy ){
+    if( sqlite3_stricmp(zType, db->init.azInit[0])
+     || sqlite3_stricmp(zName, db->init.azInit[1])
+     || sqlite3_stricmp(zTblName, db->init.azInit[2])
+    ){
+      sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
+      return SQLITE_ERROR;
+    }
+  }else{
+    if( pParse->nested==0 
+     && 0==sqlite3StrNICmp(zName, "sqlite_", 7)
+    ){
+      sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
+                      zName);
+      return SQLITE_ERROR;
+    }
   }
   return SQLITE_OK;
 }
@@ -912,7 +937,7 @@ void sqlite3StartTable(
   }
   pParse->sNameToken = *pName;
   if( zName==0 ) return;
-  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+  if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
     goto begin_table_error;
   }
   if( db->init.iDb==1 ) isTemp = 1;
@@ -3211,7 +3236,7 @@ void sqlite3CreateIndex(
     zName = sqlite3NameFromToken(db, pName);
     if( zName==0 ) goto exit_create_index;
     assert( pName->z!=0 );
-    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
       goto exit_create_index;
     }
     if( !IN_RENAME_OBJECT ){
index 3f1a79b14b683d825e43f11ae810dedb49444747..62abc9f6c3087dab33ddf2e6e6d2bc9e71d3da3a 100644 (file)
@@ -64,9 +64,11 @@ int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
 **
 ** Each callback contains the following information:
 **
-**     argv[0] = name of thing being created
-**     argv[1] = root page number for table or index. 0 for trigger or view.
-**     argv[2] = SQL text for the CREATE statement.
+**     argv[0] = type of object: "table", "index", "trigger", or "view".
+**     argv[1] = name of thing being created
+**     argv[2] = associated table if an index or trigger
+**     argv[3] = root page number for table or index. 0 for trigger or view.
+**     argv[4] = SQL text for the CREATE statement.
 **
 */
 int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
@@ -74,21 +76,21 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
   sqlite3 *db = pData->db;
   int iDb = pData->iDb;
 
-  assert( argc==3 );
+  assert( argc==5 );
   UNUSED_PARAMETER2(NotUsed, argc);
   assert( sqlite3_mutex_held(db->mutex) );
   DbClearProperty(db, iDb, DB_Empty);
   pData->nInitRow++;
   if( db->mallocFailed ){
-    corruptSchema(pData, argv[0], 0);
+    corruptSchema(pData, argv[1], 0);
     return 1;
   }
 
   assert( iDb>=0 && iDb<db->nDb );
   if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
-  if( argv[1]==0 ){
-    corruptSchema(pData, argv[0], 0);
-  }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
+  if( argv[3]==0 ){
+    corruptSchema(pData, argv[1], 0);
+  }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
     /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
     ** But because db->init.busy is set to 1, no VDBE code is generated
     ** or executed.  All the parser does is build the internal data
@@ -101,9 +103,10 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
 
     assert( db->init.busy );
     db->init.iDb = iDb;
-    db->init.newTnum = sqlite3Atoi(argv[1]);
+    db->init.newTnum = sqlite3Atoi(argv[3]);
     db->init.orphanTrigger = 0;
-    TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
+    db->init.azInit = argv;
+    TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
     rc = db->errCode;
     assert( (rc&0xFF)==(rcp&0xFF) );
     db->init.iDb = saved_iDb;
@@ -116,13 +119,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
         if( rc==SQLITE_NOMEM ){
           sqlite3OomFault(db);
         }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
-          corruptSchema(pData, argv[0], sqlite3_errmsg(db));
+          corruptSchema(pData, argv[1], sqlite3_errmsg(db));
         }
       }
     }
     sqlite3_finalize(pStmt);
-  }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
-    corruptSchema(pData, argv[0], 0);
+  }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
+    corruptSchema(pData, argv[1], 0);
   }else{
     /* If the SQL column is blank it means this is an index that
     ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -131,13 +134,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
     ** to do here is record the root page number for that index.
     */
     Index *pIndex;
-    pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
+    pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
     if( pIndex==0
-     || sqlite3GetInt32(argv[1],&pIndex->tnum)==0
+     || sqlite3GetInt32(argv[3],&pIndex->tnum)==0
      || pIndex->tnum<2
      || sqlite3IndexHasDuplicateRootPage(pIndex)
     ){
-      corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
+      corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
     }
   }
   return 0;
@@ -158,7 +161,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
   int size;
 #endif
   Db *pDb;
-  char const *azArg[4];
+  char const *azArg[6];
   int meta[5];
   InitData initData;
   const char *zMasterName;
@@ -177,18 +180,20 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
   ** table name will be inserted automatically by the parser so we can just
   ** use the abbreviation "x" here.  The parser will also automatically tag
   ** the schema table as read-only. */
-  azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
-  azArg[1] = "1";
-  azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
+  azArg[0] = "table";
+  azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
+  azArg[2] = azArg[1];
+  azArg[3] = "1";
+  azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
                             "rootpage int,sql text)";
-  azArg[3] = 0;
+  azArg[5] = 0;
   initData.db = db;
   initData.iDb = iDb;
   initData.rc = SQLITE_OK;
   initData.pzErrMsg = pzErrMsg;
   initData.mInitFlags = mFlags;
   initData.nInitRow = 0;
-  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
+  sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
   if( initData.rc ){
     rc = initData.rc;
     goto error_out;
@@ -314,7 +319,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
   {
     char *zSql;
     zSql = sqlite3MPrintf(db, 
-        "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
+        "SELECT*FROM\"%w\".%s ORDER BY rowid",
         db->aDb[iDb].zDbSName, zMasterName);
 #ifndef SQLITE_OMIT_AUTHORIZATION
     {
index 72953e6009fd74986e37d1ba3a266783863f0e37..9ce759f9de14b022c3a1a85db3a6db235fbc2555 100644 (file)
@@ -1411,6 +1411,7 @@ struct sqlite3 {
     unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
     unsigned imposterTable : 1; /* Building an imposter table */
     unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
+    char **azInit;              /* "type", "name", and "tbl_name" columns */
   } init;
   int nVdbeActive;              /* Number of VDBEs currently running */
   int nVdbeRead;                /* Number of active VDBEs that read or write */
@@ -4248,7 +4249,7 @@ Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
 Expr *sqlite3ExprSkipCollate(Expr*);
 int sqlite3CheckCollSeq(Parse *, CollSeq *);
 int sqlite3WritableSchema(sqlite3*);
-int sqlite3CheckObjectName(Parse *, const char *);
+int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
 void sqlite3VdbeSetChanges(sqlite3 *, int);
 int sqlite3AddInt64(i64*,i64);
 int sqlite3SubInt64(i64*,i64);
index c37f76da720993e26c8e5d7cb7cf7a5681371569..6a58c7130879289f8b780fab6cebff0d751eb3cf 100644 (file)
@@ -177,7 +177,11 @@ void sqlite3BeginTrigger(
   /* Check that the trigger name is not reserved and that no trigger of the
   ** specified name exists */
   zName = sqlite3NameFromToken(db, pName);
-  if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+  if( zName==0 ){
+    assert( db->mallocFailed );
+    goto trigger_cleanup;
+  }
+  if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
     goto trigger_cleanup;
   }
   assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
index c004137c47572aac464cdd2e9e3f6ed9d66b8556..4ab9dc6ad9de46a1a284a327859d54e05e3d0467 100644 (file)
@@ -5787,7 +5787,7 @@ case OP_ParseSchema: {
     initData.pzErrMsg = &p->zErrMsg;
     initData.mInitFlags = 0;
     zSql = sqlite3MPrintf(db,
-       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
+       "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
        db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
     if( zSql==0 ){
       rc = SQLITE_NOMEM_BKPT;
index 213af9d34313e4b4ac7073908e477e0c486a570b..da296dd9d12e1cfce32ddfbb5c2dabf809add134 100644 (file)
@@ -228,6 +228,7 @@ do_test 2.0 {
 }]} {}
 
 do_execsql_test 2.1 {
+  PRAGMA writable_schema=on;
   INSERT INTO t1(b) VALUES(X'a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6ac8ae0d0e7c3175946e62ba2b');
 }
 
@@ -378,7 +379,7 @@ do_test 4.0 {
 
 do_catchsql_test 4.1 {
   INSERT INTO t3 SELECT * FROM t2;
-} {1 {database disk image is malformed}}
+} {1 {malformed database schema (t1)}}
 
 
 #-------------------------------------------------------------------------
@@ -632,7 +633,7 @@ do_catchsql_test 6.1 {
     INSERT INTO t1(b) VALUES(1);
     INSERT INTO t1(b) VALUES(2);
   COMMIT;
-} {1 {malformed database schema (t1b) - invalid rootpage}}
+} {1 {malformed database schema (t1)}}
 
 #-------------------------------------------------------------------------
 reset_db
@@ -836,6 +837,6 @@ do_test 8.0 {
 
 do_catchsql_test 8.1 {
   INSERT INTO t3 SELECT * FROM t2;
-} {1 {database disk image is malformed}}
+} {1 {malformed database schema (t1)}}
 
 finish_test
diff --git a/test/corruptM.test b/test/corruptM.test
new file mode 100644 (file)
index 0000000..0b9f5e4
--- /dev/null
@@ -0,0 +1,202 @@
+# 2019-08-12
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# Check to ensure that the type, name, and tbl_name fields of the
+# sqlite_master table are validated and errors are reported if they
+# are inconsistent with the sql.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix corruptM
+
+# These tests deal with corrupt database files
+#
+database_may_be_corrupt
+
+db close
+forcedelete test.db
+sqlite3 db test.db
+do_execsql_test corruptM-100 {
+  CREATE TABLE t1(a,b,c);
+  INSERT INTO t1 VALUES(111,222,333);
+  CREATE INDEX i1 ON t1(b);
+  CREATE VIEW v2 AS SELECT 15,22;
+  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT 5; END;
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+do_execsql_test corruptM-101 {
+  PRAGMA writable_schema=on;
+  UPDATE sqlite_master SET tbl_name=NULL WHERE name='t1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 {} | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-102 {
+  catchsql {
+    PRAGMA quick_check;
+  } db2
+} {1 {malformed database schema (t1)}}
+db2 close
+
+do_execsql_test corruptM-110 {
+  UPDATE sqlite_master SET tbl_name='tx' WHERE name='t1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 tx | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-111 {
+  catchsql {
+    PRAGMA quick_check;
+  } db2
+} {1 {malformed database schema (t1)}}
+db2 close
+do_execsql_test corruptM-112 {
+  UPDATE sqlite_master SET tbl_name='t1', type='tabl' WHERE name='t1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {tabl t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-113 {
+  catchsql {
+    PRAGMA quick_check;
+  } db2
+} {1 {malformed database schema (t1)}}
+db2 close
+do_execsql_test corruptM-114 {
+  UPDATE sqlite_master SET tbl_name='t9',type='table',name='t9'WHERE name='t1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t9 t9 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-114 {
+  catchsql {
+    PRAGMA quick_check;
+  } db2
+} {1 {malformed database schema (t9)}}
+db2 close
+
+do_execsql_test corruptM-120 {
+  UPDATE sqlite_master SET name='t1',tbl_name='T1' WHERE name='t9';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-121 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {0 {ok 111 222 333 15 22}}
+db2 close
+
+do_execsql_test corruptM-130 {
+  UPDATE sqlite_master SET type='view' WHERE name='t1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {view t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-131 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (t1)}}
+db2 close
+
+do_execsql_test corruptM-140 {
+  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='t1';
+  UPDATE sqlite_master SET tbl_name='tx' WHERE name='i1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 tx | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-141 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (i1)}}
+db2 close
+
+do_execsql_test corruptM-150 {
+  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='i1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | table i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-151 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (i1)}}
+db2 close
+
+do_execsql_test corruptM-160 {
+  UPDATE sqlite_master SET type='view', tbl_name='t1' WHERE name='i1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | view i1 t1 | view v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-161 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (i1)}}
+db2 close
+
+do_execsql_test corruptM-170 {
+  UPDATE sqlite_master SET type='index', tbl_name='t1' WHERE name='i1';
+  UPDATE sqlite_master SET type='table', tbl_name='v2' WHERE name='v2';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 t1 | table v2 v2 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-171 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (v2)}}
+db2 close
+
+do_execsql_test corruptM-180 {
+  UPDATE sqlite_master SET type='view',name='v3',tbl_name='v3' WHERE name='v2';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 t1 | view v3 v3 | trigger r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-181 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (v3)}}
+db2 close
+
+do_execsql_test corruptM-190 {
+  UPDATE sqlite_master SET type='view',name='v2',tbl_name='v2' WHERE name='v3';
+  UPDATE sqlite_master SET type='view' WHERE name='r1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 t1 | view v2 v2 | view r1 t1 |}
+sqlite3 db2 test.db
+do_test corruptM-191 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (r1)}}
+db2 close
+do_execsql_test corruptM-192 {
+  UPDATE sqlite_master SET type='trigger',tbl_name='v2' WHERE name='r1';
+  SELECT type, name, tbl_name, '|' FROM sqlite_master;
+} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 v2 |}
+sqlite3 db2 test.db
+do_test corruptM-193 {
+  catchsql {
+    PRAGMA quick_check;
+    SELECT * FROM t1, v2;
+  } db2
+} {1 {malformed database schema (r1)}}
+db2 close
+
+finish_test
index 77df86b30ee1cf29964201a55e12ecc3a1ac15d7..7ef4cd2a3fb34f870b80a9dcf1276f62c18960e8 100644 (file)
@@ -305,7 +305,7 @@ do_test dbfuzz001-310 {
 |    384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61   2(c,d)(......=ta
 |    400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54   blet3t3.CREATE T
 |    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
-|    432: 28 02 06 17 11 11 01 3d 74 61 74 65 6c 03 62 74   (......=tatel.bt
+|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
 |    448: 32 32 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   22CREATE TABLE t
 |    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
 |    480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .5tablet1t1.CREA
index dfd969cd571126717878a2d1e029d0d5451164a7..5b32fe6d578b9a5c2b9a6c10b8576c152c6fb165 100644 (file)
@@ -2147,6 +2147,7 @@ do_test 14.0 {
 }]} {}
 
 do_execsql_test 14.1 {
+  PRAGMA writable_schema=on;
   WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
     INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
 }
@@ -3050,6 +3051,7 @@ do_test 19.0 {
 }]} {}
 
 do_catchsql_test 19.1 {
+  PRAGMA writable_schema=ON;
   SELECT rowid,a,c,snippet(t1,85101090932165,-1,10) FROM t1 WHERE a MATCH 'rtree';
 } {1 {database disk image is malformed}}
 
@@ -3251,6 +3253,7 @@ do_test 20.0 {
 }]} {}
 
 do_execsql_test 20.1 {
+  PRAGMA writable_schema=on;
   BEGIN;
   WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<10)
     INSERT INTO t1(a) SELECT randomblob(3000) FROM c;
@@ -3473,8 +3476,8 @@ do_test 21.0 {
 | end crash-18cc014e42e828.db
 }]} {}
 
-breakpoint
 do_catchsql_test 21.1 {
+  PRAGMA writable_schema=ON;
   SELECT offsets(t1) FROM t1 WHERE t1 MATCH 'R*';
 } {1 {database disk image is malformed}}
 
@@ -3695,6 +3698,7 @@ do_test 22.0 {
 }]} {}
 
 do_catchsql_test 22.1 {
+  PRAGMA writable_schema=on;
   SELECT snippet(t1,'', '', '--',-1,01)==0
     FROM t1 WHERE a MATCH 'rtree OR json1rtree OR json1';
 } {0 {0 0 0 0 0 0 0}}
@@ -3914,6 +3918,7 @@ do_test 23.0 {
 }]} {}
 
 do_catchsql_test 23.1 {
+  PRAGMA writable_schema=on;
   SELECT 'FyzLy'FROM t1 WHERE t1 MATCH 'j';
 } {1 {database disk image is malformed}}