1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Check that read-only pages are not being modified (disabled by default). (CVS 2331)

FossilOrigin-Name: 8514a4feb2a86e93c4251c491d394e861bb65edb
This commit is contained in:
danielk1977
2005-02-15 02:54:14 +00:00
parent aee128dc20
commit 3c407374fc
3 changed files with 64 additions and 9 deletions

View File

@@ -18,7 +18,7 @@
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.188 2005/02/06 02:45:42 drh Exp $
** @(#) $Id: pager.c,v 1.189 2005/02/15 02:54:15 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -168,6 +168,9 @@ struct PgHdr {
u8 alwaysRollback; /* Disable dont_rollback() for this page */
short int nRef; /* Number of users of this page */
PgHdr *pDirty; /* Dirty pages sorted by PgHdr.pgno */
#ifdef SQLITE_CHECK_PAGES
u32 pageHash;
#endif
/* pPager->psAligned bytes of page data follow this header */
/* Pager.nExtra bytes of local data follow the page data */
};
@@ -451,6 +454,36 @@ static int pager_errcode(Pager *pPager){
return rc;
}
#ifdef SQLITE_CHECK_PAGES
/*
** Return a 32-bit hash of the page data for pPage.
*/
static u32 pager_pagehash(PgHdr *pPage){
u32 hash = 0;
int i;
unsigned char *pData = (unsigned char *)PGHDR_TO_DATA(pPage);
for(i=0; i<pPage->pPager->pageSize; i++){
hash = (hash+i)^pData[i];
}
return hash;
}
/*
** The CHECK_PAGE macro takes a PgHdr* as an argument. If SQLITE_CHECK_PAGES
** is defined, and NDEBUG is not defined, an assert() statement checks
** that the page is either dirty or still matches the calculated page-hash.
*/
#define CHECK_PAGE(x) checkPage(x)
static void checkPage(PgHdr *pPg){
Pager *pPager = pPg->pPager;
assert( !pPg->pageHash || pPager->errMask || MEMDB || pPg->dirty ||
pPg->pageHash==pager_pagehash(pPg) );
}
#else
#define CHECK_PAGE(x)
#endif
/*
** 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
@@ -841,6 +874,9 @@ static int pager_unwritelock(Pager *pPager){
pPg->inJournal = 0;
pPg->dirty = 0;
pPg->needSync = 0;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
pPager->dirtyCache = 0;
pPager->nRec = 0;
@@ -958,6 +994,9 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
if( pPager->state>=PAGER_EXCLUSIVE ){
pPg->dirty = 0;
pPg->needSync = 0;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
CODEC(pPager, pData, pPg->pgno, 3);
}
@@ -1086,6 +1125,9 @@ static int pager_reload_cache(Pager *pPager){
}
pPg->needSync = 0;
pPg->dirty = 0;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
return rc;
}
@@ -2101,6 +2143,9 @@ static int pager_write_pagelist(PgHdr *pList){
#endif
if( rc ) return rc;
pList->dirty = 0;
#ifdef SQLITE_CHECK_PAGES
pList->pageHash = pager_pagehash(pList);
#endif
pList = pList->pDirty;
}
return SQLITE_OK;
@@ -2388,6 +2433,9 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){
pPager->nRead++;
}
}
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}else{
/* The requested page is in the page cache. */
pPager->nHit++;
@@ -2440,6 +2488,8 @@ int sqlite3pager_unref(void *pData){
pPg->nRef--;
REFINFO(pPg);
CHECK_PAGE(pPg);
/* When the number of references to a page reach 0, call the
** destructor and add the page to the freelist.
*/
@@ -2628,6 +2678,8 @@ int sqlite3pager_write(void *pData){
assert( !pPager->setMaster );
CHECK_PAGE(pPg);
/* Mark the page as dirty. If the page has already been written
** to the journal then we can return right away.
*/
@@ -2831,6 +2883,9 @@ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){
}else{
TRACE3("DONT_WRITE page %d of %d\n", pgno, PAGERID(pPager));
pPg->dirty = 0;
#ifdef SQLITE_CHECK_PAGES
pPg->pageHash = pager_pagehash(pPg);
#endif
}
}
}