diff --git a/manifest b/manifest index d9c4b446c0..5fec02b7c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\scase\sfixes\sfor\sfulltest.\s(CVS\s4329) -D 2007-08-30T02:26:54 +C Add\stests\sfor\smalloc()\sfailure\swhen\sthe\satomic-write\soptimization\sis\sbeing\sused.\sAlso\sfix\sthings\sso\sthat\srollback\scan\soccur\swithout\sa\smalloc(),\seven\sif\sthere\sis\sa\smaster\sjournal\sfile.\s(CVS\s4330) +D 2007-08-30T08:08:17 F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3 F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -120,7 +120,7 @@ F src/os_unix.c 89bf24aa2475048a7833c45c522e7c6a81b83bb8 F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e F src/os_win.c 3ffd3aacff4cb69848284e29dcec0feff23b0752 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c f9830adfd3752c860a4024da5b871df5af4ed8a4 +F src/pager.c 847674a74c232f3f7c386d4b902df41a60f781c4 F src/pager.h 1ac4468049348ec72df09d138fc1d7e3a9d0d3a6 F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590 F src/pragma.c 65109b3d6a62f9a0d64e739653b76afa1122a00d @@ -357,6 +357,7 @@ F test/malloc9.test fb99833476bc1a9b0b15573b9a56ae13af843ef9 F test/mallocA.test bec59bb8c9837cea463d1e76e62d0ea5113c4292 F test/mallocB.test 56fd615f3fea97180132a89dd1dd2068852ef6a0 F test/mallocC.test 3c6385336c82c9c2249c6c28ed23f430e1d66bd3 +F test/mallocD.test 03164dad24407f2a833b8215789f05a342647926 F test/malloc_common.tcl 3c2fb94035e9085f8a687d724b6b61fdac8d961f F test/manydb.test 8de36b8d33aab5ef295b11d9e95310aeded31af8 F test/memdb.test a67bda4ff90a38f2b19f6c7f95aa7289e051d893 @@ -567,7 +568,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P e40d40a5d41c491bef852a92e5846b273b206909 -R c839fab02b445dc9c276b91a0eebee5f -U drh -Z 319e3e5c3c386bc32b0490ba9c2b3ff7 +P cddce4950569ac49c1a5224b200b00dcd83a2ba4 +R e861f1719df1b7e8bf2776501010b8d3 +U danielk1977 +Z d772ae35eed9ac8826bc4538e7174609 diff --git a/manifest.uuid b/manifest.uuid index 9998f78797..139d5e918a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cddce4950569ac49c1a5224b200b00dcd83a2ba4 \ No newline at end of file +481fd3a89e50e329596d96565170e3d9977aae29 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 5901ca1ee9..fd364ae51b 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.380 2007/08/29 12:31:27 danielk1977 Exp $ +** @(#) $Id: pager.c,v 1.381 2007/08/30 08:08:17 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" @@ -872,14 +872,19 @@ static void checkPage(PgHdr *pPg){ /* ** When this is called the journal file for pager pPager must be open. ** The master journal file name is read from the end of the file and -** written into memory obtained from sqlite3_malloc(). *pzMaster is -** set to point at the memory and SQLITE_OK returned. The caller must -** sqlite3_free() *pzMaster. +** written into memory supplied by the caller. ** -** If no master journal file name is present *pzMaster is set to 0 and +** zMaster must point to a buffer of at least nMaster bytes allocated by +** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is +** enough space to write the master journal name). If the master journal +** name in the journal is longer than nMaster bytes (including a +** nul-terminator), then this is handled as if no master journal name +** were present in the journal. +** +** If no master journal file name is present zMaster[0] is set to 0 and ** SQLITE_OK returned. */ -static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){ +static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, int nMaster){ int rc; u32 len; i64 szJ; @@ -887,7 +892,7 @@ static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){ int i; unsigned char aMagic[8]; /* A buffer to hold the magic header */ - *pzMaster = 0; + zMaster[0] = '\0'; rc = sqlite3OsFileSize(pJrnl, &szJ); if( rc!=SQLITE_OK || szJ<16 ) return rc; @@ -895,37 +900,33 @@ static int readMasterJournal(sqlite3_file *pJrnl, char **pzMaster){ rc = read32bits(pJrnl, szJ-16, &len); if( rc!=SQLITE_OK ) return rc; + if( len>=nMaster ){ + return SQLITE_OK; + } + rc = read32bits(pJrnl, szJ-12, &cksum); if( rc!=SQLITE_OK ) return rc; rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8); if( rc!=SQLITE_OK || memcmp(aMagic, aJournalMagic, 8) ) return rc; - *pzMaster = (char *)sqlite3MallocZero(len+1); - if( !*pzMaster ){ - return SQLITE_NOMEM; - } - rc = sqlite3OsRead(pJrnl, *pzMaster, len, szJ-16-len); + rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len); if( rc!=SQLITE_OK ){ - sqlite3_free(*pzMaster); - *pzMaster = 0; return rc; } + zMaster[len] = '\0'; /* See if the checksum matches the master journal name */ for(i=0; i0 ){ char *zJournal; char *zMasterPtr = 0; + int nMasterPtr = pPager->pVfs->mxPathname+1; /* Load the entire master journal file into space obtained from ** sqlite3_malloc() and pointed to by zMasterJournal. */ - zMasterJournal = (char *)sqlite3_malloc(nMasterJournal); + zMasterJournal = (char *)sqlite3_malloc(nMasterJournal + nMasterPtr); if( !zMasterJournal ){ rc = SQLITE_NOMEM; goto delmaster_out; } + zMasterPtr = &zMasterJournal[nMasterJournal]; rc = sqlite3OsRead(pMaster, zMasterJournal, nMasterJournal, 0); if( rc!=SQLITE_OK ) goto delmaster_out; @@ -1553,14 +1560,13 @@ static int pager_delmaster(Pager *pPager, const char *zMaster){ goto delmaster_out; } - rc = readMasterJournal(pJournal, &zMasterPtr); + rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr); sqlite3OsClose(pJournal); if( rc!=SQLITE_OK ){ goto delmaster_out; } - c = zMasterPtr!=0 && strcmp(zMasterPtr, zMaster)==0; - sqlite3_free(zMasterPtr); + c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0; if( c ){ /* We have a match. Do not delete the master journal file. */ goto delmaster_out; @@ -1698,17 +1704,18 @@ static int pager_playback(Pager *pPager, int isHot){ ** present on disk, then the journal is not hot and does not need to be ** played back. */ - rc = readMasterJournal(pPager->jfd, &zMaster); + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); assert( rc!=SQLITE_DONE ); if( rc!=SQLITE_OK - || (zMaster && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS)) + || (zMaster[0] && !sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS)) ){ - sqlite3_free(zMaster); zMaster = 0; if( rc==SQLITE_DONE ) rc = SQLITE_OK; goto end_playback; } pPager->journalOff = 0; + zMaster = 0; /* This loop terminates either when the readJournalHdr() call returns ** SQLITE_DONE or an IO error occurs. */ @@ -1779,17 +1786,18 @@ static int pager_playback(Pager *pPager, int isHot){ assert( 0 ); end_playback: + if( rc==SQLITE_OK ){ + zMaster = pPager->pTmpSpace; + rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1); + } if( rc==SQLITE_OK ){ rc = pager_end_transaction(pPager); } - if( zMaster ){ + if( rc==SQLITE_OK && zMaster[0] ){ /* If there was a master journal and this routine will return success, ** see if it is possible to delete the master journal. */ - if( rc==SQLITE_OK ){ - rc = pager_delmaster(pPager, zMaster); - } - sqlite3_free(zMaster); + rc = pager_delmaster(pPager, zMaster); } /* The Pager.sectorSize variable may have been updated while rolling diff --git a/test/mallocD.test b/test/mallocD.test new file mode 100644 index 0000000000..ac7cd85c46 --- /dev/null +++ b/test/mallocD.test @@ -0,0 +1,54 @@ +# 2007 Aug 29 +# +# 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. +# +#*********************************************************************** +# +# $Id: mallocD.test,v 1.1 2007/08/30 08:08:17 danielk1977 Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl + +sqlite3_simulate_device -char atomic + +set PREP { + PRAGMA page_size = 1024; + CREATE TABLE abc(a, b, c); +} + +do_malloc_test mallocD-1 -sqlprep $PREP -sqlbody { + INSERT INTO abc VALUES(1, 2, 3); +} + +do_malloc_test mallocD-2 -sqlprep $PREP -sqlbody { + BEGIN; + INSERT INTO abc VALUES(1, 2, 3); + INSERT INTO abc VALUES(4, 5, 6); + ROLLBACK; +} + +do_malloc_test mallocD-3 -sqlprep $PREP -sqlbody { + BEGIN; + INSERT INTO abc VALUES(1, 2, 3); + INSERT INTO abc VALUES(4, 5, randstr(1500,1500)); + COMMIT; +} + +do_malloc_test mallocD-4 -sqlprep $PREP -sqlbody { + ATTACH 'test2.db' AS aux; + BEGIN; + CREATE TABLE aux.def(d, e, f); + INSERT INTO abc VALUES(4, 5, 6); + COMMIT; +} + +sqlite3_simulate_device -char {} + +finish_test +