If there is no data available for a field in a corrupted record, but the type is available, have the recovery extension substitute 0, 0.0, '' or X'' instead of a NULL value.

FossilOrigin-Name: 78051359256c7e56a0aad5706bacbad5447b25ebef8088a6194886728d6deab4
(cherry picked from commit b856e0e76cef615da9cd1075f6dde9d0a85a010a)


Fix a problem causing the recovery extension to use excessive memory and CPU time in some cases.

FossilOrigin-Name: bc394acb6e6bcaccd17d8afe559d743799c0cb8d7aec709306181673a35dcb86
(cherry picked from commit 89282ca576e7b2bbfc1e4cd3642f5ddb02fac80a)
Bug: 336833464
Change-Id: Idfb69a8adeb23eb5b6a3f30736cc4f40be3ca1fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/sqlite/+/5541666
Reviewed-by: Evan Stade <[email protected]>
Commit-Queue: Nathan Memmott <[email protected]>
diff --git a/amalgamation/shell/shell.c b/amalgamation/shell/shell.c
index 5230da9..078c2f1 100644
--- a/amalgamation/shell/shell.c
+++ b/amalgamation/shell/shell.c
@@ -14347,6 +14347,15 @@
 
 typedef struct DbdataTable DbdataTable;
 typedef struct DbdataCursor DbdataCursor;
+typedef struct DbdataBuffer DbdataBuffer;
+
+/*
+** Buffer type.
+*/
+struct DbdataBuffer {
+  u8 *aBuf;
+  sqlite3_int64 nBuf;
+};
 
 /* Cursor object */
 struct DbdataCursor {
@@ -14363,7 +14372,7 @@
   sqlite3_int64 iRowid;
 
   /* Only for the sqlite_dbdata table */
-  u8 *pRec;                       /* Buffer containing current record */
+  DbdataBuffer rec;
   sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
   sqlite3_int64 nHdr;             /* Size of header in bytes */
   int iField;                     /* Current field number */
@@ -14409,6 +14418,31 @@
       ")"
 
 /*
+** Ensure the buffer passed as the first argument is at least nMin bytes
+** in size. If an error occurs while attempting to resize the buffer,
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
+  if( nMin>pBuf->nBuf ){
+    sqlite3_int64 nNew = nMin+16384;
+    u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
+
+    if( aNew==0 ) return SQLITE_NOMEM;
+    pBuf->aBuf = aNew;
+    pBuf->nBuf = nNew;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Release the allocation managed by buffer pBuf.
+*/
+static void dbdataBufferFree(DbdataBuffer *pBuf){
+  sqlite3_free(pBuf->aBuf);
+  memset(pBuf, 0, sizeof(*pBuf));
+}
+
+/*
 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual 
 ** table.
 */
@@ -14548,8 +14582,7 @@
   pCsr->iField = 0;
   pCsr->bOnePage = 0;
   sqlite3_free(pCsr->aPage);
-  sqlite3_free(pCsr->pRec);
-  pCsr->pRec = 0;
+  dbdataBufferFree(&pCsr->rec);
   pCsr->aPage = 0;
 }
 
@@ -14692,62 +14725,74 @@
   u8 *pData,
   sqlite3_int64 nData
 ){
-  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
-    switch( eType ){
-      case 0: 
-      case 10: 
-      case 11: 
-        sqlite3_result_null(pCtx);
-        break;
-      
-      case 8: 
-        sqlite3_result_int(pCtx, 0);
-        break;
-      case 9:
-        sqlite3_result_int(pCtx, 1);
-        break;
-  
-      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
-        sqlite3_uint64 v = (signed char)pData[0];
-        pData++;
-        switch( eType ){
-          case 7:
-          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 4:  v = (v<<8) + pData[0];  pData++;
-          case 3:  v = (v<<8) + pData[0];  pData++;
-          case 2:  v = (v<<8) + pData[0];  pData++;
-        }
-  
-        if( eType==7 ){
-          double r;
-          memcpy(&r, &v, sizeof(r));
-          sqlite3_result_double(pCtx, r);
-        }else{
-          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
-        }
-        break;
-      }
-  
-      default: {
-        int n = ((eType-12) / 2);
-        if( eType % 2 ){
-          switch( enc ){
-#ifndef SQLITE_OMIT_UTF16
-            case SQLITE_UTF16BE:
-              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-            case SQLITE_UTF16LE:
-              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-#endif
-            default:
-              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
-              break;
+  if( eType>=0 ){
+    if( dbdataValueBytes(eType)<=nData ){
+      switch( eType ){
+        case 0: 
+        case 10: 
+        case 11: 
+          sqlite3_result_null(pCtx);
+          break;
+        
+        case 8: 
+          sqlite3_result_int(pCtx, 0);
+          break;
+        case 9:
+          sqlite3_result_int(pCtx, 1);
+          break;
+    
+        case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+          sqlite3_uint64 v = (signed char)pData[0];
+          pData++;
+          switch( eType ){
+            case 7:
+            case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 4:  v = (v<<8) + pData[0];  pData++;
+            case 3:  v = (v<<8) + pData[0];  pData++;
+            case 2:  v = (v<<8) + pData[0];  pData++;
           }
-        }else{
-          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+    
+          if( eType==7 ){
+            double r;
+            memcpy(&r, &v, sizeof(r));
+            sqlite3_result_double(pCtx, r);
+          }else{
+            sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+          }
+          break;
         }
+    
+        default: {
+          int n = ((eType-12) / 2);
+          if( eType % 2 ){
+            switch( enc ){
+  #ifndef SQLITE_OMIT_UTF16
+              case SQLITE_UTF16BE:
+                sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+              case SQLITE_UTF16LE:
+                sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+  #endif
+              default:
+                sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+                break;
+            }
+          }else{
+            sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+          }
+        }
+      }
+    }else{
+      if( eType==7 ){
+        sqlite3_result_double(pCtx, 0.0);
+      }else if( eType<7 ){
+        sqlite3_result_int(pCtx, 0);
+      }else if( eType%2 ){
+        sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+      }else{
+        sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
       }
     }
   }
@@ -14810,7 +14855,7 @@
       }
     }else{
       /* If there is no record loaded, load it now. */
-      if( pCsr->pRec==0 ){
+      if( pCsr->nRec==0 ){
         int bHasRowid = 0;
         int nPointer = 0;
         sqlite3_int64 nPayload = 0;
@@ -14854,6 +14899,7 @@
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
             if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
+            if( nPayload==0 ) nPayload = 1;
           }
     
           /* If this is a leaf intkey cell, load the rowid */
@@ -14888,13 +14934,12 @@
             /* Allocate space for payload. And a bit more to catch small buffer
             ** overruns caused by attempting to read a varint or similar from 
             ** near the end of a corrupt record.  */
-            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
-            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
-            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
-            pCsr->nRec = nPayload;
+            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
+            if( rc!=SQLITE_OK ) return rc;
+            assert( nPayload!=0 );
 
             /* Load the nLocal bytes of payload */
-            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
+            memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
             iOff += nLocal;
 
             /* Load content from overflow pages */
@@ -14912,19 +14957,22 @@
 
                 nCopy = U-4;
                 if( nCopy>nRem ) nCopy = nRem;
-                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
+                memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
                 nRem -= nCopy;
 
                 pgnoOvfl = get_uint32(aOvfl);
                 sqlite3_free(aOvfl);
               }
+              nPayload -= nRem;
             }
+            memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
+            pCsr->nRec = nPayload;
     
-            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+            iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
             if( nHdr>nPayload ) nHdr = 0;
             pCsr->nHdr = nHdr;
-            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
-            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+            pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
+            pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
             pCsr->iField = (bHasRowid ? -1 : 0);
           }
         }
