From: danielk1977 Date: Sat, 10 Jan 2009 16:15:09 +0000 (+0000) Subject: Improve coverage of pager.c. (CVS 6158) X-Git-Tag: version-3.6.10~26 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7cbd589da0bcb115d1e36b0b5b5001d7b29d38ea;p=thirdparty%2Fsqlite.git Improve coverage of pager.c. (CVS 6158) FossilOrigin-Name: 855c4093cf331496d9ef508011ad814e91e3882f --- diff --git a/manifest b/manifest index 34f07a27d8..4df5076602 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sbug\scaused\sby\soverzealous\scode\stest\scoverage\ssimplifications.\nBug\sfound\sby\sTH3.\s(CVS\s6157) -D 2009-01-10T15:34:12 +C Improve\scoverage\sof\spager.c.\s(CVS\s6158) +D 2009-01-10T16:15:09 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 05461a9b5803d5ad10c79f989801e9fd2cc3e592 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -142,7 +142,7 @@ F src/os_common.h 24525d8b7bce66c374dfc1810a6c9043f3359b60 F src/os_os2.c bed77dc26e3a95ce4a204936b9a1ca6fe612fcc5 F src/os_unix.c 7825c6178597713382d74adbf8c8c00ffcdc42d4 F src/os_win.c 496e3ceb499aedc63622a89ef76f7af2dd902709 -F src/pager.c 97bfbacae6131b8d228628803606e98dd763b474 +F src/pager.c a1e23f2c55bda1303cb6236d4aca9666e58eb610 F src/pager.h 9870acb2d653848d90d765d7cbf163496d6c8111 F src/parse.y 4d0e33a702dc3ea7b69d8ae1914b3fbd32e46057 F src/pcache.c 16dc8da6e6ba6250f8dfd9ee46036db1cbceedc6 @@ -159,7 +159,7 @@ F src/shell.c 65d19f8996a160f288087e31810f24025439c62a F src/sqlite.h.in 6cd2489e40fe97ba58c60044a4ced377e08b6d09 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqliteInt.h 4b2a8eb466c30daa90d25f9d3bb2e85b60ad47af -F src/sqliteLimit.h 651a2757ba55aeba1da167786b6a8c3404433940 +F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c 23db1e5f27c03160987c122a078b4bb51ef0b2f8 F src/tclsqlite.c 4415e1033bd3e92b05a6a9cde911ee4de3b82df9 @@ -288,7 +288,7 @@ F test/crash4.test 02ff4f15c149ca1e88a5c299b4896c84d9450c3b F test/crash5.test 80a2f7073381837fc082435c97df52a830abcd80 F test/crash6.test 9c730cf06335003cb1f5cfceddacd044155336e0 F test/crash7.test e20a7b9ee1d16eaef7c94a4cb7ed2191b4d05970 -F test/crash8.test 2ee8ecfed37eea4b987148fe36d6b56175c7d049 +F test/crash8.test 5b0e499c1dfaa2025e8ab69e4be32f71d4d92b23 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272 F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c @@ -413,7 +413,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 86675fc2919269aa923c84dd00ee4249b97990fe F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19 -F test/jrnlmode.test e004a5ed138e06464d74dbd6bead01908f264c52 +F test/jrnlmode.test a77f95a7cbdc8373582fd274f24124ad0d3a8fb6 F test/lastinsert.test 474d519c68cb79d07ecae56a763aa7f322c72f51 F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200 F test/like.test 22f7857f9d7da7ff5061ded8806c43a6271109fc @@ -430,7 +430,7 @@ F test/lock6.test f4e9052b14da3bd6807a757d5aed15c17321031a F test/lookaside.test e69f822f13745f1d5c445c6e30e30f059f30c8e5 F test/main.test 187a9a1b5248ed74a83838c581c15ec6023b555b F test/make-where7.tcl 40bb740b37eead343eaf57b74ab72d2a5a304745 -F test/malloc.test 86f378c52202b5b39b54a7fc560a4a75d77ce4f1 +F test/malloc.test 95e94f8a3dd1169c8774788ec4148ea032ea20d8 F test/malloc3.test 4bc57f850b212f706f3e1b37c4eced1d5a727cd1 F test/malloc4.test 957337613002b7058a85116493a262f679f3a261 F test/malloc5.test 20d1a0884b03edf811bfd7005faade028367e7c8 @@ -696,7 +696,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 2cbea64fb00a1b5b8aa0e9c958b2a09256ae59bc -R 7759d6bbe5785c316ce1fcb98ad155c6 -U drh -Z 8f01cd8c083356c8b7a4a4354e84f698 +P 3da5578726cb22118dfca38a2098a1e378644387 +R 320ab8e7bd88e5e4d3a0d64f8789cffb +U danielk1977 +Z 43f0761b39243fe434b2dca241a4ad9a diff --git a/manifest.uuid b/manifest.uuid index 0f5f9aaded..abf1c9538f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3da5578726cb22118dfca38a2098a1e378644387 \ No newline at end of file +855c4093cf331496d9ef508011ad814e91e3882f \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index db8d0d4e39..baae60ec22 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.544 2009/01/09 17:11:05 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.545 2009/01/10 16:15:09 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -116,6 +116,14 @@ int sqlite3PagerTrace=1; /* True to enable tracing */ # define CODEC2(P,D,N,X) ((char*)D) #endif +/* +** The maximum allowed sector size. 16MB. If the xSectorsize() method +** returns a value larger than this, then MAX_SECTOR_SIZE is used instead. +** This could conceivably cause corruption following a power failure on +** such a system. This is currently an undocumented limit. +*/ +#define MAX_SECTOR_SIZE 0x0100000 + /* ** An instance of the following structure is allocated for each active ** savepoint and statement transaction in the system. All such structures @@ -401,7 +409,7 @@ static int jrnlBufferSize(Pager *pPager){ if( fd->pMethods ){ dc = sqlite3OsDeviceCharacteristics(fd); - nSector = sqlite3OsSectorSize(fd); + nSector = pPager->sectorSize; szPage = pPager->pageSize; } @@ -760,7 +768,8 @@ static int readJournalHdr( int rc; unsigned char aMagic[8]; /* A buffer to hold the magic header */ i64 jrnlOff; - int iPageSize; + u32 iPageSize; + u32 iSectorSize; seekJournalHdr(pPager); if( pPager->journalOff+JOURNAL_HDR_SZ(pPager) > journalSize ){ @@ -785,28 +794,41 @@ static int readJournalHdr( rc = read32bits(pPager->jfd, jrnlOff+8, pDbSize); if( rc ) return rc; - rc = read32bits(pPager->jfd, jrnlOff+16, (u32 *)&iPageSize); - if( rc==SQLITE_OK - && iPageSize>=512 - && iPageSize<=SQLITE_MAX_PAGE_SIZE - && ((iPageSize-1)&iPageSize)==0 - ){ - u16 pagesize = (u16)iPageSize; - rc = sqlite3PagerSetPagesize(pPager, &pagesize); - } - if( rc ) return rc; + if( pPager->journalOff==0 ){ + rc = read32bits(pPager->jfd, jrnlOff+16, &iPageSize); + if( rc ) return rc; - /* Update the assumed sector-size to match the value used by - ** the process that created this journal. If this journal was - ** created by a process other than this one, then this routine - ** is being called from within pager_playback(). The local value - ** of Pager.sectorSize is restored at the end of that routine. - */ - rc = read32bits(pPager->jfd, jrnlOff+12, &pPager->sectorSize); - if( rc ) return rc; - if( (pPager->sectorSize & (pPager->sectorSize-1))!=0 - || pPager->sectorSize>0x1000000 ){ - return SQLITE_DONE; + if( iPageSize<512 + || iPageSize>SQLITE_MAX_PAGE_SIZE + || ((iPageSize-1)&iPageSize)!=0 + ){ + /* If the page-size in the journal-header is invalid, then the process + ** that wrote the journal-header must have crashed before the header + ** was synced. In this case stop reading the journal file here. + */ + rc = SQLITE_DONE; + }else{ + u16 pagesize = (u16)iPageSize; + rc = sqlite3PagerSetPagesize(pPager, &pagesize); + assert( rc!=SQLITE_OK || pagesize==(u16)iPageSize ); + } + if( rc ) return rc; + + /* Update the assumed sector-size to match the value used by + ** the process that created this journal. If this journal was + ** created by a process other than this one, then this routine + ** is being called from within pager_playback(). The local value + ** of Pager.sectorSize is restored at the end of that routine. + */ + rc = read32bits(pPager->jfd, jrnlOff+12, &iSectorSize); + if( rc ) return rc; + if( (iSectorSize&(iSectorSize-1)) + || iSectorSize<512 + || iSectorSize>MAX_SECTOR_SIZE + ){ + return SQLITE_DONE; + } + pPager->sectorSize = iSectorSize; } pPager->journalOff += JOURNAL_HDR_SZ(pPager); @@ -1503,7 +1525,7 @@ static int pager_truncate(Pager *pPager, Pgno nPage){ ** Set the sectorSize for the given pager. ** ** The sector size is at least as big as the sector size reported -** by sqlite3OsSectorSize(). The minimum sector size is 512. +** by sqlite3OsSectorSize(). The minimum sector size is 512. */ static void setSectorSize(Pager *pPager){ assert(pPager->fd->pMethods||pPager->tempFile); @@ -1517,6 +1539,9 @@ static void setSectorSize(Pager *pPager){ if( pPager->sectorSize<512 ){ pPager->sectorSize = 512; } + if( pPager->sectorSize>MAX_SECTOR_SIZE ){ + pPager->sectorSize = MAX_SECTOR_SIZE; + } } /* @@ -2022,9 +2047,9 @@ int sqlite3PagerOpen( ** + The largest page size that can be written atomically. */ if( rc==SQLITE_OK && !readOnly ){ - int iSectorSize = sqlite3OsSectorSize(pPager->fd); - if( szPageDfltsectorSize ){ + szPageDflt = pPager->sectorSize; } #ifdef SQLITE_ENABLE_ATOMIC_WRITE { diff --git a/src/sqliteLimit.h b/src/sqliteLimit.h index 8d77d0da22..26375197bc 100644 --- a/src/sqliteLimit.h +++ b/src/sqliteLimit.h @@ -12,7 +12,7 @@ ** ** This file defines various limits of what SQLite can process. ** -** @(#) $Id: sqliteLimit.h,v 1.9 2009/01/07 16:15:43 danielk1977 Exp $ +** @(#) $Id: sqliteLimit.h,v 1.10 2009/01/10 16:15:09 danielk1977 Exp $ */ /* @@ -130,6 +130,13 @@ /* Maximum page size. The upper bound on this value is 32768. This a limit ** imposed by the necessity of storing the value in a 2-byte unsigned integer ** and the fact that the page size must be a power of 2. +** +** If this limit is changed, then the compiled library is technically +** incompatible with an SQLite library compiled with a different limit. If +** a process operating on a database with a page-size of 65536 bytes +** crashes, then an instance of SQLite compiled with the default page-size +** limit will not be able to rollback the aborted transaction. This could +** lead to database corruption. */ #ifndef SQLITE_MAX_PAGE_SIZE # define SQLITE_MAX_PAGE_SIZE 32768 diff --git a/test/crash8.test b/test/crash8.test index 3f6c2f35fd..10a1b2cef5 100644 --- a/test/crash8.test +++ b/test/crash8.test @@ -15,7 +15,7 @@ # Later: Also, some other specific scenarios required for coverage # testing that do not lead to corruption. # -# $Id: crash8.test,v 1.2 2009/01/09 10:49:14 danielk1977 Exp $ +# $Id: crash8.test,v 1.3 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] @@ -118,13 +118,27 @@ proc read_file {zFile} { close $fd return $zData } +proc write_file {zFile zData} { + set fd [open $zFile w] + fconfigure $fd -translation binary + puts -nonewline $fd $zData + close $fd +} # The following tests check that SQLite will not roll back a hot-journal # file if the sector-size field in the first journal file header is # suspect. Definition of suspect: # +# a) Not a power of 2, or (crash8-3.5) +# b) Greater than 0x01000000 (16MB), or (crash8-3.6) +# c) Less than 512. (crash8-3.7) +# +# Also test that SQLite will not rollback a hot-journal file with a +# suspect page-size. In this case "suspect" means: +# # a) Not a power of 2, or -# b) Greater than 0x1000000 (16MB). +# b) Less than 512, or +# c) Greater than SQLITE_MAX_PAGE_SIZE # do_test crash8-3.1 { list [file exists test.db-joural] [file exists test.db] @@ -148,34 +162,61 @@ do_test crash8-3.4 { binary scan [string range $zJournal 20 23] I nSector set nSector } {512} + do_test crash8-3.5 { - set zJournal2 [ - string replace $zJournal 20 23 [binary format I 511] - ] - set fd [open test.db-journal w] - fconfigure $fd -translation binary - puts -nonewline $fd $zJournal2 - close $fd - + set zJournal2 [string replace $zJournal 20 23 [binary format I 513]] + write_file test.db-journal $zJournal2 + execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.6 { - set zJournal2 [ - string replace $zJournal 20 23 [binary format I [expr 0x2000000]] - ] - set fd [open test.db-journal w] - fconfigure $fd -translation binary - puts -nonewline $fd $zJournal2 - close $fd + set zJournal2 [string replace $zJournal 20 23 [binary format I 0x2000000]] + write_file test.db-journal $zJournal2 execsql { SELECT count(*) FROM t1; PRAGMA integrity_check } } {0 ok} do_test crash8-3.7 { + set zJournal2 [string replace $zJournal 20 23 [binary format I 256]] + write_file test.db-journal $zJournal2 + execsql { + SELECT count(*) FROM t1; + PRAGMA integrity_check + } +} {0 ok} + +do_test crash8-3.8 { + set zJournal2 [string replace $zJournal 24 27 [binary format I 513]] + write_file test.db-journal $zJournal2 + + execsql { + SELECT count(*) FROM t1; + PRAGMA integrity_check + } +} {0 ok} +do_test crash8-3.9 { + set big [expr $SQLITE_MAX_PAGE_SIZE * 2] + set zJournal2 [string replace $zJournal 24 27 [binary format I $big]] + write_file test.db-journal $zJournal2 + execsql { + SELECT count(*) FROM t1; + PRAGMA integrity_check + } +} {0 ok} +do_test crash8-3.10 { + set zJournal2 [string replace $zJournal 24 27 [binary format I 256]] + write_file test.db-journal $zJournal2 + execsql { + SELECT count(*) FROM t1; + PRAGMA integrity_check + } +} {0 ok} + +do_test crash8-3.11 { set fd [open test.db-journal w] fconfigure $fd -translation binary puts -nonewline $fd $zJournal diff --git a/test/jrnlmode.test b/test/jrnlmode.test index 7b230e03fc..540928de1b 100644 --- a/test/jrnlmode.test +++ b/test/jrnlmode.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # -# $Id: jrnlmode.test,v 1.10 2009/01/09 10:49:14 danielk1977 Exp $ +# $Id: jrnlmode.test,v 1.11 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -419,6 +419,23 @@ ifcapable pragma { set sz [file size test.db-journal] expr {$sz>=$journalsize} } {1} + + # Test a size-limit of 0. + # + do_test jrnlmode-5.20 { + execsql { + PRAGMA journal_size_limit = 0; + BEGIN; + UPDATE t1 SET a = randomblob(1000); + } + } {0} + do_test jrnlmode-5.21 { + expr {[file size test.db-journal] > 1024} + } {1} + do_test jrnlmode-5.22 { + execsql COMMIT + list [file exists test.db-journal] [file size test.db-journal] + } {1 0} } ifcapable pragma { diff --git a/test/malloc.test b/test/malloc.test index 236dd4f496..ddd6c2eaf3 100644 --- a/test/malloc.test +++ b/test/malloc.test @@ -16,7 +16,7 @@ # to see what happens in the library if a malloc were to really fail # due to an out-of-memory situation. # -# $Id: malloc.test,v 1.72 2009/01/10 11:13:40 danielk1977 Exp $ +# $Id: malloc.test,v 1.73 2009/01/10 16:15:09 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -678,7 +678,7 @@ do_malloc_test 29 -sqlprep { INSERT INTO t1 SELECT * FROM t1 UNION ALL SELECT * FROM t1; } -do_malloc_test 29 -tclprep { +do_malloc_test 30 -tclprep { db eval { CREATE TABLE t1(x PRIMARY KEY); INSERT INTO t1 VALUES(randstr(500,500)); @@ -708,6 +708,18 @@ do_malloc_test 29 -tclprep { SELECT * FROM t1 ORDER BY x; } +# After committing a transaction in persistent-journal mode, if a journal +# size limit is configured SQLite may attempt to truncate the journal file. +# This test verifies the libraries response to a malloc() failure during +# this operation. +# +do_malloc_test 31 -sqlprep { + PRAGMA journal_mode = persist; + PRAGMA journal_size_limit = 1024; + CREATE TABLE t1(a PRIMARY KEY, b); +} -sqlbody { + INSERT INTO t1 VALUES(1, 2); +} # Ensure that no file descriptors were leaked. do_test malloc-99.X {