github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/corruptH.test (about)

     1  # 2014-01-20
     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  
    13  set testdir [file dirname $argv0]
    14  source $testdir/tester.tcl
    15  set testprefix corruptH
    16  
    17  # This module uses hard-coded offsets which do not work if the reserved_bytes
    18  # value is nonzero.
    19  if {[nonzero_reserved_bytes]} {finish_test; return;}
    20  
    21  database_may_be_corrupt
    22  
    23  # The corruption migrations tested by the code in this file are not detected
    24  # mmap mode.
    25  #
    26  # The reason is that in mmap mode, the different queries may use different
    27  # PgHdr objects for the same page (same data, but different PgHdr container 
    28  # objects). And so the corruption is not detected. 
    29  #
    30  if {[permutation]=="mmap"} {
    31    finish_test
    32    return
    33  }
    34  
    35  # Initialize the database.
    36  #
    37  do_execsql_test 1.1 {
    38    PRAGMA page_size=1024;
    39  
    40    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    41    INSERT INTO t1 VALUES(1, 'one');
    42    INSERT INTO t1 VALUES(2, 'two');
    43  
    44    CREATE TABLE t2(x);
    45    INSERT INTO t2 VALUES(randomblob(200));
    46    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    47    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    48    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    49    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    50    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    51    INSERT INTO t2 SELECT randomblob(200) FROM t2;
    52  } {}
    53  
    54  # Corrupt the file so that the root page of t1 is also linked into t2 as
    55  # a leaf page.
    56  #
    57  do_test 1.2 {
    58    db eval { SELECT name, rootpage FROM sqlite_master } { 
    59      set r($name) $rootpage 
    60    }
    61    db close
    62    hexio_write test.db [expr {($r(t2)-1)*1024 + 11}] [format %.2X $r(t1)]
    63    sqlite3 db test.db
    64  } {}
    65  
    66  do_test 1.3 {
    67    db eval { PRAGMA secure_delete=1 }
    68    list [catch {
    69      db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
    70        db eval { DELETE FROM t2 }
    71      }
    72    } msg] $msg
    73  } {1 {database disk image is malformed}}
    74  
    75  #-------------------------------------------------------------------------
    76  reset_db
    77  
    78  # Initialize the database.
    79  #
    80  do_execsql_test 2.1 {
    81    PRAGMA auto_vacuum=0;
    82    PRAGMA page_size=1024;
    83  
    84    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
    85    INSERT INTO t1 VALUES(1, 'one');
    86    INSERT INTO t1 VALUES(2, 'two');
    87  
    88    CREATE TABLE t3(x);
    89  
    90    CREATE TABLE t2(x PRIMARY KEY) WITHOUT ROWID;
    91    INSERT INTO t2 VALUES(randomblob(100));
    92  
    93    DROP TABLE t3;
    94  } {}
    95  
    96  do_test 2.2 {
    97    db eval { SELECT name, rootpage FROM sqlite_master } { 
    98      set r($name) $rootpage 
    99    }
   100    db close
   101    set fl [hexio_get_int [hexio_read test.db 32 4]]
   102  
   103    hexio_write test.db [expr {($fl-1) * 1024 + 0}] 00000000 
   104    hexio_write test.db [expr {($fl-1) * 1024 + 4}] 00000001 
   105    hexio_write test.db [expr {($fl-1) * 1024 + 8}] [format %.8X $r(t1)]
   106    hexio_write test.db 36 00000002
   107  
   108    sqlite3 db test.db
   109  } {}
   110  
   111  
   112  # The trick here is that the root page of the tree scanned by the outer 
   113  # query is also currently on the free-list. So while the first seek on
   114  # the table (for a==1) works, by the time the second is attempted The 
   115  # "INSERT INTO t2..." statements have recycled the root page of t1 and
   116  # used it as an index leaf. Normally, BtreeMovetoUnpacked() detects
   117  # that the PgHdr object associated with said root page does not match
   118  # the cursor (as it is now marked with PgHdr.intKey==0) and returns
   119  # SQLITE_CORRUPT. 
   120  #
   121  set res23 {1 {database disk image is malformed}}
   122  do_test 2.3 {
   123    list [catch {
   124    set res [list]
   125    db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
   126      db eval { 
   127        INSERT INTO t2 SELECT randomblob(100) FROM t2;
   128        INSERT INTO t2 SELECT randomblob(100) FROM t2;
   129        INSERT INTO t2 SELECT randomblob(100) FROM t2;
   130        INSERT INTO t2 SELECT randomblob(100) FROM t2;
   131        INSERT INTO t2 SELECT randomblob(100) FROM t2;
   132      }
   133      lappend res $b
   134    }
   135    set res
   136    } msg] $msg
   137  } $res23
   138  
   139  #-------------------------------------------------------------------------
   140  reset_db
   141  
   142  # Initialize the database.
   143  #
   144  do_execsql_test 3.1 {
   145    PRAGMA page_size=1024;
   146  
   147    CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
   148    INSERT INTO t1 VALUES(1, 'one');
   149    INSERT INTO t1 VALUES(2, 'two');
   150  
   151    CREATE TABLE t2(c INTEGER PRAGMA KEY, d);
   152    INSERT INTO t2 VALUES(1, randomblob(1100));
   153  } {}
   154  
   155  do_test 3.2 {
   156    db eval { SELECT name, rootpage FROM sqlite_master } { 
   157      set r($name) $rootpage 
   158    }
   159    db close
   160  
   161    hexio_write test.db [expr {($r(t2)-1) * 1024 + 1020}] 00000002
   162  
   163    sqlite3 db test.db
   164  } {}
   165  
   166  do_test 3.3 {
   167    list [catch {
   168    db eval { SELECT * FROM t1 WHERE a IN (1, 2) } {
   169      db eval { 
   170        DELETE FROM t2 WHERE c=1;
   171      }
   172    }
   173    } msg] $msg
   174  } {1 {database disk image is malformed}}
   175  
   176  finish_test