@@ -14932,7 +14980,7 @@
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec] 
+          if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec] 
            || pCsr->iField>=DBDATA_MX_FIELD
           ){
             bNextPage = 1;
@@ -14940,8 +14988,8 @@
             int szField = 0;
             pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
             szField = dbdataValueBytes(iType);
-            if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
-              pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
+            if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
+              pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
             }else{
               pCsr->pPtr += szField;
             }
@@ -14951,20 +14999,18 @@
 
       if( bNextPage ){
         sqlite3_free(pCsr->aPage);
-        sqlite3_free(pCsr->pRec);
         pCsr->aPage = 0;
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         if( pCsr->bOnePage ) return SQLITE_OK;
         pCsr->iPgno++;
       }else{
-        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
           return SQLITE_OK;
         }
 
         /* Advance to the next cell. The next iteration of the loop will load
         ** the record and so on. */
-        sqlite3_free(pCsr->pRec);
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         pCsr->iCell++;
       }
     }
@@ -15154,12 +15200,12 @@
       case DBDATA_COLUMN_VALUE: {
         if( pCsr->iField<0 ){
           sqlite3_result_int64(ctx, pCsr->iIntkey);
-        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
+        }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
           sqlite3_int64 iType;
           dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
           dbdataValue(
               ctx, pCsr->enc, iType, pCsr->pPtr, 
-              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+              &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
           );
         }
         break;
diff --git a/amalgamation/sqlite3.c b/amalgamation/sqlite3.c
index e7f7b27..7878abf 100644
--- a/amalgamation/sqlite3.c
+++ b/amalgamation/sqlite3.c
@@ -18,7 +18,7 @@
 ** separate file. This file contains only code for the core SQLite library.
 **
 ** The content in this amalgamation comes from Fossil check-in
-** c0b03aa071b8b0936237d880e5c46eef604a with changes in files:
+** a58bd3cd7e0eae429f4b0aa288be7cc7783b with changes in files:
 **
 **    manifest.uuid
 */
@@ -463,7 +463,7 @@
 */
 #define SQLITE_VERSION        "3.45.2"
 #define SQLITE_VERSION_NUMBER 3045002
-#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 c0b03aa071b8b0936237d880e5c46eef604af4ef77d91f73984b3253267ab149"
+#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 a58bd3cd7e0eae429f4b0aa288be7cc7783b9798674bc0e4adde311f23a3e3cd"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -258507,6 +258507,15 @@
 
 typedef struct DbdataTable DbdataTable;
 typedef struct DbdataCursor DbdataCursor;
+typedef struct DbdataBuffer DbdataBuffer;
+
+/*
+** Buffer type.
+*/
+struct DbdataBuffer {
+  u8 *aBuf;
+  sqlite3_int64 nBuf;
+};
 
 /* Cursor object */
 struct DbdataCursor {
@@ -258523,7 +258532,7 @@
   sqlite3_int64 iRowid;
 
   /* Only for the sqlite_dbdata table */
-  u8 *pRec;                       /* Buffer containing current record */
+  DbdataBuffer rec;
   sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
   sqlite3_int64 nHdr;             /* Size of header in bytes */
   int iField;                     /* Current field number */
@@ -258569,6 +258578,31 @@
       ")"
 
 /*
+** Ensure the buffer passed as the first argument is at least nMin bytes
+** in size. If an error occurs while attempting to resize the buffer,
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
+  if( nMin>pBuf->nBuf ){
+    sqlite3_int64 nNew = nMin+16384;
+    u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
+
+    if( aNew==0 ) return SQLITE_NOMEM;
+    pBuf->aBuf = aNew;
+    pBuf->nBuf = nNew;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Release the allocation managed by buffer pBuf.
+*/
+static void dbdataBufferFree(DbdataBuffer *pBuf){
+  sqlite3_free(pBuf->aBuf);
+  memset(pBuf, 0, sizeof(*pBuf));
+}
+
+/*
 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
 ** table.
 */
@@ -258708,8 +258742,7 @@
   pCsr->iField = 0;
   pCsr->bOnePage = 0;
   sqlite3_free(pCsr->aPage);
-  sqlite3_free(pCsr->pRec);
-  pCsr->pRec = 0;
+  dbdataBufferFree(&pCsr->rec);
   pCsr->aPage = 0;
 }
 
@@ -258852,62 +258885,74 @@
   u8 *pData,
   sqlite3_int64 nData
 ){
-  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
-    switch( eType ){
-      case 0:
-      case 10:
-      case 11:
-        sqlite3_result_null(pCtx);
-        break;
+  if( eType>=0 ){
+    if( dbdataValueBytes(eType)<=nData ){
+      switch( eType ){
+        case 0:
+        case 10:
+        case 11:
+          sqlite3_result_null(pCtx);
+          break;
 
-      case 8:
-        sqlite3_result_int(pCtx, 0);
-        break;
-      case 9:
-        sqlite3_result_int(pCtx, 1);
-        break;
+        case 8:
+          sqlite3_result_int(pCtx, 0);
+          break;
+        case 9:
+          sqlite3_result_int(pCtx, 1);
+          break;
 
-      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
-        sqlite3_uint64 v = (signed char)pData[0];
-        pData++;
-        switch( eType ){
-          case 7:
-          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 4:  v = (v<<8) + pData[0];  pData++;
-          case 3:  v = (v<<8) + pData[0];  pData++;
-          case 2:  v = (v<<8) + pData[0];  pData++;
-        }
-
-        if( eType==7 ){
-          double r;
-          memcpy(&r, &v, sizeof(r));
-          sqlite3_result_double(pCtx, r);
-        }else{
-          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
-        }
-        break;
-      }
-
-      default: {
-        int n = ((eType-12) / 2);
-        if( eType % 2 ){
-          switch( enc ){
-#ifndef SQLITE_OMIT_UTF16
-            case SQLITE_UTF16BE:
-              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-            case SQLITE_UTF16LE:
-              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-#endif
-            default:
-              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
-              break;
+        case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+          sqlite3_uint64 v = (signed char)pData[0];
+          pData++;
+          switch( eType ){
+            case 7:
+            case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 4:  v = (v<<8) + pData[0];  pData++;
+            case 3:  v = (v<<8) + pData[0];  pData++;
+            case 2:  v = (v<<8) + pData[0];  pData++;
           }
-        }else{
-          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+
+          if( eType==7 ){
+            double r;
+            memcpy(&r, &v, sizeof(r));
+            sqlite3_result_double(pCtx, r);
+          }else{
+            sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+          }
+          break;
         }
+
+        default: {
+          int n = ((eType-12) / 2);
+          if( eType % 2 ){
+            switch( enc ){
+  #ifndef SQLITE_OMIT_UTF16
+              case SQLITE_UTF16BE:
+                sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+              case SQLITE_UTF16LE:
+                sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+  #endif
+              default:
+                sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+                break;
+            }
+          }else{
+            sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+          }
+        }
+      }
+    }else{
+      if( eType==7 ){
+        sqlite3_result_double(pCtx, 0.0);
+      }else if( eType<7 ){
+        sqlite3_result_int(pCtx, 0);
+      }else if( eType%2 ){
+        sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+      }else{
+        sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
       }
     }
   }
@@ -258970,7 +259015,7 @@
       }
     }else{
       /* If there is no record loaded, load it now. */
-      if( pCsr->pRec==0 ){
+      if( pCsr->nRec==0 ){
         int bHasRowid = 0;
         int nPointer = 0;
         sqlite3_int64 nPayload = 0;
@@ -259014,6 +259059,7 @@
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
             if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
+            if( nPayload==0 ) nPayload = 1;
           }
 
           /* If this is a leaf intkey cell, load the rowid */
@@ -259048,13 +259094,12 @@
             /* Allocate space for payload. And a bit more to catch small buffer
             ** overruns caused by attempting to read a varint or similar from
             ** near the end of a corrupt record.  */
-            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
-            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
-            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
-            pCsr->nRec = nPayload;
+            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
+            if( rc!=SQLITE_OK ) return rc;
+            assert( nPayload!=0 );
 
             /* Load the nLocal bytes of payload */
-            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
+            memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
             iOff += nLocal;
 
             /* Load content from overflow pages */
@@ -259072,19 +259117,22 @@
 
                 nCopy = U-4;
                 if( nCopy>nRem ) nCopy = nRem;
-                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
+                memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
                 nRem -= nCopy;
 
                 pgnoOvfl = get_uint32(aOvfl);
                 sqlite3_free(aOvfl);
               }
+              nPayload -= nRem;
             }
+            memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
+            pCsr->nRec = nPayload;
 
-            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+            iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
             if( nHdr>nPayload ) nHdr = 0;
             pCsr->nHdr = nHdr;
-            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
-            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+            pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
+            pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
             pCsr->iField = (bHasRowid ? -1 : 0);
           }
         }
