/ Check-in [724f4df9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Validate the type, name, and tbl_name fields of the sqlite_master table when loading the schema, unless writable_schema is engaged.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 724f4df9ccc2b683f7091a3f7a8c20ee210f44d7a610cd1b4c49da1c274add08
User & Date: drh 2019-08-12 00:08:07
References
2019-08-13
17:27
Update some corruption test cases to take [724f4df9c] into account. check-in: 927cd7b4 user: dan tags: trunk
Context
2020-01-17
15:24
Validate the type, name, and tbl_name fields of the sqlite_master table when loading the schema, unless writable_schema is engaged. check-in: 3d13fbf2 user: drh tags: branch-3.28
2019-08-12
14:17
Add a TESTCTRL that disables the verification of type, name, and tbl_name in the sqlite_master table. check-in: 48d9b48a user: drh tags: trunk
00:08
Validate the type, name, and tbl_name fields of the sqlite_master table when loading the schema, unless writable_schema is engaged. check-in: 724f4df9 user: drh tags: trunk
2019-08-10
15:06
Fix the sqliteExprImpliesExpr() routine so that it recognizes that "(NULL IS FALSE) IS FALSE" doe not imply "NULL NOT NULL". Ticket [9080b6227fabb466] check-in: da01ba4f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

   132    132   
   133    133     /* Make sure it is not a system table being altered, or a reserved name
   134    134     ** that the table is being renamed to.
   135    135     */
   136    136     if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
   137    137       goto exit_rename_table;
   138    138     }
   139         -  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
   140         -    exit_rename_table;
          139  +  if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
          140  +    goto exit_rename_table;
   141    141     }
   142    142   
   143    143   #ifndef SQLITE_OMIT_VIEW
   144    144     if( pTab->pSelect ){
   145    145       sqlite3ErrorMsg(pParse, "view %s may not be altered", pTab->zName);
   146    146       goto exit_rename_table;
   147    147     }

