Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Prevent a possible infinite loop when trying to DROP a table from a corrupt database. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
395bb3e677a6551b06ba96fc58c39313 |
User & Date: | drh 2015-03-30 23:43:56.191 |
References
2015-04-06
| ||
22:05 | Detect and suppress an endless loops in clearDatabasePage() that might result from a corrupt database file. This is an edited cherry-pick from [30011ad2f55c] and [395bb3e677a]. (Leaf check-in: e5f5ef008d user: drh tags: apple-osx-385) | |
Context
2015-03-31
| ||
11:42 | Ensure that comparison operators do not mess up the MEM_Dyn flag on registers when reverting affinity changes. (check-in: 02e3c88fbf user: drh tags: trunk) | |
00:10 | Merge all recent trunk enhancements and fixes into the sessions branch. (check-in: df94e61f93 user: drh tags: sessions) | |
2015-03-30
| ||
23:52 | Merge the latest trunk enhancements, and especially the fix for the infinite loop on a DROP TABLE in a corrupt database, into the apple-osx branch. (check-in: 4d42bf5e18 user: drh tags: apple-osx) | |
23:43 | Prevent a possible infinite loop when trying to DROP a table from a corrupt database. (check-in: 395bb3e677 user: drh tags: trunk) | |
2015-03-27
| ||
18:20 | Enhancements to OSTRACE usage in the Win32 VFS. (check-in: ab5800291e user: mistachkin tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 | ){ MemPage *pPage; int rc; unsigned char *pCell; int i; int hdr; u16 szCell; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; hdr = pPage->hdrOffset; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); | > > > | | | 7974 7975 7976 7977 7978 7979 7980 7981 7982 7983 7984 7985 7986 7987 7988 7989 7990 7991 7992 7993 7994 7995 7996 7997 7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 | ){ MemPage *pPage; int rc; unsigned char *pCell; int i; int hdr; u16 szCell; u8 hasChildren; assert( sqlite3_mutex_held(pBt->mutex) ); if( pgno>btreePagecount(pBt) ){ return SQLITE_CORRUPT_BKPT; } rc = getAndInitPage(pBt, pgno, &pPage, 0); if( rc ) return rc; hasChildren = !pPage->leaf; pPage->leaf = 1; /* Block looping if the database is corrupt */ hdr = pPage->hdrOffset; for(i=0; i<pPage->nCell; i++){ pCell = findCell(pPage, i); if( hasChildren ){ rc = clearDatabasePage(pBt, get4byte(pCell), 1, pnChange); if( rc ) goto cleardatabasepage_out; } rc = clearCell(pPage, pCell, &szCell); if( rc ) goto cleardatabasepage_out; } if( hasChildren ){ rc = clearDatabasePage(pBt, get4byte(&pPage->aData[hdr+8]), 1, pnChange); if( rc ) goto cleardatabasepage_out; }else if( pnChange ){ assert( pPage->intKey ); *pnChange += pPage->nCell; } if( freePageFlag ){ |
︙ | ︙ |
Added test/corruptJ.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | # 2015-03-30 # # 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. # #*********************************************************************** # # Corruption consisting of a database page that thinks it is a child # of itself. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix corruptJ if {[permutation]=="mmap"} { finish_test return } # Do not use a codec for tests in this file, as the database file is # manipulated directly using tcl scripts (using the [hexio_write] command). # do_not_use_codec database_may_be_corrupt # Initialize the database. # do_execsql_test 1.1 { PRAGMA page_size=1024; PRAGMA auto_vacuum=0; CREATE TABLE t1(a,b); WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10) INSERT INTO t1(a,b) SELECT i, zeroblob(700) FROM c; } {} db close # Corrupt the root page of the t1 table such that the left-child pointer # for the very first cell points back to the root. Then try to DROP the # table. The clearDatabasePage() routine should not loop. # do_test 1.2 { hexio_write test.db [expr {2*1024-2}] 02 sqlite3 db test.db catchsql { DROP TABLE t1 } } {1 {database disk image is malformed}} # Similar test using a WITHOUT ROWID table # do_test 2.1 { db close forcedelete test.db sqlite3 db test.db db eval { PRAGMA page_size=1024; PRAGMA auto_vacuum=0; CREATE TABLE t1(a,b,PRIMARY KEY(a,b)) WITHOUT ROWID; WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<100) INSERT INTO t1(a,b) SELECT i, zeroblob(200) FROM c; } } {} # The table is three levels deep. Corrupt the left child of an intermediate # page so that it points back to the root page. # do_test 2.2 { db close hexio_read test.db [expr {9*1024+391}] 8 } {00000008814D0401} do_test 2.2b { hexio_write test.db [expr {9*1024+391}] 00000002 sqlite3 db test.db catchsql { DROP TABLE t1 } } {0 {}} finish_test |