gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/corrupt4.test (about)

     1  # 2007 Sept 7
     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  # This file implements regression tests for SQLite library.
    12  #
    13  # This file implements tests to make sure SQLite does not crash or
    14  # segfault if it sees a corrupt database file.
    15  #
    16  
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  set testprefix corrupt4
    20  
    21  # This module uses hard-coded offsets which do not work if the reserved_bytes
    22  # value is nonzero.
    23  if {[nonzero_reserved_bytes]} {finish_test; return;}
    24  
    25  # These tests deal with corrupt database files
    26  #
    27  database_may_be_corrupt
    28  
    29  # We must have the page_size pragma for these tests to work.
    30  #
    31  ifcapable !pager_pragmas {
    32    finish_test
    33    return
    34  }
    35  
    36  # Create a database with a freelist containing at least two pages.
    37  #
    38  do_test corrupt4-1.1 {
    39    set bigstring [string repeat 0123456789 200]
    40    execsql {
    41      PRAGMA auto_vacuum=OFF;
    42      PRAGMA page_size=1024;
    43      CREATE TABLE t1(x);
    44      INSERT INTO t1 VALUES($bigstring);
    45      CREATE TABLE t2(y);
    46      INSERT INTO t2 VALUES(1);
    47      DROP TABLE t1;
    48    }
    49    file size test.db
    50  } [expr {1024*4}]
    51  
    52  # Verify that there are two pages on the freelist.
    53  #
    54  do_test corrupt4-1.2 {
    55    execsql {PRAGMA freelist_count}
    56  } {2}
    57  
    58  # Get the page number for the trunk of the freelist.
    59  #
    60  set trunkpgno [hexio_get_int [hexio_read test.db 32 4]]
    61  set baseaddr [expr {($trunkpgno-1)*1024}]
    62  
    63  # Verify that the trunk of the freelist has exactly one
    64  # leaf.
    65  #
    66  do_test corrupt4-1.3 {
    67    hexio_get_int [hexio_read test.db [expr {$::baseaddr+4}] 4]
    68  } {1}
    69  
    70  # Insert a negative number as the number of leaves on the trunk.
    71  # Then try to add a new element to the freelist.
    72  #
    73  do_test corrupt4-1.4 {
    74    hexio_write test.db [expr {$::baseaddr+4}] [hexio_render_int32 -100000000]
    75    db close
    76    sqlite3 db test.db
    77    catchsql {
    78      DROP TABLE t2
    79    }
    80  } {1 {database disk image is malformed}}
    81  
    82  #-------------------------------------------------------------------------
    83  
    84  reset_db
    85  do_execsql_test 2.0 {
    86    PRAGMA page_size = 512;
    87    CREATE TABLE t1(a, b, c);
    88  }
    89  
    90  # Create a database with a schema so large that the root of the 
    91  # sqlite_schema table is the grandparent of its leaves.
    92  #
    93  set nView 1000
    94  do_test 2.1 {
    95    execsql BEGIN
    96    for {set ii 0} {$ii<$nView} {incr ii} {
    97      execsql " CREATE VIEW v$ii AS SELECT a, b, c FROM t1 "
    98    }
    99    execsql COMMIT
   100  } {}
   101  db close
   102  
   103  proc get2byte {fd offset} {
   104    seek $fd $offset
   105    set bin [read $fd 2]
   106    binary scan $bin S val
   107    set val
   108  }
   109  proc get4byte {fd offset} {
   110    seek $fd $offset
   111    set bin [read $fd 4]
   112    binary scan $bin I val
   113    set val
   114  }
   115  proc put4byte {fd offset val} {
   116    seek $fd $offset
   117    set bin [binary format I $val]
   118    puts -nonewline $fd $bin
   119  }
   120  
   121  # Page 1 is now the grandparent of its leaves. Corrupt the database by setting 
   122  # the second rightmost child page number of page 1 to 1.
   123  #
   124  set fd [open test.db r+]
   125  fconfigure $fd -encoding binary -translation binary
   126  set nChild [get2byte $fd 103]
   127  set offChild [get2byte $fd [expr 100+12+($nChild-2)*2]]
   128  set pgnoChild [get4byte $fd $offChild]
   129  put4byte $fd $offChild 1
   130  close $fd
   131  
   132  if {![info exists ::G(perm:presql)]} {
   133    sqlite3 db test.db
   134  
   135    do_catchsql_test 2.2 {
   136      PRAGMA writable_schema = 1;
   137      SELECT * FROM sqlite_schema;
   138    } {1 {database disk image is malformed}}
   139  
   140    do_test 2.3 {
   141      list [catch {
   142        for {set ii $nView} {$ii<$nView*2} {incr ii} {
   143          execsql "INSERT INTO sqlite_master VALUES(1, 2, 3, 4, 5)"
   144        }
   145      } msg] $msg
   146    } {1 {database disk image is malformed}}
   147  }
   148  
   149  finish_test