diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c index f6b5c22336..a47c2c0073 100644 --- a/amalgamation/sqlite3.c +++ b/amalgamation/sqlite3.c @@ -77704,6 +77704,12 @@ static int accessPayload( (eOp==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ + if( eOp!=0 + && (sqlite3PagerPageRefcount(pDbPage)!=1 + || ((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit) ){ + sqlite3PagerUnref(pDbPage); + return SQLITE_CORRUPT_PAGE(pPage); + } aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage); diff --git a/src/btree.c b/src/btree.c index 8d0f92222d..152b35e7d3 100644 --- a/src/btree.c +++ b/src/btree.c @@ -5266,6 +5266,18 @@ static int accessPayload( (eOp==0 ? PAGER_GET_READONLY : 0) ); if( rc==SQLITE_OK ){ + if( eOp!=0 + && (sqlite3PagerPageRefcount(pDbPage)!=1 + || ((MemPage*)sqlite3PagerGetExtra(pDbPage))->isInit) ){ + /* A corrupt overflow chain has redirected us onto a page that + ** is already in use as a btree page (isInit) or that another + ** cursor is currently referencing (refcount>1). Writing into + ** it would desynchronise that cursor's cached MemPage from the + ** page bytes. The same guard exists in + ** btreeOverwriteOverflowCell(). */ + sqlite3PagerUnref(pDbPage); + return SQLITE_CORRUPT_PAGE(pPage); + } aPayload = sqlite3PagerGetData(pDbPage); nextPage = get4byte(aPayload); rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);