Changes to src/build.c.

   825    825   
   826    826   /*
   827    827   ** This routine is used to check if the UTF-8 string zName is a legal
   828    828   ** unqualified name for a new schema object (table, index, view or
   829    829   ** trigger). All names are legal except those that begin with the string
   830    830   ** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
   831    831   ** is reserved for internal use.
          832  +**
          833  +** When parsing the sqlite_master table, this routine also checks to
          834  +** make sure the "type", "name", and "tbl_name" columns are consistent
          835  +** with the SQL.
   832    836   */
   833         -int sqlite3CheckObjectName(Parse *pParse, const char *zName){
   834         -  if( !pParse->db->init.busy && pParse->nested==0 
   835         -          && sqlite3WritableSchema(pParse->db)==0
   836         -          && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
   837         -    sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
   838         -    return SQLITE_ERROR;
          837  +int sqlite3CheckObjectName(
          838  +  Parse *pParse,            /* Parsing context */
          839  +  const char *zName,        /* Name of the object to check */
          840  +  const char *zType,        /* Type of this object */
          841  +  const char *zTblName      /* Parent table name for triggers and indexes */
          842  +){
          843  +  sqlite3 *db = pParse->db;
          844  +  if( sqlite3WritableSchema(db) || db->init.imposterTable ){
          845  +    /* Skip these error checks for writable_schema=ON */
          846  +    return SQLITE_OK;
          847  +  }
          848  +  if( db->init.busy ){
          849  +    if( sqlite3_stricmp(zType, db->init.azInit[0])
          850  +     || sqlite3_stricmp(zName, db->init.azInit[1])
          851  +     || sqlite3_stricmp(zTblName, db->init.azInit[2])
          852  +    ){
          853  +      sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
          854  +      return SQLITE_ERROR;
          855  +    }
          856  +  }else{
          857  +    if( pParse->nested==0 
          858  +     && 0==sqlite3StrNICmp(zName, "sqlite_", 7)
          859  +    ){
          860  +      sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
          861  +                      zName);
          862  +      return SQLITE_ERROR;
          863  +    }
   839    864     }
   840    865     return SQLITE_OK;
   841    866   }
   842    867   
   843    868   /*
   844    869   ** Return the PRIMARY KEY index of a table
   845    870   */
................................................................................
   912    937       zName = sqlite3NameFromToken(db, pName);
   913    938       if( IN_RENAME_OBJECT ){
   914    939         sqlite3RenameTokenMap(pParse, (void*)zName, pName);
   915    940       }
   916    941     }
   917    942     pParse->sNameToken = *pName;
   918    943     if( zName==0 ) return;
   919         -  if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
          944  +  if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
   920    945       goto begin_table_error;
   921    946     }
   922    947     if( db->init.iDb==1 ) isTemp = 1;
   923    948   #ifndef SQLITE_OMIT_AUTHORIZATION
   924    949     assert( isTemp==0 || isTemp==1 );
   925    950     assert( isView==0 || isView==1 );
   926    951     {
................................................................................
  3271   3296     ** dealing with a primary key or UNIQUE constraint.  We have to invent our
  3272   3297     ** own name.
  3273   3298     */
  3274   3299     if( pName ){
  3275   3300       zName = sqlite3NameFromToken(db, pName);
  3276   3301       if( zName==0 ) goto exit_create_index;
  3277   3302       assert( pName->z!=0 );
  3278         -    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
         3303  +    if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
  3279   3304         goto exit_create_index;
  3280   3305       }
  3281   3306       if( !IN_RENAME_OBJECT ){
  3282   3307         if( !db->init.busy ){
  3283   3308           if( sqlite3FindTable(db, zName, 0)!=0 ){
  3284   3309             sqlite3ErrorMsg(pParse, "there is already a table named %s", zName);
  3285   3310             goto exit_create_index;

Changes to src/prepare.c.

    60     60   /*
    61     61   ** This is the callback routine for the code that initializes the
    62     62   ** database.  See sqlite3Init() below for additional information.
    63     63   ** This routine is also called from the OP_ParseSchema opcode of the VDBE.
    64     64   **
    65     65   ** Each callback contains the following information:
    66     66   **
    67         -**     argv[0] = name of thing being created
    68         -**     argv[1] = root page number for table or index. 0 for trigger or view.
    69         -**     argv[2] = SQL text for the CREATE statement.
           67  +**     argv[0] = type of object: "table", "index", "trigger", or "view".
           68  +**     argv[1] = name of thing being created
           69  +**     argv[2] = associated table if an index or trigger
           70  +**     argv[3] = root page number for table or index. 0 for trigger or view.
           71  +**     argv[4] = SQL text for the CREATE statement.
    70     72   **
    71     73   */
    72     74   int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
    73     75     InitData *pData = (InitData*)pInit;
    74     76     sqlite3 *db = pData->db;
    75     77     int iDb = pData->iDb;
    76     78   
    77         -  assert( argc==3 );
           79  +  assert( argc==5 );
    78     80     UNUSED_PARAMETER2(NotUsed, argc);
    79     81     assert( sqlite3_mutex_held(db->mutex) );
    80     82     DbClearProperty(db, iDb, DB_Empty);
    81     83     pData->nInitRow++;
    82     84     if( db->mallocFailed ){
    83         -    corruptSchema(pData, argv[0], 0);
           85  +    corruptSchema(pData, argv[1], 0);
    84     86       return 1;
    85     87     }
    86     88   
    87     89     assert( iDb>=0 && iDb<db->nDb );
    88     90     if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
    89         -  if( argv[1]==0 ){
    90         -    corruptSchema(pData, argv[0], 0);
    91         -  }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
           91  +  if( argv[3]==0 ){
           92  +    corruptSchema(pData, argv[1], 0);
           93  +  }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
    92     94       /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
    93     95       ** But because db->init.busy is set to 1, no VDBE code is generated
    94     96       ** or executed.  All the parser does is build the internal data
    95     97       ** structures that describe the table, index, or view.
    96     98       */
    97     99       int rc;
    98    100       u8 saved_iDb = db->init.iDb;
    99    101       sqlite3_stmt *pStmt;
   100    102       TESTONLY(int rcp);            /* Return code from sqlite3_prepare() */
   101    103   
   102    104       assert( db->init.busy );
   103    105       db->init.iDb = iDb;
   104         -    db->init.newTnum = sqlite3Atoi(argv[1]);
          106  +    db->init.newTnum = sqlite3Atoi(argv[3]);
   105    107       db->init.orphanTrigger = 0;
   106         -    TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
          108  +    db->init.azInit = argv;
          109  +    TESTONLY(rcp = ) sqlite3_prepare(db, argv[4], -1, &pStmt, 0);
   107    110       rc = db->errCode;
   108    111       assert( (rc&0xFF)==(rcp&0xFF) );
   109    112       db->init.iDb = saved_iDb;
   110    113       /* assert( saved_iDb==0 || (db->mDbFlags & DBFLAG_Vacuum)!=0 ); */
   111    114       if( SQLITE_OK!=rc ){
   112    115         if( db->init.orphanTrigger ){
   113    116           assert( iDb==1 );
   114    117         }else{
   115    118           pData->rc = rc;
   116    119           if( rc==SQLITE_NOMEM ){
   117    120             sqlite3OomFault(db);
   118    121           }else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
   119         -          corruptSchema(pData, argv[0], sqlite3_errmsg(db));
          122  +          corruptSchema(pData, argv[1], sqlite3_errmsg(db));
   120    123           }
   121    124         }
   122    125       }
   123    126       sqlite3_finalize(pStmt);
   124         -  }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
   125         -    corruptSchema(pData, argv[0], 0);
          127  +  }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
          128  +    corruptSchema(pData, argv[1], 0);
   126    129     }else{
   127    130       /* If the SQL column is blank it means this is an index that
   128    131       ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
   129    132       ** constraint for a CREATE TABLE.  The index should have already
   130    133       ** been created when we processed the CREATE TABLE.  All we have
   131    134       ** to do here is record the root page number for that index.
   132    135       */
   133    136       Index *pIndex;
   134         -    pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
          137  +    pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
   135    138       if( pIndex==0
   136         -     || sqlite3GetInt32(argv[1],&pIndex->tnum)==0
          139  +     || sqlite3GetInt32(argv[3],&pIndex->tnum)==0
   137    140        || pIndex->tnum<2
   138    141        || sqlite3IndexHasDuplicateRootPage(pIndex)
   139    142       ){
   140         -      corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
          143  +      corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
   141    144       }
   142    145     }
   143    146     return 0;
   144    147   }
   145    148   
   146    149   /*
   147    150   ** Attempt to read the database schema and initialize internal
................................................................................
   154    157   int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
   155    158     int rc;
   156    159     int i;
   157    160   #ifndef SQLITE_OMIT_DEPRECATED
   158    161     int size;
   159    162   #endif
   160    163     Db *pDb;
   161         -  char const *azArg[4];
          164  +  char const *azArg[6];
   162    165     int meta[5];
   163    166     InitData initData;
   164    167     const char *zMasterName;
   165    168     int openedTransaction = 0;
   166    169   
   167    170     assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
   168    171     assert( iDb>=0 && iDb<db->nDb );
................................................................................
   173    176     db->init.busy = 1;
   174    177   
   175    178     /* Construct the in-memory representation schema tables (sqlite_master or
   176    179     ** sqlite_temp_master) by invoking the parser directly.  The appropriate
   177    180     ** table name will be inserted automatically by the parser so we can just
   178    181     ** use the abbreviation "x" here.  The parser will also automatically tag
   179    182     ** the schema table as read-only. */
   180         -  azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
   181         -  azArg[1] = "1";
   182         -  azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
          183  +  azArg[0] = "table";
          184  +  azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
          185  +  azArg[2] = azArg[1];
          186  +  azArg[3] = "1";
          187  +  azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
   183    188                               "rootpage int,sql text)";
   184         -  azArg[3] = 0;
          189  +  azArg[5] = 0;
   185    190     initData.db = db;
   186    191     initData.iDb = iDb;
   187    192     initData.rc = SQLITE_OK;
   188    193     initData.pzErrMsg = pzErrMsg;
   189    194     initData.mInitFlags = mFlags;
   190    195     initData.nInitRow = 0;
   191         -  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
          196  +  sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
   192    197     if( initData.rc ){
   193    198       rc = initData.rc;
   194    199       goto error_out;
   195    200     }
   196    201   
   197    202     /* Create a cursor to hold the database open
   198    203     */