@@ -259092,7 +259140,7 @@
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec]
+          if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
            || pCsr->iField>=DBDATA_MX_FIELD
           ){
             bNextPage = 1;
@@ -259100,8 +259148,8 @@
             int szField = 0;
             pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
             szField = dbdataValueBytes(iType);
-            if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
-              pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
+            if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
+              pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
             }else{
               pCsr->pPtr += szField;
             }
@@ -259111,20 +259159,18 @@
 
       if( bNextPage ){
         sqlite3_free(pCsr->aPage);
-        sqlite3_free(pCsr->pRec);
         pCsr->aPage = 0;
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         if( pCsr->bOnePage ) return SQLITE_OK;
         pCsr->iPgno++;
       }else{
-        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
           return SQLITE_OK;
         }
 
         /* Advance to the next cell. The next iteration of the loop will load
         ** the record and so on. */
-        sqlite3_free(pCsr->pRec);
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         pCsr->iCell++;
       }
     }
@@ -259314,12 +259360,12 @@
       case DBDATA_COLUMN_VALUE: {
         if( pCsr->iField<0 ){
           sqlite3_result_int64(ctx, pCsr->iIntkey);
-        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
+        }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
           sqlite3_int64 iType;
           dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
           dbdataValue(
               ctx, pCsr->enc, iType, pCsr->pPtr,
-              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+              &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
           );
         }
         break;
diff --git a/amalgamation/sqlite3.h b/amalgamation/sqlite3.h
index afe3715..8ace9da 100644
--- a/amalgamation/sqlite3.h
+++ b/amalgamation/sqlite3.h
@@ -148,7 +148,7 @@
 */
 #define SQLITE_VERSION        "3.45.2"
 #define SQLITE_VERSION_NUMBER 3045002
-#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 c0b03aa071b8b0936237d880e5c46eef604af4ef77d91f73984b3253267ab149"
+#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 a58bd3cd7e0eae429f4b0aa288be7cc7783b9798674bc0e4adde311f23a3e3cd"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
diff --git a/amalgamation_dev/shell/shell.c b/amalgamation_dev/shell/shell.c
index 5230da9..078c2f1 100644
--- a/amalgamation_dev/shell/shell.c
+++ b/amalgamation_dev/shell/shell.c
@@ -14347,6 +14347,15 @@
 
 typedef struct DbdataTable DbdataTable;
 typedef struct DbdataCursor DbdataCursor;
+typedef struct DbdataBuffer DbdataBuffer;
+
+/*
+** Buffer type.
+*/
+struct DbdataBuffer {
+  u8 *aBuf;
+  sqlite3_int64 nBuf;
+};
 
 /* Cursor object */
 struct DbdataCursor {
@@ -14363,7 +14372,7 @@
   sqlite3_int64 iRowid;
 
   /* Only for the sqlite_dbdata table */
-  u8 *pRec;                       /* Buffer containing current record */
+  DbdataBuffer rec;
   sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
   sqlite3_int64 nHdr;             /* Size of header in bytes */
   int iField;                     /* Current field number */
@@ -14409,6 +14418,31 @@
       ")"
 
 /*
+** Ensure the buffer passed as the first argument is at least nMin bytes
+** in size. If an error occurs while attempting to resize the buffer,
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
+  if( nMin>pBuf->nBuf ){
+    sqlite3_int64 nNew = nMin+16384;
+    u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
+
+    if( aNew==0 ) return SQLITE_NOMEM;
+    pBuf->aBuf = aNew;
+    pBuf->nBuf = nNew;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Release the allocation managed by buffer pBuf.
+*/
+static void dbdataBufferFree(DbdataBuffer *pBuf){
+  sqlite3_free(pBuf->aBuf);
+  memset(pBuf, 0, sizeof(*pBuf));
+}
+
+/*
 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual 
 ** table.
 */
@@ -14548,8 +14582,7 @@
   pCsr->iField = 0;
   pCsr->bOnePage = 0;
   sqlite3_free(pCsr->aPage);
-  sqlite3_free(pCsr->pRec);
-  pCsr->pRec = 0;
+  dbdataBufferFree(&pCsr->rec);
   pCsr->aPage = 0;
 }
 
