/ Check-in [70390bbc]
Login

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

Overview
Comment:Do not allow shadow tables to be dropped in defensive mode.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 70390bbca49e706649ca5b7c031f0baf416fc38798c17e5f3b73746b3e66e3b5
User & Date: drh 2019-11-16 12:04:38
Context
2019-11-16
18:36
Do not allow shadow tables to be dropped in defensive mode. Leaf check-in: 0a988ce3 user: drh tags: apple-osx
16:54
More restrictions on changes to shadow tables when in defensive mode. check-in: bae76a5c user: drh tags: trunk
13:51
Break out the test for writable shadow tables into a separate subroutine. check-in: 8ad34d36 user: drh tags: defensive-improvements
12:04
Do not allow shadow tables to be dropped in defensive mode. check-in: 70390bbc user: drh tags: trunk
11:33
Fix a potential NULL pointer dereference on a RENAME TABLE that references a VIEW with a logic error in a window function in the ORDER BY clause. check-in: 0adb273f user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

2889
2890
2891
2892
2893
2894
2895
















2896
2897
2898
2899
2900
2901
2902
....
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
    sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
  sqlite3ChangeCookie(pParse, iDb);
  sqliteViewResetAll(db, iDb);
}

















/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
................................................................................
      goto exit_drop_table;
    }
    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
      goto exit_drop_table;
    }
  }
#endif
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
    && sqlite3StrNICmp(pTab->zName+7, "stat", 4)!=0
    && sqlite3StrNICmp(pTab->zName+7, "parameters", 10)!=0 ){
    sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
    goto exit_drop_table;
  }

#ifndef SQLITE_OMIT_VIEW
  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
  ** on a table.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
<
<







2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
....
2975
2976
2977
2978
2979
2980
2981
2982


2983
2984
2985
2986
2987
2988
2989
    sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
    sqlite3MayAbort(pParse);
  }
  sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
  sqlite3ChangeCookie(pParse, iDb);
  sqliteViewResetAll(db, iDb);
}

/*
** Return true if it is not allowed to drop the given table
*/
static int tableMayNotBeDropped(Parse *pParse, Table *pTab){
  if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
    if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
    if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
    return 1;
  }
  if( pTab->tabFlags & TF_Shadow ){
    sqlite3 *db = pParse->db;
    if( (db->flags & SQLITE_Defensive)!=0 && db->nVdbeExec==0 ) return 1;
  }
  return 0;
}

/*
** This routine is called to do the work of a DROP TABLE statement.
** pName is the name of the table to be dropped.
*/
void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
  Table *pTab;
................................................................................
      goto exit_drop_table;
    }
    if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){
      goto exit_drop_table;
    }
  }
#endif
  if( tableMayNotBeDropped(pParse, pTab) ){


    sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
    goto exit_drop_table;
  }

#ifndef SQLITE_OMIT_VIEW
  /* Ensure DROP TABLE is not used on a view, and DROP VIEW is not used
  ** on a table.

Changes to test/altertab.test.

538
539
540
541
542
543
544
545
546
547
548
549
550
551
552




553
554
555
556
557
558
559
560
561
562
563
564

  sqlite3_db_config db DEFENSIVE 1

  do_execsql_test 16.0 {
    CREATE VIRTUAL TABLE y1 USING fts3;
  }

  do_catchsql_test 16.1 {
    INSERT INTO y1_segments VALUES(1, X'1234567890');
  } {1 {table y1_segments may not be modified}}

  do_catchsql_test 16.2 {
    ALTER TABLE y1_segments RENAME TO abc;
  } {1 {table y1_segments may not be altered}}





  do_execsql_test 16.3 {
    ALTER TABLE y1 RENAME TO z1;
  }

  do_execsql_test 16.4 {
    SELECT * FROM z1_segments;
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 17.0 {







|



|



>
>
>
>
|



|







538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568

  sqlite3_db_config db DEFENSIVE 1

  do_execsql_test 16.0 {
    CREATE VIRTUAL TABLE y1 USING fts3;
  }

  do_catchsql_test 16.10 {
    INSERT INTO y1_segments VALUES(1, X'1234567890');
  } {1 {table y1_segments may not be modified}}

  do_catchsql_test 16.20 {
    ALTER TABLE y1_segments RENAME TO abc;
  } {1 {table y1_segments may not be altered}}

  do_catchsql_test 16.21 {
    DROP TABLE y1_segments;
  } {1 {table y1_segments may not be dropped}}

  do_execsql_test 16.30 {
    ALTER TABLE y1 RENAME TO z1;
  }

  do_execsql_test 16.40 {
    SELECT * FROM z1_segments;
  }
}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 17.0 {