-C Remove\sa\ssurplus\sspace\sfrom\sa\scomment
-D 2020-07-24T11:01:29.118
+C When\strying\sto\sread\sthe\sindex\sheader,\saccept\seither\sof\sthe\stwo\sheaders\sthat\nhave\sa\svalid\schecksum\safter\s15\sattempts\sto\sget\sexactly\smatching\sheaders\nfail.
+D 2020-07-25T20:16:35.579
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/vdbevtab.c ee5b4c902fdda2230f9503ac7b84c6d614c91e8f6f4dc1633e2e8dfef8ffb144
F src/vtab.c 5f5fc793092f53bbdfde296c50f563fb7bda58cf48e9cf6a8bdfbc5abd409845
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 231044ecf7d5d78bc705af9dcec6c10ec59e891366362b6be54bb6a0bc7c17db
+F src/wal.c 701b03c19b721d67f2b9e2e091716a450abeec3eb7ab9d09e2ff3dc8bd6db6ed
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
F src/walker.c 3df26a33dc4f54e8771600fb7fdebe1ece0896c2ad68c30ab40b017aa4395049
F src/where.c 2ea911238674e9baaeddf105dddabed92692a01996073c4d4983f9a7efe481f9
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 270ac1a0f232d75537be40abae559004e950b992cb2c7e94cd6de66e96ae17bd
-R 0212ebf857b7a36fab6e1708725a20d6
+P 73fecc688ab5c459245c9bb89432139a083ef378404b4dae3397a7f4e253f72a
+R 8b78d8957ed058ded3a7dbd973cc6886
+T *branch * more-aggressive-wal-recovery
+T *sym-more-aggressive-wal-recovery *
+T -sym-trunk *
U drh
-Z 7c8911d20a18c22808c4eb3363f6ff12
+Z 3aeeeda48c6b870c6fcde25fed7c5eb2
return rc;
}
+/*
+** Return true if the wal-index header seems valid based on the
+** checksum.
+*/
+static int walIndexHdrValid(WalIndexHdr *p){
+ u32 aCksum[2];
+ if( p->isInit==0 ) return 0;
+ walChecksumBytes(1, (u8*)p, sizeof(*p)-sizeof(p->aCksum), 0, aCksum);
+ if( aCksum[0]!=p->aCksum[0] ) return 0;
+ if( aCksum[1]!=p->aCksum[1] ) return 0;
+ return 1;
+}
+
/*
** Try to read the wal-index header. Return 0 on success and 1 if
** there is a problem.
** If the checksum cannot be verified return non-zero. If the header
** is read successfully and the checksum verified, return zero.
*/
-static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged, int cnt){
u32 aCksum[2]; /* Checksum on the header content */
WalIndexHdr h1, h2; /* Two copies of the header content */
WalIndexHdr volatile *aHdr; /* Header in shared memory */
** reliably in that environment.
*/
aHdr = walIndexHdr(pWal);
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
walShmBarrier(pWal);
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
if( memcmp(&h1, &h2, sizeof(h1))!=0 ){
- return 1; /* Dirty read */
- }
- if( h1.isInit==0 ){
- return 1; /* Malformed header - probably all zeros */
- }
- walChecksumBytes(1, (u8*)&h1, sizeof(h1)-sizeof(h1.aCksum), 0, aCksum);
- if( aCksum[0]!=h1.aCksum[0] || aCksum[1]!=h1.aCksum[1] ){
- return 1; /* Checksum does not match */
+ if( cnt<15 ) return 1;
+ if( !walIndexHdrValid(&h1) ){
+ memcpy(&h1, &h2, sizeof(h1));
+ }
}
+ if( !walIndexHdrValid(&h1) ) return 1;
if( memcmp(&pWal->hdr, &h1, sizeof(WalIndexHdr)) ){
*pChanged = 1;
** If the wal-index header is successfully read, return SQLITE_OK.
** Otherwise an SQLite error code.
*/
-static int walIndexReadHdr(Wal *pWal, int *pChanged){
+static int walIndexReadHdr(Wal *pWal, int *pChanged, int cnt){
int rc; /* Return code */
int badHdr; /* True if a header read failed */
volatile u32 *page0; /* Chunk of wal-index containing header */
** works, but may fail if the wal-index header is corrupt or currently
** being modified by another thread or process.
*/
- badHdr = (page0 ? walIndexTryHdr(pWal, pChanged) : 1);
+ badHdr = (page0 ? walIndexTryHdr(pWal, pChanged, 0) : 1);
/* If the first attempt failed, it might have been due to a race
** with a writer. So get a WRITE lock and try again.
if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
- badHdr = walIndexTryHdr(pWal, pChanged);
+ badHdr = walIndexTryHdr(pWal, pChanged, cnt);
if( badHdr ){
/* If the wal-index header is still malformed even while holding
** a WRITE lock, it can only mean that the header is corrupted and
if( !useWal ){
assert( rc==SQLITE_OK );
if( pWal->bShmUnreliable==0 ){
- rc = walIndexReadHdr(pWal, pChanged);
+ rc = walIndexReadHdr(pWal, pChanged, cnt);
}
if( rc==SQLITE_BUSY ){
/* If there is not a recovery running in another thread or process
/* Read the wal-index header. */
if( rc==SQLITE_OK ){
walDisableBlocking(pWal);
- rc = walIndexReadHdr(pWal, &isChanged);
+ rc = walIndexReadHdr(pWal, &isChanged, 0);
(void)walEnableBlocking(pWal);
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);