Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -110,10 +110,35 @@ #define downgradeAllSharedCacheTableLocks(a) #define hasSharedCacheTableLock(a,b,c,d) 1 #define hasReadConflicts(a, b) 0 #endif +/* +** Implementation of the SQLITE_CORRUPT_PAGE() macro. Takes a single +** (MemPage*) as an argument. The (MemPage*) must not be NULL. +** +** If SQLITE_DEBUG is not defined, then this macro is equivalent to +** SQLITE_CORRUPT_BKPT. Or, if SQLITE_DEBUG is set, then the log message +** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented +** with the page number and filename associated with the (MemPage*). +*/ +#ifdef SQLITE_DEBUG +int corruptPageError(int lineno, MemPage *p){ + char *zMsg = sqlite3_mprintf("database corruption page %d of %s", + (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) + ); + if( zMsg ){ + sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); + } + sqlite3_free(zMsg); + return SQLITE_CORRUPT_BKPT; +} +# define SQLITE_CORRUPT_PAGE(pMemPage) corruptPageError(__LINE__, pMemPage) +#else +# define SQLITE_CORRUPT_PAGE(pMemPage) SQLITE_CORRUPT_PGNO(pMemPage->pgno) +#endif + #ifndef SQLITE_OMIT_SHARED_CACHE #ifdef SQLITE_DEBUG /* **** This function is only used as part of an assert() statement. *** @@ -1398,11 +1423,11 @@ u8 *pAddr; int sz2 = 0; int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); if( top>=iFree ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFree2 ){ assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */ sz2 = get2byte(&data[iFree2+2]); assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); @@ -1432,17 +1457,17 @@ testcase( pc==iCellLast ); /* These conditions have already been verified in btreeInitPage() ** if PRAGMA cell_size_check=ON. */ if( pciCellLast ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pc>=iCellFirst && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrkusableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); testcase( cbrk+size==usableSize ); testcase( pc+size==usableSize ); put2byte(pAddr, cbrk); @@ -1458,11 +1483,11 @@ } data[hdr+7] = 0; defragment_out: if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); data[hdr+1] = 0; data[hdr+2] = 0; @@ -1502,11 +1527,11 @@ size = get2byte(&aData[pc+2]); if( (x = size - nByte)>=0 ){ testcase( x==4 ); testcase( x==3 ); if( size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); + *pRc = SQLITE_CORRUPT_PAGE(pPg); return 0; }else if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total ** number of bytes in fragments may not exceed 60. */ if( aData[hdr+7]>57 ) return 0; @@ -1525,11 +1550,11 @@ iAddr = pc; pc = get2byte(&aData[pc]); if( pcpgno); + *pRc = SQLITE_CORRUPT_PAGE(pPg); } return 0; } @@ -1573,11 +1598,11 @@ assert( top<=(int)pPage->pBt->usableSize ); /* Prevent by getAndInitPage() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } /* If there is enough space between gap and top for one more cell pointer ** array entry offset, and if the freelist is not empty, then search the @@ -1663,16 +1688,16 @@ iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */ }else{ while( (iFreeBlk = get2byte(&data[iPtr]))pgno); + return SQLITE_CORRUPT_PAGE(pPage); } iPtr = iFreeBlk; } if( iFreeBlk>pPage->pBt->usableSize-4 ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( iFreeBlk>iPtr || iFreeBlk==0 ); /* At this point: ** iFreeBlk: First freeblock after iStart, or zero if none @@ -1680,14 +1705,14 @@ ** ** Check to see if iFreeBlk should be coalesced onto the end of iStart. */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); if( iEnd > pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); } @@ -1696,25 +1721,25 @@ ** coalesced onto the end of iPtr. */ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PAGE(pPage); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } x = get2byte(&data[hdr+5]); if( iStart<=x ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iStartpgno); + if( iStartmaxLocal = pBt->maxLocal; pPage->minLocal = pBt->minLocal; }else{ /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is ** an error. */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; } @@ -1824,11 +1849,11 @@ hdr = pPage->hdrOffset; data = pPage->aData; /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ if( decodeFlags(pPage, data[hdr]) ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); pPage->nOverflow = 0; usableSize = pBt->usableSize; @@ -1843,11 +1868,11 @@ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } testcase( pPage->nCell==MX_CELL(pBt) ); /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only ** possible for a root page of a table that contains no rows) then the ** offset to the cell content area will equal the page size minus the @@ -1871,16 +1896,16 @@ for(i=0; inCell; i++){ pc = get2byteAligned(&data[cellOffset+i*2]); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pciCellLast ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } sz = pPage->xCellSize(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } if( !pPage->leaf ) iCellLast++; } @@ -1894,30 +1919,30 @@ u32 next, size; if( pcpgno); + return SQLITE_CORRUPT_PAGE(pPage); } while( 1 ){ if( pc>iCellLast ){ /* Freeblock off the end of the page */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); nFree = nFree + size; if( next<=pc+size+3 ) break; pc = next; } if( next>0 ){ /* Freeblock not in ascending order */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( pc+size>(unsigned int)usableSize ){ /* Last freeblock extends past page end */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } /* At this point, nFree contains the sum of the offset to the start ** of the cell-content area plus the number of free bytes within @@ -1925,11 +1950,11 @@ ** of the page, then the page must be corrupted. This check also ** serves to verify that the offset to the start of the cell-content ** area, according to the page header, lies within the page. */ if( nFree>usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } pPage->nFree = (u16)(nFree - iCellFirst); pPage->isInit = 1; return SQLITE_OK; } @@ -3456,11 +3481,11 @@ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(pPage->aData, iTo); }else{ int i; int nCell; @@ -3475,11 +3500,11 @@ if( eType==PTRMAP_OVERFLOW1 ){ CellInfo info; pPage->xParseCell(pPage, pCell, &info); if( info.nLocal pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); break; } @@ -3493,11 +3518,11 @@ } if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } } return SQLITE_OK; @@ -4591,11 +4616,11 @@ /* Trying to read or write past the end of the data is an error. The ** conditional above is really: ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } /* Check if data must be read/written to/from the btree page itself. */ if( offsetinfo.nLocal ){ int a = amt; @@ -4739,11 +4764,11 @@ } } if( rc==SQLITE_OK && amt>0 ){ /* Overflow chain ends prematurely */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } return rc; } /* @@ -5017,11 +5042,11 @@ ** 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_PGNO(pCur->pPage->pgno); + return SQLITE_CORRUPT_PAGE(pCur->pPage); } skip_init: pCur->ix = 0; pCur->info.nSize = 0; @@ -5290,11 +5315,11 @@ i64 nCellKey; pCell = findCellPastPtr(pPage, idx); if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ if( pCell>=pPage->aDataEnd ){ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } } } getVarint(pCell, (u64*)&nCellKey); if( nCellKeypgno); + rc = SQLITE_CORRUPT_PAGE(pPage); goto moveto_finish; } pCellKey = sqlite3Malloc( nCell+18 ); if( pCellKey==0 ){ rc = SQLITE_NOMEM_BKPT; @@ -6167,11 +6192,11 @@ if( pInfo->nLocal==pInfo->nPayload ){ return SQLITE_OK; /* No overflow pages. Return without doing anything */ } if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ /* Cell extends past end of page */ - return SQLITE_CORRUPT_PGNO(pPage->pgno); + return SQLITE_CORRUPT_PAGE(pPage); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); pBt = pPage->pBt; assert( pBt->usableSize > 4 ); ovflPageSize = pBt->usableSize - 4; Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -3342,41 +3342,41 @@ ** to detect when version error conditions occurs. ** ** 2. Invoke sqlite3_log() to provide the source code location where ** a low-level error is first detected. */ -static int reportError(int iErr, int lineno, const char *zType){ +int sqlite3ReportError(int iErr, int lineno, const char *zType){ sqlite3_log(iErr, "%s at line %d of [%.10s]", zType, lineno, 20+sqlite3_sourceid()); return iErr; } int sqlite3CorruptError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CORRUPT, lineno, "database corruption"); + return sqlite3ReportError(SQLITE_CORRUPT, lineno, "database corruption"); } int sqlite3MisuseError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_MISUSE, lineno, "misuse"); + return sqlite3ReportError(SQLITE_MISUSE, lineno, "misuse"); } int sqlite3CantopenError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); + return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file"); } #ifdef SQLITE_DEBUG int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ char zMsg[100]; sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_CORRUPT, lineno, zMsg); + return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); } int sqlite3NomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_NOMEM, lineno, "OOM"); + return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM"); } int sqlite3IoerrnomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); - return reportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); + return sqlite3ReportError(SQLITE_IOERR_NOMEM, lineno, "I/O OOM error"); } #endif #ifndef SQLITE_OMIT_DEPRECATED /* Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -3429,10 +3429,11 @@ ** the same name but without the _BKPT suffix. These macros invoke ** routines that report the line-number on which the error originated ** using sqlite3_log(). The routines also provide a convenient place ** to set a debugger breakpoint. */ +int sqlite3ReportError(int iErr, int lineno, const char *zType); int sqlite3CorruptError(int); int sqlite3MisuseError(int); int sqlite3CantopenError(int); #define SQLITE_CORRUPT_BKPT sqlite3CorruptError(__LINE__) #define SQLITE_MISUSE_BKPT sqlite3MisuseError(__LINE__)