@@ -14692,62 +14725,74 @@
   u8 *pData,
   sqlite3_int64 nData
 ){
-  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
-    switch( eType ){
-      case 0: 
-      case 10: 
-      case 11: 
-        sqlite3_result_null(pCtx);
-        break;
-      
-      case 8: 
-        sqlite3_result_int(pCtx, 0);
-        break;
-      case 9:
-        sqlite3_result_int(pCtx, 1);
-        break;
-  
-      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
-        sqlite3_uint64 v = (signed char)pData[0];
-        pData++;
-        switch( eType ){
-          case 7:
-          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 4:  v = (v<<8) + pData[0];  pData++;
-          case 3:  v = (v<<8) + pData[0];  pData++;
-          case 2:  v = (v<<8) + pData[0];  pData++;
-        }
-  
-        if( eType==7 ){
-          double r;
-          memcpy(&r, &v, sizeof(r));
-          sqlite3_result_double(pCtx, r);
-        }else{
-          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
-        }
-        break;
-      }
-  
-      default: {
-        int n = ((eType-12) / 2);
-        if( eType % 2 ){
-          switch( enc ){
-#ifndef SQLITE_OMIT_UTF16
-            case SQLITE_UTF16BE:
-              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-            case SQLITE_UTF16LE:
-              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-#endif
-            default:
-              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
-              break;
+  if( eType>=0 ){
+    if( dbdataValueBytes(eType)<=nData ){
+      switch( eType ){
+        case 0: 
+        case 10: 
+        case 11: 
+          sqlite3_result_null(pCtx);
+          break;
+        
+        case 8: 
+          sqlite3_result_int(pCtx, 0);
+          break;
+        case 9:
+          sqlite3_result_int(pCtx, 1);
+          break;
+    
+        case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+          sqlite3_uint64 v = (signed char)pData[0];
+          pData++;
+          switch( eType ){
+            case 7:
+            case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 4:  v = (v<<8) + pData[0];  pData++;
+            case 3:  v = (v<<8) + pData[0];  pData++;
+            case 2:  v = (v<<8) + pData[0];  pData++;
           }
-        }else{
-          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+    
+          if( eType==7 ){
+            double r;
+            memcpy(&r, &v, sizeof(r));
+            sqlite3_result_double(pCtx, r);
+          }else{
+            sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+          }
+          break;
         }
+    
+        default: {
+          int n = ((eType-12) / 2);
+          if( eType % 2 ){
+            switch( enc ){
+  #ifndef SQLITE_OMIT_UTF16
+              case SQLITE_UTF16BE:
+                sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+              case SQLITE_UTF16LE:
+                sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+  #endif
+              default:
+                sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+                break;
+            }
+          }else{
+            sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+          }
+        }
+      }
+    }else{
+      if( eType==7 ){
+        sqlite3_result_double(pCtx, 0.0);
+      }else if( eType<7 ){
+        sqlite3_result_int(pCtx, 0);
+      }else if( eType%2 ){
+        sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+      }else{
+        sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
       }
     }
   }
@@ -14810,7 +14855,7 @@
       }
     }else{
       /* If there is no record loaded, load it now. */
-      if( pCsr->pRec==0 ){
+      if( pCsr->nRec==0 ){
         int bHasRowid = 0;
         int nPointer = 0;
         sqlite3_int64 nPayload = 0;
@@ -14854,6 +14899,7 @@
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
             if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
+            if( nPayload==0 ) nPayload = 1;
           }
     
           /* If this is a leaf intkey cell, load the rowid */
@@ -14888,13 +14934,12 @@
             /* Allocate space for payload. And a bit more to catch small buffer
             ** overruns caused by attempting to read a varint or similar from 
             ** near the end of a corrupt record.  */
-            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
-            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
-            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
-            pCsr->nRec = nPayload;
+            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
+            if( rc!=SQLITE_OK ) return rc;
+            assert( nPayload!=0 );
 
             /* Load the nLocal bytes of payload */
-            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
+            memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
             iOff += nLocal;
 
             /* Load content from overflow pages */
@@ -14912,19 +14957,22 @@
 
                 nCopy = U-4;
                 if( nCopy>nRem ) nCopy = nRem;
-                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
+                memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
                 nRem -= nCopy;
 
                 pgnoOvfl = get_uint32(aOvfl);
                 sqlite3_free(aOvfl);
               }
+              nPayload -= nRem;
             }
+            memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
+            pCsr->nRec = nPayload;
     
-            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+            iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
             if( nHdr>nPayload ) nHdr = 0;
             pCsr->nHdr = nHdr;
-            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
-            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+            pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
+            pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
             pCsr->iField = (bHasRowid ? -1 : 0);
           }
         }
@@ -14932,7 +14980,7 @@
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec] 
+          if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec] 
            || pCsr->iField>=DBDATA_MX_FIELD
           ){
             bNextPage = 1;
@@ -14940,8 +14988,8 @@
             int szField = 0;
             pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
             szField = dbdataValueBytes(iType);
-            if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
-              pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
+            if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
+              pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
             }else{
               pCsr->pPtr += szField;
             }
@@ -14951,20 +14999,18 @@
 
       if( bNextPage ){
         sqlite3_free(pCsr->aPage);
-        sqlite3_free(pCsr->pRec);
         pCsr->aPage = 0;
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         if( pCsr->bOnePage ) return SQLITE_OK;
         pCsr->iPgno++;
       }else{
-        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
           return SQLITE_OK;
         }
 
         /* Advance to the next cell. The next iteration of the loop will load
         ** the record and so on. */
-        sqlite3_free(pCsr->pRec);
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         pCsr->iCell++;
       }
     }
@@ -15154,12 +15200,12 @@
       case DBDATA_COLUMN_VALUE: {
         if( pCsr->iField<0 ){
           sqlite3_result_int64(ctx, pCsr->iIntkey);
-        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
+        }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
           sqlite3_int64 iType;
           dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
           dbdataValue(
               ctx, pCsr->enc, iType, pCsr->pPtr, 
-              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+              &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
           );
         }
         break;
diff --git a/amalgamation_dev/sqlite3.c b/amalgamation_dev/sqlite3.c
index 1583c4f..b1e0e62 100644
--- a/amalgamation_dev/sqlite3.c
+++ b/amalgamation_dev/sqlite3.c
@@ -18,7 +18,7 @@
 ** separate file. This file contains only code for the core SQLite library.
 **
 ** The content in this amalgamation comes from Fossil check-in
-** c0b03aa071b8b0936237d880e5c46eef604a with changes in files:
+** a58bd3cd7e0eae429f4b0aa288be7cc7783b with changes in files:
 **
 **    manifest.uuid
 */
@@ -463,7 +463,7 @@
 */
 #define SQLITE_VERSION        "3.45.2"
 #define SQLITE_VERSION_NUMBER 3045002
-#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 c0b03aa071b8b0936237d880e5c46eef604af4ef77d91f73984b3253267ab149"
+#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 a58bd3cd7e0eae429f4b0aa288be7cc7783b9798674bc0e4adde311f23a3e3cd"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -259026,6 +259026,15 @@
 
 typedef struct DbdataTable DbdataTable;
 typedef struct DbdataCursor DbdataCursor;
+typedef struct DbdataBuffer DbdataBuffer;
+
+/*
+** Buffer type.
+*/
+struct DbdataBuffer {
+  u8 *aBuf;
+  sqlite3_int64 nBuf;
+};
 
 /* Cursor object */
 struct DbdataCursor {
@@ -259042,7 +259051,7 @@
   sqlite3_int64 iRowid;
 
   /* Only for the sqlite_dbdata table */
-  u8 *pRec;                       /* Buffer containing current record */
+  DbdataBuffer rec;
   sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
   sqlite3_int64 nHdr;             /* Size of header in bytes */
   int iField;                     /* Current field number */
@@ -259088,6 +259097,31 @@
       ")"
 
 /*
+** Ensure the buffer passed as the first argument is at least nMin bytes
+** in size. If an error occurs while attempting to resize the buffer,
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
+  if( nMin>pBuf->nBuf ){
+    sqlite3_int64 nNew = nMin+16384;
+    u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
+
+    if( aNew==0 ) return SQLITE_NOMEM;
+    pBuf->aBuf = aNew;
+    pBuf->nBuf = nNew;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Release the allocation managed by buffer pBuf.
+*/
+static void dbdataBufferFree(DbdataBuffer *pBuf){
+  sqlite3_free(pBuf->aBuf);
+  memset(pBuf, 0, sizeof(*pBuf));
+}
+
+/*
 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual
 ** table.
 */
@@ -259227,8 +259261,7 @@
   pCsr->iField = 0;
   pCsr->bOnePage = 0;
   sqlite3_free(pCsr->aPage);
-  sqlite3_free(pCsr->pRec);
-  pCsr->pRec = 0;
+  dbdataBufferFree(&pCsr->rec);
   pCsr->aPage = 0;
 }
 