................................................................................
   310    315   
   311    316     /* Read the schema information out of the schema tables
   312    317     */
   313    318     assert( db->init.busy );
   314    319     {
   315    320       char *zSql;
   316    321       zSql = sqlite3MPrintf(db, 
   317         -        "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
          322  +        "SELECT*FROM\"%w\".%s ORDER BY rowid",
   318    323           db->aDb[iDb].zDbSName, zMasterName);
   319    324   #ifndef SQLITE_OMIT_AUTHORIZATION
   320    325       {
   321    326         sqlite3_xauth xAuth;
   322    327         xAuth = db->xAuth;
   323    328         db->xAuth = 0;
   324    329   #endif

Changes to src/sqliteInt.h.

  1394   1394     struct sqlite3InitInfo {      /* Information used during initialization */
  1395   1395       int newTnum;                /* Rootpage of table being initialized */
  1396   1396       u8 iDb;                     /* Which db file is being initialized */
  1397   1397       u8 busy;                    /* TRUE if currently initializing */
  1398   1398       unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
  1399   1399       unsigned imposterTable : 1; /* Building an imposter table */
  1400   1400       unsigned reopenMemdb : 1;   /* ATTACH is really a reopen using MemDB */
         1401  +    char **azInit;              /* "type", "name", and "tbl_name" columns */
  1401   1402     } init;
  1402   1403     int nVdbeActive;              /* Number of VDBEs currently running */
  1403   1404     int nVdbeRead;                /* Number of active VDBEs that read or write */
  1404   1405     int nVdbeWrite;               /* Number of active VDBEs that read and write */
  1405   1406     int nVdbeExec;                /* Number of nested calls to VdbeExec() */
  1406   1407     int nVDestroy;                /* Number of active OP_VDestroy operations */
  1407   1408     int nExtension;               /* Number of loaded extensions */
................................................................................
  4264   4265   CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
  4265   4266   int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
  4266   4267   Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
  4267   4268   Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
  4268   4269   Expr *sqlite3ExprSkipCollate(Expr*);
  4269   4270   int sqlite3CheckCollSeq(Parse *, CollSeq *);
  4270   4271   int sqlite3WritableSchema(sqlite3*);
  4271         -int sqlite3CheckObjectName(Parse *, const char *);
         4272  +int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
  4272   4273   void sqlite3VdbeSetChanges(sqlite3 *, int);
  4273   4274   int sqlite3AddInt64(i64*,i64);
  4274   4275   int sqlite3SubInt64(i64*,i64);
  4275   4276   int sqlite3MulInt64(i64*,i64);
  4276   4277   int sqlite3AbsInt32(int);
  4277   4278   #ifdef SQLITE_ENABLE_8_3_NAMES
  4278   4279   void sqlite3FileSuffix3(const char*, char*);

Changes to src/trigger.c.

   173    173       sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
   174    174       goto trigger_cleanup;
   175    175     }
   176    176   
   177    177     /* Check that the trigger name is not reserved and that no trigger of the
   178    178     ** specified name exists */
   179    179     zName = sqlite3NameFromToken(db, pName);
   180         -  if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
          180  +  if( zName==0 ){
          181  +    assert( db->mallocFailed );
          182  +    goto trigger_cleanup;
          183  +  }
          184  +  if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
   181    185       goto trigger_cleanup;
   182    186     }
   183    187     assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   184    188     if( !IN_RENAME_OBJECT ){
   185    189       if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){
   186    190         if( !noErr ){
   187    191           sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);

Changes to src/vdbe.c.

  5959   5959     {
  5960   5960       zMaster = MASTER_NAME;
  5961   5961       initData.db = db;
  5962   5962       initData.iDb = iDb;
  5963   5963       initData.pzErrMsg = &p->zErrMsg;
  5964   5964       initData.mInitFlags = 0;
  5965   5965       zSql = sqlite3MPrintf(db,
  5966         -       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
         5966  +       "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
  5967   5967          db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
  5968   5968       if( zSql==0 ){
  5969   5969         rc = SQLITE_NOMEM_BKPT;
  5970   5970       }else{
  5971   5971         assert( db->init.busy==0 );
  5972   5972         db->init.busy = 1;
  5973   5973         initData.rc = SQLITE_OK;

Changes to test/corruptL.test.

   224    224   |   4080: 01 04 04 03 08 01 13 04 03 08 01 02 03 03 08 09   ................
   225    225   | page 5 offset 16384
   226    226   |      0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00   ................
   227    227   | end crash.txt.db
   228    228   }]} {}
   229    229   
   230    230   do_execsql_test 2.1 {
          231  +  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
   231    232     INSERT INTO t1(b) VALUES(X'a0fee3669f9fddefc5cba913e4225d4b6ce2b04f26b87fad3ee6f9b7d90a1ea62a169bf41e5d32707a6ca5c3d05e4bde05c9d89eaaa8c50e74333d2e9fcd7dfe95528a3a016aac1102d825c5cd70cf99d8a88e0ea7f798d4334386518b7ad359beb168b93aba059a2a3bd93112d65b44c12b9904ea786b204d80531cdf0504bf9b203dbe927061974caf7b9f30cbc3397b61f802e732012a6663d41c3607d6f1c0dbcfd489adac05ca500c0b04439d894cd93a840159225ef73b627e178b9f84b3ffe66cf22a963a8368813ff7961fc47f573211ccec95e0220dcbb3bf429f4a50ba54d7a53784ac51bfef346e6ac8ae0d0e7c3175946e62ba2b');
   232    233   }
   233    234   
   234    235   do_catchsql_test 2.2 {
   235    236     SELECT b,c FROM t1 ORDER BY a;
   236    237   } {1 {database disk image is malformed}}
   237    238   
................................................................................
   373    374   |    464: 05 01 01 09 09 02 02 19 04 05 17 17 17 17 10 65   ...............e
   374    375   |    480: 76 65 6e 65 69 67 68 74 65 40 18 00 00 00 00 01   veneighte@......
   375    376   |    496: 02 03 07 04 01 01 01 03 04 02 05 04 09 01 ff fd   ................
   376    377   | end crash-6b48ba69806134.db
   377    378   }]} {}
   378    379   
   379    380   do_catchsql_test 4.1 {
          381  +  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
   380    382     INSERT INTO t3 SELECT * FROM t2;
   381    383   } {1 {database disk image is malformed}}
   382    384   
   383    385   
   384    386   #-------------------------------------------------------------------------
   385    387   reset_db
   386    388   do_test 5.0 {
................................................................................
   601    603   |   3808: 05 43 52 45 41 54 45 20 49 4e 44 45 58 20 74 31   .CREATE INDEX t1
   602    604   |   3824: 62 20 4f 4e 20 74 31 28 62 29 50 03 06 17 2b 2b   b ON t1(b)P...++
   603    605   |   3840: 01 59 74 61 62 6c 65 73 71 6c 69 74 65 5f 73 65   .Ytablesqlite_se
   604    606   |   3856: 71 75 65 6e 63 65 73 71 6c 69 74 65 5f 73 65 71   quencesqlite_seq
   605    607   |   3872: 75 65 6e 63 65 04 43 52 45 41 54 45 20 54 41 42   uence.CREATE TAB
   606    608   |   3888: 4c 45 20 73 71 6c 69 74 65 5f 73 65 71 75 65 6e   LE sqlite_sequen
   607    609   |   3904: 63 65 28 6e 61 6d 65 2c 73 65 71 29 81 04 01 07   ce(name,seq)....
   608         -|   3920: 17 11 11 01 81 73 74 61 c2 6c 65 74 31 74 31 02   .....sta.let1t1.
          610  +|   3920: 17 11 11 01 81 73 74 61 62 6c 65 74 31 74 31 02   .....stablet1t1.
   609    611   |   3936: 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 31 28   CREATE TABLE t1(
   610    612   |   3952: 61 20 52 45 41 4c 20 4e 4f 54 20 4e 55 4c 4c 20   a REAL NOT NULL 
   611    613   |   3968: 44 45 46 41 55 4c 54 28 32 35 2b 33 32 29 2c 62   DEFAULT(25+32),b
   612    614   |   3984: 20 46 4c 4f 41 54 2c 63 20 44 4f 55 42 4c 45 20    FLOAT,c DOUBLE 
   613    615   |   4000: 55 4e 49 51 55 45 2c 0a 64 20 43 4c 4f 42 2c 65   UNIQUE,.d CLOB,e
   614    616   |   4016: 20 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59    INTEGER PRIMARY
   615    617   |   4032: 20 4b 45 59 20 41 55 54 4f 49 4e 43 52 45 4d 45    KEY AUTOINCREME
................................................................................
   831    833   | page 4 offset 1536
   832    834   |      0: 0d 00 39 00 00 02 00 00 00 00 00 00 00 00 00 00   ..9.............
   833    835   | end a.db
   834    836   }]} {}
   835    837   
   836    838   
   837    839   do_catchsql_test 8.1 {
          840  +  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
   838    841     INSERT INTO t3 SELECT * FROM t2;
   839    842   } {1 {database disk image is malformed}}
   840    843   
   841    844   #-------------------------------------------------------------------------
   842    845   reset_db
   843    846   do_test 9.0 {
   844    847     sqlite3 db {}
................................................................................
  1000   1003   |   2512: 00 00 00 00 00 00 00 96 00 00 00 00 00 00 00 00   ................
  1001   1004   | page 44 offset 176128
  1002   1005   |   2512: 00 00 00 00 00 00 00 00 aa 00 00 00 00 00 00 00   ................
  1003   1006   | end crash-41390d95d613b6.db
  1004   1007   }]} {}
  1005   1008   
  1006   1009   do_catchsql_test 10.1 {
         1010  +  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  1007   1011     SELECT * FROM t1 WHERE a<='2019-05-09' ORDER BY a DESC;
  1008   1012   } {1 {database disk image is malformed}}
  1009   1013   
  1010   1014   
  1011   1015   #-------------------------------------------------------------------------
  1012   1016   reset_db
  1013   1017   do_test 11.0 {
................................................................................
  1053   1057   |     48: 3f 69 33 74 6e 65 78 78 74 64 33 ff 43 52 45 a0   ?i3tnexxtd3.CRE.
  1054   1058   |     64: a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 a0 74 13 11 01   ............t...
  1055   1059   |     80: 49 45 74 00 00 00 00 00 00 00 00 00 00 00 00 00   IEt.............
  1056   1060   | end x.db
  1057   1061   }]} {}
  1058   1062   
  1059   1063   do_catchsql_test 11.1 {
         1064  +  PRAGMA writable_schema=ON; -- bypass improved sqlite_master consistency checking
  1060   1065     DELETE FROM t3 WHERE x IN (SELECT x FROM t4);
  1061   1066   } {1 {database disk image is malformed}}
  1062   1067   
  1063   1068   finish_test

