Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Handle a few obscure problems that could manifest if a database corrupted in a certain way was written by a connection in the middle of a SELECT statement on the same db. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
eba8a564e62f84a9620008beead80081 |
User & Date: | dan 2014-01-20 18:25:44.841 |
Context
2014-01-20
| ||
19:55 | In where.c, do not allocate space in sqlite3_index_info structures for the internal WHERE clause "terms" generated to record column equivalencies. Fix for ticket [1a1a194d1e5f8]. (check-in: 7d9e22187d user: dan tags: trunk) | |
18:25 | Handle a few obscure problems that could manifest if a database corrupted in a certain way was written by a connection in the middle of a SELECT statement on the same db. (check-in: eba8a564e6 user: dan tags: trunk) | |
14:58 | Remove an unused #define and add an assert(), both associated with WITH logic. (check-in: a06235e0f6 user: drh tags: trunk) | |
Changes
Changes to src/btree.c.
︙ | ︙ | |||
3750 3751 3752 3753 3754 3755 3756 | */ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ CellInfo info; int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); | | | 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 | */ #ifndef NDEBUG static void assertCellInfo(BtCursor *pCur){ CellInfo info; int iPage = pCur->iPage; memset(&info, 0, sizeof(info)); btreeParseCell(pCur->apPage[iPage], pCur->aiIdx[iPage], &info); assert( CORRUPT_DB || memcmp(&info, &pCur->info, sizeof(info))==0 ); } #else #define assertCellInfo(x) #endif #ifdef _MSC_VER /* Use a real function in MSVC to work around bugs in that compiler. */ static void getCellInfo(BtCursor *pCur){ |
︙ | ︙ | |||
4386 4387 4388 4389 4390 4391 4392 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } pCur->iPage = 0; | | > > > | | | | > > > > > > | | | | < < < < < < < < < < < | 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 | rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0], pCur->wrFlag==0 ? PAGER_GET_READONLY : 0); if( rc!=SQLITE_OK ){ pCur->eState = CURSOR_INVALID; return rc; } pCur->iPage = 0; } pRoot = pCur->apPage[0]; assert( pRoot->pgno==pCur->pgnoRoot ); /* If pCur->pKeyInfo is not NULL, then the caller that opened this cursor ** expected to open it on an index b-tree. Otherwise, if pKeyInfo is ** NULL, the caller expects a table b-tree. If this is not the case, ** return an SQLITE_CORRUPT error. ** ** Earlier versions of SQLite assumed that this test could not fail ** if the root page was already loaded when this function was called (i.e. ** if pCur->iPage>=0). But this is not so if the database is corrupted ** in such a way that page pRoot is linked into a second b-tree table ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ return SQLITE_CORRUPT_BKPT; } pCur->aiIdx[0] = 0; pCur->info.nSize = 0; pCur->atLast = 0; pCur->validNKey = 0; if( pRoot->nCell>0 ){ |
︙ | ︙ | |||
5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 | end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); if( rc==SQLITE_OK ){ if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ releasePage(*ppPage); return SQLITE_CORRUPT_BKPT; } (*ppPage)->isInit = 0; }else{ *ppPage = 0; } assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) ); | > | 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 | end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); if( rc==SQLITE_OK ){ if( sqlite3PagerPageRefcount((*ppPage)->pDbPage)>1 ){ releasePage(*ppPage); *ppPage = 0; return SQLITE_CORRUPT_BKPT; } (*ppPage)->isInit = 0; }else{ *ppPage = 0; } assert( rc!=SQLITE_OK || sqlite3PagerIswriteable((*ppPage)->pDbPage) ); |
︙ | ︙ |
Added test/corruptH.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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 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 | # 2014-01-20 # # 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. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix corruptH # 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; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); CREATE TABLE t2(x); INSERT INTO t2 VALUES(randomblob(200)); INSERT INTO t2 SELECT randomblob(200) FROM t2; INSERT INTO t2 SELECT randomblob(200) FROM t2; INSERT INTO t2 SELECT randomblob(200) FROM t2; INSERT INTO t2 SELECT randomblob(200) FROM t2; INSERT INTO t2 SELECT randomblob(200) FROM t2; INSERT INTO t2 SELECT randomblob(200) FROM t2; } {} # Corrupt the file so that the root page of t1 is also linked into t2 as # a leaf page. # do_test 1.2 { db eval { SELECT name, rootpage FROM sqlite_master } { set r($name) $rootpage } db close hexio_write test.db [expr {($r(t2)-1)*1024 + 11}] [format %.2X $r(t1)] sqlite3 db test.db } {} do_test 1.3 { db eval { PRAGMA secure_delete=1 } list [catch { db eval { SELECT * FROM t1 WHERE a IN (1, 2) } { db eval { DELETE FROM t2 } } } msg] $msg } {1 {database disk image is malformed}} #------------------------------------------------------------------------- reset_db # Initialize the database. # do_execsql_test 2.1 { PRAGMA page_size=1024; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); CREATE TABLE t3(x); CREATE TABLE t2(x PRIMARY KEY) WITHOUT ROWID; INSERT INTO t2 VALUES(randomblob(100)); DROP TABLE t3; } {} do_test 2.2 { db eval { SELECT name, rootpage FROM sqlite_master } { set r($name) $rootpage } db close set fl [hexio_get_int [hexio_read test.db 32 4]] hexio_write test.db [expr {($fl-1) * 1024 + 0}] 00000000 hexio_write test.db [expr {($fl-1) * 1024 + 4}] 00000001 hexio_write test.db [expr {($fl-1) * 1024 + 8}] [format %.8X $r(t1)] hexio_write test.db 36 00000002 sqlite3 db test.db } {} do_test 2.3 { list [catch { db eval { SELECT * FROM t1 WHERE a IN (1, 2) } { db eval { INSERT INTO t2 SELECT randomblob(100) FROM t2; INSERT INTO t2 SELECT randomblob(100) FROM t2; INSERT INTO t2 SELECT randomblob(100) FROM t2; INSERT INTO t2 SELECT randomblob(100) FROM t2; INSERT INTO t2 SELECT randomblob(100) FROM t2; } } } msg] $msg } {1 {database disk image is malformed}} #------------------------------------------------------------------------- reset_db # Initialize the database. # do_execsql_test 3.1 { PRAGMA page_size=1024; CREATE TABLE t1(a INTEGER PRIMARY KEY, b); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); CREATE TABLE t2(c INTEGER PRAGMA KEY, d); INSERT INTO t2 VALUES(1, randomblob(1100)); } {} do_test 3.2 { db eval { SELECT name, rootpage FROM sqlite_master } { set r($name) $rootpage } db close hexio_write test.db [expr {($r(t2)-1) * 1024 + 1020}] 00000002 sqlite3 db test.db } {} do_test 3.3 { list [catch { db eval { SELECT * FROM t1 WHERE a IN (1, 2) } { db eval { DELETE FROM t2 WHERE c=1; } } } msg] $msg } {1 {database disk image is malformed}} finish_test |