@@ -259371,62 +259404,74 @@
   u8 *pData,
   sqlite3_int64 nData
 ){
-  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
-    switch( eType ){
-      case 0:
-      case 10:
-      case 11:
-        sqlite3_result_null(pCtx);
-        break;
+  if( eType>=0 ){
+    if( dbdataValueBytes(eType)<=nData ){
+      switch( eType ){
+        case 0:
+        case 10:
+        case 11:
+          sqlite3_result_null(pCtx);
+          break;
 
-      case 8:
-        sqlite3_result_int(pCtx, 0);
-        break;
-      case 9:
-        sqlite3_result_int(pCtx, 1);
-        break;
+        case 8:
+          sqlite3_result_int(pCtx, 0);
+          break;
+        case 9:
+          sqlite3_result_int(pCtx, 1);
+          break;
 
-      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
-        sqlite3_uint64 v = (signed char)pData[0];
-        pData++;
-        switch( eType ){
-          case 7:
-          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 4:  v = (v<<8) + pData[0];  pData++;
-          case 3:  v = (v<<8) + pData[0];  pData++;
-          case 2:  v = (v<<8) + pData[0];  pData++;
-        }
-
-        if( eType==7 ){
-          double r;
-          memcpy(&r, &v, sizeof(r));
-          sqlite3_result_double(pCtx, r);
-        }else{
-          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
-        }
-        break;
-      }
-
-      default: {
-        int n = ((eType-12) / 2);
-        if( eType % 2 ){
-          switch( enc ){
-#ifndef SQLITE_OMIT_UTF16
-            case SQLITE_UTF16BE:
-              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-            case SQLITE_UTF16LE:
-              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-#endif
-            default:
-              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
-              break;
+        case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+          sqlite3_uint64 v = (signed char)pData[0];
+          pData++;
+          switch( eType ){
+            case 7:
+            case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 4:  v = (v<<8) + pData[0];  pData++;
+            case 3:  v = (v<<8) + pData[0];  pData++;
+            case 2:  v = (v<<8) + pData[0];  pData++;
           }
-        }else{
-          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+
+          if( eType==7 ){
+            double r;
+            memcpy(&r, &v, sizeof(r));
+            sqlite3_result_double(pCtx, r);
+          }else{
+            sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+          }
+          break;
         }
+
+        default: {
+          int n = ((eType-12) / 2);
+          if( eType % 2 ){
+            switch( enc ){
+  #ifndef SQLITE_OMIT_UTF16
+              case SQLITE_UTF16BE:
+                sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+              case SQLITE_UTF16LE:
+                sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+  #endif
+              default:
+                sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+                break;
+            }
+          }else{
+            sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+          }
+        }
+      }
+    }else{
+      if( eType==7 ){
+        sqlite3_result_double(pCtx, 0.0);
+      }else if( eType<7 ){
+        sqlite3_result_int(pCtx, 0);
+      }else if( eType%2 ){
+        sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+      }else{
+        sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
       }
     }
   }
@@ -259489,7 +259534,7 @@
       }
     }else{
       /* If there is no record loaded, load it now. */
-      if( pCsr->pRec==0 ){
+      if( pCsr->nRec==0 ){
         int bHasRowid = 0;
         int nPointer = 0;
         sqlite3_int64 nPayload = 0;
@@ -259533,6 +259578,7 @@
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
             if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
+            if( nPayload==0 ) nPayload = 1;
           }
 
           /* If this is a leaf intkey cell, load the rowid */
@@ -259567,13 +259613,12 @@
             /* Allocate space for payload. And a bit more to catch small buffer
             ** overruns caused by attempting to read a varint or similar from
             ** near the end of a corrupt record.  */
-            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
-            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
-            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
-            pCsr->nRec = nPayload;
+            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
+            if( rc!=SQLITE_OK ) return rc;
+            assert( nPayload!=0 );
 
             /* Load the nLocal bytes of payload */
-            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
+            memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
             iOff += nLocal;
 
             /* Load content from overflow pages */
@@ -259591,19 +259636,22 @@
 
                 nCopy = U-4;
                 if( nCopy>nRem ) nCopy = nRem;
-                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
+                memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
                 nRem -= nCopy;
 
                 pgnoOvfl = get_uint32(aOvfl);
                 sqlite3_free(aOvfl);
               }
+              nPayload -= nRem;
             }
+            memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
+            pCsr->nRec = nPayload;
 
-            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+            iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
             if( nHdr>nPayload ) nHdr = 0;
             pCsr->nHdr = nHdr;
-            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
-            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+            pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
+            pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
             pCsr->iField = (bHasRowid ? -1 : 0);
           }
         }
@@ -259611,7 +259659,7 @@
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec]
+          if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec]
            || pCsr->iField>=DBDATA_MX_FIELD
           ){
             bNextPage = 1;
@@ -259619,8 +259667,8 @@
             int szField = 0;
             pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
             szField = dbdataValueBytes(iType);
-            if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
-              pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
+            if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
+              pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
             }else{
               pCsr->pPtr += szField;
             }
@@ -259630,20 +259678,18 @@
 
       if( bNextPage ){
         sqlite3_free(pCsr->aPage);
-        sqlite3_free(pCsr->pRec);
         pCsr->aPage = 0;
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         if( pCsr->bOnePage ) return SQLITE_OK;
         pCsr->iPgno++;
       }else{
-        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
           return SQLITE_OK;
         }
 
         /* Advance to the next cell. The next iteration of the loop will load
         ** the record and so on. */
-        sqlite3_free(pCsr->pRec);
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         pCsr->iCell++;
       }
     }
@@ -259833,12 +259879,12 @@
       case DBDATA_COLUMN_VALUE: {
         if( pCsr->iField<0 ){
           sqlite3_result_int64(ctx, pCsr->iIntkey);
-        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
+        }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
           sqlite3_int64 iType;
           dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
           dbdataValue(
               ctx, pCsr->enc, iType, pCsr->pPtr,
-              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+              &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
           );
         }
         break;
diff --git a/amalgamation_dev/sqlite3.h b/amalgamation_dev/sqlite3.h
index afe3715..8ace9da 100644
--- a/amalgamation_dev/sqlite3.h
+++ b/amalgamation_dev/sqlite3.h
@@ -148,7 +148,7 @@
 */
 #define SQLITE_VERSION        "3.45.2"
 #define SQLITE_VERSION_NUMBER 3045002
-#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 c0b03aa071b8b0936237d880e5c46eef604af4ef77d91f73984b3253267ab149"
+#define SQLITE_SOURCE_ID      "2024-03-12 11:06:23 a58bd3cd7e0eae429f4b0aa288be7cc7783b9798674bc0e4adde311f23a3e3cd"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
diff --git a/ext/recover/dbdata.c b/ext/recover/dbdata.c
index ca63710..a999f1a 100644
--- a/ext/recover/dbdata.c
+++ b/ext/recover/dbdata.c
@@ -88,6 +88,15 @@
 
 typedef struct DbdataTable DbdataTable;
 typedef struct DbdataCursor DbdataCursor;
