summaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/recover/dbdata.c24
-rw-r--r--ext/recover/recovercorrupt2.test28
-rw-r--r--ext/recover/sqlite3recover.c2
-rw-r--r--ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js2
4 files changed, 49 insertions, 7 deletions
diff --git a/ext/recover/dbdata.c b/ext/recover/dbdata.c
index b6cb26e..ca63710 100644
--- a/ext/recover/dbdata.c
+++ b/ext/recover/dbdata.c
@@ -494,6 +494,15 @@ static void dbdataValue(
}
}
+/* This macro is a copy of the MX_CELL() macro in the SQLite core. Given
+** a page-size, it returns the maximum number of cells that may be present
+** on the page. */
+#define DBDATA_MX_CELL(pgsz) ((pgsz-8)/6)
+
+/* Maximum number of fields that may appear in a single record. This is
+** the "hard-limit", according to comments in sqliteLimit.h. */
+#define DBDATA_MX_FIELD 32676
+
/*
** Move an sqlite_dbdata or sqlite_dbptr cursor to the next entry.
*/
@@ -522,6 +531,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
assert( iOff+3+2<=pCsr->nPage );
pCsr->iCell = pTab->bPtr ? -2 : 0;
pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]);
+ if( pCsr->nCell>DBDATA_MX_CELL(pCsr->nPage) ){
+ pCsr->nCell = DBDATA_MX_CELL(pCsr->nPage);
+ }
}
if( pTab->bPtr ){
@@ -566,19 +578,19 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
if( pCsr->iCell>=pCsr->nCell ){
bNextPage = 1;
}else{
+ int iCellPtr = iOff + 8 + nPointer + pCsr->iCell*2;
- iOff += 8 + nPointer + pCsr->iCell*2;
- if( iOff>pCsr->nPage ){
+ if( iCellPtr>pCsr->nPage ){
bNextPage = 1;
}else{
- iOff = get_uint16(&pCsr->aPage[iOff]);
+ iOff = get_uint16(&pCsr->aPage[iCellPtr]);
}
/* For an interior node cell, skip past the child-page number */
iOff += nPointer;
/* Load the "byte of payload including overflow" field */
- if( bNextPage || iOff>pCsr->nPage ){
+ if( bNextPage || iOff>pCsr->nPage || iOff<=iCellPtr ){
bNextPage = 1;
}else{
iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
@@ -661,7 +673,9 @@ static int dbdataNext(sqlite3_vtab_cursor *pCursor){
pCsr->iField++;
if( pCsr->iField>0 ){
sqlite3_int64 iType;
- if( pCsr->pHdrPtr>&pCsr->pRec[pCsr->nRec] ){
+ if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec]
+ || pCsr->iField>=DBDATA_MX_FIELD
+ ){
bNextPage = 1;
}else{
int szField = 0;
diff --git a/ext/recover/recovercorrupt2.test b/ext/recover/recovercorrupt2.test
index 29acc27..6c21630 100644
--- a/ext/recover/recovercorrupt2.test
+++ b/ext/recover/recovercorrupt2.test
@@ -524,5 +524,33 @@ do_test 7.1 {
list [catch { $R finish } msg] $msg
} {1 {file is not a database}}
+reset_db
+breakpoint
+do_test 8.0 {
+ sqlite3 db {}
+ db deserialize [decode_hexdb {
+| size 8192 pagesize 4096 filename db.sqlite
+| page 1 offset 0
+| 0: ac ae b3 76 74 65 20 66 6f 72 6d 61 74 20 33 00 ...vte format 3.
+| 16: 10 00 01 01 00 40 20 20 00 00 00 01 00 00 00 02 .....@ ........
+| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
+| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
+| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ................
+| 96: 00 2e 76 8a 0d ff ff ff 1e 0f cb 00 0f cb 00 00 ..v.............
+| 4032: 00 00 00 00 00 00 00 00 00 00 00 33 01 06 17 19 ...........3....
+| 4048: 19 01 43 74 61 62 6c 65 54 61 62 6c 65 30 54 61 ..CtableTable0Ta
+| 4064: 62 6c 65 30 02 43 52 45 41 54 45 20 54 41 42 4c ble0.CREATE TABL
+| 4080: 45 20 54 61 62 6c 65 30 20 28 43 6f 6c 30 20 29 E Table0 (Col0 )
+| page 2 offset 4096
+| 0: 0d 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 ................
+| end db.sqlite
+}]} {}
+
+do_test 8.1 {
+ set R [sqlite3_recover_init db main test.db2]
+ catch { $R run }
+ list [catch { $R finish } msg] $msg
+} {0 {}}
+
finish_test
diff --git a/ext/recover/sqlite3recover.c b/ext/recover/sqlite3recover.c
index c445c51..1d858c0 100644
--- a/ext/recover/sqlite3recover.c
+++ b/ext/recover/sqlite3recover.c
@@ -1189,7 +1189,7 @@ static int recoverWriteSchema1(sqlite3_recover *p){
if( bTable && !bVirtual ){
if( SQLITE_ROW==sqlite3_step(pTblname) ){
const char *zTbl = (const char*)sqlite3_column_text(pTblname, 0);
- recoverAddTable(p, zTbl, iRoot);
+ if( zTbl ) recoverAddTable(p, zTbl, iRoot);
}
recoverReset(p, pTblname);
}
diff --git a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
index 870073c..2089ece 100644
--- a/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
+++ b/ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js
@@ -1271,7 +1271,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){
return poolUtil;
}).catch(async (e)=>{
await thePool.removeVfs().catch(()=>{});
- return e;
+ throw e;
});
}).catch((err)=>{
//error("rejecting promise:",err);