Annotation of embedaddon/sqlite3/test/fuzz3.test, revision 1.1.1.1

1.1       misho       1: # 2007 May 10
                      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.  The focus
                     12: # of this file is checking the libraries response to subtly corrupting
                     13: # the database file by changing the values of pseudo-randomly selected
                     14: # bytes.
                     15: #
                     16: # $Id: fuzz3.test,v 1.3 2009/01/05 17:19:03 drh Exp $
                     17: 
                     18: set testdir [file dirname $argv0]
                     19: source $testdir/tester.tcl
                     20: 
                     21: 
                     22: expr srand(123)
                     23: 
                     24: proc rstring {n} {
                     25:   set str s
                     26:   while {[string length $str] < $n} {
                     27:     append str [expr rand()]
                     28:   }
                     29:   return [string range $str 0 $n]
                     30: }
                     31: 
                     32: # Return a randomly generated SQL literal.
                     33: #
                     34: proc rvalue {} {
                     35:   switch -- [expr int(rand()*5)] {
                     36:     0 { # SQL NULL value.
                     37:       return NULL 
                     38:     }
                     39:     1 { # Integer value.
                     40:       return [expr int(rand()*1024)] 
                     41:     }
                     42:     2 { # Real value.
                     43:       return [expr rand()] 
                     44:     }
                     45:     3 { # String value.
                     46:       set n [expr int(rand()*2500)]
                     47:       return "'[rstring $n]'"
                     48:     }
                     49:     4 { # Blob value.
                     50:       set n [expr int(rand()*2500)]
                     51:       return "CAST('[rstring $n]' AS BLOB)"
                     52:     }
                     53:   }
                     54: }
                     55: 
                     56: proc db_checksum {} {
                     57:   set    cksum [execsql { SELECT md5sum(a, b, c) FROM t1 }]
                     58:   append cksum [execsql { SELECT md5sum(d, e, f) FROM t2 }]
                     59:   set cksum
                     60: }
                     61: 
                     62: # Modify a single byte in the file 'test.db' using tcl IO commands. The
                     63: # argument value, which must be an integer, determines both the offset of
                     64: # the byte that is modified, and the value that it is set to. The lower
                     65: # 8 bits of iMod determine the new byte value. The offset of the byte
                     66: # modified is the value of ($iMod >> 8).
                     67: #
                     68: # The return value is the iMod value required to restore the file
                     69: # to its original state. The command:
                     70: #
                     71: #   modify_database [modify_database $x]
                     72: #
                     73: # leaves the file in the same state as it was in at the start of the
                     74: # command (assuming that the file is at least ($x>>8) bytes in size).
                     75: #
                     76: proc modify_database {iMod} {
                     77:   set blob [binary format c [expr {$iMod&0xFF}]]
                     78:   set offset [expr {$iMod>>8}]
                     79: 
                     80:   set fd [open test.db r+]
                     81:   fconfigure $fd -encoding binary -translation binary
                     82:   seek $fd $offset
                     83:   set old_blob [read $fd 1]
                     84:   seek $fd $offset
                     85:   puts -nonewline $fd $blob
                     86:   close $fd
                     87: 
                     88:   binary scan $old_blob c iOld
                     89:   return [expr {($offset<<8) + ($iOld&0xFF)}]
                     90: }
                     91: 
                     92: proc purge_pcache {} {
                     93:   ifcapable !memorymanage {
                     94:     db close
                     95:     sqlite3 db test.db
                     96:   } else {
                     97:     sqlite3_release_memory 10000000
                     98:   }
                     99:   if {[lindex [pcache_stats] 1] != 0} {
                    100:     error "purge_pcache failed: [pcache_stats]"
                    101:   }
                    102: }
                    103: 
                    104: # This block creates a database to work with. 
                    105: #
                    106: do_test fuzz3-1 {
                    107:   execsql {
                    108:     BEGIN;
                    109:     CREATE TABLE t1(a, b, c);
                    110:     CREATE TABLE t2(d, e, f);
                    111:     CREATE INDEX i1 ON t1(a, b, c);
                    112:     CREATE INDEX i2 ON t2(d, e, f);
                    113:   }
                    114:   for {set i 0} {$i < 50} {incr i} {
                    115:     execsql "INSERT INTO t1 VALUES([rvalue], [rvalue], [rvalue])"
                    116:     execsql "INSERT INTO t2 VALUES([rvalue], [rvalue], [rvalue])"
                    117:   }
                    118:   execsql COMMIT
                    119: } {}
                    120: 
                    121: set ::cksum [db_checksum]
                    122: do_test fuzz3-2 {
                    123:   db_checksum
                    124: } $::cksum
                    125: 
                    126: for {set ii 0} {$ii < 5000} {incr ii} {
                    127:   purge_pcache
                    128: 
                    129:   # Randomly modify a single byte of the database file somewhere within
                    130:   # the first 100KB of the file.
                    131:   set iNew [expr int(rand()*5*1024*256)]
                    132:   set iOld [modify_database $iNew]
                    133: 
                    134:   set iTest 0
                    135:   foreach sql {
                    136:     {SELECT * FROM t2 ORDER BY d}      
                    137:     {SELECT * FROM t1}                 
                    138:     {SELECT * FROM t2}                 
                    139:     {SELECT * FROM t1 ORDER BY a}      
                    140:     {SELECT * FROM t1 WHERE a = (SELECT a FROM t1 WHERE rowid=25)} 
                    141:     {SELECT * FROM t2 WHERE d = (SELECT d FROM t2 WHERE rowid=1)}  
                    142:     {SELECT * FROM t2 WHERE d = (SELECT d FROM t2 WHERE rowid=50)} 
                    143:     {PRAGMA integrity_check}           
                    144:   } {
                    145:     do_test fuzz3-$ii.$iNew.[incr iTest] {
                    146:       foreach {rc msg} [catchsql $sql] {}
                    147:       if {$rc == 0 
                    148:        || $msg eq "database or disk is full"
                    149:        || $msg eq "database disk image is malformed"
                    150:        || $msg eq "file is encrypted or is not a database"
                    151:        || [string match "malformed database schema*" $msg]
                    152:       } {
                    153:         set msg ok
                    154:       }
                    155:       set msg
                    156:     } {ok}
                    157:   }
                    158: 
                    159:   # Restore the original database file content. Test that the correct 
                    160:   # checksum is now returned.
                    161:   #
                    162:   purge_pcache
                    163:   modify_database $iOld
                    164:   do_test fuzz3-$ii.$iNew.[incr iTest] {
                    165:     db_checksum
                    166:   } $::cksum
                    167: }
                    168: 
                    169: finish_test

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>