1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fix a possible UAF in SEH if an exception occurs at an inopportune moment

during WAL processing.

FossilOrigin-Name: 91b91037e348fa10cf6a9d8a0ffbfdebb4a40e0e336b65b112ed1c828e75cda7
This commit is contained in:
drh
2023-08-17 14:19:44 +00:00
parent 936f7deee4
commit 36a9f5c24c
3 changed files with 31 additions and 8 deletions

View File

@@ -531,6 +531,8 @@ struct Wal {
#ifdef SQLITE_USE_SEH
u32 lockMask; /* Mask of locks held */
void *pFree; /* Pointer to sqlite3_free() if exception thrown */
u32 *pWiValue; /* Value to write into apWiData[iWiPg] */
int iWiPg; /* Write pWiValue into apWiData[iWiPg] */
int iSysErrno; /* System error code following exception */
#endif
#ifdef SQLITE_DEBUG
@@ -702,11 +704,24 @@ static void sehInjectFault(Wal *pWal){
#define SEH_FREE_ON_ERROR(X,Y) \
assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y
/*
** There are two ways to use this macro. To arrange for pWal->apWiData[iPg]
** to be set to pValue if an exception is thrown:
**
** SEH_SET_ON_ERROR(iPg, pValue);
**
** and to cancel the same:
**
** SEH_SET_ON_ERROR(0, 0);
*/
#define SEH_SET_ON_ERROR(X,Y) pWal->iWiPg = X; pWal->pWiValue = Y
#else
# define SEH_TRY VVA_ONLY(pWal->nSehTry++);
# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 );
# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 );
# define SEH_FREE_ON_ERROR(X,Y)
# define SEH_SET_ON_ERROR(X,Y)
#endif /* ifdef SQLITE_USE_SEH */
@@ -1467,6 +1482,7 @@ static int walIndexRecover(Wal *pWal){
rc = walIndexPage(pWal, iPg, (volatile u32**)&aShare);
assert( aShare!=0 || rc!=SQLITE_OK );
if( aShare==0 ) break;
SEH_SET_ON_ERROR(iPg, aShare);
pWal->apWiData[iPg] = aPrivate;
for(iFrame=iFirst; iFrame<=iLast; iFrame++){
@@ -1494,6 +1510,7 @@ static int walIndexRecover(Wal *pWal){
}
}
pWal->apWiData[iPg] = aShare;
SEH_SET_ON_ERROR(0,0);
nHdr = (iPg==0 ? WALINDEX_HDR_SIZE : 0);
nHdr32 = nHdr / sizeof(u32);
#ifndef SQLITE_SAFER_WALINDEX_RECOVERY
@@ -2387,7 +2404,9 @@ static void walLimitSize(Wal *pWal, i64 nMax){
**
** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free().
**
** 3) Returns SQLITE_IOERR.
** 3) Set pWal->apWiData[pWal->iWiPg] to pWal->pWiValue if not NULL
**
** 4) Returns SQLITE_IOERR.
*/
static int walHandleException(Wal *pWal){
if( pWal->exclusiveMode==0 ){
@@ -2406,6 +2425,10 @@ static int walHandleException(Wal *pWal){
}
sqlite3_free(pWal->pFree);
pWal->pFree = 0;
if( pWal->pWiValue ){
pWal->apWiData[pWal->iWiPg] = pWal->pWiValue;
pWal->pWiValue = 0;
}
return SQLITE_IOERR_IN_PAGE;
}