File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sqlite3 / test / corruptD.test
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 17:04:16 2012 UTC (12 years, 4 months ago) by misho
Branches: sqlite3, MAIN
CVS tags: v3_7_10, HEAD
sqlite3

    1: # 2009 June 3
    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: # $Id: corruptD.test,v 1.1.1.1 2012/02/21 17:04:16 misho Exp $
   13: 
   14: set testdir [file dirname $argv0]
   15: source $testdir/tester.tcl
   16: 
   17: # Do not use a codec for tests in this file, as the database file is
   18: # manipulated directly using tcl scripts (using the [hexio_write] command).
   19: #
   20: do_not_use_codec
   21: 
   22: #--------------------------------------------------------------------------
   23: # OVERVIEW
   24: #
   25: #   This test file attempts to verify that SQLite does not read past the 
   26: #   end of any in-memory buffers as a result of corrupted database page 
   27: #   images. Usually this happens because a field within a database page
   28: #   that contains an offset to some other structure within the same page
   29: #   is set to too large a value. A database page contains the following
   30: #   such fields:
   31: #
   32: #     1. The page header field that contains the offset to the first 
   33: #        free block of space.
   34: #
   35: #     2. The first two bytes of all but the last free block on the free-block
   36: #        list (the offset to the next free block).
   37: #
   38: #     3. The page header field containing the number of cells on the page
   39: #        (implicitly defines the offset to the final element in the cell offset
   40: #        array, which could potentially be off the end of the page).
   41: #
   42: #     4. The page header field containing the offset to the start of the cell
   43: #        content area.
   44: #
   45: #     5. The contents of the cell offset array.
   46: #
   47: #     6. The first few bytes of each cell determine the size of the cell
   48: #        stored within the page, and hence the offset to the final byte of
   49: #        the cell.
   50: #
   51: #   If any of the above fields are set to too large a value, then a buffer
   52: #   overread may occur. This test script creates and operates on various
   53: #   strategically corrupted database files to attempt to provoke such buffer
   54: #   overreads.
   55: #
   56: #   Very often, a buffer overread passes unnoticed, particularly in workstation
   57: #   environments. For this reason, this test script should be run using valgrind
   58: #   (or similar) in order to verify that no overreads occur.
   59: #
   60: # TEST PLAN
   61: # 
   62: #   Test cases corruptD-1.* are white-box tests. They attempt to corrupt
   63: #   one of the above fields, then exercise each part of the code in btree.c
   64: #   that uses said field.
   65: #   
   66: #   Offset variables 1, 2, 3 and 4 are all checked to make sure they
   67: #   will not result in buffer overruns as part of page initialization in
   68: #   sqlite3BtreeInitPage(). Offsets 5 and 6 cannot be tested as part of
   69: #   page initialization, as trying to do so causes a performance hit.
   70: #
   71: 
   72: do_test corruptD-1.0 {
   73:   execsql { 
   74:     PRAGMA auto_vacuum = 0;
   75:     PRAGMA page_size = 1024;
   76:     CREATE TABLE t1(a, b);
   77:     CREATE INDEX i1 ON t1(a, b);
   78:   }
   79:   for {set ii 1} {$ii < 50} {incr ii} {
   80:     execsql { INSERT INTO t1 VALUES($ii, $ii * $ii) }
   81:   }
   82:   execsql {
   83:     DELETE FROM t1 WHERE a = 10;
   84:     DELETE FROM t1 WHERE a = 20;
   85:     DELETE FROM t1 WHERE a = 30;
   86:     DELETE FROM t1 WHERE a = 40;
   87:   }
   88:   forcecopy test.db test.bu
   89: } {}
   90: 
   91: proc incr_change_counter {} {
   92:   hexio_write test.db 24 [
   93:     hexio_render_int32 [expr [hexio_get_int [hexio_read test.db 24 4]] + 1]
   94:   ]
   95: }
   96: 
   97: proc restore_file {} {
   98:   db close
   99:   forcecopy test.bu test.db
  100:   sqlite3 db test.db
  101: }
  102: 
  103: #-------------------------------------------------------------------------
  104: # The following tests, corruptD-1.1.*, focus on the page header field
  105: # containing the offset of the first free block in a page. 
  106: #
  107: do_test corruptD-1.1.1 {
  108:   incr_change_counter
  109:   hexio_write test.db [expr 1024+1] FFFF
  110:   catchsql { SELECT * FROM t1 }
  111: } {1 {database disk image is malformed}}
  112: do_test corruptD-1.1.2 {
  113:   incr_change_counter
  114:   hexio_write test.db [expr 1024+1] [hexio_render_int32 1021]
  115:   catchsql { SELECT * FROM t1 }
  116: } {1 {database disk image is malformed}}
  117: 
  118: #-------------------------------------------------------------------------
  119: # The following tests, corruptD-1.2.*, focus on the offsets contained
  120: # in the first 2 byte of each free-block on the free-list.
  121: #
  122: do_test corruptD-1.2.1 {
  123:   restore_file
  124: } {}
  125: do_test corruptD-1.2.2 {
  126: } {}
  127: 
  128: #-------------------------------------------------------------------------
  129: # The following tests, corruptD-1.4.*, ...
  130: #
  131: 
  132: 
  133: #-------------------------------------------------------------------------
  134: # The following tests, corruptD-1.5.*, focus on the offsets contained
  135: # in the cell offset array.
  136: # 
  137: #   defragmentPage
  138: #
  139: 
  140: finish_test

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