+typedef struct DbdataBuffer DbdataBuffer;
+
+/*
+** Buffer type.
+*/
+struct DbdataBuffer {
+  u8 *aBuf;
+  sqlite3_int64 nBuf;
+};
 
 /* Cursor object */
 struct DbdataCursor {
@@ -104,7 +113,7 @@
   sqlite3_int64 iRowid;
 
   /* Only for the sqlite_dbdata table */
-  u8 *pRec;                       /* Buffer containing current record */
+  DbdataBuffer rec;
   sqlite3_int64 nRec;             /* Size of pRec[] in bytes */
   sqlite3_int64 nHdr;             /* Size of header in bytes */
   int iField;                     /* Current field number */
@@ -150,6 +159,31 @@
       ")"
 
 /*
+** Ensure the buffer passed as the first argument is at least nMin bytes
+** in size. If an error occurs while attempting to resize the buffer,
+** SQLITE_NOMEM is returned. Otherwise, SQLITE_OK.
+*/
+static int dbdataBufferSize(DbdataBuffer *pBuf, sqlite3_int64 nMin){
+  if( nMin>pBuf->nBuf ){
+    sqlite3_int64 nNew = nMin+16384;
+    u8 *aNew = (u8*)sqlite3_realloc64(pBuf->aBuf, nNew);
+
+    if( aNew==0 ) return SQLITE_NOMEM;
+    pBuf->aBuf = aNew;
+    pBuf->nBuf = nNew;
+  }
+  return SQLITE_OK;
+}
+
+/*
+** Release the allocation managed by buffer pBuf.
+*/
+static void dbdataBufferFree(DbdataBuffer *pBuf){
+  sqlite3_free(pBuf->aBuf);
+  memset(pBuf, 0, sizeof(*pBuf));
+}
+
+/*
 ** Connect to an sqlite_dbdata (pAux==0) or sqlite_dbptr (pAux!=0) virtual 
 ** table.
 */
@@ -289,8 +323,7 @@
   pCsr->iField = 0;
   pCsr->bOnePage = 0;
   sqlite3_free(pCsr->aPage);
-  sqlite3_free(pCsr->pRec);
-  pCsr->pRec = 0;
+  dbdataBufferFree(&pCsr->rec);
   pCsr->aPage = 0;
 }
 
