Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix a case where database corruption may cause SQLite to write past the end of a buffer. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
97806a78142b15f89878e25ee70dc5b0 |
User & Date: | dan 2015-05-25 17:07:29.779 |
References
2015-05-26
| ||
17:33 | Add a cast to one side of the test added by [97806a78] in order to avoid a signed/unsigned comparison warning. (check-in: 5b46d2a78a user: dan tags: trunk) | |
Context
2015-05-25
| ||
18:48 | First code for a new utility program to rerun checks on a large number of fuzzer-generated test cases. (check-in: c5b4e36352 user: drh tags: fuzzcheck) | |
18:47 | Fix a couple of btree asserts that would fail when encountering 32-bit rollover in cell payload size fields (cell payloads this large always indicate corruption). (check-in: 8fa0937a2f user: dan tags: trunk) | |
17:07 | Fix a case where database corruption may cause SQLite to write past the end of a buffer. (check-in: 97806a7814 user: dan tags: trunk) | |
15:03 | Fix an assert() in btree routine freeSpace() that may be false if the database is corrupt. (check-in: 00a473c561 user: dan tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
1339 1340 1341 1342 1343 1344 1345 | assert( gap<=65536 ); /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size ** and the reserved space is zero (the usual value for reserved space) ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ top = get2byteNotZero(&data[hdr+5]); | | | 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | assert( gap<=65536 ); /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size ** and the reserved space is zero (the usual value for reserved space) ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ top = get2byteNotZero(&data[hdr+5]); if( gap>top || top>pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT; /* If there is enough space between gap and top for one more cell pointer ** array entry offset, and if the freelist is not empty, then search the ** freelist looking for a free slot big enough to satisfy the request. */ testcase( gap+2==top ); testcase( gap+1==top ); |
︙ | ︙ |
Changes to test/corruptI.test.
︙ | ︙ | |||
126 127 128 129 130 131 132 133 134 | do_test 4.1 { db close hexio_write test.db [expr $offset + 8 + 2] 0000 hexio_write test.db [expr $offset + 5] 0000 sqlite3 db test.db execsql { DELETE FROM t1 WHERE a=0 } } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | do_test 4.1 { db close hexio_write test.db [expr $offset + 8 + 2] 0000 hexio_write test.db [expr $offset + 5] 0000 sqlite3 db test.db execsql { DELETE FROM t1 WHERE a=0 } } {} #------------------------------------------------------------------------- # Database properties: # # * Incremental vacuum mode. # * Database root table has a single leaf page. # * Free list consists of a single trunk page. # # The db is then corrupted by adding the root table leaf page as a free-list # leaf page (so that it is referenced twice). # # Then, a new table is created. The new root page is the current free-list # trunk. This means that the root table leaf page is made into the new # free list trunk, which corrupts its header. Then, when the new entry is # inserted into the root table, things would get chaotic. # reset_db do_test 5.0 { execsql { PRAGMA page_size = 512; PRAGMA auto_vacuum = 2; } for {set i 3} {1} {incr i} { execsql "CREATE TABLE t${i}(x)" if {[db one {PRAGMA page_count}]>$i} break } set nPage [db one {PRAGMA page_count}] execsql { CREATE TABLE t100(x); DROP TABLE t100; } } {} do_execsql_test 5.1 { PRAGMA page_count } [expr $nPage+1] do_test 5.2 { # The last page of the db is now the only leaf of the sqlite_master table. # Corrupt the db by adding it to the free-list as well (the second last # page of the db is the free-list trunk). db close hexio_write test.db [expr 512*($nPage-1)] [ format "%.8X%.8X%.8X" 0 1 [expr $nPage+1] ] } {12} do_test 5.3 { sqlite3 db test.db catchsql { CREATE TABLE tx(x); } } {1 {database disk image is malformed}} finish_test |