From 8aa22ffe98071496f2f7a5a0d265cc9c267d9b58 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 19 Aug 2021 21:01:15 +0000 Subject: [PATCH 01/21] If SQLITE_USE_SEH is defined, handle structured-exceptions thrown by MSVC builds if the *-shm file mapping is accessed after it becomes invalid for some reason. FossilOrigin-Name: 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 --- manifest | 20 +- manifest.uuid | 2 +- src/wal.c | 448 +++++++++++++++++++++++++++++---------- test/snapshot_fault.test | 1 + test/walseh1.test | 106 +++++++++ 5 files changed, 451 insertions(+), 126 deletions(-) create mode 100644 test/walseh1.test diff --git a/manifest b/manifest index 6e4b8ae466..aa4b2f1276 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sON\sCONFLICT\sclause\sprocessing\sfor\sNOT\sNULL\sconstraints\sof\sPRIMARY\sKEY\ncolumns\son\sWITHOUT\sROWID\stables.\nTicket\s[f2be158c57aaa8c6] -D 2021-08-18T22:26:51.356 +C If\sSQLITE_USE_SEH\sis\sdefined,\shandle\sstructured-exceptions\sthrown\sby\sMSVC\sbuilds\sif\sthe\s*-shm\sfile\smapping\sis\saccessed\safter\sit\sbecomes\sinvalid\sfor\ssome\sreason. +D 2021-08-19T21:01:15.043 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 2be08331d798237ad5d7ae0b252700ffb2b63189cb18d993496d009a93e2f81c +F src/wal.c dd9ca83fcd91eb237790c18e972f8f2fd30cf86848d6fa9fc09da25e8acf56ae F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1393,7 +1393,7 @@ F test/snapshot.test a504f2e7009f512ef66c719f0ea1c55a556bdaf1e1312c80a04d46fc1a3 F test/snapshot2.test 8d6ff5dd9cc503f6e12d408a30409c3f9c653507b24408d9cd7195931c89bc54 F test/snapshot3.test 8744313270c55f6e18574283553d3c5c5fe4c5970585663613a0e75c151e599b F test/snapshot4.test d4e9347ef2fcabc491fc893506c7bbaf334da3be111d6eb4f3a97cc623b78322 -F test/snapshot_fault.test f6c5ef7cb93bf92fbb4e864ecc5c87df7d3a250064838822db5b4d3a5563ede4 +F test/snapshot_fault.test 129234ceb9b26a0e1000e8563a16e790f5c1412354e70749cbd78c3d5d07d60a F test/snapshot_up.test a0a29c4cf33475fcef07c3f8e64af795e24ab91b4cc68295863402a393cdd41c F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087 @@ -1739,6 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 +F test/walseh1.test 970946bdd40bc37d1552811b54ec94dd4a5a4178354b4afa129f2053b99bf09f F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1920,7 +1921,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b9b0dcd5af072c22f2ce71cf9584b5b572fbcfbce6410a7d703b586adb8938ba -R f57d6ed5153ac1a3784cf20c59f627b9 -U drh -Z 19e6156db8fe8743846e026420e0b856 +P 13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 +R f5105d1628b1a51745c8bcb5cc4af959 +T *branch * wal-shm-exceptions +T *sym-wal-shm-exceptions * +T -sym-trunk * +U dan +Z 55cb3a3675f7aa624d05737d0648760c diff --git a/manifest.uuid b/manifest.uuid index e76a74f795..7c3a0bb78c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 \ No newline at end of file +5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 83929ea467..c8cf4cc1b3 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,6 +528,13 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ +#ifdef SQLITE_USE_SEH +# ifdef SQLITE_DEBUG + int nSehTry; /* Number of nested SEH_TRY{} blocks */ +# endif + u32 lockMask; /* Mask of locks held */ + void *pFree; /* Pointer to sqlite3_free() if exception thrown */ +#endif #ifdef SQLITE_DEBUG u8 lockError; /* True if a locking error has occurred */ #endif @@ -610,6 +617,46 @@ struct WalIterator { sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) +#ifdef SQLITE_USE_SEH + +#include + +# define SEH_TRY __try { \ + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); + +# define SEH_EXCEPT TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ + } __except( sehExceptionFilter(pWal, GetExceptionCode()) ) + +# define SEH_INJECT_FAULT sehInjectFault(pWal) + +/* +** The second argument is the return value of GetExceptionCode() for the +** current exception. Return EXCEPTION_EXECUTE_HANDLER if the exception code +** indicates that the exception may have been caused by accessing the *-shm +** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. +*/ +static int sehExceptionFilter(Wal *pWal, int eCode){ + TESTONLY(pWal->nSehTry--); + if( eCode==EXCEPTION_ACCESS_VIOLATION ){ + return EXCEPTION_EXECUTE_HANDLER; + } + return EXCEPTION_CONTINUE_SEARCH; +} + +static void sehInjectFault(Wal *pWal){ + assert( pWal->nSehTry>0 ); + if( sqlite3FaultSim(650) ){ + RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL); + } +} + +#else +# define SEH_TRY +# define SEH_EXCEPT if(0) +# define SEH_INJECT_FAULT +#endif /* ifdef SQLITE_USE_SEH */ + + /* ** Obtain a pointer to the iPage'th page of the wal-index. The wal-index ** is broken into pages of WALINDEX_PGSZ bytes. Wal-index pages are @@ -676,6 +723,7 @@ static int walIndexPage( int iPage, /* The page we seek */ volatile u32 **ppPage /* Write the page pointer here */ ){ + SEH_INJECT_FAULT; if( pWal->nWiData<=iPage || (*ppPage = pWal->apWiData[iPage])==0 ){ return walIndexPageRealloc(pWal, iPage, ppPage); } @@ -687,6 +735,7 @@ static int walIndexPage( */ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalCkptInfo*)&(pWal->apWiData[0][sizeof(WalIndexHdr)/2]); } @@ -695,6 +744,7 @@ static volatile WalCkptInfo *walCkptInfo(Wal *pWal){ */ static volatile WalIndexHdr *walIndexHdr(Wal *pWal){ assert( pWal->nWiData>0 && pWal->apWiData[0] ); + SEH_INJECT_FAULT; return (volatile WalIndexHdr*)pWal->apWiData[0]; } @@ -931,12 +981,18 @@ static int walLockShared(Wal *pWal, int lockIdx){ WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal, walLockName(lockIdx), rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ) pWal->lockMask |= (1 << lockIdx); +#endif return rc; } static void walUnlockShared(Wal *pWal, int lockIdx){ if( pWal->exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, 1, SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(1 << lockIdx); +#endif WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx))); } static int walLockExclusive(Wal *pWal, int lockIdx, int n){ @@ -947,12 +1003,20 @@ static int walLockExclusive(Wal *pWal, int lockIdx, int n){ WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal, walLockName(lockIdx), n, rc ? "failed" : "ok")); VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); ) +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_OK ){ + pWal->lockMask |= (((1<exclusiveMode ) return; (void)sqlite3OsShmLock(pWal->pDbFd, lockIdx, n, SQLITE_SHM_UNLOCK | SQLITE_SHM_EXCLUSIVE); +#ifdef SQLITE_USE_SEH + pWal->lockMask &= ~(((1<pFree = aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1380,6 +1444,7 @@ static int walIndexRecover(Wal *pWal){ } sqlite3_free(aFrame); + pWal->pFree = 0; } finished: @@ -1789,22 +1854,16 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ nByte = sizeof(WalIterator) + (nSegment-1)*sizeof(struct WalSegment) + iLast*sizeof(ht_slot); - p = (WalIterator *)sqlite3_malloc64(nByte); + p = (WalIterator *)sqlite3_malloc64(nByte + + sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) + ); if( !p ){ return SQLITE_NOMEM_BKPT; } memset(p, 0, nByte); p->nSegment = nSegment; - - /* Allocate temporary space used by the merge-sort routine. This block - ** of memory will be freed before this function returns. - */ - aTmp = (ht_slot *)sqlite3_malloc64( - sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast) - ); - if( !aTmp ){ - rc = SQLITE_NOMEM_BKPT; - } + aTmp = (ht_slot*)&(((u8*)p)[nByte]); + pWal->pFree = p; for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && iaSegment[i].aPgno = (u32 *)sLoc.aPgno; } } - sqlite3_free(aTmp); if( rc!=SQLITE_OK ){ walIteratorFree(p); - p = 0; + pWal->pFree = p = 0; } *pp = p; return rc; @@ -2062,7 +2120,7 @@ static int walCheckpoint( mxSafeFrame = pWal->hdr.mxFrame; mxPage = pWal->hdr.nPage; for(i=1; iaReadMark+i); + u32 y = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxSafeFrame>y ){ assert( y<=pWal->hdr.mxFrame ); rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); @@ -2089,8 +2147,7 @@ static int walCheckpoint( && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK ){ u32 nBackfill = pInfo->nBackfill; - - pInfo->nBackfillAttempted = mxSafeFrame; + pInfo->nBackfillAttempted = mxSafeFrame; SEH_INJECT_FAULT; /* Sync the WAL to disk */ rc = sqlite3OsSync(pWal->pWalFd, CKPT_SYNC_FLAGS(sync_flags)); @@ -2172,6 +2229,7 @@ static int walCheckpoint( */ if( rc==SQLITE_OK && eMode!=SQLITE_CHECKPOINT_PASSIVE ){ assert( pWal->writeLock ); + SEH_INJECT_FAULT; if( pInfo->nBackfillhdr.mxFrame ){ rc = SQLITE_BUSY; }else if( eMode>=SQLITE_CHECKPOINT_RESTART ){ @@ -2203,7 +2261,9 @@ static int walCheckpoint( } walcheckpoint_out: + assert( pWal->pFree==(void*)pIter ); walIteratorFree(pIter); + pWal->pFree = 0; return rc; } @@ -2239,6 +2299,10 @@ int sqlite3WalClose( if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ +#ifdef SQLITE_USE_SEH + assert( pWal->lockMask==0 ); +#endif + /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the ** connection associated with this log file is the only connection to @@ -2779,6 +2843,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ assert( pWal->nWiData>0 ); assert( pWal->apWiData[0]!=0 ); pInfo = walCkptInfo(pWal); + SEH_INJECT_FAULT; if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame #ifdef SQLITE_ENABLE_SNAPSHOT && (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0) @@ -2828,7 +2893,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ } #endif for(i=1; iaReadMark+i); + u32 thisMark = AtomicLoad(pInfo->aReadMark+i); SEH_INJECT_FAULT; if( mxReadMark<=thisMark && thisMark<=mxFrame ){ assert( thisMark!=READMARK_NOT_USED ); mxReadMark = thisMark; @@ -2894,7 +2959,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** we can guarantee that the checkpointer that set nBackfill could not ** see any pages past pWal->hdr.mxFrame, this problem does not come up. */ - pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; + pWal->minFrame = AtomicLoad(&pInfo->nBackfill)+1; SEH_INJECT_FAULT; walShmBarrier(pWal); if( AtomicLoad(pInfo->aReadMark+mxI)!=mxReadMark || memcmp((void *)walIndexHdr(pWal), &pWal->hdr, sizeof(WalIndexHdr)) @@ -2908,7 +2973,112 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc; } +#ifdef SQLITE_USE_SEH +/* +** This is the "standard" exception handler used in a few places to handle +** an exception thrown by reading from the *-shm mapping after it has become +** invalid in SQLITE_USE_SEH builds. It is used as follows: +** +** SEH_TRY { ... } +** SEH_EXCEPT { rc = walHandleException(pWal); } +** +** This function does three things: +** +** 1) Determines the locks that should be held, based on the contents of +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other +** held locks are assumed to be transient locks that would have been +** released had the exception not been thrown and are dropped. +** +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). +** +** 3) Returns SQLITE_IOERR. +*/ +static int walHandleException(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<lockMask & ~( + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) + ); + for(ii=0; iipFree); + pWal->pFree = 0; + return SQLITE_IOERR; +} + +static int walAssertLockmask(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) #ifdef SQLITE_ENABLE_SNAPSHOT + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) +#endif + ); + assert( mExpect==pWal->lockMask ); + } + return 1; +} +#endif + +#ifdef SQLITE_ENABLE_SNAPSHOT +/* +** This function does the work of sqlite3WalSnapshotRecover(). +*/ +static int walSnapshotRecover( + Wal *pWal, /* WAL handle */ + void *pBuf1, /* Temp buffer pWal->szPage bytes in size */ + void *pBuf2 /* Temp buffer pWal->szPage bytes in size */ +){ + int szPage = (int)pWal->szPage; + int rc; + i64 szDb; /* Size of db file in bytes */ + + rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); + if( rc==SQLITE_OK ){ + volatile WalCkptInfo *pInfo = walCkptInfo(pWal); + u32 i = pInfo->nBackfillAttempted; + for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ + WalHashLoc sLoc; /* Hash table location */ + u32 pgno; /* Page number in db file */ + i64 iDbOff; /* Offset of db file entry */ + i64 iWalOff; /* Offset of wal file entry */ + + rc = walHashGet(pWal, walFramePage(i), &sLoc); + if( rc!=SQLITE_OK ) break; + pgno = sLoc.aPgno[i-sLoc.iZero]; + iDbOff = (i64)(pgno-1) * szPage; + + if( iDbOff+szPage<=szDb ){ + iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; + rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); + + if( rc==SQLITE_OK ){ + rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); + } + + if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ + break; + } + } + + pInfo->nBackfillAttempted = i-1; + } + } + + return rc; +} + /* ** Attempt to reduce the value of the WalCkptInfo.nBackfillAttempted ** variable so that older snapshots can be accessed. To do this, loop @@ -2934,49 +3104,23 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ assert( pWal->readLock>=0 ); rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1); if( rc==SQLITE_OK ){ - volatile WalCkptInfo *pInfo = walCkptInfo(pWal); - int szPage = (int)pWal->szPage; - i64 szDb; /* Size of db file in bytes */ - - rc = sqlite3OsFileSize(pWal->pDbFd, &szDb); - if( rc==SQLITE_OK ){ - void *pBuf1 = sqlite3_malloc(szPage); - void *pBuf2 = sqlite3_malloc(szPage); - if( pBuf1==0 || pBuf2==0 ){ - rc = SQLITE_NOMEM; - }else{ - u32 i = pInfo->nBackfillAttempted; - for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){ - WalHashLoc sLoc; /* Hash table location */ - u32 pgno; /* Page number in db file */ - i64 iDbOff; /* Offset of db file entry */ - i64 iWalOff; /* Offset of wal file entry */ - - rc = walHashGet(pWal, walFramePage(i), &sLoc); - if( rc!=SQLITE_OK ) break; - pgno = sLoc.aPgno[i-sLoc.iZero]; - iDbOff = (i64)(pgno-1) * szPage; - - if( iDbOff+szPage<=szDb ){ - iWalOff = walFrameOffset(i, szPage) + WAL_FRAME_HDRSIZE; - rc = sqlite3OsRead(pWal->pWalFd, pBuf1, szPage, iWalOff); - - if( rc==SQLITE_OK ){ - rc = sqlite3OsRead(pWal->pDbFd, pBuf2, szPage, iDbOff); - } - - if( rc!=SQLITE_OK || 0==memcmp(pBuf1, pBuf2, szPage) ){ - break; - } - } - - pInfo->nBackfillAttempted = i-1; - } + void *pBuf1 = sqlite3_malloc(pWal->szPage); + void *pBuf2 = sqlite3_malloc(pWal->szPage); + if( pBuf1==0 || pBuf2==0 ){ + rc = SQLITE_NOMEM; + }else{ + pWal->ckptLock = 1; + SEH_TRY { + rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - - sqlite3_free(pBuf1); - sqlite3_free(pBuf2); + SEH_EXCEPT { + rc = SQLITE_IOERR; + } + pWal->ckptLock = 0; } + + sqlite3_free(pBuf1); + sqlite3_free(pBuf2); walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1); } @@ -2998,10 +3142,11 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ ** Pager layer will use this to know that its cache is stale and ** needs to be flushed. */ -int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ +static int walBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ int cnt = 0; /* Number of TryBeginRead attempts */ #ifdef SQLITE_ENABLE_SNAPSHOT + int ckptLock = 0; int bChanged = 0; WalIndexHdr *pSnapshot = pWal->pSnapshot; #endif @@ -3029,7 +3174,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ if( rc!=SQLITE_OK ){ return rc; } - pWal->ckptLock = 1; + ckptLock = 1; } #endif @@ -3093,15 +3238,25 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ } /* Release the shared CKPT lock obtained above. */ - if( pWal->ckptLock ){ + if( ckptLock ){ assert( pSnapshot ); walUnlockShared(pWal, WAL_CKPT_LOCK); - pWal->ckptLock = 0; } #endif return rc; } +int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ + int rc; + SEH_TRY { + rc = walBeginReadTransaction(pWal, pChanged); + } + SEH_EXCEPT { + rc = walHandleException(pWal); + } + return rc; +} + /* ** Finish with a read transaction. All this does is release the ** read-lock. @@ -3122,7 +3277,7 @@ void sqlite3WalEndReadTransaction(Wal *pWal){ ** Return SQLITE_OK if successful, or an error code if an error occurs. If an ** error does occur, the final value of *piRead is undefined. */ -int sqlite3WalFindFrame( +static int walFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ u32 *piRead /* OUT: Frame number (or zero) */ @@ -3185,6 +3340,7 @@ int sqlite3WalFindFrame( } nCollide = HASHTABLE_NSLOT; iKey = walHash(pgno); + SEH_INJECT_FAULT; while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){ u32 iFrame = iH + sLoc.iZero; if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){ @@ -3221,6 +3377,19 @@ int sqlite3WalFindFrame( return SQLITE_OK; } +int sqlite3WalFindFrame( + Wal *pWal, /* WAL handle */ + Pgno pgno, /* Database page number to read data for */ + u32 *piRead /* OUT: Frame number (or zero) */ +){ + int rc; + SEH_TRY { + rc = walFindFrame(pWal, pgno, piRead); + } + SEH_EXCEPT { rc = SQLITE_IOERR; } + return rc; +} + /* ** Read the contents of frame iRead from the wal file into buffer pOut ** (which is nOut bytes in size). Return SQLITE_OK if successful, or an @@ -3302,12 +3471,17 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ ** time the read transaction on this connection was started, then ** the write is disallowed. */ - if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + SEH_TRY { + if( memcmp(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr))!=0 ){ + rc = SQLITE_BUSY_SNAPSHOT; + } + } + SEH_EXCEPT { rc = SQLITE_IOERR; } + + if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); pWal->writeLock = 0; - rc = SQLITE_BUSY_SNAPSHOT; } - return rc; } @@ -3343,30 +3517,35 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ Pgno iMax = pWal->hdr.mxFrame; Pgno iFrame; - /* Restore the clients cache of the wal-index header to the state it - ** was in before the client began writing to the database. - */ - memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); - - for(iFrame=pWal->hdr.mxFrame+1; - ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; - iFrame++ - ){ - /* This call cannot fail. Unless the page for which the page number - ** is passed as the second argument is (a) in the cache and - ** (b) has an outstanding reference, then xUndo is either a no-op - ** (if (a) is false) or simply expels the page from the cache (if (b) - ** is false). - ** - ** If the upper layer is doing a rollback, it is guaranteed that there - ** are no outstanding references to any page other than page 1. And - ** page 1 is never written to the log until the transaction is - ** committed. As a result, the call to xUndo may not fail. + SEH_TRY { + /* Restore the clients cache of the wal-index header to the state it + ** was in before the client began writing to the database. */ - assert( walFramePgno(pWal, iFrame)!=1 ); - rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + memcpy(&pWal->hdr, (void *)walIndexHdr(pWal), sizeof(WalIndexHdr)); + + for(iFrame=pWal->hdr.mxFrame+1; + ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; + iFrame++ + ){ + /* This call cannot fail. Unless the page for which the page number + ** is passed as the second argument is (a) in the cache and + ** (b) has an outstanding reference, then xUndo is either a no-op + ** (if (a) is false) or simply expels the page from the cache (if (b) + ** is false). + ** + ** If the upper layer is doing a rollback, it is guaranteed that there + ** are no outstanding references to any page other than page 1. And + ** page 1 is never written to the log until the transaction is + ** committed. As a result, the call to xUndo may not fail. + */ + assert( walFramePgno(pWal, iFrame)!=1 ); + rc = xUndo(pUndoCtx, walFramePgno(pWal, iFrame)); + } + if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); + } + SEH_EXCEPT { + rc = SQLITE_IOERR; } - if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } return rc; } @@ -3410,7 +3589,12 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ pWal->hdr.mxFrame = aWalData[0]; pWal->hdr.aFrameCksum[0] = aWalData[1]; pWal->hdr.aFrameCksum[1] = aWalData[2]; - walCleanupHash(pWal); + SEH_TRY { + walCleanupHash(pWal); + } + SEH_EXCEPT { + rc = SQLITE_IOERR; + } } return rc; @@ -3591,7 +3775,7 @@ static int walRewriteChecksums(Wal *pWal, u32 iLast){ ** Write a set of frames to the log. The caller must hold the write-lock ** on the log file (obtained using sqlite3WalBeginWriteTransaction()). */ -int sqlite3WalFrames( +static int walFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ PgHdr *pList, /* List of dirty pages to write */ @@ -3700,7 +3884,7 @@ int sqlite3WalFrames( ** checksums must be recomputed when the transaction is committed. */ if( iFirst && (p->pDirty || isCommit==0) ){ u32 iWrite = 0; - VVA_ONLY(rc =) sqlite3WalFindFrame(pWal, p->pgno, &iWrite); + VVA_ONLY(rc =) walFindFrame(pWal, p->pgno, &iWrite); assert( rc==SQLITE_OK || iWrite==0 ); if( iWrite>=iFirst ){ i64 iOff = walFrameOffset(iWrite, szPage) + WAL_FRAME_HDRSIZE; @@ -3819,6 +4003,24 @@ int sqlite3WalFrames( return rc; } +int sqlite3WalFrames( + Wal *pWal, /* Wal handle to write to */ + int szPage, /* Database page-size in bytes */ + PgHdr *pList, /* List of dirty pages to write */ + Pgno nTruncate, /* Database size after this commit */ + int isCommit, /* True if this is a commit */ + int sync_flags /* Flags to pass to OsSync() (or 0) */ +){ + int rc; + SEH_TRY { + rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); + } + SEH_EXCEPT { + rc = walHandleException(pWal); + } + return rc; +} + /* ** This routine is called to implement sqlite3_wal_checkpoint() and ** related interfaces. @@ -3848,6 +4050,7 @@ int sqlite3WalCheckpoint( assert( pWal->ckptLock==0 ); assert( pWal->writeLock==0 ); + assert( pWal->readLock<0 ); /* EVIDENCE-OF: R-62920-47450 The busy-handler callback is never invoked ** in the SQLITE_CHECKPOINT_PASSIVE mode. */ @@ -3898,30 +4101,34 @@ int sqlite3WalCheckpoint( /* Read the wal-index header. */ - if( rc==SQLITE_OK ){ - walDisableBlocking(pWal); - rc = walIndexReadHdr(pWal, &isChanged); - (void)walEnableBlocking(pWal); - if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ - sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + SEH_TRY { + if( rc==SQLITE_OK ){ + walDisableBlocking(pWal); + rc = walIndexReadHdr(pWal, &isChanged); + (void)walEnableBlocking(pWal); + if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){ + sqlite3OsUnfetch(pWal->pDbFd, 0, 0); + } } - } - - /* Copy data from the log to the database file. */ - if( rc==SQLITE_OK ){ - - if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ - rc = SQLITE_CORRUPT_BKPT; - }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + + /* Copy data from the log to the database file. */ + if( rc==SQLITE_OK ){ + if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ + rc = SQLITE_CORRUPT_BKPT; + }else{ + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + } } - + /* If no error occurred, set the output variables. */ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } + SEH_EXCEPT { + rc = walHandleException(pWal); + } if( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -3998,7 +4205,9 @@ int sqlite3WalExclusiveMode(Wal *pWal, int op){ ** locks are taken in this case). Nor should the pager attempt to ** upgrade to exclusive-mode following such an error. */ +#ifndef SQLITE_USE_SEH assert( pWal->readLock>=0 || pWal->lockError ); +#endif assert( pWal->readLock>=0 || (op<=0 && pWal->exclusiveMode==0) ); if( op==0 ){ @@ -4099,16 +4308,21 @@ int sqlite3_snapshot_cmp(sqlite3_snapshot *p1, sqlite3_snapshot *p2){ */ int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ int rc; - rc = walLockShared(pWal, WAL_CKPT_LOCK); - if( rc==SQLITE_OK ){ - WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; - if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) - || pNew->mxFramenBackfillAttempted - ){ - rc = SQLITE_ERROR_SNAPSHOT; - walUnlockShared(pWal, WAL_CKPT_LOCK); + SEH_TRY { + rc = walLockShared(pWal, WAL_CKPT_LOCK); + if( rc==SQLITE_OK ){ + WalIndexHdr *pNew = (WalIndexHdr*)pSnapshot; + if( memcmp(pNew->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt)) + || pNew->mxFramenBackfillAttempted + ){ + rc = SQLITE_ERROR_SNAPSHOT; + walUnlockShared(pWal, WAL_CKPT_LOCK); + } } } + SEH_EXCEPT { + rc = walHandleException(pWal); + } return rc; } diff --git a/test/snapshot_fault.test b/test/snapshot_fault.test index 2adb793650..10c5094594 100644 --- a/test/snapshot_fault.test +++ b/test/snapshot_fault.test @@ -23,6 +23,7 @@ set testprefix snapshot_fault # checkpointing the db. # do_faultsim_test 1.0 -prep { + catch { db2 close } faultsim_delete_and_reopen sqlite3 db2 test.db db2 eval { diff --git a/test/walseh1.test b/test/walseh1.test new file mode 100644 index 0000000000..ba5d786c48 --- /dev/null +++ b/test/walseh1.test @@ -0,0 +1,106 @@ +# 2021 August 16 +# +# 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. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/malloc_common.tcl +set testprefix seh1 + +set ::seh_countdown 0 +proc seh_faultsim_callback {iFault} { + if {$iFault==650} { + incr ::seh_countdown -1 + if {$::seh_countdown==0} { return 1 } + } + return 0 +} + +proc seh_injectinstall {} { + sqlite3_test_control_fault_install seh_faultsim_callback +} +proc seh_injectuninstall {} { + sqlite3_test_control_fault_install +} +proc seh_injectstart {iFail} { + set ::seh_countdown $iFail +} +proc seh_injectstop {} { + set res [expr $::seh_countdown<=0] + set ::seh_countdown 0 + set res +} + +set FAULTSIM(seh) [list \ + -injectinstall seh_injectinstall \ + -injectstart seh_injectstart \ + -injectstop seh_injectstop \ + -injecterrlist {{1 {disk I/O error}}} \ + -injectuninstall seh_injectuninstall \ +] + +do_execsql_test 1.0 { + PRAGMA journal_mode = wal; + CREATE TABLE t1(x, y); + INSERT INTO t1 VALUES(1, 2); + INSERT INTO t1 VALUES(3, 4); +} {wal} +faultsim_save_and_close + +do_faultsim_test 1 -faults seh -prep { + catch { db2 close } + faultsim_restore_and_reopen + execsql { SELECT * FROM sqlite_schema } + sqlite3 db2 test.db +} -body { + execsql { SELECT * FROM t1 } db2 +} -test { + faultsim_test_result {0 {1 2 3 4}} +} +catch { db2 close } + +faultsim_save_and_close + +do_faultsim_test 2 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4}} +} + +do_faultsim_test 3 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { INSERT INTO t1 VALUES(5, 6) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 5 6}} +} +catch { db close } + +do_faultsim_test 4 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { PRAGMA wal_checkpoint } + execsql { INSERT INTO t1 VALUES(7, 8) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 7 8}} +} +catch { db close } + +finish_test + + From aecd7f9d75d0fd7d3d03a8ea23b1507c632ca30b Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 19 Aug 2021 23:10:57 +0000 Subject: [PATCH 02/21] Enable this branch to run both with and without the -DSQLITE_USE_SEH option. FossilOrigin-Name: 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f --- manifest | 17 +++++++-------- manifest.uuid | 2 +- src/wal.c | 57 ++++++++++++++++++++++----------------------------- 3 files changed, 33 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index aa4b2f1276..66ae90556b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\sSQLITE_USE_SEH\sis\sdefined,\shandle\sstructured-exceptions\sthrown\sby\sMSVC\sbuilds\sif\sthe\s*-shm\sfile\smapping\sis\saccessed\safter\sit\sbecomes\sinvalid\sfor\ssome\sreason. -D 2021-08-19T21:01:15.043 +C Enable\sthis\sbranch\sto\srun\sboth\swith\sand\swithout\sthe\s-DSQLITE_USE_SEH\soption. +D 2021-08-19T23:10:57.409 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c dd9ca83fcd91eb237790c18e972f8f2fd30cf86848d6fa9fc09da25e8acf56ae +F src/wal.c c07f7f1301f2af98e2ae83b5bde451b715da14ca88a355f85a7d4656f8f295c3 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,10 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 13abba0941a724eb62455650976b03678e4455b6b3090c84a2ab2f4a7656b4d8 -R f5105d1628b1a51745c8bcb5cc4af959 -T *branch * wal-shm-exceptions -T *sym-wal-shm-exceptions * -T -sym-trunk * -U dan -Z 55cb3a3675f7aa624d05737d0648760c +P 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 +R 7dea1ca77fe483a4591a9d63bfe86a5f +U drh +Z 84658daaaacd80f58fddb8eaeaf9e417 diff --git a/manifest.uuid b/manifest.uuid index 7c3a0bb78c..5bfd9ee381 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 \ No newline at end of file +840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index c8cf4cc1b3..9a4451a091 100644 --- a/src/wal.c +++ b/src/wal.c @@ -624,8 +624,8 @@ struct WalIterator { # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode()) ) +# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ + } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -650,10 +650,13 @@ static void sehInjectFault(Wal *pWal){ } } +#define SEH_FREE_ON_ERROR(X) pWal->pFree = X + #else # define SEH_TRY -# define SEH_EXCEPT if(0) +# define SEH_EXCEPT(X) # define SEH_INJECT_FAULT +# define SEH_FREE_ON_ERROR(X) #endif /* ifdef SQLITE_USE_SEH */ @@ -1365,7 +1368,8 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; - pWal->pFree = aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); + aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); + SEH_FREE_ON_ERROR(aFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1444,7 +1448,7 @@ static int walIndexRecover(Wal *pWal){ } sqlite3_free(aFrame); - pWal->pFree = 0; + SEH_FREE_ON_ERROR(0); } finished: @@ -1863,7 +1867,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ memset(p, 0, nByte); p->nSegment = nSegment; aTmp = (ht_slot*)&(((u8*)p)[nByte]); - pWal->pFree = p; + SEH_FREE_ON_ERROR(p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && ipFree = p = 0; + p = 0; + SEH_FREE_ON_ERROR(0); } *pp = p; return rc; @@ -2261,9 +2266,11 @@ static int walCheckpoint( } walcheckpoint_out: +#ifdef SQLITE_USE_SEH assert( pWal->pFree==(void*)pIter ); - walIteratorFree(pIter); pWal->pFree = 0; +#endif + walIteratorFree(pIter); return rc; } @@ -2980,7 +2987,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ ** invalid in SQLITE_USE_SEH builds. It is used as follows: ** ** SEH_TRY { ... } -** SEH_EXCEPT { rc = walHandleException(pWal); } +** SEH_EXCEPT( rc = walHandleException(pWal); ) ** ** This function does three things: ** @@ -3113,9 +3120,7 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ SEH_TRY { rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) pWal->ckptLock = 0; } @@ -3251,9 +3256,7 @@ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ SEH_TRY { rc = walBeginReadTransaction(pWal, pChanged); } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } @@ -3386,7 +3389,7 @@ int sqlite3WalFindFrame( SEH_TRY { rc = walFindFrame(pWal, pgno, piRead); } - SEH_EXCEPT { rc = SQLITE_IOERR; } + SEH_EXCEPT( rc = SQLITE_IOERR; ) return rc; } @@ -3476,7 +3479,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ rc = SQLITE_BUSY_SNAPSHOT; } } - SEH_EXCEPT { rc = SQLITE_IOERR; } + SEH_EXCEPT( rc = SQLITE_IOERR; ) if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); @@ -3543,9 +3546,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) } return rc; } @@ -3592,9 +3593,7 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ SEH_TRY { walCleanupHash(pWal); } - SEH_EXCEPT { - rc = SQLITE_IOERR; - } + SEH_EXCEPT( rc = SQLITE_IOERR; ) } return rc; @@ -4015,9 +4014,7 @@ int sqlite3WalFrames( SEH_TRY { rc = walFrames(pWal, szPage, pList, nTruncate, isCommit, sync_flags); } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } @@ -4126,9 +4123,7 @@ int sqlite3WalCheckpoint( if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) if( isChanged ){ /* If a new wal-index header was loaded before the checkpoint was @@ -4320,9 +4315,7 @@ int sqlite3WalSnapshotCheck(Wal *pWal, sqlite3_snapshot *pSnapshot){ } } } - SEH_EXCEPT { - rc = walHandleException(pWal); - } + SEH_EXCEPT( rc = walHandleException(pWal); ) return rc; } From b15c63cbb954aafebd8a01826e9154830f6d03e6 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 11:50:12 +0000 Subject: [PATCH 03/21] Fix a problem on this branch causing checkpoints that do not proceed because they can't get the CHECKPOINT lock to return incorrect output values. FossilOrigin-Name: 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 14 +++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 66ae90556b..a3c3624cf6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enable\sthis\sbranch\sto\srun\sboth\swith\sand\swithout\sthe\s-DSQLITE_USE_SEH\soption. -D 2021-08-19T23:10:57.409 +C Fix\sa\sproblem\son\sthis\sbranch\scausing\scheckpoints\sthat\sdo\snot\sproceed\sbecause\sthey\scan't\sget\sthe\sCHECKPOINT\slock\sto\sreturn\sincorrect\soutput\svalues. +D 2021-08-20T11:50:12.817 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c c07f7f1301f2af98e2ae83b5bde451b715da14ca88a355f85a7d4656f8f295c3 +F src/wal.c 42c64a0c198c0610a4f54158faff9ad8b0f3f390cb03c1a69692dc70f886b711 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5c5fa47076c5da25ca92248df3a4c11b90a0225a07f05d7220fa95d9bbb36f43 -R 7dea1ca77fe483a4591a9d63bfe86a5f -U drh -Z 84658daaaacd80f58fddb8eaeaf9e417 +P 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f +R 97abf4da384cedc02121f231f21869ab +U dan +Z 53bdf1f79fced94468e78efd135afd05 diff --git a/manifest.uuid b/manifest.uuid index 5bfd9ee381..827b32b4dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f \ No newline at end of file +5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 9a4451a091..e17d3959b0 100644 --- a/src/wal.c +++ b/src/wal.c @@ -4113,14 +4113,14 @@ int sqlite3WalCheckpoint( if( pWal->hdr.mxFrame && walPagesize(pWal)!=nBuf ){ rc = SQLITE_CORRUPT_BKPT; }else{ - rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags, zBuf); + rc = walCheckpoint(pWal, db, eMode2, xBusy2, pBusyArg, sync_flags,zBuf); + } + + /* If no error occurred, set the output variables. */ + if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ + if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } - } - - /* If no error occurred, set the output variables. */ - if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ - if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; - if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } SEH_EXCEPT( rc = walHandleException(pWal); ) From c6effdbfba68315a45593a29febf4e915549befa Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 16:19:19 +0000 Subject: [PATCH 04/21] Add some assert() statements and fix small issues with code on this branch. FossilOrigin-Name: bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 --- manifest | 12 +++--- manifest.uuid | 2 +- src/wal.c | 110 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 86 insertions(+), 38 deletions(-) diff --git a/manifest b/manifest index a3c3624cf6..d417bb139e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\son\sthis\sbranch\scausing\scheckpoints\sthat\sdo\snot\sproceed\sbecause\sthey\scan't\sget\sthe\sCHECKPOINT\slock\sto\sreturn\sincorrect\soutput\svalues. -D 2021-08-20T11:50:12.817 +C Add\ssome\sassert()\sstatements\sand\sfix\ssmall\sissues\swith\scode\son\sthis\sbranch. +D 2021-08-20T16:19:19.544 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 42c64a0c198c0610a4f54158faff9ad8b0f3f390cb03c1a69692dc70f886b711 +F src/wal.c d47742fa0d58fa622416cfd105b4b309f39006f30d903e02db2f48236f3d83d7 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 840e0a14ebc4a85d4ede0223287d4c1e4465e9f20c3c43bfc74775dddec1fa8f -R 97abf4da384cedc02121f231f21869ab +P 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa +R eab33be79c818813f4366ae19768ee1d U dan -Z 53bdf1f79fced94468e78efd135afd05 +Z 8887602c0a0185b63b60ad6538fd96e1 diff --git a/manifest.uuid b/manifest.uuid index 827b32b4dd..4034ae736f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa \ No newline at end of file +bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index e17d3959b0..f6c2d86df8 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,10 +528,10 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -#ifdef SQLITE_USE_SEH # ifdef SQLITE_DEBUG int nSehTry; /* Number of nested SEH_TRY{} blocks */ # endif +#ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ #endif @@ -622,9 +622,12 @@ struct WalIterator { #include # define SEH_TRY __try { \ - assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); TESTONLY(pWal->nSehTry++); + assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ + TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); \ +# define SEH_EXCEPT(X) \ + TESTONLY(pWal->nSehTry--); \ + assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -643,6 +646,12 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ return EXCEPTION_CONTINUE_SEARCH; } +/* +** If one is configured, invoke the xTestCallback callback with 650 as +** the argument. If it returns true, throw the same exception that is +** thrown by the system if the *-shm file mapping is accessed after it +** has been invalidated. +*/ static void sehInjectFault(Wal *pWal){ assert( pWal->nSehTry>0 ); if( sqlite3FaultSim(650) ){ @@ -650,13 +659,27 @@ static void sehInjectFault(Wal *pWal){ } } -#define SEH_FREE_ON_ERROR(X) pWal->pFree = X +/* +** There are two ways to use this macro. To set a pointer to be freed +** if an exception is thrown: +** +** SEH_FREE_ON_ERROR(0, pPtr); +** +** and to cancel the same: +** +** SEH_FREE_ON_ERROR(pPtr, 0); +** +** In the first case, there must not already be a pointer registered to +** be freed. In the second case, pPtr must be the registered pointer. +*/ +#define SEH_FREE_ON_ERROR(X,Y) \ + assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y #else -# define SEH_TRY -# define SEH_EXCEPT(X) -# define SEH_INJECT_FAULT -# define SEH_FREE_ON_ERROR(X) +# define SEH_TRY TESTONLY(pWal->nSehTry++); +# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); +# define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); +# define SEH_FREE_ON_ERROR(X,Y) #endif /* ifdef SQLITE_USE_SEH */ @@ -1369,7 +1392,7 @@ static int walIndexRecover(Wal *pWal){ /* Malloc a buffer to read frames into. */ szFrame = szPage + WAL_FRAME_HDRSIZE; aFrame = (u8 *)sqlite3_malloc64(szFrame + WALINDEX_PGSZ); - SEH_FREE_ON_ERROR(aFrame); + SEH_FREE_ON_ERROR(0, aFrame); if( !aFrame ){ rc = SQLITE_NOMEM_BKPT; goto recovery_error; @@ -1447,8 +1470,8 @@ static int walIndexRecover(Wal *pWal){ if( iFrame<=iLast ) break; } + SEH_FREE_ON_ERROR(aFrame, 0); sqlite3_free(aFrame); - SEH_FREE_ON_ERROR(0); } finished: @@ -1867,7 +1890,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){ memset(p, 0, nByte); p->nSegment = nSegment; aTmp = (ht_slot*)&(((u8*)p)[nByte]); - SEH_FREE_ON_ERROR(p); + SEH_FREE_ON_ERROR(0, p); for(i=walFramePage(nBackfill+1); rc==SQLITE_OK && ipFree==(void*)pIter ); - pWal->pFree = 0; -#endif + SEH_FREE_ON_ERROR(pIter, 0); walIteratorFree(pIter); return rc; } @@ -2306,9 +2326,7 @@ int sqlite3WalClose( if( pWal ){ int isDelete = 0; /* True to unlink wal and wal-index files */ -#ifdef SQLITE_USE_SEH - assert( pWal->lockMask==0 ); -#endif + assert( walAssertLockmask(pWal) ); /* If an EXCLUSIVE lock can be obtained on the database file (using the ** ordinary, rollback-mode locking methods, this guarantees that the @@ -3020,6 +3038,13 @@ static int walHandleException(Wal *pWal){ return SQLITE_IOERR; } +/* +** Assert that the Wal.lockMask mask, which indicates the locks held +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock +** and Wal.ckptLock variables. To be used as: +** +** assert( walAssertLockmask(pWal) ); +*/ static int walAssertLockmask(Wal *pWal){ if( pWal->exclusiveMode==0 ){ static const int S = 1; @@ -3134,18 +3159,8 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ #endif /* SQLITE_ENABLE_SNAPSHOT */ /* -** Begin a read transaction on the database. -** -** This routine used to be called sqlite3OpenSnapshot() and with good reason: -** it takes a snapshot of the state of the WAL and wal-index for the current -** instant in time. The current thread will continue to use this snapshot. -** Other threads might append new content to the WAL and wal-index but -** that extra content is ignored by the current thread. -** -** If the database contents have changes since the previous read -** transaction, then *pChanged is set to 1 before returning. The -** Pager layer will use this to know that its cache is stale and -** needs to be flushed. +** This function does the work of sqlite3WalBeginReadTransaction() (see +** below). That function simply calls this one inside an SEH_TRY{...} block. */ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; /* Return code */ @@ -3157,6 +3172,7 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ #endif assert( pWal->ckptLock==0 ); + assert( pWal->nSehTry>0 ); #ifdef SQLITE_ENABLE_SNAPSHOT if( pSnapshot ){ @@ -3251,6 +3267,20 @@ static int walBeginReadTransaction(Wal *pWal, int *pChanged){ return rc; } +/* +** Begin a read transaction on the database. +** +** This routine used to be called sqlite3OpenSnapshot() and with good reason: +** it takes a snapshot of the state of the WAL and wal-index for the current +** instant in time. The current thread will continue to use this snapshot. +** Other threads might append new content to the WAL and wal-index but +** that extra content is ignored by the current thread. +** +** If the database contents have changes since the previous read +** transaction, then *pChanged is set to 1 before returning. The +** Pager layer will use this to know that its cache is stale and +** needs to be flushed. +*/ int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){ int rc; SEH_TRY { @@ -3380,6 +3410,17 @@ static int walFindFrame( return SQLITE_OK; } +/* +** Search the wal file for page pgno. If found, set *piRead to the frame that +** contains the page. Otherwise, if pgno is not in the wal file, set *piRead +** to zero. +** +** Return SQLITE_OK if successful, or an error code if an error occurs. If an +** error does occur, the final value of *piRead is undefined. +** +** The difference between this function and walFindFrame() is that this +** function wraps walFindFrame() in an SEH_TRY{...} block. +*/ int sqlite3WalFindFrame( Wal *pWal, /* WAL handle */ Pgno pgno, /* Database page number to read data for */ @@ -4002,6 +4043,13 @@ static int walFrames( return rc; } +/* +** Write a set of frames to the log. The caller must hold the write-lock +** on the log file (obtained using sqlite3WalBeginWriteTransaction()). +** +** The difference between this function and walFrames() is that this +** function wraps walFrames() in an SEH_TRY{...} block. +*/ int sqlite3WalFrames( Wal *pWal, /* Wal handle to write to */ int szPage, /* Database page-size in bytes */ From 5b6c3c8f7d27226a0386867c1c110f79435d9ba0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 20 Aug 2021 17:23:19 +0000 Subject: [PATCH 05/21] Add missing SEH_INJECT_FAULT macros. FossilOrigin-Name: 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded --- manifest | 12 ++--- manifest.uuid | 2 +- src/wal.c | 143 ++++++++++++++++++++++++++------------------------ 3 files changed, 82 insertions(+), 75 deletions(-) diff --git a/manifest b/manifest index d417bb139e..18648cc431 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\sassert()\sstatements\sand\sfix\ssmall\sissues\swith\scode\son\sthis\sbranch. -D 2021-08-20T16:19:19.544 +C Add\smissing\sSEH_INJECT_FAULT\smacros. +D 2021-08-20T17:23:19.198 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c d47742fa0d58fa622416cfd105b4b309f39006f30d903e02db2f48236f3d83d7 +F src/wal.c 5f98987c924f3262e19bc1c124cc4e02553f768a86cfdfb4d193db04c4d0b3da F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 5a98820c3d20766813bb4b0da23247ac90f380c07827ff13b61d5b606d8311aa -R eab33be79c818813f4366ae19768ee1d +P bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 +R 18bce27bc9709a49e95cb84782c68c82 U dan -Z 8887602c0a0185b63b60ad6538fd96e1 +Z 8c053f205f09cec18507fce552900c67 diff --git a/manifest.uuid b/manifest.uuid index 4034ae736f..f413569b7c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 \ No newline at end of file +27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index f6c2d86df8..ef50aac040 100644 --- a/src/wal.c +++ b/src/wal.c @@ -1133,6 +1133,7 @@ static int walFramePage(u32 iFrame){ */ static u32 walFramePgno(Wal *pWal, u32 iFrame){ int iHash = walFramePage(iFrame); + SEH_INJECT_FAULT; if( iHash==0 ){ return pWal->apWiData[0][WALINDEX_HDR_SIZE/sizeof(u32) + iFrame - 1]; } @@ -1228,7 +1229,7 @@ static int walIndexAppend(Wal *pWal, u32 iFrame, u32 iPage){ idx = iFrame - sLoc.iZero; assert( idx <= HASHTABLE_NSLOT/2 + 1 ); - + /* If this is the first entry to be added to this hash-table, zero the ** entire hash table and aPgno[] array before proceeding. */ @@ -1467,6 +1468,7 @@ static int walIndexRecover(Wal *pWal){ } } #endif + SEH_INJECT_FAULT; if( iFrame<=iLast ) break; } @@ -1498,6 +1500,7 @@ finished: }else{ pInfo->aReadMark[i] = READMARK_NOT_USED; } + SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc!=SQLITE_BUSY ){ goto recovery_error; @@ -2154,7 +2157,7 @@ static int walCheckpoint( rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1); if( rc==SQLITE_OK ){ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED); - AtomicStore(pInfo->aReadMark+i, iMark); + AtomicStore(pInfo->aReadMark+i, iMark); SEH_INJECT_FAULT; walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1); }else if( rc==SQLITE_BUSY ){ mxSafeFrame = y; @@ -2206,6 +2209,7 @@ static int walCheckpoint( while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){ i64 iOffset; assert( walFramePgno(pWal, iFrame)==iDbpage ); + SEH_INJECT_FAULT; if( AtomicLoad(&db->u1.isInterrupted) ){ rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT; break; @@ -2235,7 +2239,7 @@ static int walCheckpoint( } } if( rc==SQLITE_OK ){ - AtomicStore(&pInfo->nBackfill, mxSafeFrame); + AtomicStore(&pInfo->nBackfill, mxSafeFrame); SEH_INJECT_FAULT; } } @@ -2312,6 +2316,73 @@ static void walLimitSize(Wal *pWal, i64 nMax){ } } +#ifdef SQLITE_USE_SEH +/* +** This is the "standard" exception handler used in a few places to handle +** an exception thrown by reading from the *-shm mapping after it has become +** invalid in SQLITE_USE_SEH builds. It is used as follows: +** +** SEH_TRY { ... } +** SEH_EXCEPT( rc = walHandleException(pWal); ) +** +** This function does three things: +** +** 1) Determines the locks that should be held, based on the contents of +** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other +** held locks are assumed to be transient locks that would have been +** released had the exception not been thrown and are dropped. +** +** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). +** +** 3) Returns SQLITE_IOERR. +*/ +static int walHandleException(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<lockMask & ~( + (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) + ); + for(ii=0; iipFree); + pWal->pFree = 0; + return SQLITE_IOERR; +} + +/* +** Assert that the Wal.lockMask mask, which indicates the locks held +** by the connenction, is consistent with the Wal.readLock, Wal.writeLock +** and Wal.ckptLock variables. To be used as: +** +** assert( walAssertLockmask(pWal) ); +*/ +static int walAssertLockmask(Wal *pWal){ + if( pWal->exclusiveMode==0 ){ + static const int S = 1; + static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) + | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) + | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) +#ifdef SQLITE_ENABLE_SNAPSHOT + | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) +#endif + ); + assert( mExpect==pWal->lockMask ); + } + return 1; +} +#else +# define walAssertLockmask(x) 1 +#endif /* ifdef SQLITE_USE_SEH */ + /* ** Close a connection to a log file. */ @@ -2998,71 +3069,6 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){ return rc; } -#ifdef SQLITE_USE_SEH -/* -** This is the "standard" exception handler used in a few places to handle -** an exception thrown by reading from the *-shm mapping after it has become -** invalid in SQLITE_USE_SEH builds. It is used as follows: -** -** SEH_TRY { ... } -** SEH_EXCEPT( rc = walHandleException(pWal); ) -** -** This function does three things: -** -** 1) Determines the locks that should be held, based on the contents of -** the Wal.readLock, Wal.writeLock and Wal.ckptLock variables. All other -** held locks are assumed to be transient locks that would have been -** released had the exception not been thrown and are dropped. -** -** 2) Frees the pointer at Wal.pFree, if any, using sqlite3_free(). -** -** 3) Returns SQLITE_IOERR. -*/ -static int walHandleException(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<lockMask & ~( - (pWal->readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) - ); - for(ii=0; iipFree); - pWal->pFree = 0; - return SQLITE_IOERR; -} - -/* -** Assert that the Wal.lockMask mask, which indicates the locks held -** by the connenction, is consistent with the Wal.readLock, Wal.writeLock -** and Wal.ckptLock variables. To be used as: -** -** assert( walAssertLockmask(pWal) ); -*/ -static int walAssertLockmask(Wal *pWal){ - if( pWal->exclusiveMode==0 ){ - static const int S = 1; - static const int E = (1<readLock<0 ? 0 : (S << WAL_READ_LOCK(pWal->readLock))) - | (pWal->writeLock ? (E << WAL_WRITE_LOCK) : 0) - | (pWal->ckptLock ? (E << WAL_CKPT_LOCK) : 0) -#ifdef SQLITE_ENABLE_SNAPSHOT - | (pWal->pSnapshot ? (pWal->lockMask & (1 << WAL_CKPT_LOCK)) : 0) -#endif - ); - assert( mExpect==pWal->lockMask ); - } - return 1; -} -#endif - #ifdef SQLITE_ENABLE_SNAPSHOT /* ** This function does the work of sqlite3WalSnapshotRecover(). @@ -4167,6 +4173,7 @@ int sqlite3WalCheckpoint( /* If no error occurred, set the output variables. */ if( rc==SQLITE_OK || rc==SQLITE_BUSY ){ if( pnLog ) *pnLog = (int)pWal->hdr.mxFrame; + SEH_INJECT_FAULT; if( pnCkpt ) *pnCkpt = (int)(walCkptInfo(pWal)->nBackfill); } } From 67ae593ffecb046d94882fdadcb1f174e91631a5 Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 20 Aug 2021 18:18:12 +0000 Subject: [PATCH 06/21] Use VVA_ONLY() instead of TESTONLY() in SEH macros so that the build works for coverage testing. FossilOrigin-Name: 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index 18648cc431..0ba922e1f6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\smissing\sSEH_INJECT_FAULT\smacros. -D 2021-08-20T17:23:19.198 +C Use\sVVA_ONLY()\sinstead\sof\sTESTONLY()\sin\sSEH\smacros\sso\sthat\sthe\sbuild\nworks\sfor\scoverage\stesting. +D 2021-08-20T18:18:12.982 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 5f98987c924f3262e19bc1c124cc4e02553f768a86cfdfb4d193db04c4d0b3da +F src/wal.c 2000742eae6204d2e6dff721eabf7905171af22bb99e3760670188f8a18d66f4 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P bd9b373b177a71f5eaeb7ce8dd1dc755b34951ee1376c24652418bb329bfcb45 -R 18bce27bc9709a49e95cb84782c68c82 -U dan -Z 8c053f205f09cec18507fce552900c67 +P 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded +R 66057be76f6babcd4edb6b4970a8bed6 +U drh +Z 72862037c4132917dc5cd800ca04f4aa diff --git a/manifest.uuid b/manifest.uuid index f413569b7c..e50bfb0721 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded \ No newline at end of file +9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index ef50aac040..d32e639735 100644 --- a/src/wal.c +++ b/src/wal.c @@ -623,10 +623,10 @@ struct WalIterator { # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ - TESTONLY(pWal->nSehTry++); + VVA_ONLY(pWal->nSehTry++); # define SEH_EXCEPT(X) \ - TESTONLY(pWal->nSehTry--); \ + VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } @@ -639,7 +639,7 @@ struct WalIterator { ** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. */ static int sehExceptionFilter(Wal *pWal, int eCode){ - TESTONLY(pWal->nSehTry--); + VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_ACCESS_VIOLATION ){ return EXCEPTION_EXECUTE_HANDLER; } @@ -676,8 +676,8 @@ static void sehInjectFault(Wal *pWal){ assert( (X==0 || Y==0) && pWal->pFree==X ); pWal->pFree = Y #else -# define SEH_TRY TESTONLY(pWal->nSehTry++); -# define SEH_EXCEPT(X) TESTONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); +# define SEH_TRY VVA_ONLY(pWal->nSehTry++); +# define SEH_EXCEPT(X) VVA_ONLY(pWal->nSehTry--); assert( pWal->nSehTry==0 ); # define SEH_INJECT_FAULT assert( pWal->nSehTry>0 ); # define SEH_FREE_ON_ERROR(X,Y) #endif /* ifdef SQLITE_USE_SEH */ From 101a6b87c79f83dcc08cd513f3fc30bbe808962c Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 21 Aug 2021 15:49:15 +0000 Subject: [PATCH 07/21] Add test cases to ensure that there is at least one test that causes an exception to be thrown from each SEH_INJECT_FAULT macro. FossilOrigin-Name: e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e --- manifest | 14 +++++++------- manifest.uuid | 2 +- test/walseh1.test | 32 +++++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 0ba922e1f6..76b263f2dc 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Use\sVVA_ONLY()\sinstead\sof\sTESTONLY()\sin\sSEH\smacros\sso\sthat\sthe\sbuild\nworks\sfor\scoverage\stesting. -D 2021-08-20T18:18:12.982 +C Add\stest\scases\sto\sensure\sthat\sthere\sis\sat\sleast\sone\stest\sthat\scauses\san\sexception\sto\sbe\sthrown\sfrom\seach\sSEH_INJECT_FAULT\smacro. +D 2021-08-21T15:49:15.749 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 970946bdd40bc37d1552811b54ec94dd4a5a4178354b4afa129f2053b99bf09f +F test/walseh1.test 7aff09e275a10a4b140f0a34c9da55de2d3747582590f16b638831e1dd7396b2 F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 27e9bdb3a90a5826f45d32e0378e9afa90a16ac762a75236f38218f41bc45ded -R 66057be76f6babcd4edb6b4970a8bed6 -U drh -Z 72862037c4132917dc5cd800ca04f4aa +P 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 +R 1ec6de0718c621705d76375df7f5b74b +U dan +Z 1df868f8b39d7326ed3c02e05075825f diff --git a/manifest.uuid b/manifest.uuid index e50bfb0721..d330c3b47b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 \ No newline at end of file +e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e \ No newline at end of file diff --git a/test/walseh1.test b/test/walseh1.test index ba5d786c48..b5b22d2a82 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -13,7 +13,7 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl source $testdir/malloc_common.tcl -set testprefix seh1 +set testprefix walseh1 set ::seh_countdown 0 proc seh_faultsim_callback {iFault} { @@ -101,6 +101,36 @@ do_faultsim_test 4 -faults seh -prep { } catch { db close } +do_faultsim_test 5 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen + execsql { + PRAGMA cache_size = 5; + BEGIN; + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50 + ) + INSERT INTO t1 SELECT randomblob(500), randomblob(500) FROM s; + } +} -body { + execsql ROLLBACK +} -test { + faultsim_test_result {0 {}} +} +catch { db close } + +do_faultsim_test 6 -faults seh -prep { + catch { db close } + faultsim_restore_and_reopen +} -body { + execsql { PRAGMA wal_checkpoint = TRUNCATE } + execsql { INSERT INTO t1 VALUES(7, 8) } + execsql { SELECT * FROM t1 } +} -test { + faultsim_test_result {0 {1 2 3 4 7 8}} +} +catch { db close } + finish_test From ee7c667a364035db0ca9ced959b918e6ed40d7bf Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Aug 2021 21:12:07 +0000 Subject: [PATCH 08/21] Change the structuree exception handler in wal.c to catch EXCEPTION_IN_PAGE_ERROR instead of EXCEPTION_ACCESS_VIOLATION. FossilOrigin-Name: 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wal.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index 76b263f2dc..7b07305bc4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\stest\scases\sto\sensure\sthat\sthere\sis\sat\sleast\sone\stest\sthat\scauses\san\sexception\sto\sbe\sthrown\sfrom\seach\sSEH_INJECT_FAULT\smacro. -D 2021-08-21T15:49:15.749 +C Change\sthe\sstructuree\sexception\shandler\sin\swal.c\sto\scatch\sEXCEPTION_IN_PAGE_ERROR\sinstead\sof\sEXCEPTION_ACCESS_VIOLATION. +D 2021-08-26T21:12:07.088 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -628,7 +628,7 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 2000742eae6204d2e6dff721eabf7905171af22bb99e3760670188f8a18d66f4 +F src/wal.c 75bcffce59a3108ad3e24c186977821ffe5083ab2044ff477a5bbc4a9e8a5455 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 9e9d5b566da72adf780685ea27da7d76a7274e904a533438255af92875c94503 -R 1ec6de0718c621705d76375df7f5b74b +P e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e +R e565d7a955f7dfbceec6b3e9d7245e4b U dan -Z 1df868f8b39d7326ed3c02e05075825f +Z 2c7b74af84f6da4d9875b4b1565fc82a diff --git a/manifest.uuid b/manifest.uuid index d330c3b47b..4b4b64c0bd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e \ No newline at end of file +0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index d32e639735..f832e1b017 100644 --- a/src/wal.c +++ b/src/wal.c @@ -640,7 +640,7 @@ struct WalIterator { */ static int sehExceptionFilter(Wal *pWal, int eCode){ VVA_ONLY(pWal->nSehTry--); - if( eCode==EXCEPTION_ACCESS_VIOLATION ){ + if( eCode==EXCEPTION_IN_PAGE_ERROR ){ return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; @@ -655,7 +655,7 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ static void sehInjectFault(Wal *pWal){ assert( pWal->nSehTry>0 ); if( sqlite3FaultSim(650) ){ - RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, NULL); + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 0, NULL); } } From 9023444fea771dd0b38bf92efa1751e02b0e89d0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 10 Sep 2021 21:28:56 +0000 Subject: [PATCH 09/21] If an EXCEPTION_IN_PAGE_ERROR exception is caught, make the underlying OS error code available via sqlite3_system_errno(). FossilOrigin-Name: fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b --- manifest | 24 +++++++++++------------ manifest.uuid | 2 +- src/pager.c | 6 ++++++ src/pager.h | 4 ++++ src/sqlite.h.in | 1 + src/util.c | 17 ++++++++++++++++ src/wal.c | 49 +++++++++++++++++++++++++++++++++++------------ src/wal.h | 4 ++++ test/walseh1.test | 13 ++++++++++++- 9 files changed, 94 insertions(+), 26 deletions(-) diff --git a/manifest b/manifest index 7b07305bc4..a0bc1c1835 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\sstructuree\sexception\shandler\sin\swal.c\sto\scatch\sEXCEPTION_IN_PAGE_ERROR\sinstead\sof\sEXCEPTION_ACCESS_VIOLATION. -D 2021-08-26T21:12:07.088 +C If\san\sEXCEPTION_IN_PAGE_ERROR\sexception\sis\scaught,\smake\sthe\sunderlying\sOS\serror\scode\savailable\svia\ssqlite3_system_errno(). +D 2021-09-10T21:28:56.797 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -531,8 +531,8 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c b11e4610769922253dec27d7af4a07ff84f65169d19bda5e9b12a152a706f7f5 F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0 -F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f +F src/pager.c 555cff0be2d255827dbc93761c0265d077faf34f31b65ccf16d76d053dfd0467 +F src/pager.h 53b3ba002dbc7568608489f67c249224102d10f372c098a1a9dd58308bc76d3c F src/parse.y 0ba0baec5de6921ec8ba8bbcf1018969144ef29d26112e17539d8fbb1662e3eb F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 @@ -546,7 +546,7 @@ F src/resolve.c 42b94d37a54200707a95566eff4f7e8a380e32d080016b699f23bd79a73a5028 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 F src/select.c 0577308f097363b6ebac223e210418810acf74e677f580597f7d0718476fe3ef F src/shell.c.in f795a4ae3c35631f5edcfa754c7824ff1d8a75b23a07e22e664b50f82e826346 -F src/sqlite.h.in 43fcf0fe2af04081f420a906fc020bde1243851ba44b0aa567a27f94bf8c3145 +F src/sqlite.h.in 79d8c9a7e9886851243183e4b610022d87e6dd73bf2e1218d3105ab4577af9a0 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 F src/sqliteInt.h a65ddfb177549c82dcd1374a2f23260328eb65ced55b50843419386177e159be @@ -614,7 +614,7 @@ F src/trigger.c 3f612ce5f0858b6c23460a3c799d01f408b49b0b29d931d8b8e6fc224a8667de F src/update.c 69c4c10bc6873a80c0a77cb578f9fc60ee90003d03f9530bc3370fa24615772d F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 -F src/util.c eafc8cfeb66fdbf8839922d13019b7882f242ac31b383e3451aab7744c54df3e +F src/util.c a14724ed2a504488c34bd3a510ae33e46be00d0b80296651aba3a3d36303e460 F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45 F src/vdbe.c e5cdac52d7163c032ae3c54f1cff9391acd23ba79cea0d5a9524c00cc0a856e8 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe @@ -628,8 +628,8 @@ F src/vdbetrace.c 666c6fd9f1b62be6999e072a45b913e3c2c3518bc60dfd4d54fe304130acb7 F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c F src/vtab.c 88404ac1517903b3eb2abe256772ee95bb09f81ac0a17e13afe5d467df4de4ee F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 75bcffce59a3108ad3e24c186977821ffe5083ab2044ff477a5bbc4a9e8a5455 -F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a +F src/wal.c 8cc813d34b345728987b78bcb0a02f7b6e4734031eea1feb1b6d1d0e56ac5a21 +F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7342becedf3f8a26f9817f08436bdf8b56ad69af83705f6b9320a0ad3092c2ac F src/where.c 99b6e13664a7bd9a553c554978d0e253066995dade621f44cffa8928c8b493b5 F src/whereInt.h 9248161dd004f625ce5d3841ca9b99fed3fc8d61522cf76340fc5217dbe1375b @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 7aff09e275a10a4b140f0a34c9da55de2d3747582590f16b638831e1dd7396b2 +F test/walseh1.test 5a94409fb1a7029070040286336fef5ce61315121123e25cfb7e0622b017e59d F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e480146f49004c818ad93464289761d8a7246b502bd079f8140d0a6f684ebe4e -R e565d7a955f7dfbceec6b3e9d7245e4b +P 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d +R 33294cd0e1de3328b05fc8fdf4f59e56 U dan -Z 2c7b74af84f6da4d9875b4b1565fc82a +Z ff4d8e1dd5c81ec2fdd90cee5190a162 diff --git a/manifest.uuid b/manifest.uuid index 4b4b64c0bd..e5d92301b8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d \ No newline at end of file +fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 12a78cde80..31bcb32a04 100644 --- a/src/pager.c +++ b/src/pager.c @@ -7706,4 +7706,10 @@ int sqlite3PagerWalFramesize(Pager *pPager){ } #endif +#ifdef SQLITE_USE_SEH +int sqlite3PagerWalSystemErrno(Pager *pPager){ + return sqlite3WalSystemErrno(pPager->pWal); +} +#endif + #endif /* SQLITE_OMIT_DISKIO */ diff --git a/src/pager.h b/src/pager.h index 8d899bd1a6..dde845a023 100644 --- a/src/pager.h +++ b/src/pager.h @@ -239,4 +239,8 @@ void sqlite3PagerRekey(DbPage*, Pgno, u16); # define enable_simulated_io_errors() #endif +#ifdef SQLITE_USE_SEH +int sqlite3PagerWalSystemErrno(Pager*); +#endif + #endif /* SQLITE_PAGER_H */ diff --git a/src/sqlite.h.in b/src/sqlite.h.in index e4ea66a725..6a2cc53c66 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -528,6 +528,7 @@ int sqlite3_exec( #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8)) #define SQLITE_IOERR_CORRUPTFS (SQLITE_IOERR | (33<<8)) +#define SQLITE_IOERR_IN_PAGE (SQLITE_IOERR | (34<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) diff --git a/src/util.c b/src/util.c index 2d1c64ad13..3eb0419b66 100644 --- a/src/util.c +++ b/src/util.c @@ -136,6 +136,23 @@ void sqlite3ErrorClear(sqlite3 *db){ */ void sqlite3SystemError(sqlite3 *db, int rc){ if( rc==SQLITE_IOERR_NOMEM ) return; +#ifdef SQLITE_USE_SEH + if( rc==SQLITE_IOERR_IN_PAGE ){ + int ii; + int iErr; + sqlite3BtreeEnterAll(db); + for(ii=0; iinDb; ii++){ + if( db->aDb[ii].pBt ){ + iErr = sqlite3PagerWalSystemErrno(sqlite3BtreePager(db->aDb[ii].pBt)); + if( iErr ){ + db->iSysErrno = iErr; + } + } + } + sqlite3BtreeLeaveAll(db); + return; + } +#endif rc &= 0xff; if( rc==SQLITE_CANTOPEN || rc==SQLITE_IOERR ){ db->iSysErrno = sqlite3OsGetLastError(db->pVfs); diff --git a/src/wal.c b/src/wal.c index f832e1b017..78ef82145c 100644 --- a/src/wal.c +++ b/src/wal.c @@ -534,6 +534,7 @@ struct Wal { #ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ + int iSysErrno; /* System error code following exception */ #endif #ifdef SQLITE_DEBUG u8 lockError; /* True if a locking error has occurred */ @@ -628,7 +629,7 @@ struct WalIterator { # define SEH_EXCEPT(X) \ VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ - } __except( sehExceptionFilter(pWal, GetExceptionCode()) ){ X } + } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } # define SEH_INJECT_FAULT sehInjectFault(pWal) @@ -638,9 +639,12 @@ struct WalIterator { ** indicates that the exception may have been caused by accessing the *-shm ** file mapping. Or EXCEPTION_CONTINUE_SEARCH otherwise. */ -static int sehExceptionFilter(Wal *pWal, int eCode){ +static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_IN_PAGE_ERROR ){ + if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ + pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; + } return EXCEPTION_EXECUTE_HANDLER; } return EXCEPTION_CONTINUE_SEARCH; @@ -653,10 +657,17 @@ static int sehExceptionFilter(Wal *pWal, int eCode){ ** has been invalidated. */ static void sehInjectFault(Wal *pWal){ - assert( pWal->nSehTry>0 ); - if( sqlite3FaultSim(650) ){ - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 0, NULL); - } + int res; + assert( pWal->nSehTry>0 ); + + res = sqlite3FaultSim(650); + if( res!=0 ){ + ULONG aArg[3]; + aArg[0] = 0; + aArg[1] = 0; + aArg[2] = (ULONG)res; + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, aArg); + } } /* @@ -2353,7 +2364,7 @@ static int walHandleException(Wal *pWal){ } sqlite3_free(pWal->pFree); pWal->pFree = 0; - return SQLITE_IOERR; + return SQLITE_IOERR_IN_PAGE; } /* @@ -2379,6 +2390,20 @@ static int walAssertLockmask(Wal *pWal){ } return 1; } + +/* +** Return and zero the "system error" field set when an +** EXCEPTION_IN_PAGE_ERROR exception is caught. +*/ +int sqlite3WalSystemErrno(Wal *pWal){ + int iRet = 0; + if( pWal ){ + iRet = pWal->iSysErrno; + pWal->iSysErrno = 0; + } + return iRet; +} + #else # define walAssertLockmask(x) 1 #endif /* ifdef SQLITE_USE_SEH */ @@ -3151,7 +3176,7 @@ int sqlite3WalSnapshotRecover(Wal *pWal){ SEH_TRY { rc = walSnapshotRecover(pWal, pBuf1, pBuf2); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) pWal->ckptLock = 0; } @@ -3436,7 +3461,7 @@ int sqlite3WalFindFrame( SEH_TRY { rc = walFindFrame(pWal, pgno, piRead); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) return rc; } @@ -3526,7 +3551,7 @@ int sqlite3WalBeginWriteTransaction(Wal *pWal){ rc = SQLITE_BUSY_SNAPSHOT; } } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) if( rc!=SQLITE_OK ){ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1); @@ -3593,7 +3618,7 @@ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx){ } if( iMax!=pWal->hdr.mxFrame ) walCleanupHash(pWal); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; } @@ -3640,7 +3665,7 @@ int sqlite3WalSavepointUndo(Wal *pWal, u32 *aWalData){ SEH_TRY { walCleanupHash(pWal); } - SEH_EXCEPT( rc = SQLITE_IOERR; ) + SEH_EXCEPT( rc = SQLITE_IOERR_IN_PAGE; ) } return rc; diff --git a/src/wal.h b/src/wal.h index 02e2bab360..d39bb50f3d 100644 --- a/src/wal.h +++ b/src/wal.h @@ -151,5 +151,9 @@ int sqlite3WalWriteLock(Wal *pWal, int bLock); void sqlite3WalDb(Wal *pWal, sqlite3 *db); #endif +#ifdef SQLITE_USE_SEH +int sqlite3WalSystemErrno(Wal*); +#endif + #endif /* ifndef SQLITE_OMIT_WAL */ #endif /* SQLITE_WAL_H */ diff --git a/test/walseh1.test b/test/walseh1.test index b5b22d2a82..62fb9a47a8 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -16,10 +16,11 @@ source $testdir/malloc_common.tcl set testprefix walseh1 set ::seh_countdown 0 +set ::seh_errno 10 proc seh_faultsim_callback {iFault} { if {$iFault==650} { incr ::seh_countdown -1 - if {$::seh_countdown==0} { return 1 } + if {$::seh_countdown==0} { return $::seh_errno } } return 0 } @@ -31,6 +32,7 @@ proc seh_injectuninstall {} { sqlite3_test_control_fault_install } proc seh_injectstart {iFail} { + set ::seh_errno [expr 2+$iFail*10] set ::seh_countdown $iFail } proc seh_injectstop {} { @@ -47,6 +49,13 @@ set FAULTSIM(seh) [list \ -injectuninstall seh_injectuninstall \ ] +proc test_system_errno {db expect} { + set serrno [sqlite3_system_errno $db] + if {$serrno!=$expect} { + error "surprising system_errno. Expected $expect, got $serrno" + } +} + do_execsql_test 1.0 { PRAGMA journal_mode = wal; CREATE TABLE t1(x, y); @@ -64,6 +73,7 @@ do_faultsim_test 1 -faults seh -prep { execsql { SELECT * FROM t1 } db2 } -test { faultsim_test_result {0 {1 2 3 4}} + if {$testrc} { test_system_errno db2 $::seh_errno } } catch { db2 close } @@ -76,6 +86,7 @@ do_faultsim_test 2 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4}} + if {$testrc} { test_system_errno db $::seh_errno } } do_faultsim_test 3 -faults seh -prep { From 51f0c762f0dad1126568d08f85a71113858c35b1 Mon Sep 17 00:00:00 2001 From: dan Date: Sat, 11 Sep 2021 14:33:05 +0000 Subject: [PATCH 10/21] Fix a case where the system error was not being set correctly. FossilOrigin-Name: 13a524b351a0812214b223aa4e0a9d778ae7a75cf9875da1147a09c5cb76b9fe --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/vdbeaux.c | 1 + test/walseh1.test | 5 ++++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index a0bc1c1835..bef88c5593 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C If\san\sEXCEPTION_IN_PAGE_ERROR\sexception\sis\scaught,\smake\sthe\sunderlying\sOS\serror\scode\savailable\svia\ssqlite3_system_errno(). -D 2021-09-10T21:28:56.797 +C Fix\sa\scase\swhere\sthe\ssystem\serror\swas\snot\sbeing\sset\scorrectly. +D 2021-09-11T14:33:05.275 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -620,7 +620,7 @@ F src/vdbe.c e5cdac52d7163c032ae3c54f1cff9391acd23ba79cea0d5a9524c00cc0a856e8 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5 -F src/vdbeaux.c 2368a8888f17368d4040a05966f7d2a2276cac4eeeba50793828186d999e3c8f +F src/vdbeaux.c 258c4ea5afea94b0d21aa9f46015769de7d7c9cf41b9d94672de74a6f4a3a241 F src/vdbeblob.c 60a7694760e35b2bba166cf49eb6a1eb0b31581102b49de78008ca3032406065 F src/vdbemem.c 53881aa0a7845922a075b3f375695588618098871a7a4120af4c297b80fa3e64 F src/vdbesort.c cd5130f683706c1a43e165a74187745fb3351cb56052cf9dc91de820634bbde2 @@ -1739,7 +1739,7 @@ F test/walprotocol2.test 7d3b6b4bf0b12f8007121b1e6ef714bc99101fb3b48e46371df1db8 F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c20 F test/walro2.test 0e79dd15cbdb4f482c01ea248373669c732414a726b357d04846a816afafb768 F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68 -F test/walseh1.test 5a94409fb1a7029070040286336fef5ce61315121123e25cfb7e0622b017e59d +F test/walseh1.test 82da37763b0d87942dccd191e58321532ce3d44b87ef36e04ff9ce13f382bbae F test/walsetlk.test 3185bebc90557e0d611442c8d64f7a0cb7b06f8e156eea37a4a7358f722715be F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417 F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f @@ -1921,7 +1921,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0c6ab539cfbc908550fa993a587e85d644b6335853ff9781caae860c461c045d -R 33294cd0e1de3328b05fc8fdf4f59e56 +P fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b +R 19613aef7c9a0f6d6a0d415bcd0e8fe9 U dan -Z ff4d8e1dd5c81ec2fdd90cee5190a162 +Z 115def4376f9950aab2266e8ac285bc1 diff --git a/manifest.uuid b/manifest.uuid index e5d92301b8..1f797882d8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -fdb20e9ee48465b94aa6ac3c5e263ecaa7c3b10f4a193e79f965b7c35944b08b \ No newline at end of file +13a524b351a0812214b223aa4e0a9d778ae7a75cf9875da1147a09c5cb76b9fe \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index c04bd0d379..e93d5cbf46 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3118,6 +3118,7 @@ int sqlite3VdbeHalt(Vdbe *p){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ + sqlite3SystemError(db, rc); p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; diff --git a/test/walseh1.test b/test/walseh1.test index 62fb9a47a8..c3a655f534 100644 --- a/test/walseh1.test +++ b/test/walseh1.test @@ -97,8 +97,8 @@ do_faultsim_test 3 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 5 6}} + if {$testrc} { test_system_errno db $::seh_errno } } -catch { db close } do_faultsim_test 4 -faults seh -prep { catch { db close } @@ -109,6 +109,7 @@ do_faultsim_test 4 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 7 8}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } @@ -127,6 +128,7 @@ do_faultsim_test 5 -faults seh -prep { execsql ROLLBACK } -test { faultsim_test_result {0 {}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } @@ -139,6 +141,7 @@ do_faultsim_test 6 -faults seh -prep { execsql { SELECT * FROM t1 } } -test { faultsim_test_result {0 {1 2 3 4 7 8}} + if {$testrc} { test_system_errno db $::seh_errno } } catch { db close } From 5d3cc0c09b1f64efd0bebde0ffc85eea571c00dd Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jul 2023 18:16:49 +0000 Subject: [PATCH 11/21] Fix a warning. Unclear yet if the code is correct this way or not. FossilOrigin-Name: 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/wal.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 3c7a4ef6e2..1e805163d5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\swal-shm-exceptions\sbranch. -D 2023-07-10T18:05:23.333 +C Fix\sa\swarning.\s\sUnclear\syet\sif\sthe\scode\sis\scorrect\sthis\sway\sor\snot. +D 2023-07-10T18:16:49.671 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -719,7 +719,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c df70125aa233626b8aa56dd6be7cbbe7234e10e01a0610152e583b65eeebc474 +F src/wal.c b4668b94644c79bd9e44ba0aacaeb32631413d1ccee72e67606443a30cc6e56e F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P e59cea2d851be68559e7d01a01cb05684c44d151d022ea9790ce99671016ab00 07d95ed60f0a17ea13b4bc19c2ab2ec9052fedd27c9e1e57a1ec6e3a6470e5b7 -R ccbc614d43527056706e7e54f93af172 +P f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 +R 7d2a7db7a45657e046a46b76cd581cc4 U drh -Z da656ee3765bdd3f9ae04fb3fd79cf86 +Z 908a871ddbc8b91ee09e4dbf74793fad # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 8d0a378f48..1ce8d7c8d6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 \ No newline at end of file +2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 1e1382129b..0cb4f0344a 100644 --- a/src/wal.c +++ b/src/wal.c @@ -666,7 +666,7 @@ static void sehInjectFault(Wal *pWal){ aArg[0] = 0; aArg[1] = 0; aArg[2] = (ULONG)res; - RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG*)aArg); + RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); } } From 7994d9dab77cfb9adaf01ef04601eb9856fb2f7b Mon Sep 17 00:00:00 2001 From: drh <> Date: Mon, 10 Jul 2023 19:13:40 +0000 Subject: [PATCH 12/21] Compile for SEH if the USE_SEH=1 option is specified on the nmake command line. FossilOrigin-Name: 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae --- Makefile.msc | 7 +++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index e8efe58296..c250810008 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -402,6 +402,13 @@ EXT_FEATURE_FLAGS = !ENDIF !ENDIF +# Include USE_SEH=1 on the nmake command-line to activate the +# structured exception handling logic. +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH +!ENDIF + ############################################################################### ############################### END OF OPTIONS ################################ ############################################################################### diff --git a/manifest b/manifest index 1e805163d5..81fa654b49 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Fix\sa\swarning.\s\sUnclear\syet\sif\sthe\scode\sis\scorrect\sthis\sway\sor\snot. -D 2023-07-10T18:16:49.671 +C Compile\sfor\sSEH\sif\sthe\sUSE_SEH=1\soption\sis\sspecified\son\sthe\snmake\scommand\sline. +D 2023-07-10T19:13:40.460 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 7248d860f71ab164b4cec3c415e6cc1bd9fee860c370d65bd8bb49e9572521e2 +F Makefile.msc 3cd72b65de28d1355dd5bf496c190dc50578b77b0cfe080986abaef3abfb21c8 F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f655d08d019bab0c578886e91ca24fd956d1b3dea9b9c9104812b3cf62e5e556 -R 7d2a7db7a45657e046a46b76cd581cc4 +P 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b +R 023694c34457958614951e26d46dca77 U drh -Z 908a871ddbc8b91ee09e4dbf74793fad +Z 96490a1ad3ea195c140b420d8f7d8322 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1ce8d7c8d6..dabe35bc53 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b \ No newline at end of file +0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae \ No newline at end of file From c0b6112d04758f95555b6f9aa2a59bc6fd7e1a23 Mon Sep 17 00:00:00 2001 From: mistachkin Date: Mon, 10 Jul 2023 19:21:09 +0000 Subject: [PATCH 13/21] Minor style changes to the previous MSVC makefile changes on this branch. FossilOrigin-Name: 4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 --- Makefile.msc | 21 ++++++++++++++------- autoconf/Makefile.msc | 14 ++++++++++++++ manifest | 16 ++++++++-------- manifest.uuid | 2 +- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/Makefile.msc b/Makefile.msc index c250810008..6fc4c83390 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0 USE_STDCALL = 0 !ENDIF +# Set this non-0 to use structured exception handling (SEH) for WAL mode +# in the core library. +# +!IFNDEF USE_SEH +USE_SEH = 0 +!ENDIF + # Set this non-0 to have the shell executable link against the core dynamic # link library. # @@ -389,6 +396,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1 !ENDIF +# Should structured exception handling (SEH) be enabled for WAL mode in +# the core library? +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1 +!ENDIF + # These are the "extended" SQLite compilation options used when compiling for # the Windows 10 platform. # @@ -402,13 +416,6 @@ EXT_FEATURE_FLAGS = !ENDIF !ENDIF -# Include USE_SEH=1 on the nmake command-line to activate the -# structured exception handling logic. -# -!IF $(USE_SEH)!=0 -OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH -!ENDIF - ############################################################################### ############################### END OF OPTIONS ################################ ############################################################################### diff --git a/autoconf/Makefile.msc b/autoconf/Makefile.msc index 09daa867ec..24154dd5d8 100644 --- a/autoconf/Makefile.msc +++ b/autoconf/Makefile.msc @@ -52,6 +52,13 @@ MINIMAL_AMALGAMATION = 0 USE_STDCALL = 0 !ENDIF +# Set this non-0 to use structured exception handling (SEH) for WAL mode +# in the core library. +# +!IFNDEF USE_SEH +USE_SEH = 0 +!ENDIF + # Set this non-0 to have the shell executable link against the core dynamic # link library. # @@ -311,6 +318,13 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MATH_FUNCTIONS OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1 !ENDIF +# Should structured exception handling (SEH) be enabled for WAL mode in +# the core library? +# +!IF $(USE_SEH)!=0 +OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_USE_SEH=1 +!ENDIF + # These are the "extended" SQLite compilation options used when compiling for # the Windows 10 platform. # diff --git a/manifest b/manifest index 81fa654b49..983bba5257 100644 --- a/manifest +++ b/manifest @@ -1,11 +1,11 @@ -C Compile\sfor\sSEH\sif\sthe\sUSE_SEH=1\soption\sis\sspecified\son\sthe\snmake\scommand\sline. -D 2023-07-10T19:13:40.460 +C Minor\sstyle\schanges\sto\sthe\sprevious\sMSVC\smakefile\schanges\son\sthis\sbranch. +D 2023-07-10T19:21:09.466 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F Makefile.in 0f4cb3955aaff8a40ec3857ba1784bd98b69802e51eff979f874b65713b627b2 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241 -F Makefile.msc 3cd72b65de28d1355dd5bf496c190dc50578b77b0cfe080986abaef3abfb21c8 +F Makefile.msc daad4a19e0b3c3c3b79b64d4ddbf75e3f506405e8d3f3f604d6f48b26043c51f F README.md c1c4218efcc4071a6e26db2b517fdbc1035696a29b370edd655faddbef02b224 F VERSION c6366dc72582d3144ce87b013cc35fe48d62f6d07d5be0c9716ea33c862144aa F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -15,7 +15,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2 F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903 F autoconf/Makefile.am a8d1d24affe52ebf8d7ddcf91aa973fa0316618ab95bb68c87cabf8faf527dc8 F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac -F autoconf/Makefile.msc 20366d19fbfc3fceecce95344a2114069eaab4fc22e4f02430da167a1e2ddf04 +F autoconf/Makefile.msc 00f11ce1f7904416fe841c33e7d789defe8c39e1df6b97e93ed2af3b1bbaf9d7 F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7 F autoconf/README.txt 42cfd21d0b19dc7d5d85fb5c405c5f3c6a4c923021c39128f6ba685355d8fd56 F autoconf/configure.ac ec7fa914c5e74ff212fe879f9bb6918e1234497e05facfb641f30c4d5893b277 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2df4fd76ef48bb63389df8d783059af6b8f2cbb2c11d07953b408e71f50b625b -R 023694c34457958614951e26d46dca77 -U drh -Z 96490a1ad3ea195c140b420d8f7d8322 +P 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae +R 2485a85a908a05b5fd0644b2f7fd3722 +U mistachkin +Z 5b8cb43f82a279de421ae118ca8d7765 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index dabe35bc53..3f7af51b45 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae \ No newline at end of file +4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 \ No newline at end of file From 66422b57f9892262c0d5638a0c5d165658fcee43 Mon Sep 17 00:00:00 2001 From: drh <> Date: Tue, 11 Jul 2023 15:52:52 +0000 Subject: [PATCH 14/21] Get fault injection for testing working correctly. Other code clean-up. FossilOrigin-Name: ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/wal.c | 23 +++++++++++++++++------ 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/manifest b/manifest index 983bba5257..bd506d9ad1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\sstyle\schanges\sto\sthe\sprevious\sMSVC\smakefile\schanges\son\sthis\sbranch. -D 2023-07-10T19:21:09.466 +C Get\sfault\sinjection\sfor\stesting\sworking\scorrectly.\s\sOther\scode\sclean-up. +D 2023-07-11T15:52:52.116 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -719,7 +719,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c b4668b94644c79bd9e44ba0aacaeb32631413d1ccee72e67606443a30cc6e56e +F src/wal.c e4bfb243cc1f6f89c7fba5dd8872ae38a8c1dcc760c276dbb164edb7290072a6 F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 2dc708cf8b6a691fb79f16bbc46567497ee6f991043318d421e294b2da114d93 @@ -2044,8 +2044,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 0e67a82f6cfe681d4676ac5c92d92e95b9dcc3198df21516bccdde002f5e52ae -R 2485a85a908a05b5fd0644b2f7fd3722 -U mistachkin -Z 5b8cb43f82a279de421ae118ca8d7765 +P 4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 +R 966aa4944515db815a2a3b1d2b09adbd +U drh +Z 4e4c72cb034026cb3cf7caeaeea5ca69 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 3f7af51b45..066d2d9ef2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c950872c870a5968fa4cb8840cf60569a66c0e508811ee79992825ec9c02da3 \ No newline at end of file +ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 0cb4f0344a..6c153d65ba 100644 --- a/src/wal.c +++ b/src/wal.c @@ -528,15 +528,13 @@ struct Wal { u32 iReCksum; /* On commit, recalculate checksums from here */ const char *zWalName; /* Name of WAL file */ u32 nCkpt; /* Checkpoint sequence counter in the wal-header */ -# ifdef SQLITE_DEBUG - int nSehTry; /* Number of nested SEH_TRY{} blocks */ -# endif #ifdef SQLITE_USE_SEH u32 lockMask; /* Mask of locks held */ void *pFree; /* Pointer to sqlite3_free() if exception thrown */ int iSysErrno; /* System error code following exception */ #endif #ifdef SQLITE_DEBUG + int nSehTry; /* Number of nested SEH_TRY{} blocks */ u8 lockError; /* True if a locking error has occurred */ #endif #ifdef SQLITE_ENABLE_SNAPSHOT @@ -618,19 +616,32 @@ struct WalIterator { sizeof(ht_slot)*HASHTABLE_NSLOT + HASHTABLE_NPAGE*sizeof(u32) \ ) +/* +** Structured Exception Handling (SEH) is a Windows-specific technique +** for catching exceptions raised while accessing memory-mapped files. +** +** The -DSQLITE_USE_SEH compile-time option means to use SEH to catch and +** deal with system-level errors that arise during WAL -shm file processing. +** Without this compile-time option, any system-level faults that appear +** while accessing the memory-mapped -shm file will cause a process-wide +** signal to be deliver, which will more than likely cause the entire +** process to exit. +*/ #ifdef SQLITE_USE_SEH - #include +/* Beginning of a block of code in which an exception might occur */ # define SEH_TRY __try { \ assert( walAssertLockmask(pWal) && pWal->nSehTry==0 ); \ VVA_ONLY(pWal->nSehTry++); +/* The end of a block of code in which an exception might occur */ # define SEH_EXCEPT(X) \ VVA_ONLY(pWal->nSehTry--); \ assert( pWal->nSehTry==0 ); \ } __except( sehExceptionFilter(pWal, GetExceptionCode(), GetExceptionInformation() ) ){ X } +/* Simulate a memory-mapping fault in the -shm file for testing purposes */ # define SEH_INJECT_FAULT sehInjectFault(pWal) /* @@ -662,10 +673,10 @@ static void sehInjectFault(Wal *pWal){ res = sqlite3FaultSim(650); if( res!=0 ){ - ULONG aArg[3]; + ULONG_PTR aArg[3]; aArg[0] = 0; aArg[1] = 0; - aArg[2] = (ULONG)res; + aArg[2] = (ULONG_PTR)res; RaiseException(EXCEPTION_IN_PAGE_ERROR, 0, 3, (const ULONG_PTR*)aArg); } } From 5e22dfb6a582bc6df0bfbcf6e5b63df0ada22904 Mon Sep 17 00:00:00 2001 From: dan Date: Wed, 26 Jul 2023 18:34:34 +0000 Subject: [PATCH 15/21] Add a comment describing the contents of the ExceptionInformation[] array for win32 EXCEPTION_IN_PAGE_ERROR exceptions. No changes to code. FossilOrigin-Name: 8e20354242d5f34a90b6c00d9034535ef6f6086ee4971230c7fd69985e2777d2 --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/wal.c | 5 +++++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 7da2e11f83..3e7111a133 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\sthe\slatest\strunk\senhancements\sinto\sthe\swal-shm-exceptions\sbranch. -D 2023-07-24T12:59:53.689 +C Add\sa\scomment\sdescribing\sthe\scontents\sof\sthe\sExceptionInformation[]\sarray\sfor\swin32\sEXCEPTION_IN_PAGE_ERROR\sexceptions.\sNo\schanges\sto\scode. +D 2023-07-26T18:34:34.647 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -535,8 +535,8 @@ F ext/wasm/index.html b4e55de741be9fb7656445ea55085f703a784aebde620e1c4852fa21c1 F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54 F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10 -F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 w ext/wasm/scratchpad-wasmfs-main.html -F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 w ext/wasm/scratchpad-wasmfs-main.js +F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 +F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d F ext/wasm/speedtest1-wasmfs.mjs ac5cadbf4ffe69e9eaac8b45e8523f030521e02bb67d654c6eb5236d9c456cbe F ext/wasm/speedtest1-worker.html e33e2064bda572c0c3ebaec7306c35aa758d9d27e245d67e807f8cc4a9351cc5 @@ -720,7 +720,7 @@ F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf8 F src/vdbevtab.c aae4bd769410eb7e1d02c42613eec961d514459b1c3c1c63cfc84e92a137daac F src/vtab.c 1ecf8c3745d29275688d583e12822fa984d421e0286b5ef50c137bc3bf6d7a64 F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 -F src/wal.c 17a7ec957bd66e46a7d6403a8d55ce92518fb382ec598a5f50e2326de0206a80 +F src/wal.c 02e10f033a6972bc7d50122b400318003199c504cda48f61ad404564505f4e89 F src/wal.h 04a9e53121d5076f2a173b0f2facb39d33047093fee71bd3bbe6b1f6f1f5fd4b F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2 F src/where.c 477fcc5e561ef169e6002499602af6b805156c2aae6b2f5c2c93ef8c1cd64768 @@ -2045,8 +2045,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ff492277ed00c1f637a5b4ccd6d8193ea22f6781f90073861588a2b7d5c045b7 c1b080e39397c983c13a5e79303223827de7b4946c18a79396851ec1814782f3 -R 2d227170a4d38cef4891eb7e41ae2e61 -U drh -Z bee2c2751faa3281b3853d97c12aa683 +P 3187ee3f69fc28a259ba0e951ac10a65c07ef2c3866acbefaf9544333a930cc6 +R 7f170a7bcc2480971e636112d216d36a +U dan +Z abd48397a81b9e2e4bef4b928510bd64 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index a0ad36f77d..7fc53587a5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3187ee3f69fc28a259ba0e951ac10a65c07ef2c3866acbefaf9544333a930cc6 \ No newline at end of file +8e20354242d5f34a90b6c00d9034535ef6f6086ee4971230c7fd69985e2777d2 \ No newline at end of file diff --git a/src/wal.c b/src/wal.c index 48f5586209..c9d8eaebe5 100644 --- a/src/wal.c +++ b/src/wal.c @@ -654,6 +654,11 @@ static int sehExceptionFilter(Wal *pWal, int eCode, EXCEPTION_POINTERS *p){ VVA_ONLY(pWal->nSehTry--); if( eCode==EXCEPTION_IN_PAGE_ERROR ){ if( p && p->ExceptionRecord && p->ExceptionRecord->NumberParameters>=3 ){ + /* From MSDN: For this type of exception, the first element of the + ** ExceptionInformation[] array is a read-write flag - 0 if the exception + ** was thrown while reading, 1 if while writing. The second element is + ** the virtual address being accessed. The "third array element specifies + ** the underlying NTSTATUS code that resulted in the exception". */ pWal->iSysErrno = (int)p->ExceptionRecord->ExceptionInformation[2]; } return EXCEPTION_EXECUTE_HANDLER; From 89e1caf294e50ccbbc94cb75ba8a21c41aeb160c Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 10 Aug 2023 18:50:00 +0000 Subject: [PATCH 16/21] New testcase() macro in the tokenizer, to better document its behavior. FossilOrigin-Name: b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc --- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/tokenize.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index 60b7cd6a54..38ca5e045f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Move\sext/wasm/version-info.c\sto\stool/\sfor\sre-use\sin\sbuild\sother\sdist\sbundles. -D 2023-08-10T17:32:37.469 +C New\stestcase()\smacro\sin\sthe\stokenizer,\sto\sbetter\sdocument\sits\sbehavior. +D 2023-08-10T18:50:00.513 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -705,7 +705,7 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7 F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c -F src/tokenize.c 0fb405f9adf3f757c26bfc1ae6d58ac5dccbb918917ba9e5ef0e6673a06563d3 +F src/tokenize.c 23d9f4539880b40226254ad9072f4ecf12eb1902e62aea47aac29928afafcfd5 F src/treeview.c 1d52fbc4e97161e65858d36e3424ea6e3fc045dd8a679c82b4b9593dc30de3bd F src/trigger.c ad6ab9452715fa9a8075442e15196022275b414b9141b566af8cdb7a1605f2b0 F src/update.c 0bb9171afaa4d0b100ad946873bccda7aef90ffe083ef5c63668fce08c4df9da @@ -2025,7 +2025,7 @@ F tool/symbols.sh 1612bd947750e21e7b47befad5f6b3825b06cce0705441f903bf35ced65ae9 F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003 F tool/vdbe-compress.tcl 1dcb7632e57cf57105248029e6e162fddaf6c0fccb3bb9e6215603752c5a2d4a F tool/vdbe_profile.tcl 3ac5a4a9449f4baf77059358ea050db3e34395ccf59c5464d29b91746d5b961e -F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5 w ext/wasm/version-info.c +F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd72273503ae7d5 F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7 F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f @@ -2050,8 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P aa6de539c09faa320b68c63659e602107145c4263fa680d5b40fe4d7d7ac4534 -R e8c10ce35c97a4689d66203c4b77aa02 -U stephan -Z e2d880944a873fb45826adfc8f1da470 +P 4b0871fd367b6d9706e892aa13f64604967f5e3ba92381960f73aeabd3d23f84 +R a40fe5763d111aa30a3a21c2dead52e5 +U drh +Z d5cf7898ce1eeb270f6b6924ff8af0dd # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 636bc42bb1..6016c15688 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4b0871fd367b6d9706e892aa13f64604967f5e3ba92381960f73aeabd3d23f84 \ No newline at end of file +b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc \ No newline at end of file diff --git a/src/tokenize.c b/src/tokenize.c index e3ca9a82a2..f4d013deea 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -433,7 +433,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){ testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' ); testcase( z[0]=='3' ); testcase( z[0]=='4' ); testcase( z[0]=='5' ); testcase( z[0]=='6' ); testcase( z[0]=='7' ); testcase( z[0]=='8' ); - testcase( z[0]=='9' ); + testcase( z[0]=='9' ); testcase( z[0]=='.' ); *tokenType = TK_INTEGER; #ifndef SQLITE_OMIT_HEX_INTEGER if( z[0]=='0' && (z[1]=='x' || z[1]=='X') && sqlite3Isxdigit(z[2]) ){ From 91c009291756e7e7fa338f8f28335a3d2f3bc3ea Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 11 Aug 2023 11:12:46 +0000 Subject: [PATCH 17/21] Up until version 3.42.0, there was a bug in json_valid() such that it would return False (0) for a NULL input. That bug is fixed in 3.42.0. This check-in adds a compile-time option -DSQLITE_LEGACY_JSON_VALID that restores the old buggy behavior for applications that depend on it. FossilOrigin-Name: 15c2eadbff8e732cca45d6c3771d1fcea5aab2127e87f2a611b41ccfef4d1a0d --- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/ctime.c | 6 +++--- src/json.c | 8 +++++++- test/json101.test | 12 +++++++++--- tool/mkctimec.tcl | 1 + 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 38ca5e045f..a289cba21e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stestcase()\smacro\sin\sthe\stokenizer,\sto\sbetter\sdocument\sits\sbehavior. -D 2023-08-10T18:50:00.513 +C Up\suntil\sversion\s3.42.0,\sthere\swas\sa\sbug\sin\sjson_valid()\ssuch\sthat\sit\swould\nreturn\sFalse\s(0)\sfor\sa\sNULL\sinput.\s\sThat\sbug\sis\sfixed\sin\s3.42.0.\s\sThis\ncheck-in\sadds\sa\scompile-time\soption\s-DSQLITE_LEGACY_JSON_VALID\sthat\srestores\nthe\sold\sbuggy\sbehavior\sfor\sapplications\sthat\sdepend\son\sit. +D 2023-08-11T11:12:46.745 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -588,7 +588,7 @@ F src/btreeInt.h 91a9e0c41a0e71fa91a742ec285c63dd8dcb38b73d14fae0ed7209174ff0fdc F src/build.c a8ae3b32d9aa9bbd2c0e97d7c0dd80def9fbca408425de1608f57ee6f47f45f4 F src/callback.c db3a45e376deff6a16c0058163fe0ae2b73a2945f3f408ca32cf74960b28d490 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e -F src/ctime.c 20507cc0b0a6c19cd882fcd0eaeda32ae6a4229fb4b024cfdf3183043d9b703d +F src/ctime.c cff2b493de894383832347c3a3f936a05f4e089a92b42366838da1735f3848b5 F src/date.c f73f203b3877cef866c60ab402aec2bf89597219b60635cf50cbe3c5e4533e94 F src/dbpage.c f3eea5f7ec47e09ee7da40f42b25092ecbe961fc59566b8e5f705f34335b2387 F src/dbstat.c ec92074baa61d883de58c945162d9e666c13cd7cf3a23bc38b4d1c4d0b2c2bef @@ -603,7 +603,7 @@ F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51 F src/hwtime.h f9c2dfb84dce7acf95ce6d289e46f5f9d3d1afd328e53da8f8e9008e3b3caae6 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 F src/insert.c 3f0a94082d978bbdd33c38fefea15346c6c6bffb70bc645a71dc0f1f87dd3276 -F src/json.c 9c231a853268ce6aee2e300e26d4445ba42117374a2275f8e9537b2f912909d6 +F src/json.c ae840f87b418f039f5d336b488933d09396bd31e6b31e855b93055ccaee4e255 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 176d6b2cb18a6ad73b133db17f6fc351c4d9a2d510deebdb76c22bde9cfd1465 F src/main.c fde8f13c876a658b4e8b74b77d875ca887915c174ea6a2f3122d80966f93d865 @@ -1232,7 +1232,7 @@ F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35 F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307 F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x -F test/json101.test 94126d4291d4a00e45f6988ce885c410de69243490e46e70e9946cb6e6f9ea02 +F test/json101.test c98eca791dc29990e560264d6a46aad7966eb16a5f1b818d85a7c00bc2a4e9cd F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1 @@ -1972,7 +1972,7 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439 F tool/merge-test.tcl de76b62f2de2a92d4c1ca4f976bce0aea6899e0229e250479b229b2a1914b176 F tool/mkautoconfamal.sh f62353eb6c06ab264da027fd4507d09914433dbdcab9cb011cdc18016f1ab3b8 F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x -F tool/mkctimec.tcl 38e3db33210a200aae791635125052a643a27aa0619a0debf19aa9c55e1b2dde x +F tool/mkctimec.tcl aca4b83e49aecf10368cd5d11bc4847061041ade026db5bd8da17ef201f1403b x F tool/mkkeywordhash.c b9faa0ae7e14e4dbbcd951cddd786bf46b8a65bb07b129ba8c0cfade723aaffd F tool/mkmsvcmin.tcl 8897d515ef7f94772322db95a3b6fce6c614d84fe0bdd06ba5a1c786351d5a1d F tool/mkopcodec.tcl 33d20791e191df43209b77d37f0ff0904620b28465cca6990cf8d60da61a07ef @@ -2050,8 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4b0871fd367b6d9706e892aa13f64604967f5e3ba92381960f73aeabd3d23f84 -R a40fe5763d111aa30a3a21c2dead52e5 +P b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc +R e87775d4810d0d66e5c1c0ab0600235d U drh -Z d5cf7898ce1eeb270f6b6924ff8af0dd +Z 4c6d3fbedad1c472acffb2c80d4f6273 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 6016c15688..e3a385c129 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc \ No newline at end of file +15c2eadbff8e732cca45d6c3771d1fcea5aab2127e87f2a611b41ccfef4d1a0d \ No newline at end of file diff --git a/src/ctime.c b/src/ctime.c index c853e5ba46..3687241680 100644 --- a/src/ctime.c +++ b/src/ctime.c @@ -60,9 +60,6 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_4_BYTE_ALIGNED_MALLOC "4_BYTE_ALIGNED_MALLOC", #endif -#ifdef SQLITE_64BIT_STATS - "64BIT_STATS", -#endif #ifdef SQLITE_ALLOW_COVERING_INDEX_SCAN # if SQLITE_ALLOW_COVERING_INDEX_SCAN != 1 "ALLOW_COVERING_INDEX_SCAN=" CTIMEOPT_VAL(SQLITE_ALLOW_COVERING_INDEX_SCAN), @@ -399,6 +396,9 @@ static const char * const sqlite3azCompileOpt[] = { #ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX "INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX), #endif +#ifdef SQLITE_LEGACY_JSON_VALID + "LEGACY_JSON_VALID", +#endif #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS "LIKE_DOESNT_MATCH_BLOBS", #endif diff --git a/src/json.c b/src/json.c index fcaa9d84b9..f8d4aa2a77 100644 --- a/src/json.c +++ b/src/json.c @@ -3009,7 +3009,13 @@ static void jsonValidFunc( ){ JsonParse *p; /* The parse */ UNUSED_PARAMETER(argc); - if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; + if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ +#ifdef SQLITE_LEGACY_JSON_VALID + /* Incorrect legacy behavior was to return FALSE for a NULL input */ + sqlite3_result_int(ctx, 0); +#endif + return; + } p = jsonParseCached(ctx, argv[0], 0, 0); if( p==0 || p->oom ){ sqlite3_result_error_nomem(ctx); diff --git a/test/json101.test b/test/json101.test index 543e4c71e7..555232e4ab 100644 --- a/test/json101.test +++ b/test/json101.test @@ -923,9 +923,15 @@ do_execsql_test json-20.3 { # a NULL value as the JSON input. # db null NULL -do_execsql_test json-21.1 { - SELECT json_valid(NULL); -} NULL +if {[db exists {SELECT * FROM pragma_compile_options WHERE compile_options LIKE '%legacy_json_valid%'}] { + do_execsql_test json-21.1-legacy { + SELECT json_valid(NULL); + } 0 +} else { + do_execsql_test json-21.1-correct { + SELECT json_valid(NULL); + } NULL +} do_execsql_test json-21.2 { SELECT json_error_position(NULL); } NULL diff --git a/tool/mkctimec.tcl b/tool/mkctimec.tcl index bcb1a54bb8..317f30a35f 100755 --- a/tool/mkctimec.tcl +++ b/tool/mkctimec.tcl @@ -180,6 +180,7 @@ set boolean_defnil_options { SQLITE_IGNORE_FLOCK_LOCK_ERRORS SQLITE_INLINE_MEMCPY SQLITE_INT64_TYPE + SQLITE_LEGACY_JSON_VALID SQLITE_LIKE_DOESNT_MATCH_BLOBS SQLITE_LOCK_TRACE SQLITE_LOG_CACHE_SPILL From b8a0fc52a208be84a13b80874df635f46a72bfab Mon Sep 17 00:00:00 2001 From: drh <> Date: Fri, 11 Aug 2023 11:24:44 +0000 Subject: [PATCH 18/21] Fix bug in the test case for the previous check-in. FossilOrigin-Name: c5daae88612607aa7a8b13b021cf586fc66e8bcd1fa9d948a860c881b7247761 --- manifest | 12 ++++++------ manifest.uuid | 2 +- test/json101.test | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index a289cba21e..71a0136e3d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Up\suntil\sversion\s3.42.0,\sthere\swas\sa\sbug\sin\sjson_valid()\ssuch\sthat\sit\swould\nreturn\sFalse\s(0)\sfor\sa\sNULL\sinput.\s\sThat\sbug\sis\sfixed\sin\s3.42.0.\s\sThis\ncheck-in\sadds\sa\scompile-time\soption\s-DSQLITE_LEGACY_JSON_VALID\sthat\srestores\nthe\sold\sbuggy\sbehavior\sfor\sapplications\sthat\sdepend\son\sit. -D 2023-08-11T11:12:46.745 +C Fix\sbug\sin\sthe\stest\scase\sfor\sthe\sprevious\scheck-in. +D 2023-08-11T11:24:44.728 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1232,7 +1232,7 @@ F test/json/README.md 63e3e589e1df8fd3cc1588ba1faaff659214003f8b77a15af5c6452b35 F test/json/json-generator.tcl dc0dd0f393800c98658fc4c47eaa6af29d4e17527380cd28656fb261bddc8a3f F test/json/json-q1.txt 65f9d1cdcc4cffa9823fb73ed936aae5658700cd001fde448f68bfb91c807307 F test/json/json-speed-check.sh 8b7babf530faa58bd59d6d362cec8e9036a68c5457ff46f3b1f1511d21af6737 x -F test/json101.test c98eca791dc29990e560264d6a46aad7966eb16a5f1b818d85a7c00bc2a4e9cd +F test/json101.test 243b0a2650218ac5eafde6ce2a92a0e9d02bf24f62aec68693b69d9a693f120a F test/json102.test 24f6f204f9cde45b971016691d0b92a9b4c58040d699e36d6b12cb165f9083ff F test/json103.test 53df87f83a4e5fa0c0a56eb29ff6c94055c6eb919f33316d62161a8880112dbe F test/json104.test 1b844a70cddcfa2e4cd81a5db0657b2e61e7f00868310f24f56a9ba0114348c1 @@ -2050,8 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc -R e87775d4810d0d66e5c1c0ab0600235d +P 15c2eadbff8e732cca45d6c3771d1fcea5aab2127e87f2a611b41ccfef4d1a0d +R 1fd792e259ede50066032d9f52ebbec8 U drh -Z 4c6d3fbedad1c472acffb2c80d4f6273 +Z 90d7041782e85db6a33263bb95988886 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index e3a385c129..888fa3e59b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -15c2eadbff8e732cca45d6c3771d1fcea5aab2127e87f2a611b41ccfef4d1a0d \ No newline at end of file +c5daae88612607aa7a8b13b021cf586fc66e8bcd1fa9d948a860c881b7247761 \ No newline at end of file diff --git a/test/json101.test b/test/json101.test index 555232e4ab..8bb133ec73 100644 --- a/test/json101.test +++ b/test/json101.test @@ -923,7 +923,7 @@ do_execsql_test json-20.3 { # a NULL value as the JSON input. # db null NULL -if {[db exists {SELECT * FROM pragma_compile_options WHERE compile_options LIKE '%legacy_json_valid%'}] { +if {[db exists {SELECT * FROM pragma_compile_options WHERE compile_options LIKE '%legacy_json_valid%'}]} { do_execsql_test json-21.1-legacy { SELECT json_valid(NULL); } 0 From 7e131529526d1f86689f1e9a3d07adac87bf21c3 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 11 Aug 2023 14:31:20 +0000 Subject: [PATCH 19/21] Deprecate sqlite3_js_vfs_create_file() because, it was discovered today, its out-of-scope use of the sqlite3_vfs, sqlite3_file, and sqlite3_io_methods APIs triggers unresolvable assertions in the core when built with SQLITE_DEBUG. FossilOrigin-Name: f3647a3ac8eca8c821b0b1e403da7bfb0feabd0eb5ee83709cd4956dfc56a492 --- ext/wasm/GNUmakefile | 4 ++++ ext/wasm/api/sqlite3-api-prologue.js | 6 ++++++ ext/wasm/api/sqlite3-wasm.c | 9 ++++++++- manifest | 19 +++++++++---------- manifest.uuid | 2 +- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index 3990d227c1..8fa80f7676 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -188,6 +188,10 @@ SQLITE_OPT = \ -DSQLITE_WASM_ENABLE_C_TESTS \ -DSQLITE_C=$(sqlite3.c) +# achtung: enabling -DSQLITE_DEBUG breaks +# sqlite3_wasm_vfs_create_file(), causing it to trigger assertions in +# the core. That was unfortunately not discovered until 2023-08-11. + .NOTPARALLEL: $(sqlite3.h) $(sqlite3.h): $(MAKE) -C $(dir.top) sqlite3.c diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index 3b29041c37..fe167f0259 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -1357,6 +1357,12 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( }; /** + Achtung: this function does not work in debug builds of sqlite3 + because its out-of-scope use of the sqlite3_vfs API triggers + unresolvable assertions in the core library. That was + unfortunately not discovered until 2023-08-11. Because of that, + this function is now deprecated and should be used in new code. + Creates a file using the storage appropriate for the given sqlite3_vfs. The first argument may be a VFS name (JS string only, NOT a WASM C-string), WASM-managed `sqlite3_vfs*`, or diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index 94b16d7500..431eddcebe 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -295,7 +295,7 @@ SQLITE_WASM_EXPORT void * sqlite3_wasm_pstack_ptr(void){ */ SQLITE_WASM_EXPORT void sqlite3_wasm_pstack_restore(unsigned char * p){ assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos); - assert(0==(p & 0x7)); + assert(0==((unsigned long long)p & 0x7)); if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){ PStack.pPos = p; } @@ -1395,6 +1395,12 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, const char *zFilename, const unsigned char * pData, int nData ){ +#ifdef SQLITE_DEBUG + fprintf(stderr,"%s does not work in debug builds because its out-of-scope use of " + "the sqlite3_vfs API triggers assertions in the core library.\n", __func__); + /* ^^^ That was unfortunately not discovered until 2023-08-11. */ + return SQLITE_ERROR; +#else int rc; sqlite3_file *pFile = 0; sqlite3_io_methods const *pIo; @@ -1462,6 +1468,7 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, RC; #undef RC return rc; +#endif } /* diff --git a/manifest b/manifest index 03fd812199..87ccce5ee9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sthe\s-DSQLITE_LEGACY_JSON_VALID\scompile-time\soption\sto\srestore\sthe\n(incorrect)\slegacy\sbehavior\sof\sjson_valid(NULL). -D 2023-08-11T11:30:43.332 +C Deprecate\ssqlite3_js_vfs_create_file()\sbecause,\sit\swas\sdiscovered\stoday,\sits\sout-of-scope\suse\sof\sthe\ssqlite3_vfs,\ssqlite3_file,\sand\ssqlite3_io_methods\sAPIs\striggers\sunresolvable\sassertions\sin\sthe\score\swhen\sbuilt\swith\sSQLITE_DEBUG. +D 2023-08-11T14:31:20.718 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -488,7 +488,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c -F ext/wasm/GNUmakefile 50a4bd40ee01a90badfc28d0042789740e47e2855d3b9acaa8801b6dc2763aba +F ext/wasm/GNUmakefile 887923b481caf78b5b7eba42a2919fc154314075b2f95e9ab9de79ba1e2c49be F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576 F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab @@ -503,14 +503,14 @@ F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057af F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e F ext/wasm/api/sqlite3-api-glue.js cc6b0bb093bdb6279d4af259200b7b9e150e3796a8a3a4cd09a4928c43d25e56 F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8 -F ext/wasm/api/sqlite3-api-prologue.js 76258e160bf6a89cc75a7d3c05646a054c8cab7219cd1e10bc20cacaad022131 +F ext/wasm/api/sqlite3-api-prologue.js 57faa6d9b2025cd4431153dde1c0242257c87c5a92d099c331816ce56842fab7 F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379 F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js abb69b5e008961026bf5ff433d7116cb046359af92a5daf73208af2e7ac80ae7 F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e7a690e0e78ff4d563f2eca468f91db69f001ff4b79c6d2304cbb6f62dca437d -F ext/wasm/api/sqlite3-wasm.c 8867f1d41c112fb4a2cfe22ff224eccaf309fcdea266cee0ec554f85db72ef0f +F ext/wasm/api/sqlite3-wasm.c c19041158df467281b74b0fdb5d2a2d947d3f7248d0e8a9174ddfbcd5b9158bd F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8 @@ -2050,9 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P b2fdac0b151864eb2aa79f0b0ee60f9c6d9f3eb8c7626605eac17a02a8cf59bc c5daae88612607aa7a8b13b021cf586fc66e8bcd1fa9d948a860c881b7247761 -R 1fd792e259ede50066032d9f52ebbec8 -T +closed c5daae88612607aa7a8b13b021cf586fc66e8bcd1fa9d948a860c881b7247761 -U drh -Z ea3c39c8df0296b13770ed14b59d7f43 +P 00bc9f1b573d683829bf5eb301606c38d6a60fba957d8edaf59116c02cc650bf +R 09f42f2546af1fc630e5de807fbbefd6 +U stephan +Z db3821e23214c8f5fc4f09d6344513ee # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 479b2e5b05..dd51fbaeef 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -00bc9f1b573d683829bf5eb301606c38d6a60fba957d8edaf59116c02cc650bf \ No newline at end of file +f3647a3ac8eca8c821b0b1e403da7bfb0feabd0eb5ee83709cd4956dfc56a492 \ No newline at end of file From b949244ea1c73f744b557524810c7945d3b0c5de Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 11 Aug 2023 17:38:17 +0000 Subject: [PATCH 20/21] Add sqlite3.capi.sqlite3_js_posix_create_file() and oo1.OpfsDb.importDb() as alternatives for the newly-deprecated sqlite3_js_vfs_create_file(). FossilOrigin-Name: da6eaf8d8258f3e2c8633fd7faf4e90c3307b5c60bd8b69c626b3c82b19dbdef --- ext/wasm/GNUmakefile | 11 ++-- ext/wasm/api/sqlite3-api-glue.js | 1 + ext/wasm/api/sqlite3-api-prologue.js | 80 ++++++++++++++++++++++++--- ext/wasm/api/sqlite3-vfs-opfs.c-pp.js | 41 ++++++++++++-- ext/wasm/api/sqlite3-wasm.c | 54 ++++++++++++++---- ext/wasm/tester1.c-pp.js | 56 ++++++------------- manifest | 22 ++++---- manifest.uuid | 2 +- 8 files changed, 188 insertions(+), 79 deletions(-) diff --git a/ext/wasm/GNUmakefile b/ext/wasm/GNUmakefile index 8fa80f7676..ed5550e7b8 100644 --- a/ext/wasm/GNUmakefile +++ b/ext/wasm/GNUmakefile @@ -179,7 +179,6 @@ SQLITE_OPT = \ -DSQLITE_OMIT_DEPRECATED \ -DSQLITE_OMIT_UTF16 \ -DSQLITE_OMIT_SHARED_CACHE \ - -DSQLITE_OMIT_WAL \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=2 \ -DSQLITE_OS_KV_OPTIONAL=1 \ @@ -187,10 +186,12 @@ SQLITE_OPT = \ -DSQLITE_USE_URI=1 \ -DSQLITE_WASM_ENABLE_C_TESTS \ -DSQLITE_C=$(sqlite3.c) - -# achtung: enabling -DSQLITE_DEBUG breaks -# sqlite3_wasm_vfs_create_file(), causing it to trigger assertions in -# the core. That was unfortunately not discovered until 2023-08-11. +#SQLITE_OPT += -DSQLITE_DEBUG +# Enabling SQLITE_DEBUG will break sqlite3_wasm_vfs_create_file() +# (and thus sqlite3_js_vfs_create_file()). Those functions are +# deprecated and alternatives are in place, but this crash behavior +# can be used to find errant uses of sqlite3_js_vfs_create_file() +# in client code. .NOTPARALLEL: $(sqlite3.h) $(sqlite3.h): diff --git a/ext/wasm/api/sqlite3-api-glue.js b/ext/wasm/api/sqlite3-api-glue.js index 572efeed5c..60050461c7 100644 --- a/ext/wasm/api/sqlite3-api-glue.js +++ b/ext/wasm/api/sqlite3-api-glue.js @@ -608,6 +608,7 @@ globalThis.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ ["sqlite3_wasm_db_vfs", "sqlite3_vfs*", "sqlite3*","string"], ["sqlite3_wasm_vfs_create_file", "int", "sqlite3_vfs*","string","*", "int"], + ["sqlite3_wasm_posix_create_file", "int", "string","*", "int"], ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] ]; diff --git a/ext/wasm/api/sqlite3-api-prologue.js b/ext/wasm/api/sqlite3-api-prologue.js index fe167f0259..ca5d1c44ff 100644 --- a/ext/wasm/api/sqlite3-api-prologue.js +++ b/ext/wasm/api/sqlite3-api-prologue.js @@ -1357,11 +1357,73 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( }; /** - Achtung: this function does not work in debug builds of sqlite3 - because its out-of-scope use of the sqlite3_vfs API triggers - unresolvable assertions in the core library. That was - unfortunately not discovered until 2023-08-11. Because of that, - this function is now deprecated and should be used in new code. + If the current environment supports the POSIX file APIs, this routine + creates (or overwrites) the given file using those APIs. This is + primarily intended for use in Emscripten-based builds where the POSIX + APIs are transparently proxied by an in-memory virtual filesystem. + It may behave diffrently in other environments. + + The first argument must be either a JS string or WASM C-string + holding the filename. Note that this routine does _not_ create + intermediary directories if the filename has a directory part. + + The 2nd argument may either a valid WASM memory pointer, an + ArrayBuffer, or a Uint8Array. The 3rd must be the length, in + bytes, of the data array to copy. If the 2nd argument is an + ArrayBuffer or Uint8Array and the 3rd is not a positive integer + then the 3rd defaults to the array's byteLength value. + + Results are undefined if data is a WASM pointer and dataLen is + exceeds data's bounds. + + Throws if any arguments are invalid or if creating or writing to + the file fails. + + Added in 3.43 as an alternative for the deprecated + sqlite3_js_vfs_create_file(). + */ + capi.sqlite3_js_posix_create_file = function(filename, data, dataLen){ + let pData; + if(data && wasm.isPtr(data)){ + pData = data; + }else if(data instanceof ArrayBuffer || data instanceof Uint8Array){ + pData = wasm.allocFromTypedArray(data); + if(arguments.length<3 || !util.isInt32(dataLen) || dataLen<0){ + dataLen = data.byteLength; + } + }else{ + SQLite3Error.toss("Invalid 2nd argument for sqlite3_js_posix_create_file()."); + } + try{ + if(!util.isInt32(dataLen) || dataLen<0){ + SQLite3Error.toss("Invalid 3rd argument for sqlite3_js_posix_create_file()."); + } + const rc = wasm.sqlite3_wasm_posix_create_file(filename, pData, dataLen); + if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code", + capi.sqlite3_js_rc_str(rc)); + }finally{ + wasm.dealloc(pData); + } + }; + + /** + Deprecation warning: this function does not work properly in + debug builds of sqlite3 because its out-of-scope use of the + sqlite3_vfs API triggers assertions in the core library. That + was unfortunately not discovered until 2023-08-11. This function + is now deprecated and should not be used in new code. + + Alternative options: + + - "unix" VFS and its variants can get equivalent functionality + with sqlite3_js_posix_create_file(). + + - OPFS: use either sqlite3.oo1.OpfsDb.importDb(), for the "opfs" + VFS, or the importDb() method of the PoolUtil object provided + by the "opfs-sahpool" OPFS (noting that its VFS name may differ + depending on client-side configuration). We cannot proxy those + from here because the former is necessarily asynchronous and + the latter requires information not available to this function. Creates a file using the storage appropriate for the given sqlite3_vfs. The first argument may be a VFS name (JS string @@ -1408,9 +1470,13 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( VFS nor the WASM environment imposes requirements which break it. - "opfs": uses OPFS storage and creates directory parts of the - filename. + filename. It can only be used to import an SQLite3 database + file and will fail if given anything else. */ capi.sqlite3_js_vfs_create_file = function(vfs, filename, data, dataLen){ + config.warn("sqlite3_js_vfs_create_file() is deprecated and", + "should be avoided because it can lead to C-level crashes.", + "See its documentation for alternative options."); let pData; if(data){ if(wasm.isPtr(data)){ @@ -1438,7 +1504,7 @@ globalThis.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( if(rc) SQLite3Error.toss("Creation of file failed with sqlite3 result code", capi.sqlite3_js_rc_str(rc)); }finally{ - wasm.dealloc(pData); + wasm.dealloc(pData); } }; diff --git a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js index 58c511082c..93482505ac 100644 --- a/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js +++ b/ext/wasm/api/sqlite3-vfs-opfs.c-pp.js @@ -1168,11 +1168,41 @@ const installOpfsVfs = function callee(options){ doDir(opt.directory, 0); }; - //TODO to support fiddle and worker1 db upload: - //opfsUtil.createFile = function(absName, content=undefined){...} - //We have sqlite3.wasm.sqlite3_wasm_vfs_create_file() for this - //purpose but its interface and name are still under - //consideration. + /** + Asynchronously imports the given bytes (a byte array or + ArrayBuffer) into the given database file. + + It very specifically requires the input to be an SQLite3 + database and throws if that's not the case. It does so in + order to prevent this function from taking on a larger scope + than it is specifically intended to. i.e. we do not want it to + become a convenience for importing arbitrary files into OPFS. + + Throws on error. Resolves to the number of bytes written. + */ + opfsUtil.importDb = async function(filename, bytes){ + if(bytes instanceof ArrayBuffer) bytes = new Uint8Array(bytes); + const n = bytes.byteLength; + if(n<512 || n%512!=0){ + toss("Byte array size is invalid for an SQLite db."); + } + const header = "SQLite format 3"; + for(let i = 0; i < header.length; ++i){ + if( header.charCodeAt(i) !== bytes[i] ){ + toss("Input does not contain an SQLite database header."); + } + } + const [hDir, fnamePart] = await opfsUtil.getDirForFilename(filename, true); + const hFile = await hDir.getFileHandle(fnamePart, {create:true}); + const sah = await hFile.createSyncAccessHandle(); + sah.truncate(0); + const nWrote = sah.write(bytes, {at: 0}); + sah.close(); + if(nWrote != n){ + toss("Expected to write "+n+" bytes but wrote "+nWrote+"."); + } + return nWrote; + }; if(sqlite3.oo1){ const OpfsDb = function(...args){ @@ -1182,6 +1212,7 @@ const installOpfsVfs = function callee(options){ }; OpfsDb.prototype = Object.create(sqlite3.oo1.DB.prototype); sqlite3.oo1.OpfsDb = OpfsDb; + OpfsDb.importDb = opfsUtil.importDb; sqlite3.oo1.DB.dbCtorHelper.setVfsPostOpenSql( opfsVfs.pointer, function(oo1Db, sqlite3){ diff --git a/ext/wasm/api/sqlite3-wasm.c b/ext/wasm/api/sqlite3-wasm.c index 431eddcebe..fcfbc06929 100644 --- a/ext/wasm/api/sqlite3-wasm.c +++ b/ext/wasm/api/sqlite3-wasm.c @@ -141,9 +141,6 @@ #ifndef SQLITE_OMIT_UTF16 # define SQLITE_OMIT_UTF16 1 #endif -#ifndef SQLITE_OMIT_WAL -# define SQLITE_OMIT_WAL 1 -#endif #ifndef SQLITE_OS_KV_OPTIONAL # define SQLITE_OS_KV_OPTIONAL 1 #endif @@ -1353,6 +1350,13 @@ int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema, ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** +** ACHTUNG: it was discovered on 2023-08-11 that, with SQLITE_DEBUG, +** this function's out-of-scope use of the sqlite3_vfs/file/io_methods +** APIs leads to triggering of assertions in the core library. Its use +** is now deprecated and VFS-specific APIs for importing files need to +** be found to replace it. sqlite3_wasm_posix_create_file() is +** suitable for the "unix" family of VFSes. +** ** Creates a new file using the I/O API of the given VFS, containing ** the given number of bytes of the given data. If the file exists, it ** is truncated to the given length and populated with the given @@ -1395,16 +1399,17 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, const char *zFilename, const unsigned char * pData, int nData ){ -#ifdef SQLITE_DEBUG - fprintf(stderr,"%s does not work in debug builds because its out-of-scope use of " - "the sqlite3_vfs API triggers assertions in the core library.\n", __func__); - /* ^^^ That was unfortunately not discovered until 2023-08-11. */ - return SQLITE_ERROR; -#else int rc; sqlite3_file *pFile = 0; sqlite3_io_methods const *pIo; - const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + const int openFlags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE +#if 0 && defined(SQLITE_DEBUG) + | SQLITE_OPEN_MAIN_JOURNAL + /* ^^^^ This is for testing a horrible workaround to avoid + triggering a specific assert() in os_unix.c:unixOpen(). Please + do not enable this in real builds. */ +#endif + ; int flagsOut = 0; int fileExisted = 0; int doUnlock = 0; @@ -1468,7 +1473,34 @@ int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, RC; #undef RC return rc; -#endif +} + +/** +** This function is NOT part of the sqlite3 public API. It is strictly +** for use by the sqlite project's own JS/WASM bindings. +** +** Creates or overwrites a file using the POSIX file API, +** i.e. Emscripten's virtual filesystem. Creates or truncates +** zFilename, appends pData bytes to it, and returns 0 on success or +** SQLITE_IOERR on error. +*/ +SQLITE_WASM_EXPORT +int sqlite3_wasm_posix_create_file( const char *zFilename, + const unsigned char * pData, + int nData ){ + int rc; + FILE * pFile = 0; + int fileExisted = 0; + size_t nWrote = 1; + + if( !zFilename || nData<0 || (pData==0 && nData>0) ) return SQLITE_MISUSE; + pFile = fopen(zFilename, "w"); + if( 0==pFile ) return SQLITE_IOERR; + if( nData>0 ){ + nWrote = fwrite(pData, (size_t)nData, 1, pFile); + } + fclose(pFile); + return 1==nWrote ? 0 : SQLITE_IOERR; } /* diff --git a/ext/wasm/tester1.c-pp.js b/ext/wasm/tester1.c-pp.js index c1b16d5e81..bd945dcab7 100644 --- a/ext/wasm/tester1.c-pp.js +++ b/ext/wasm/tester1.c-pp.js @@ -1657,7 +1657,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .assert('number'===typeof rc[0]) .assert(rc[0]|0 === rc[0] /* is small integer */); }) - //////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// .t({ name: 'sqlite3_js_db_export()', predicate: ()=>true, @@ -1671,13 +1671,12 @@ globalThis.sqlite3InitModule = sqlite3InitModule; } }/*sqlite3_js_db_export()*/) .t({ - name: 'sqlite3_js_vfs_create_file() with db in default VFS', + name: 'sqlite3_js_posix_create_file()', predicate: ()=>true, test: function(sqlite3){ const db = this.db; - const pVfs = capi.sqlite3_js_db_vfs(db); - const filename = "sqlite3_js_vfs_create_file().db"; - capi.sqlite3_js_vfs_create_file(pVfs, filename, this.dbExport); + const filename = "sqlite3_js_posix_create_file.db"; + capi.sqlite3_js_posix_create_file(filename, this.dbExport); delete this.dbExport; const db2 = new sqlite3.oo1.DB(filename,'r'); try { @@ -1686,7 +1685,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; T.assert(n>0 && db2.selectValue(sql) === n); }finally{ db2.close(); - wasm.sqlite3_wasm_vfs_unlink(pVfs, filename); + wasm.sqlite3_wasm_vfs_unlink(0, filename); } } }/*sqlite3_js_vfs_create_file()*/) @@ -2907,7 +2906,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; .t({ name: 'OPFS db sanity checks', test: async function(sqlite3){ - const filename = this.opfsDbFile = 'sqlite3-tester1.db'; + const filename = this.opfsDbFile = '/dir/sqlite3-tester1.db'; const pVfs = this.opfsVfs = capi.sqlite3_vfs_find('opfs'); T.assert(pVfs); const unlink = this.opfsUnlink = @@ -2935,22 +2934,23 @@ globalThis.sqlite3InitModule = sqlite3InitModule; } }/*OPFS db sanity checks*/) .t({ - name: 'OPFS export/import', + name: 'OPFS import', test: async function(sqlite3){ let db; try { const exp = this.opfsDbExport; delete this.opfsDbExport; - capi.sqlite3_js_vfs_create_file("opfs", this.opfsDbFile, exp); - const db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); - T.assert(6 === db.selectValue('select count(*) from p')); + this.opfsImportSize = await sqlite3.oo1.OpfsDb.importDb(this.opfsDbFile, exp); + db = new sqlite3.oo1.OpfsDb(this.opfsDbFile); + T.assert(6 === db.selectValue('select count(*) from p')). + assert( this.opfsImportSize == exp.byteLength ); }finally{ if(db) db.close(); } } }/*OPFS export/import*/) .t({ - name: 'OPFS utility APIs and sqlite3_js_vfs_create_file()', + name: '(Internal-use) OPFS utility APIs', test: async function(sqlite3){ const filename = this.opfsDbFile; const pVfs = this.opfsVfs; @@ -2959,8 +2959,6 @@ globalThis.sqlite3InitModule = sqlite3InitModule; delete this.opfsDbFile; delete this.opfsVfs; delete this.opfsUnlink; - unlink(); - // Sanity-test sqlite3_js_vfs_create_file()... /************************************************************** ATTENTION CLIENT-SIDE USERS: sqlite3.opfs is NOT intended for client-side use. It is only for this project's own @@ -2968,39 +2966,19 @@ globalThis.sqlite3InitModule = sqlite3InitModule; any time. ***************************************************************/ const opfs = sqlite3.opfs; - const fSize = 1379; + const fSize = this.opfsImportSize; + delete this.opfsImportSize; let sh; try{ - T.assert(!(await opfs.entryExists(filename))); - capi.sqlite3_js_vfs_create_file( - pVfs, filename, null, fSize - ); T.assert(await opfs.entryExists(filename)); - let fh = await opfs.rootDirectory.getFileHandle(filename); + const [dirHandle, filenamePart] = await opfs.getDirForFilename(filename, false); + const fh = await dirHandle.getFileHandle(filenamePart); sh = await fh.createSyncAccessHandle(); T.assert(fSize === await sh.getSize()); await sh.close(); sh = undefined; unlink(); T.assert(!(await opfs.entryExists(filename))); - - const ba = new Uint8Array([1,2,3,4,5]); - capi.sqlite3_js_vfs_create_file( - "opfs", filename, ba - ); - T.assert(await opfs.entryExists(filename)); - fh = await opfs.rootDirectory.getFileHandle(filename); - sh = await fh.createSyncAccessHandle(); - T.assert(ba.byteLength === await sh.getSize()); - await sh.close(); - sh = undefined; - unlink(); - - T.mustThrowMatching(()=>{ - capi.sqlite3_js_vfs_create_file( - "no-such-vfs", filename, ba - ); - }, "SQLITE_NOTFOUND: Unknown sqlite3_vfs name: no-such-vfs"); }finally{ if(sh) await sh.close(); unlink(); @@ -3103,7 +3081,7 @@ globalThis.sqlite3InitModule = sqlite3InitModule; const conf2 = JSON.parse(JSON.stringify(sahPoolConfig)); conf2.name += '-test2'; const POther = await inst(conf2); - log("Installed second SAH instance as",conf2.name); + //log("Installed second SAH instance as",conf2.name); T.assert(0 === POther.getFileCount()) .assert(true === await POther.removeVfs()); diff --git a/manifest b/manifest index 87ccce5ee9..8aeb2eff1a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Deprecate\ssqlite3_js_vfs_create_file()\sbecause,\sit\swas\sdiscovered\stoday,\sits\sout-of-scope\suse\sof\sthe\ssqlite3_vfs,\ssqlite3_file,\sand\ssqlite3_io_methods\sAPIs\striggers\sunresolvable\sassertions\sin\sthe\score\swhen\sbuilt\swith\sSQLITE_DEBUG. -D 2023-08-11T14:31:20.718 +C Add\ssqlite3.capi.sqlite3_js_posix_create_file()\sand\soo1.OpfsDb.importDb()\sas\salternatives\sfor\sthe\snewly-deprecated\ssqlite3_js_vfs_create_file(). +D 2023-08-11T17:38:17.359 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -488,7 +488,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb F ext/wasm/EXPORTED_FUNCTIONS.fiddle.in 27450c8b8c70875a260aca55435ec927068b34cef801a96205adb81bdcefc65c -F ext/wasm/GNUmakefile 887923b481caf78b5b7eba42a2919fc154314075b2f95e9ab9de79ba1e2c49be +F ext/wasm/GNUmakefile 8159bc5f9433fe21022c1a8e8c30cb1a523530ba9ef53bdf5d1e0a2186554806 F ext/wasm/README-dist.txt 6382cb9548076fca472fb3330bbdba3a55c1ea0b180ff9253f084f07ff383576 F ext/wasm/README.md a8a2962c3aebdf8d2104a9102e336c5554e78fc6072746e5daf9c61514e7d193 F ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-api d6a5078f48a5301ed17b9a30331075d9b2506e1360c1f0dee0c7816c10acd9ab @@ -501,16 +501,16 @@ F ext/wasm/api/post-js-footer.js cd0a8ec768501d9bd45d325ab0442037fb0e33d1f3b4f08 F ext/wasm/api/post-js-header.js 47b6b281f39ad59fa6e8b658308cd98ea292c286a68407b35ff3ed9cfd281a62 F ext/wasm/api/pre-js.c-pp.js ad906703f7429590f2fbf5e6498513bf727a1a4f0ebfa057afb08161d7511219 F ext/wasm/api/sqlite3-api-cleanup.js d235ad237df6954145404305040991c72ef8b1881715d2a650dda7b3c2576d0e -F ext/wasm/api/sqlite3-api-glue.js cc6b0bb093bdb6279d4af259200b7b9e150e3796a8a3a4cd09a4928c43d25e56 +F ext/wasm/api/sqlite3-api-glue.js b65e546568f1dfb35205b9792feb5146a6323d71b55cda58e2ed30def6dd52f3 F ext/wasm/api/sqlite3-api-oo1.js 9678dc4d9a5d39632b6ffe6ea94a023119260815bf32f265bf5f6c36c9516db8 -F ext/wasm/api/sqlite3-api-prologue.js 57faa6d9b2025cd4431153dde1c0242257c87c5a92d099c331816ce56842fab7 +F ext/wasm/api/sqlite3-api-prologue.js 5f283b096b98bfb1ee2f2201e7ff0489dff00e29e1030c30953bdb4f5b87f4bd F ext/wasm/api/sqlite3-api-worker1.js 9f32af64df1a031071912eea7a201557fe39b1738645c0134562bb84e88e2fec F ext/wasm/api/sqlite3-license-version-header.js 0c807a421f0187e778dc1078f10d2994b915123c1223fe752b60afdcd1263f89 F ext/wasm/api/sqlite3-opfs-async-proxy.js 8cf8a897726f14071fae6be6648125162b256dfb4f96555b865dbb7a6b65e379 F ext/wasm/api/sqlite3-v-helper.js 7daa0eab0a513a25b05e9abae7b5beaaa39209b3ed12f86aeae9ef8d2719ed25 F ext/wasm/api/sqlite3-vfs-opfs-sahpool.c-pp.js abb69b5e008961026bf5ff433d7116cb046359af92a5daf73208af2e7ac80ae7 -F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e7a690e0e78ff4d563f2eca468f91db69f001ff4b79c6d2304cbb6f62dca437d -F ext/wasm/api/sqlite3-wasm.c c19041158df467281b74b0fdb5d2a2d947d3f7248d0e8a9174ddfbcd5b9158bd +F ext/wasm/api/sqlite3-vfs-opfs.c-pp.js e04fc2fda6a0200ef80efdbb4ddfa0254453558adb17ec3a230f93d2bf1d711c +F ext/wasm/api/sqlite3-wasm.c d4d4c2b349b43b7b861e6d2994299630fb79e07573ea6b61e28e8071b7d16b61 F ext/wasm/api/sqlite3-worker1-promiser.c-pp.js bc06df0d599e625bde6a10a394e326dc68da9ff07fa5404354580f81566e591f F ext/wasm/api/sqlite3-worker1.c-pp.js da509469755035e919c015deea41b4514b5e84c12a1332e6cc8d42cb2cc1fb75 F ext/wasm/batch-runner.html 4deeed44fe41496dc6898d9fb17938ea3291f40f4bfb977e29d0cef96fbbe4c8 @@ -555,7 +555,7 @@ F ext/wasm/test-opfs-vfs.html 1f2d672f3f3fce810dfd48a8d56914aba22e45c6834e262555 F ext/wasm/test-opfs-vfs.js f09266873e1a34d9bdb6d3981ec8c9e382f31f215c9fd2f9016d2394b8ae9b7b F ext/wasm/tester1-worker.html ebc4b820a128963afce328ecf63ab200bd923309eb939f4110510ab449e9814c F ext/wasm/tester1.c-pp.html 1c1bc78b858af2019e663b1a31e76657b73dc24bede28ca92fbe917c3a972af2 -F ext/wasm/tester1.c-pp.js b88dcad5424a652e8204c44a71bbc3deb22a4922c97ba792aedbabb7a6827b91 +F ext/wasm/tester1.c-pp.js 64eb0ee6e695d5638d0f758f31a0ca2231e627ca5d768de3d8b44f9f494de8d4 F ext/wasm/tests/opfs/concurrency/index.html 0802373d57034d51835ff6041cda438c7a982deea6079efd98098d3e42fbcbc1 F ext/wasm/tests/opfs/concurrency/test.js a98016113eaf71e81ddbf71655aa29b0fed9a8b79a3cdd3620d1658eb1cc9a5d F ext/wasm/tests/opfs/concurrency/worker.js 0a8c1a3e6ebb38aabbee24f122693f1fb29d599948915c76906681bb7da1d3d2 @@ -2050,8 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 00bc9f1b573d683829bf5eb301606c38d6a60fba957d8edaf59116c02cc650bf -R 09f42f2546af1fc630e5de807fbbefd6 +P f3647a3ac8eca8c821b0b1e403da7bfb0feabd0eb5ee83709cd4956dfc56a492 +R 13a39a740b050094d1512ca0996c2993 U stephan -Z db3821e23214c8f5fc4f09d6344513ee +Z 31bd22683b0e5ce210b31aa9d7b3099d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index dd51fbaeef..5ae0cdb5dd 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f3647a3ac8eca8c821b0b1e403da7bfb0feabd0eb5ee83709cd4956dfc56a492 \ No newline at end of file +da6eaf8d8258f3e2c8633fd7faf4e90c3307b5c60bd8b69c626b3c82b19dbdef \ No newline at end of file From c3b7e1c4e8930e7a9f630e04ecff50cee1d345e3 Mon Sep 17 00:00:00 2001 From: stephan Date: Fri, 11 Aug 2023 17:45:23 +0000 Subject: [PATCH 21/21] Add a doc link for the new sqlite3_js_posix_create_file(). FossilOrigin-Name: 0d7aac45b8e7078cc80757e12d6f0b2584f2b0b184dacc2348ad3519978e5bf9 --- ext/wasm/module-symbols.html | 1 + manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/ext/wasm/module-symbols.html b/ext/wasm/module-symbols.html index 865f1b3338..c5c6bc162b 100644 --- a/ext/wasm/module-symbols.html +++ b/ext/wasm/module-symbols.html @@ -355,6 +355,7 @@ sqlite3_js_db_vfs: 'wasm:/api-c-style.md#sqlite3_js_db_vfs', sqlite3_js_kvvfs_clear: 'wasm:/api-c-style.md#sqlite3_js_kvvfs', sqlite3_js_kvvfs_size: 'wasm:/api-c-style.md#sqlite3_js_kvvfs', + sqlite3_js_posix_create_file: 'wasm:/api-c-style.md#sqlite3_js_posix_create_file', sqlite3_js_rc_str: 'wasm:/api-c-style.md#sqlite3_js_rc_str', sqlite3_js_vfs_create_file: 'wasm:/api-c-style.md#sqlite3_js_vfs_create_file', sqlite3_js_vfs_list: 'wasm:/api-c-style.md#sqlite3_js_vfs_list', diff --git a/manifest b/manifest index 8aeb2eff1a..13c42a9886 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssqlite3.capi.sqlite3_js_posix_create_file()\sand\soo1.OpfsDb.importDb()\sas\salternatives\sfor\sthe\snewly-deprecated\ssqlite3_js_vfs_create_file(). -D 2023-08-11T17:38:17.359 +C Add\sa\sdoc\slink\sfor\sthe\snew\ssqlite3_js_posix_create_file(). +D 2023-08-11T17:45:23.996 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -540,7 +540,7 @@ F ext/wasm/index-dist.html 22379774f0ad4edcaaa8cf9c674c82e794cc557719a8addabed74 F ext/wasm/index.html 4e7847b909f4ae0da8c829b150b79454050e53b3658431f138636257729cd42b F ext/wasm/jaccwabyt/jaccwabyt.js 1264710db3cfbcb6887d95665b7aeba60c1126eaef789ca4cf1a4a17d5bc7f54 F ext/wasm/jaccwabyt/jaccwabyt.md 37911f00db12cbcca73aa1ed72594430365f30aafae2fa9c886961de74e5e0eb -F ext/wasm/module-symbols.html 841de62fc198988b8330e238c260e70ec93028b096e1a1234db31b187a899d10 +F ext/wasm/module-symbols.html dc476b403369b26a1a23773e13b80f41b9a49f0825e81435fe3600a7cfbbe337 F ext/wasm/scratchpad-wasmfs.html a3d7388f3c4b263676b58b526846e9d02dfcb4014ff29d3a5040935286af5b96 F ext/wasm/scratchpad-wasmfs.mjs 66034b9256b218de59248aad796760a1584c1dd842231505895eff00dbd57c63 F ext/wasm/speedtest1-wasmfs.html 0e9d335a9b5b5fafe6e1bc8dc0f0ca7e22e6eb916682a2d7c36218bb7d67379d @@ -2050,8 +2050,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f3647a3ac8eca8c821b0b1e403da7bfb0feabd0eb5ee83709cd4956dfc56a492 -R 13a39a740b050094d1512ca0996c2993 +P da6eaf8d8258f3e2c8633fd7faf4e90c3307b5c60bd8b69c626b3c82b19dbdef +R 883ed82f11d6e3475fe4daa3dfd8e6de U stephan -Z 31bd22683b0e5ce210b31aa9d7b3099d +Z 1fde302b034bd5c3763f88d8c5683be2 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 5ae0cdb5dd..f855b50ce1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -da6eaf8d8258f3e2c8633fd7faf4e90c3307b5c60bd8b69c626b3c82b19dbdef \ No newline at end of file +0d7aac45b8e7078cc80757e12d6f0b2584f2b0b184dacc2348ad3519978e5bf9 \ No newline at end of file