@@ -433,62 +466,74 @@
   u8 *pData,
   sqlite3_int64 nData
 ){
-  if( eType>=0 && dbdataValueBytes(eType)<=nData ){
-    switch( eType ){
-      case 0: 
-      case 10: 
-      case 11: 
-        sqlite3_result_null(pCtx);
-        break;
-      
-      case 8: 
-        sqlite3_result_int(pCtx, 0);
-        break;
-      case 9:
-        sqlite3_result_int(pCtx, 1);
-        break;
-  
-      case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
-        sqlite3_uint64 v = (signed char)pData[0];
-        pData++;
-        switch( eType ){
-          case 7:
-          case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
-          case 4:  v = (v<<8) + pData[0];  pData++;
-          case 3:  v = (v<<8) + pData[0];  pData++;
-          case 2:  v = (v<<8) + pData[0];  pData++;
-        }
-  
-        if( eType==7 ){
-          double r;
-          memcpy(&r, &v, sizeof(r));
-          sqlite3_result_double(pCtx, r);
-        }else{
-          sqlite3_result_int64(pCtx, (sqlite3_int64)v);
-        }
-        break;
-      }
-  
-      default: {
-        int n = ((eType-12) / 2);
-        if( eType % 2 ){
-          switch( enc ){
-#ifndef SQLITE_OMIT_UTF16
-            case SQLITE_UTF16BE:
-              sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-            case SQLITE_UTF16LE:
-              sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
-              break;
-#endif
-            default:
-              sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
-              break;
+  if( eType>=0 ){
+    if( dbdataValueBytes(eType)<=nData ){
+      switch( eType ){
+        case 0: 
+        case 10: 
+        case 11: 
+          sqlite3_result_null(pCtx);
+          break;
+        
+        case 8: 
+          sqlite3_result_int(pCtx, 0);
+          break;
+        case 9:
+          sqlite3_result_int(pCtx, 1);
+          break;
+    
+        case 1: case 2: case 3: case 4: case 5: case 6: case 7: {
+          sqlite3_uint64 v = (signed char)pData[0];
+          pData++;
+          switch( eType ){
+            case 7:
+            case 6:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 5:  v = (v<<16) + (pData[0]<<8) + pData[1];  pData += 2;
+            case 4:  v = (v<<8) + pData[0];  pData++;
+            case 3:  v = (v<<8) + pData[0];  pData++;
+            case 2:  v = (v<<8) + pData[0];  pData++;
           }
-        }else{
-          sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+    
+          if( eType==7 ){
+            double r;
+            memcpy(&r, &v, sizeof(r));
+            sqlite3_result_double(pCtx, r);
+          }else{
+            sqlite3_result_int64(pCtx, (sqlite3_int64)v);
+          }
+          break;
         }
+    
+        default: {
+          int n = ((eType-12) / 2);
+          if( eType % 2 ){
+            switch( enc ){
+  #ifndef SQLITE_OMIT_UTF16
+              case SQLITE_UTF16BE:
+                sqlite3_result_text16be(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+              case SQLITE_UTF16LE:
+                sqlite3_result_text16le(pCtx, (void*)pData, n, SQLITE_TRANSIENT);
+                break;
+  #endif
+              default:
+                sqlite3_result_text(pCtx, (char*)pData, n, SQLITE_TRANSIENT);
+                break;
+            }
+          }else{
+            sqlite3_result_blob(pCtx, pData, n, SQLITE_TRANSIENT);
+          }
+        }
+      }
+    }else{
+      if( eType==7 ){
+        sqlite3_result_double(pCtx, 0.0);
+      }else if( eType<7 ){
+        sqlite3_result_int(pCtx, 0);
+      }else if( eType%2 ){
+        sqlite3_result_text(pCtx, "", 0, SQLITE_STATIC);
+      }else{
+        sqlite3_result_blob(pCtx, "", 0, SQLITE_STATIC);
       }
     }
   }
@@ -551,7 +596,7 @@
       }
     }else{
       /* If there is no record loaded, load it now. */
-      if( pCsr->pRec==0 ){
+      if( pCsr->nRec==0 ){
         int bHasRowid = 0;
         int nPointer = 0;
         sqlite3_int64 nPayload = 0;
@@ -595,6 +640,7 @@
           }else{
             iOff += dbdataGetVarintU32(&pCsr->aPage[iOff], &nPayload);
             if( nPayload>0x7fffff00 ) nPayload &= 0x3fff;
+            if( nPayload==0 ) nPayload = 1;
           }
     
           /* If this is a leaf intkey cell, load the rowid */
@@ -629,13 +675,12 @@
             /* Allocate space for payload. And a bit more to catch small buffer
             ** overruns caused by attempting to read a varint or similar from 
             ** near the end of a corrupt record.  */
-            pCsr->pRec = (u8*)sqlite3_malloc64(nPayload+DBDATA_PADDING_BYTES);
-            if( pCsr->pRec==0 ) return SQLITE_NOMEM;
-            memset(pCsr->pRec, 0, nPayload+DBDATA_PADDING_BYTES);
-            pCsr->nRec = nPayload;
+            rc = dbdataBufferSize(&pCsr->rec, nPayload+DBDATA_PADDING_BYTES);
+            if( rc!=SQLITE_OK ) return rc;
+            assert( nPayload!=0 );
 
             /* Load the nLocal bytes of payload */
-            memcpy(pCsr->pRec, &pCsr->aPage[iOff], nLocal);
+            memcpy(pCsr->rec.aBuf, &pCsr->aPage[iOff], nLocal);
             iOff += nLocal;
 
             /* Load content from overflow pages */
@@ -653,19 +698,22 @@
 
                 nCopy = U-4;
                 if( nCopy>nRem ) nCopy = nRem;
-                memcpy(&pCsr->pRec[nPayload-nRem], &aOvfl[4], nCopy);
+                memcpy(&pCsr->rec.aBuf[nPayload-nRem], &aOvfl[4], nCopy);
                 nRem -= nCopy;
 
                 pgnoOvfl = get_uint32(aOvfl);
                 sqlite3_free(aOvfl);
               }
+              nPayload -= nRem;
             }
+            memset(&pCsr->rec.aBuf[nPayload], 0, DBDATA_PADDING_BYTES);
+            pCsr->nRec = nPayload;
     
-            iHdr = dbdataGetVarintU32(pCsr->pRec, &nHdr);
+            iHdr = dbdataGetVarintU32(pCsr->rec.aBuf, &nHdr);
             if( nHdr>nPayload ) nHdr = 0;
             pCsr->nHdr = nHdr;
-            pCsr->pHdrPtr = &pCsr->pRec[iHdr];
-            pCsr->pPtr = &pCsr->pRec[pCsr->nHdr];
+            pCsr->pHdrPtr = &pCsr->rec.aBuf[iHdr];
+            pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nHdr];
             pCsr->iField = (bHasRowid ? -1 : 0);
           }
         }
@@ -673,7 +721,7 @@
         pCsr->iField++;
         if( pCsr->iField>0 ){
           sqlite3_int64 iType;
-          if( pCsr->pHdrPtr>=&pCsr->pRec[pCsr->nRec] 
+          if( pCsr->pHdrPtr>=&pCsr->rec.aBuf[pCsr->nRec] 
            || pCsr->iField>=DBDATA_MX_FIELD
           ){
             bNextPage = 1;
@@ -681,8 +729,8 @@
             int szField = 0;
             pCsr->pHdrPtr += dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
             szField = dbdataValueBytes(iType);
-            if( (pCsr->nRec - (pCsr->pPtr - pCsr->pRec))<szField ){
-              pCsr->pPtr = &pCsr->pRec[pCsr->nRec];
+            if( (pCsr->nRec - (pCsr->pPtr - pCsr->rec.aBuf))<szField ){
+              pCsr->pPtr = &pCsr->rec.aBuf[pCsr->nRec];
             }else{
               pCsr->pPtr += szField;
             }
@@ -692,20 +740,18 @@
 
       if( bNextPage ){
         sqlite3_free(pCsr->aPage);
-        sqlite3_free(pCsr->pRec);
         pCsr->aPage = 0;
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         if( pCsr->bOnePage ) return SQLITE_OK;
         pCsr->iPgno++;
       }else{
-        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->pRec[pCsr->nHdr] ){
+        if( pCsr->iField<0 || pCsr->pHdrPtr<&pCsr->rec.aBuf[pCsr->nHdr] ){
           return SQLITE_OK;
         }
 
         /* Advance to the next cell. The next iteration of the loop will load
         ** the record and so on. */
-        sqlite3_free(pCsr->pRec);
-        pCsr->pRec = 0;
+        pCsr->nRec = 0;
         pCsr->iCell++;
       }
     }
@@ -895,12 +941,12 @@
       case DBDATA_COLUMN_VALUE: {
         if( pCsr->iField<0 ){
           sqlite3_result_int64(ctx, pCsr->iIntkey);
-        }else if( &pCsr->pRec[pCsr->nRec] >= pCsr->pPtr ){
+        }else if( &pCsr->rec.aBuf[pCsr->nRec] >= pCsr->pPtr ){
           sqlite3_int64 iType;
           dbdataGetVarintU32(pCsr->pHdrPtr, &iType);
           dbdataValue(
               ctx, pCsr->enc, iType, pCsr->pPtr, 
-              &pCsr->pRec[pCsr->nRec] - pCsr->pPtr
+              &pCsr->rec.aBuf[pCsr->nRec] - pCsr->pPtr
           );
         }
         break;
diff --git a/ext/recover/recover1.test b/ext/recover/recover1.test
index 070dd03..11a4378 100644
--- a/ext/recover/recover1.test
+++ b/ext/recover/recover1.test
@@ -342,7 +342,7 @@
     DELETE FROM sqlite_schema WHERE name='t1';
   }
 
-  proc my_sql_hook {sql} {
+  proc my_sql_hook2 {sql} {
     if {[string match "INSERT INTO lostandfound*" $sql]} {
       lappend ::script $sql
     }
@@ -350,7 +350,7 @@
   }
   do_test 18.$enc.2 {
     set ::script [list]
-    set R [sqlite3_recover_init_sql db main my_sql_hook]
+    set R [sqlite3_recover_init_sql db main my_sql_hook2]
     $R config lostandfound lostandfound
     $R run
     $R finish
@@ -358,7 +358,18 @@
   } {{INSERT INTO lostandfound VALUES(2, 2, 2, 1, 'abc', 'def')}}
 }
 
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 19.0 {
+  CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT);
+  INSERT INTO t1 VALUES(1, 'one');
+  INSERT INTO t1 VALUES(2, 'two');
 
+  ALTER TABLE t1 ADD COLUMN c NOT NULL DEFAULT 13;
+  INSERT INTO t1 VALUES(3, 'three', 'hello world');
+}
+
+do_recover_test 19.1
 
 
 
diff --git a/ext/recover/recovercorrupt3.test b/ext/recover/recovercorrupt3.test
new file mode 100644
index 0000000..9a7c2d0
--- /dev/null
+++ b/ext/recover/recovercorrupt3.test
@@ -0,0 +1,549 @@
+# 2024 May 1
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] recover_common.tcl]
+set testprefix recovercorrupt3
+
+#|      0: d5 d5 9b d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5 d5   ................
+#|     16: 04 00 00 00 1d 00 00 00 00 00 00 00 5f 5f 5f 5f   ............____
+#|     32: 5f 5f 5f 5f 5f 5f 5f 5f 71 5f 5f 5f 02 02 02 02   ________q___....
+#|     48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+#|     64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+#|     80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+#|     96: 02 02 02 02
+
+#-------------------------------------------------------------------------
+reset_db
+do_test 1.0 {
+  sqlite3 db {}
+  db deserialize [decode_hexdb {
+| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
+| page 1 offset 0
+|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite 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 7a 70 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29   ..............))
+|    464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd   ))).............
+|    512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2   .........ni.....
+|    528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd   ................
+|    672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29   .............)))
+|    784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd   ))))))))))......
+|   1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+| page 2 offset 1024
+|      0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd   ..ni............
+|     48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29   ......))))))))))
+|    144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00   )))))))))..)))).
+|    160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00   u...[.d(|..i(-i.
+|    176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9   ..l.H...........
+|    192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0   [email protected]....
+|    208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60   ..~............`
+|    224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|   1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+| page 3 offset 2048
+|      0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|   1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+| page 4 offset 3072
+|      0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00   _______.........
+| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
+}]} {}
+
+sqlite3_dbdata_init db
+do_execsql_test 1.1 {
+  PRAGMA writable_schema = 1;
+}
+
+do_test 1.2 {
+  set R [sqlite3_recover_init db main test.db2]
+  $R run
+  $R finish
+} {}
+
+#-------------------------------------------------------------------------
+reset_db
+do_test 2.0 {
+  sqlite3 db {}
+  db deserialize [decode_hexdb {
+| size 3821 pagesize 1024 filename clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
+| page 1 offset 0
+|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
+|     16: 04 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 7a 70 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 a0 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 29 29   ..............))
+|    464: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    480: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    496: 29 29 29 dd dd dd dd dd dd dd dd dd dd dd dd dd   ))).............
+|    512: dd dd dd dd dd dd dd dd dd 6e 69 d2 e9 e9 e9 d2   .........ni.....
+|    528: d2 d2 d2 d2 dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    544: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    560: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    576: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    592: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    608: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    624: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    640: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    656: dd dd dd dd dd dd dd da dd dd dd dd dd dd dd dd   ................
+|    672: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    688: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    704: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    720: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    736: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    752: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    768: dd dd dd dd dd dd dd dd dd dd dd dd dd 29 29 29   .............)))
+|    784: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    800: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    816: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    832: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    848: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    864: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    880: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    896: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    912: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    928: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    944: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    960: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    976: 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29 29   ))))))))))))))))
+|    992: 29 29 29 29 29 29 29 29 29 29 dd dd dd dd dd dd   ))))))))))......
+|   1008: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+| page 2 offset 1024
+|      0: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     16: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     32: dd dd 6e 69 d2 e9 e9 e9 d2 d2 d2 d2 d2 dd dd dd   ..ni............
+|     48: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     64: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     80: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|     96: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    112: dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd   ................
+|    128: dd dd dd dd dd dd 29 29 29 29 29 29 29 29 29 29   ......))))))))))
+|    144: 29 29 29 29 29 29 29 29 29 ad a5 29 29 29 29 00   )))))))))..)))).
+|    160: 75 9c 11 00 5b e5 64 28 7c ca 09 69 28 2d 69 00   u...[.d(|..i(-i.
+|    176: 85 88 6c 81 48 83 a0 93 c0 c0 82 8b 81 84 85 f9   ..l.H...........
+|    192: 88 7a 00 7f 00 96 40 7b 12 4b 84 75 a0 00 99 a0   [email protected]....
+|    208: df a0 7e 81 c6 90 8f 7f 84 85 cc 84 82 90 88 60   ..~............`
+|    224: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    240: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    256: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    272: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    288: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    832: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    848: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    864: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    880: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    896: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    912: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    928: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    944: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    960: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|   1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+| page 3 offset 2048
+|      0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    752: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    768: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    784: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    800: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    816: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    832: 02 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    848: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    864: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    880: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    896: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    912: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    928: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    944: 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80 80   ................
+|    960: 80 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    976: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    992: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|   1008: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+| page 4 offset 3072
+|      0: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     16: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     32: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     48: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     64: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     80: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|     96: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    112: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    128: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    144: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    160: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    176: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    192: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    208: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    224: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    240: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    256: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    272: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    288: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    304: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    320: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    336: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    352: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    368: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    384: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    400: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    416: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    432: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    448: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    464: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    480: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    496: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    512: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    528: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    544: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    560: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    576: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    592: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    608: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    624: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    640: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    656: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    672: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    688: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    704: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    720: 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02   ................
+|    736: 5f 5f 5f 5f 5f 5f 5f 00 d5 fe fe fe 08 00 00 00   _______.........
+| end clusterfuzz-testcase-sql_recovery_fuzzer-5803962339885056
+}]} {}
+
+sqlite3_dbdata_init db
+do_execsql_test 2.1 {
+  PRAGMA writable_schema = 1;
+}
+
+do_test 2.2 {
+  set R [sqlite3_recover_init db main test.db2]
+  $R run
+  $R finish
+} {}
+
+finish_test
+
diff --git a/ext/recover/recovercorrupt4.test b/ext/recover/recovercorrupt4.test
new file mode 100644
index 0000000..53d691f
--- /dev/null
+++ b/ext/recover/recovercorrupt4.test
@@ -0,0 +1,58 @@
+# 2024 May 15
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+
+source [file join [file dirname [info script]] recover_common.tcl]
+set testprefix recovercorrupt4
+
+database_may_be_corrupt
+
+do_execsql_test 1.0 {
+  CREATE TABLE rows(indexed INTEGER NOT NULL, unindexed INTEGER NOT NULL, filler BLOB NOT NULL DEFAULT 13);
+  -- CREATE UNIQUE INDEX rows_index ON rows(indexed);
+  INSERT INTO rows(indexed, unindexed, filler) VALUES(1, 1, x'31');
+  INSERT INTO rows(indexed, unindexed, filler) VALUES(2, 2, x'32');
+  INSERT INTO rows(indexed, unindexed, filler) VALUES(4, 4, x'34');
+  INSERT INTO rows(indexed, unindexed, filler) VALUES(8, 8, randomblob(2048));
+}
+
+db close
+
+do_test 1.1 {
+  set sz [expr [file size test.db] - 1024]
+  set fd [open test.db]
+  fconfigure $fd -encoding binary -translation binary
+
+  set data [read $fd $sz]
+  set fd2 [open test.db2 w]
+  fconfigure $fd2 -encoding binary -translation binary
+  puts -nonewline $fd2 $data
+  close $fd2
+  set {} {}
+} {}
+
+do_test 1.2 {
+  forcedelete test.db3
+  sqlite3 db test.db2
+  set R [sqlite3_recover_init db main test.db3]
+  $R run
+  $R finish
+} {}
+
+do_test 1.3 {
+  sqlite3 db test.db3
+  execsql {
+    SELECT indexed, unindexed FROM rows
+  }
+} {1 1 2 2 4 4 8 8}
+
+finish_test
+
diff --git a/manifest b/manifest
index 00e29d8..8bf017a 100644
--- a/manifest
+++ b/manifest
@@ -467,8 +467,8 @@
 F ext/rbu/sqlite3rbu.c d4ddf8f0e93772556e452a6c2814063cf47efb760a0834391a9d0cd9859fa4b9
 F ext/rbu/sqlite3rbu.h 9d923eb135c5d04aa6afd7c39ca47b0d1d0707c100e02f19fdde6a494e414304
 F ext/rbu/test_rbu.c ee6ede75147bc081fe9bc3931e6b206277418d14d3fbceea6fdc6216d9b47055
-F ext/recover/dbdata.c d2e00d3cac74319c9c6def2e56ab2146b4f4ba5d820ab275e8da24e9766c247e
-F ext/recover/recover1.test c484d01502239f11b61f23c1cee9f5dd19fa17617f8974e42e74d64639c524cf
+F ext/recover/dbdata.c 0a943861ec096de375097e0aaff07b480a002eab9b01fecd3f9e828faf4ef624
+F ext/recover/recover1.test e16d78e94183562abff569967b18b7c77451d7044365516cd0fe14713a284851
 F ext/recover/recover_common.tcl a61306c1eb45c0c3fc45652c35b2d4ec19729e340bdf65a272ce4c229cefd85a
 F ext/recover/recoverbuild.test c74170e0f7b02456af41838afeb5353fdb985a48cc2331d661bbabbca7c6b8e3
 F ext/recover/recoverclobber.test 3ba6c0c373c5c63d17e82eced64c05c57ccaf26c1abe1ca7141334022a79f32e