Changes to pragma integrity_check to check rowid order. Tests of same in corruptE.test.
FossilOrigin-Name: cae47c5b09cb122689bcb020a66ce14982cc4aa8
This commit is contained in:
parent
3f28070109
commit
195475d839
27
manifest
27
manifest
@ -1,8 +1,5 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Add\sa\snew,\sexperimental\slogging\sinterface\sdesigned\sto\said\sin\sdebugging\sof\ndeeply\sembedded\sprojects\sthat\suse\sSQLite.
|
||||
D 2010-02-18T18:45:10
|
||||
C Changes\sto\spragma\sintegrity_check\sto\scheck\srowid\sorder.\s\sTests\sof\ssame\sin\scorruptE.test.
|
||||
D 2010-02-19T04:28:09
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -112,7 +109,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 744e98359dfc79fed43e8dec911e33e108b06aae
|
||||
F src/bitvec.c 06ad2c36a9c3819c0b9cbffec7b15f58d5d834e0
|
||||
F src/btmutex.c 96a12f50f7a17475155971a241d85ec5171573ff
|
||||
F src/btree.c c9ee3c30fbf21ebb4f45c244bd47d7999e6f2704
|
||||
F src/btree.c b7ac4420d10662259ad3421145eab16a279f5bd3
|
||||
F src/btree.h 0e193b7e90f1d78b79c79474040e3d66a553a4fa
|
||||
F src/btreeInt.h 71ed5e7f009caf17b7dc304350b3cb64b5970135
|
||||
F src/build.c 81412e0f3cabd0cc7a71a1644c46d9ccad9613f5
|
||||
@ -300,13 +297,14 @@ F test/corrupt3.test 263e8bb04e2728df832fddf6973cf54c91db0c32
|
||||
F test/corrupt4.test acdb01afaedf529004b70e55de1a6f5a05ae7fff
|
||||
F test/corrupt5.test c23da7bfb20917cc7fdbb13ee25c7cc4e9fffeff
|
||||
F test/corrupt6.test e69b877d478224deab7b66844566258cecacd25e
|
||||
F test/corrupt7.test e66cb109ed64e7ac985d8b4a3422c213d074c62d
|
||||
F test/corrupt7.test 1eb2214f29474fa6b155aa3da8a7d46bf52089e1
|
||||
F test/corrupt8.test 9992ef7f67cefc576b92373f6bf5ab8775280f51
|
||||
F test/corrupt9.test 4aa1cb1ef091cb0e13e89a819c72911631b5176a
|
||||
F test/corruptA.test 99e95620b980161cb3e79f06a884a4bb8ae265ff
|
||||
F test/corruptB.test 66b4544104dd03d0f33ea69ddac3fa4a682cd3c2
|
||||
F test/corruptC.test 691ed070baef5e1345939caadf270a52837a5064
|
||||
F test/corruptD.test 3ae6e2dc6e2226c6935a8a40d4b5ee3eba75f8c0
|
||||
F test/corruptE.test dbf66cae4c0e977ca9625a9114cdd01df8967bef
|
||||
F test/count.test 454e1ce985c94d13efeac405ce54439f49336163
|
||||
F test/crash.test 1b6ac8410689ff78028887f445062dc897c9ac89
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
@ -792,14 +790,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P 0e4225804010cb0e3f254e2dbffc4fe0e7d982ce
|
||||
R e1b84b3199b12981899c4cf8ff08b1fe
|
||||
U drh
|
||||
Z 01212a28378b63d61c38823b1b1cabd0
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.10 (Darwin)
|
||||
|
||||
iEYEARECAAYFAkt9irYACgkQoxKgR168RlFqLACfTtjHG4O+0YQ6hh1MZq3NFfjO
|
||||
3wAAn2U6GgjbwSAri4XLyLGkLsGJgnkn
|
||||
=i25A
|
||||
-----END PGP SIGNATURE-----
|
||||
P 103321e37ae46eacfad4e127d13477ad5dd02bab
|
||||
R becff0b48e882ac8f957bf23a46ac2b6
|
||||
U shaneh
|
||||
Z 75f7bf2a2627891ab273971d988089a2
|
||||
|
@ -1 +1 @@
|
||||
103321e37ae46eacfad4e127d13477ad5dd02bab
|
||||
cae47c5b09cb122689bcb020a66ce14982cc4aa8
|
63
src/btree.c
63
src/btree.c
@ -7411,7 +7411,9 @@ static void checkList(
|
||||
static int checkTreePage(
|
||||
IntegrityCk *pCheck, /* Context for the sanity check */
|
||||
int iPage, /* Page number of the page to check */
|
||||
char *zParentContext /* Parent context */
|
||||
char *zParentContext, /* Parent context */
|
||||
i64 *pnParentMinKey,
|
||||
i64 *pnParentMaxKey
|
||||
){
|
||||
MemPage *pPage;
|
||||
int i, rc, depth, d2, pgno, cnt;
|
||||
@ -7422,6 +7424,8 @@ static int checkTreePage(
|
||||
int usableSize;
|
||||
char zContext[100];
|
||||
char *hit = 0;
|
||||
i64 nMinKey = 0;
|
||||
i64 nMaxKey = 0;
|
||||
|
||||
sqlite3_snprintf(sizeof(zContext), zContext, "Page %d: ", iPage);
|
||||
|
||||
@ -7464,6 +7468,16 @@ static int checkTreePage(
|
||||
btreeParseCellPtr(pPage, pCell, &info);
|
||||
sz = info.nData;
|
||||
if( !pPage->intKey ) sz += (int)info.nKey;
|
||||
/* For intKey pages, check that the keys are in order.
|
||||
*/
|
||||
else if( i==0 ) nMinKey = nMaxKey = info.nKey;
|
||||
else{
|
||||
if( info.nKey <= nMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (previous was %lld)", info.nKey, nMaxKey);
|
||||
}
|
||||
nMaxKey = info.nKey;
|
||||
}
|
||||
assert( sz==info.nPayload );
|
||||
if( (sz>info.nLocal)
|
||||
&& (&pCell[info.iOverflow]<=&pPage->aData[pBt->usableSize])
|
||||
@ -7487,25 +7501,62 @@ static int checkTreePage(
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
|
||||
}
|
||||
#endif
|
||||
d2 = checkTreePage(pCheck, pgno, zContext);
|
||||
d2 = checkTreePage(pCheck, pgno, zContext, &nMinKey, i==0 ? NULL : &nMaxKey);
|
||||
if( i>0 && d2!=depth ){
|
||||
checkAppendMsg(pCheck, zContext, "Child page depth differs");
|
||||
}
|
||||
depth = d2;
|
||||
}
|
||||
}
|
||||
|
||||
if( !pPage->leaf ){
|
||||
pgno = get4byte(&pPage->aData[pPage->hdrOffset+8]);
|
||||
sqlite3_snprintf(sizeof(zContext), zContext,
|
||||
"On page %d at right child: ", iPage);
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum ){
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, 0);
|
||||
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage, zContext);
|
||||
}
|
||||
#endif
|
||||
checkTreePage(pCheck, pgno, zContext);
|
||||
checkTreePage(pCheck, pgno, zContext, NULL, !pPage->nCell ? NULL : &nMaxKey);
|
||||
}
|
||||
|
||||
/* For intKey leaf pages, check that the min/max keys are in order
|
||||
** with any left/parent/right pages.
|
||||
*/
|
||||
if( pPage->leaf && pPage->intKey ){
|
||||
/* if we are a left child page */
|
||||
if( pnParentMinKey ){
|
||||
/* if we are the left most child page */
|
||||
if( !pnParentMaxKey ){
|
||||
if( nMaxKey > *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (max larger than parent min of %lld)",
|
||||
nMaxKey, *pnParentMinKey);
|
||||
}
|
||||
}else{
|
||||
if( nMinKey <= *pnParentMinKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (min less than parent min of %lld)",
|
||||
nMinKey, *pnParentMinKey);
|
||||
}
|
||||
if( nMaxKey > *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (max larger than parent max of %lld)",
|
||||
nMaxKey, *pnParentMaxKey);
|
||||
}
|
||||
*pnParentMinKey = nMaxKey;
|
||||
}
|
||||
/* else if we're a right child page */
|
||||
} else if( pnParentMaxKey ){
|
||||
if( nMinKey <= *pnParentMaxKey ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
"Rowid %lld out of order (min less than parent max of %lld)",
|
||||
nMinKey, *pnParentMaxKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for complete coverage of the page
|
||||
*/
|
||||
data = pPage->aData;
|
||||
@ -7529,7 +7580,7 @@ static int checkTreePage(
|
||||
}
|
||||
if( (pc+size-1)>=usableSize ){
|
||||
checkAppendMsg(pCheck, 0,
|
||||
"Corruption detected in cell %d on page %d",i,iPage,0);
|
||||
"Corruption detected in cell %d on page %d",i,iPage);
|
||||
}else{
|
||||
for(j=pc+size-1; j>=pc; j--) hit[j]++;
|
||||
}
|
||||
@ -7635,7 +7686,7 @@ char *sqlite3BtreeIntegrityCheck(
|
||||
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0, 0);
|
||||
}
|
||||
#endif
|
||||
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ");
|
||||
checkTreePage(&sCheck, aRoot[i], "List of tree roots: ", NULL, NULL);
|
||||
}
|
||||
|
||||
/* Make sure every page in the file is referenced
|
||||
|
@ -89,7 +89,7 @@ Corruption detected in cell 15 on page 2}}
|
||||
sqlite3 db test.db
|
||||
db eval {PRAGMA integrity_check(1)}
|
||||
} {{*** in database main ***
|
||||
Corruption detected in cell 15 on page 2}}
|
||||
On tree page 2 cell 15: Rowid 0 out of order (previous was 15)}}
|
||||
}
|
||||
|
||||
# The code path that was causing the buffer overrun that this test
|
||||
|
171
test/corruptE.test
Normal file
171
test/corruptE.test
Normal file
@ -0,0 +1,171 @@
|
||||
# 2010 February 18
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# This file implements tests to make sure SQLite does not crash or
|
||||
# segfault if it sees a corrupt database file. It specifcally
|
||||
# focuses on rowid order corruption.
|
||||
#
|
||||
# $Id: corruptE.test,v 1.14 2009/07/11 06:55:34 danielk1977 Exp $
|
||||
|
||||
catch {file delete -force test.db test.db-journal test.bu}
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
# Construct a compact, dense database for testing.
|
||||
#
|
||||
do_test corruptE-1.1 {
|
||||
execsql {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
PRAGMA legacy_file_format=1;
|
||||
BEGIN;
|
||||
CREATE TABLE t1(x,y);
|
||||
INSERT INTO t1 VALUES(1,1);
|
||||
INSERT OR IGNORE INTO t1 SELECT x*2,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*3,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*5,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*7,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*11,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*13,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*17,y FROM t1;
|
||||
INSERT OR IGNORE INTO t1 SELECT x*19,y FROM t1;
|
||||
CREATE INDEX t1i1 ON t1(x);
|
||||
CREATE TABLE t2 AS SELECT x,2 as y FROM t1 WHERE rowid%5!=0;
|
||||
COMMIT;
|
||||
}
|
||||
} {}
|
||||
|
||||
ifcapable {integrityck} {
|
||||
integrity_check corruptE-1.2
|
||||
}
|
||||
|
||||
# Copy file $from into $to
|
||||
#
|
||||
proc copy_file {from to} {
|
||||
file copy -force $from $to
|
||||
}
|
||||
|
||||
# Setup for the tests. Make a backup copy of the good database in test.bu.
|
||||
#
|
||||
db close
|
||||
copy_file test.db test.bu
|
||||
sqlite3 db test.db
|
||||
set fsize [file size test.db]
|
||||
|
||||
|
||||
do_test corruptE-2.1 {
|
||||
db close
|
||||
copy_file test.bu test.db
|
||||
|
||||
# insert corrupt byte(s)
|
||||
hexio_write test.db 2041 [format %02x 0x2e]
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*previous was} $ans] \
|
||||
[regexp {out of order.*max larger than parent max} $ans]
|
||||
} {1 1}
|
||||
|
||||
do_test corruptE-2.2 {
|
||||
db close
|
||||
copy_file test.bu test.db
|
||||
|
||||
# insert corrupt byte(s)
|
||||
hexio_write test.db 2047 [format %02x 0x84]
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*previous was} $ans] \
|
||||
[regexp {out of order.*min less than parent min} $ans]
|
||||
} {1 1}
|
||||
|
||||
do_test corruptE-2.3 {
|
||||
db close
|
||||
copy_file test.bu test.db
|
||||
|
||||
# insert corrupt byte(s)
|
||||
hexio_write test.db 7420 [format %02x 0xa8]
|
||||
hexio_write test.db 10459 [format %02x 0x8d]
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*max larger than parent min} $ans]
|
||||
} {1}
|
||||
|
||||
do_test corruptE-2.4 {
|
||||
db close
|
||||
copy_file test.bu test.db
|
||||
|
||||
# insert corrupt byte(s)
|
||||
hexio_write test.db 10233 [format %02x 0xd0]
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order.*min less than parent max} $ans]
|
||||
} {1}
|
||||
|
||||
|
||||
set tests [list {10233 0xd0} \
|
||||
{941 0x42} \
|
||||
{1028 0x53} \
|
||||
{2041 0xd0} \
|
||||
{2042 0x1f} \
|
||||
{2047 0xaa} \
|
||||
{2263 0x29} \
|
||||
{2274 0x75} \
|
||||
{3267 0xf2} \
|
||||
{4104 0x2c} \
|
||||
{5113 0x36} \
|
||||
{10233 0x84} \
|
||||
{10234 0x74} \
|
||||
{10239 0x41} \
|
||||
{10453 0x11} \
|
||||
{11273 0x28} \
|
||||
{11455 0x11} \
|
||||
{11461 0xe6} \
|
||||
{12281 0x99} \
|
||||
{12296 0x9e} \
|
||||
{12297 0xd7} \
|
||||
{13303 0x53} ]
|
||||
|
||||
set tc 1
|
||||
foreach test $tests {
|
||||
do_test corruptE-3.$tc {
|
||||
db close
|
||||
copy_file test.bu test.db
|
||||
|
||||
# insert corrupt byte(s)
|
||||
hexio_write test.db [lindex $test 0] [format %02x [lindex $test 1]]
|
||||
|
||||
sqlite3 db test.db
|
||||
|
||||
set res [ catchsql {PRAGMA integrity_check} ]
|
||||
set ans [lindex $res 1]
|
||||
|
||||
list [regexp {out of order} $ans]
|
||||
} {1}
|
||||
incr tc 1
|
||||
}
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user