Added test/corruptM.test.

            1  +# 2019-08-12
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# Check to ensure that the type, name, and tbl_name fields of the
           13  +# sqlite_master table are validated and errors are reported if they
           14  +# are inconsistent with the sql.
           15  +#
           16  +
           17  +set testdir [file dirname $argv0]
           18  +source $testdir/tester.tcl
           19  +set testprefix corruptM
           20  +
           21  +# These tests deal with corrupt database files
           22  +#
           23  +database_may_be_corrupt
           24  +
           25  +db close
           26  +forcedelete test.db
           27  +sqlite3 db test.db
           28  +do_execsql_test corruptM-100 {
           29  +  CREATE TABLE t1(a,b,c);
           30  +  INSERT INTO t1 VALUES(111,222,333);
           31  +  CREATE INDEX i1 ON t1(b);
           32  +  CREATE VIEW v2 AS SELECT 15,22;
           33  +  CREATE TRIGGER r1 AFTER INSERT ON t1 BEGIN SELECT 5; END;
           34  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           35  +} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           36  +do_execsql_test corruptM-101 {
           37  +  PRAGMA writable_schema=on;
           38  +  UPDATE sqlite_master SET tbl_name=NULL WHERE name='t1';
           39  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           40  +} {table t1 {} | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           41  +sqlite3 db2 test.db
           42  +do_test corruptM-102 {
           43  +  catchsql {
           44  +    PRAGMA quick_check;
           45  +  } db2
           46  +} {1 {malformed database schema (t1)}}
           47  +db2 close
           48  +
           49  +do_execsql_test corruptM-110 {
           50  +  UPDATE sqlite_master SET tbl_name='tx' WHERE name='t1';
           51  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           52  +} {table t1 tx | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           53  +sqlite3 db2 test.db
           54  +do_test corruptM-111 {
           55  +  catchsql {
           56  +    PRAGMA quick_check;
           57  +  } db2
           58  +} {1 {malformed database schema (t1)}}
           59  +db2 close
           60  +do_execsql_test corruptM-112 {
           61  +  UPDATE sqlite_master SET tbl_name='t1', type='tabl' WHERE name='t1';
           62  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           63  +} {tabl t1 t1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           64  +sqlite3 db2 test.db
           65  +do_test corruptM-113 {
           66  +  catchsql {
           67  +    PRAGMA quick_check;
           68  +  } db2
           69  +} {1 {malformed database schema (t1)}}
           70  +db2 close
           71  +do_execsql_test corruptM-114 {
           72  +  UPDATE sqlite_master SET tbl_name='t9',type='table',name='t9'WHERE name='t1';
           73  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           74  +} {table t9 t9 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           75  +sqlite3 db2 test.db
           76  +do_test corruptM-114 {
           77  +  catchsql {
           78  +    PRAGMA quick_check;
           79  +  } db2
           80  +} {1 {malformed database schema (t9)}}
           81  +db2 close
           82  +
           83  +do_execsql_test corruptM-120 {
           84  +  UPDATE sqlite_master SET name='t1',tbl_name='T1' WHERE name='t9';
           85  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           86  +} {table t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
           87  +sqlite3 db2 test.db
           88  +do_test corruptM-121 {
           89  +  catchsql {
           90  +    PRAGMA quick_check;
           91  +    SELECT * FROM t1, v2;
           92  +  } db2
           93  +} {0 {ok 111 222 333 15 22}}
           94  +db2 close
           95  +
           96  +do_execsql_test corruptM-130 {
           97  +  UPDATE sqlite_master SET type='view' WHERE name='t1';
           98  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
           99  +} {view t1 T1 | index i1 t1 | view v2 v2 | trigger r1 t1 |}
          100  +sqlite3 db2 test.db
          101  +do_test corruptM-131 {
          102  +  catchsql {
          103  +    PRAGMA quick_check;
          104  +    SELECT * FROM t1, v2;
          105  +  } db2
          106  +} {1 {malformed database schema (t1)}}
          107  +db2 close
          108  +
          109  +do_execsql_test corruptM-140 {
          110  +  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='t1';
          111  +  UPDATE sqlite_master SET tbl_name='tx' WHERE name='i1';
          112  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          113  +} {table t1 t1 | index i1 tx | view v2 v2 | trigger r1 t1 |}
          114  +sqlite3 db2 test.db
          115  +do_test corruptM-141 {
          116  +  catchsql {
          117  +    PRAGMA quick_check;
          118  +    SELECT * FROM t1, v2;
          119  +  } db2
          120  +} {1 {malformed database schema (i1)}}
          121  +db2 close
          122  +
          123  +do_execsql_test corruptM-150 {
          124  +  UPDATE sqlite_master SET type='table', tbl_name='t1' WHERE name='i1';
          125  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          126  +} {table t1 t1 | table i1 t1 | view v2 v2 | trigger r1 t1 |}
          127  +sqlite3 db2 test.db
          128  +do_test corruptM-151 {
          129  +  catchsql {
          130  +    PRAGMA quick_check;
          131  +    SELECT * FROM t1, v2;
          132  +  } db2
          133  +} {1 {malformed database schema (i1)}}
          134  +db2 close
          135  +
          136  +do_execsql_test corruptM-160 {
          137  +  UPDATE sqlite_master SET type='view', tbl_name='t1' WHERE name='i1';
          138  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          139  +} {table t1 t1 | view i1 t1 | view v2 v2 | trigger r1 t1 |}
          140  +sqlite3 db2 test.db
          141  +do_test corruptM-161 {
          142  +  catchsql {
          143  +    PRAGMA quick_check;
          144  +    SELECT * FROM t1, v2;
          145  +  } db2
          146  +} {1 {malformed database schema (i1)}}
          147  +db2 close
          148  +
          149  +do_execsql_test corruptM-170 {
          150  +  UPDATE sqlite_master SET type='index', tbl_name='t1' WHERE name='i1';
          151  +  UPDATE sqlite_master SET type='table', tbl_name='v2' WHERE name='v2';
          152  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          153  +} {table t1 t1 | index i1 t1 | table v2 v2 | trigger r1 t1 |}
          154  +sqlite3 db2 test.db
          155  +do_test corruptM-171 {
          156  +  catchsql {
          157  +    PRAGMA quick_check;
          158  +    SELECT * FROM t1, v2;
          159  +  } db2
          160  +} {1 {malformed database schema (v2)}}
          161  +db2 close
          162  +
          163  +do_execsql_test corruptM-180 {
          164  +  UPDATE sqlite_master SET type='view',name='v3',tbl_name='v3' WHERE name='v2';
          165  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          166  +} {table t1 t1 | index i1 t1 | view v3 v3 | trigger r1 t1 |}
          167  +sqlite3 db2 test.db
          168  +do_test corruptM-181 {
          169  +  catchsql {
          170  +    PRAGMA quick_check;
          171  +    SELECT * FROM t1, v2;
          172  +  } db2
          173  +} {1 {malformed database schema (v3)}}
          174  +db2 close
          175  +
          176  +do_execsql_test corruptM-190 {
          177  +  UPDATE sqlite_master SET type='view',name='v2',tbl_name='v2' WHERE name='v3';
          178  +  UPDATE sqlite_master SET type='view' WHERE name='r1';
          179  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          180  +} {table t1 t1 | index i1 t1 | view v2 v2 | view r1 t1 |}
          181  +sqlite3 db2 test.db
          182  +do_test corruptM-191 {
          183  +  catchsql {
          184  +    PRAGMA quick_check;
          185  +    SELECT * FROM t1, v2;
          186  +  } db2
          187  +} {1 {malformed database schema (r1)}}
          188  +db2 close
          189  +do_execsql_test corruptM-192 {
          190  +  UPDATE sqlite_master SET type='trigger',tbl_name='v2' WHERE name='r1';
          191  +  SELECT type, name, tbl_name, '|' FROM sqlite_master;
          192  +} {table t1 t1 | index i1 t1 | view v2 v2 | trigger r1 v2 |}
          193  +sqlite3 db2 test.db
          194  +do_test corruptM-193 {
          195  +  catchsql {
          196  +    PRAGMA quick_check;
          197  +    SELECT * FROM t1, v2;
          198  +  } db2
          199  +} {1 {malformed database schema (r1)}}
          200  +db2 close
          201  +
          202  +finish_test

Changes to test/dbfuzz001.test.

   301    301   |    320: 41 54 45 20 49 4e 44 45 58 20 74 33 78 20 4f 4e   ATE INDEX t3x ON
   302    302   |    336: 20 74 33 28 78 29 2e 04 06 17 15 11 01 45 69 6e    t3(x).......Ein
   303    303   |    352: 64 65 78 74 32 63 64 74 32 05 43 52 45 41 54 45   dext2cdt2.CREATE
   304    304   |    368: 20 49 4e 44 45 58 20 74 32 63 64 20 4f 4e 20 74    INDEX t2cd ON t
   305    305   |    384: 32 28 63 2c 64 29 28 05 06 17 11 11 01 3d 74 61   2(c,d)(......=ta
   306    306   |    400: 62 6c 65 74 33 74 33 07 43 52 45 41 54 45 20 54   blet3t3.CREATE T
   307    307   |    416: 41 42 4c 45 20 74 33 28 63 2c 78 2c 65 2c 66 29   ABLE t3(c,x,e,f)
   308         -|    432: 28 02 06 17 11 11 01 3d 74 61 74 65 6c 03 62 74   (......=tatel.bt
          308  +|    432: 28 02 06 17 11 11 01 3d 74 61 62 6c 65 74 32 74   (......=tablet2t
   309    309   |    448: 32 32 43 52 45 41 54 45 20 54 41 42 4c 45 20 74   22CREATE TABLE t
   310    310   |    464: 32 28 63 2c 64 2c 65 2c 66 29 24 01 06 17 11 11   2(c,d,e,f)$.....
   311    311   |    480: 01 35 74 61 62 6c 65 74 31 74 31 02 43 52 45 41   .5tablet1t1.CREA
   312    312   |    496: 54 45 20 54 41 42 4c 45 20 74 31 28 61 2c 62 29   TE TABLE t1(a,b)
   313    313   | page 2 offset 512
   314    314   |      0: 0d 00 00 00 04 01 cf 00 01 fa 01 f3 01 de 01 cf   ................
   315    315   |    160: 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00   .. .............