From aebf4cb043e29908f586a8b8ea85caec1393ceaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Salawa?= Date: Wed, 16 Nov 2022 21:01:03 +0100 Subject: [PATCH] #4171 Updated SQLite to 3.39.4, except for SQLCipher, which has latest version at 3.39.2 --- .github/workflows/lin_release.yml | 2 +- .github/workflows/mac_release.yml | 2 +- .github/workflows/tests.yml | 2 +- .github/workflows/win32_release.yml | 2 +- .github/workflows/win64_release.yml | 2 +- ChangeLog.md | 2 +- Plugins/DbSqliteWx/update_sqlite_version.tcl | 2 +- Plugins/DbSqliteWx/wxsqlite3.c | 1194 ++++++++++++------ Plugins/DbSqliteWx/wxsqlite3.h | 113 +- 9 files changed, 945 insertions(+), 376 deletions(-) diff --git a/.github/workflows/lin_release.yml b/.github/workflows/lin_release.yml index 9d6b8921c0..1559194129 100644 --- a/.github/workflows/lin_release.yml +++ b/.github/workflows/lin_release.yml @@ -1,7 +1,7 @@ env: QT_VERSION: '5.15.2' TCL_VERSION: '8.6' - SQLITE_VERSION: '3390200' + SQLITE_VERSION: '3390400' SQLITE_RELEASE_YEAR: '2022' PYTHON_VERSION: '3.9' PORTABLE_DIR: ${{ github.workspace }}/output/portable/SQLiteStudio diff --git a/.github/workflows/mac_release.yml b/.github/workflows/mac_release.yml index cf3e795c52..a09b90756c 100644 --- a/.github/workflows/mac_release.yml +++ b/.github/workflows/mac_release.yml @@ -1,7 +1,7 @@ env: QT_VERSION: '5.15.2' TCL_VERSION: '8.6' - SQLITE_VERSION: '3390200' + SQLITE_VERSION: '3390400' SQLITE_RELEASE_YEAR: '2022' PYTHON_VERSION: '3.9' PORTABLE_DIR: ${{ github.workspace }}/output/portable/SQLiteStudio diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 3ee4c4f73b..17fa201d7c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,6 +1,6 @@ env: TCL_VERSION: '8.6' - SQLITE_VERSION: '3390200' + SQLITE_VERSION: '3390400' SQLITE_RELEASE_YEAR: '2022' PYTHON_VERSION: '3.9' PORTABLE_DIR: ${{ github.workspace }}/output/portable/SQLiteStudio diff --git a/.github/workflows/win32_release.yml b/.github/workflows/win32_release.yml index 1dd7476c39..b9be293b52 100644 --- a/.github/workflows/win32_release.yml +++ b/.github/workflows/win32_release.yml @@ -1,6 +1,6 @@ env: QT_VERSION: '5.15.2' - SQLITE_VERSION: '3390200' + SQLITE_VERSION: '3390400' SQLITE_RELEASE_YEAR: '2022' QT_ARCH: 'win32_mingw81' PYTHON_VERSION: '3.9' diff --git a/.github/workflows/win64_release.yml b/.github/workflows/win64_release.yml index 148a333336..ed4b55bee4 100644 --- a/.github/workflows/win64_release.yml +++ b/.github/workflows/win64_release.yml @@ -1,6 +1,6 @@ env: QT_VERSION: '5.15.2' - SQLITE_VERSION: '3390200' + SQLITE_VERSION: '3390400' SQLITE_RELEASE_YEAR: '2022' QT_ARCH: 'win64_mingw81' PYTHON_VERSION: '3.9' diff --git a/ChangeLog.md b/ChangeLog.md index 7d6faedd19..09fa38d1ac 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -30,7 +30,7 @@ - ADDED: #4217 Added the Invert Selection entry in data grid context menu. - ADDED: #4096 Added data grid option for filtering by strict text (not just whether contains, but if actually equals). Old filtering options remain. - ADDED: Allow drag and drop a file to the add database dialog. -- CHANGE: #4058 SQLite updated to 3.39.2. +- CHANGE: #4058 SQLite updated to 3.39.4 (except for SQLCipher, which has latest version 3.39.2). - CHANGE: #3272 Named function parameters of Custom SQL functions are now passed to script code as named variables. - CHANGE: #3337 QtScript (deprecated module) usage migrated to QML module, using QJSEngine, the EcmaScript compliant implementation. Also changed plugin language name from QtScript to JavaScript and icon from Qt icon to JS icon. - CHANGE: #2963 Application state (session) is saved (apart from normal application exit) whenever the state changes and also during critical application crash. diff --git a/Plugins/DbSqliteWx/update_sqlite_version.tcl b/Plugins/DbSqliteWx/update_sqlite_version.tcl index 147e0f1369..09c3360a75 100644 --- a/Plugins/DbSqliteWx/update_sqlite_version.tcl +++ b/Plugins/DbSqliteWx/update_sqlite_version.tcl @@ -4,7 +4,7 @@ # https://github.com/utelle/wxsqlite3/releases # Link from download page will redicrect to the codeload..... -set THE_URL "https://github.com/utelle/SQLite3MultipleCiphers/releases/download/v1.4.8/sqlite3mc-1.4.8-sqlite-3.39.2-amalgamation.zip" +set THE_URL "https://github.com/utelle/SQLite3MultipleCiphers/releases/download/v1.5.3/sqlite3mc-1.5.3-sqlite-3.39.4-amalgamation.zip" set SRC_DIR "src" set FILES [list \ diff --git a/Plugins/DbSqliteWx/wxsqlite3.c b/Plugins/DbSqliteWx/wxsqlite3.c index ebbcb61d06..c5d362453e 100644 --- a/Plugins/DbSqliteWx/wxsqlite3.c +++ b/Plugins/DbSqliteWx/wxsqlite3.c @@ -3,7 +3,7 @@ ** Purpose: Amalgamation of the SQLite3 Multiple Ciphers encryption extension for SQLite ** Author: Ulrich Telle ** Created: 2020-02-28 -** Copyright: (c) 2006-2021 Ulrich Telle +** Copyright: (c) 2006-2022 Ulrich Telle ** License: MIT */ @@ -92,7 +92,7 @@ extern SQLITE_API LPWSTR wx_sqlite3_win32_utf8_to_unicode(const char*); /*** Begin of #include "wx_sqlite3patched.c" ***/ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.39.2. By combining all the individual C code files into this +** version 3.39.4. By combining all the individual C code files into this ** single large file, the entire code can be compiled as a single translation ** unit. This allows many compilers to do optimizations that would not be ** possible if the files were compiled separately. Performance improvements @@ -544,9 +544,9 @@ extern "C" { ** [wx_sqlite3_libversion_number()], [wx_sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.39.2" -#define SQLITE_VERSION_NUMBER 3039002 -#define SQLITE_SOURCE_ID "2022-07-21 15:24:47 698edb77537b67c41adc68f9b892db56bcf9a55e00371a61420f3ddd668e6603" +#define SQLITE_VERSION "3.39.4" +#define SQLITE_VERSION_NUMBER 3039004 +#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -13243,6 +13243,11 @@ struct fts5_api { /************** End of wx_sqlite3.h *********************************************/ /************** Continuing where we left off in sqliteInt.h ******************/ +/* +** Reuse the STATIC_LRU for mutex access to wx_sqlite3_temp_directory. +*/ +#define SQLITE_MUTEX_STATIC_TEMPDIR SQLITE_MUTEX_STATIC_VFS1 + /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build @@ -29662,8 +29667,13 @@ SQLITE_PRIVATE void *wx_sqlite3OomFault(wx_sqlite3 *db){ } DisableLookaside; if( db->pParse ){ + Parse *pParse; wx_sqlite3ErrorMsg(db->pParse, "out of memory"); db->pParse->rc = SQLITE_NOMEM_BKPT; + for(pParse=db->pParse->pOuterParse; pParse; pParse = pParse->pOuterParse){ + pParse->nErr++; + pParse->rc = SQLITE_NOMEM; + } } } return 0; @@ -33558,7 +33568,7 @@ SQLITE_PRIVATE void wx_sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){ va_list ap; wx_sqlite3 *db = pParse->db; assert( db!=0 ); - assert( db->pParse==pParse ); + assert( db->pParse==pParse || db->pParse->pToplevel==pParse ); db->errByteOffset = -2; va_start(ap, zFormat); zMsg = wx_sqlite3VMPrintf(db, zFormat, ap); @@ -41419,6 +41429,7 @@ static const char *unixTempFileDir(void){ static int unixGetTempname(int nBuf, char *zBuf){ const char *zDir; int iLimit = 0; + int rc = SQLITE_OK; /* It's odd to simulate an io-error here, but really this is just ** using the io-error infrastructure to test that SQLite handles this @@ -41427,18 +41438,26 @@ static int unixGetTempname(int nBuf, char *zBuf){ zBuf[0] = 0; SimulateIOError( return SQLITE_IOERR ); + wx_sqlite3_mutex_enter(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); zDir = unixTempFileDir(); - if( zDir==0 ) return SQLITE_IOERR_GETTEMPPATH; - do{ - u64 r; - wx_sqlite3_randomness(sizeof(r), &r); - assert( nBuf>2 ); - zBuf[nBuf-2] = 0; - wx_sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", - zDir, r, 0); - if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ) return SQLITE_ERROR; - }while( osAccess(zBuf,0)==0 ); - return SQLITE_OK; + if( zDir==0 ){ + rc = SQLITE_IOERR_GETTEMPPATH; + }else{ + do{ + u64 r; + wx_sqlite3_randomness(sizeof(r), &r); + assert( nBuf>2 ); + zBuf[nBuf-2] = 0; + wx_sqlite3_snprintf(nBuf, zBuf, "%s/"SQLITE_TEMP_FILE_PREFIX"%llx%c", + zDir, r, 0); + if( zBuf[nBuf-2]!=0 || (iLimit++)>10 ){ + rc = SQLITE_ERROR; + break; + } + }while( osAccess(zBuf,0)==0 ); + } + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) @@ -45577,10 +45596,12 @@ SQLITE_API int wx_sqlite3_win32_set_directory8( const char *zValue /* New value for directory being set or reset */ ){ char **ppDirectory = 0; + int rc; #ifndef SQLITE_OMIT_AUTOINIT - int rc = wx_sqlite3_initialize(); + rc = wx_sqlite3_initialize(); if( rc ) return rc; #endif + wx_sqlite3_mutex_enter(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( type==SQLITE_WIN32_DATA_DIRECTORY_TYPE ){ ppDirectory = &wx_sqlite3_data_directory; }else if( type==SQLITE_WIN32_TEMP_DIRECTORY_TYPE ){ @@ -45595,14 +45616,19 @@ SQLITE_API int wx_sqlite3_win32_set_directory8( if( zValue && zValue[0] ){ zCopy = wx_sqlite3_mprintf("%s", zValue); if ( zCopy==0 ){ - return SQLITE_NOMEM_BKPT; + rc = SQLITE_NOMEM_BKPT; + goto set_directory8_done; } } wx_sqlite3_free(*ppDirectory); *ppDirectory = zCopy; - return SQLITE_OK; + rc = SQLITE_OK; + }else{ + rc = SQLITE_ERROR; } - return SQLITE_ERROR; +set_directory8_done: + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return rc; } /* @@ -48376,6 +48402,18 @@ static int winMakeEndInDirSep(int nBuf, char *zBuf){ return 0; } +/* +** If wx_sqlite3_temp_directory is not, take the mutex and return true. +** +** If wx_sqlite3_temp_directory is NULL, omit the mutex and return false. +*/ +static int winTempDirDefined(void){ + wx_sqlite3_mutex_enter(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + if( wx_sqlite3_temp_directory!=0 ) return 1; + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); + return 0; +} + /* ** Create a temporary file name and store the resulting pointer into pzBuf. ** The pointer returned in pzBuf must be freed via wx_sqlite3_free(). @@ -48412,20 +48450,23 @@ static int winGetTempname(wx_sqlite3_vfs *pVfs, char **pzBuf){ */ nDir = nMax - (nPre + 15); assert( nDir>0 ); - if( wx_sqlite3_temp_directory ){ + if( winTempDirDefined() ){ int nDirLen = wx_sqlite3Strlen30(wx_sqlite3_temp_directory); if( nDirLen>0 ){ if( !winIsDirSep(wx_sqlite3_temp_directory[nDirLen-1]) ){ nDirLen++; } if( nDirLen>nDir ){ + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); wx_sqlite3_free(zBuf); OSTRACE(("TEMP-FILENAME rc=SQLITE_ERROR\n")); return winLogError(SQLITE_ERROR, 0, "winGetTempname1", 0); } wx_sqlite3_snprintf(nMax, zBuf, "%s", wx_sqlite3_temp_directory); } + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); } + #if defined(__CYGWIN__) else{ static const char *azDirs[] = { @@ -49214,7 +49255,7 @@ static BOOL winIsVerbatimPathname( ** pathname into zOut[]. zOut[] will be at least pVfs->mxPathname ** bytes in size. */ -static int winFullPathname( +static int winFullPathnameNoMutex( wx_sqlite3_vfs *pVfs, /* Pointer to vfs object */ const char *zRelative, /* Possibly relative input path */ int nFull, /* Size of output buffer in bytes */ @@ -49393,6 +49434,19 @@ static int winFullPathname( } #endif } +static int winFullPathname( + wx_sqlite3_vfs *pVfs, /* Pointer to vfs object */ + const char *zRelative, /* Possibly relative input path */ + int nFull, /* Size of output buffer in bytes */ + char *zFull /* Output buffer */ +){ + int rc; + wx_sqlite3_mutex *pMutex = wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR); + wx_sqlite3_mutex_enter(pMutex); + rc = winFullPathnameNoMutex(pVfs, zRelative, nFull, zFull); + wx_sqlite3_mutex_leave(pMutex); + return rc; +} #ifndef SQLITE_OMIT_LOAD_EXTENSION /* @@ -51737,14 +51791,24 @@ SQLITE_PRIVATE void wx_sqlite3PcacheClearSyncFlags(PCache *pCache){ */ SQLITE_PRIVATE void wx_sqlite3PcacheMove(PgHdr *p, Pgno newPgno){ PCache *pCache = p->pCache; + wx_sqlite3_pcache_page *pOther; assert( p->nRef>0 ); assert( newPgno>0 ); assert( wx_sqlite3PcachePageSanity(p) ); pcacheTrace(("%p.MOVE %d -> %d\n",pCache,p->pgno,newPgno)); + pOther = wx_sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, newPgno, 0); + if( pOther ){ + PgHdr *pXPage = (PgHdr*)pOther->pExtra; + assert( pXPage->nRef==0 ); + pXPage->nRef++; + pCache->nRefSum++; + wx_sqlite3PcacheDrop(pXPage); + } wx_sqlite3GlobalConfig.pcache2.xRekey(pCache->pCache, p->pPage, p->pgno,newPgno); p->pgno = newPgno; if( (p->flags&PGHDR_DIRTY) && (p->flags&PGHDR_NEED_SYNC) ){ pcacheManageDirtyList(p, PCACHE_DIRTYLIST_FRONT); + assert( wx_sqlite3PcachePageSanity(p) ); } } @@ -53126,23 +53190,26 @@ static void pcache1Rekey( PCache1 *pCache = (PCache1 *)p; PgHdr1 *pPage = (PgHdr1 *)pPg; PgHdr1 **pp; - unsigned int h; + unsigned int hOld, hNew; assert( pPage->iKey==iOld ); assert( pPage->pCache==pCache ); + assert( iOld!=iNew ); /* The page number really is changing */ pcache1EnterMutex(pCache->pGroup); - h = iOld%pCache->nHash; - pp = &pCache->apHash[h]; + assert( pcache1FetchNoMutex(p, iOld, 0)==pPage ); /* pPg really is iOld */ + hOld = iOld%pCache->nHash; + pp = &pCache->apHash[hOld]; while( (*pp)!=pPage ){ pp = &(*pp)->pNext; } *pp = pPage->pNext; - h = iNew%pCache->nHash; + assert( pcache1FetchNoMutex(p, iNew, 0)==0 ); /* iNew not in cache */ + hNew = iNew%pCache->nHash; pPage->iKey = iNew; - pPage->pNext = pCache->apHash[h]; - pCache->apHash[h] = pPage; + pPage->pNext = pCache->apHash[hNew]; + pCache->apHash[hNew] = pPage; if( iNew>pCache->iMaxKey ){ pCache->iMaxKey = iNew; } @@ -59775,6 +59842,7 @@ static int pager_open_journal(Pager *pPager){ if( rc!=SQLITE_OK ){ wx_sqlite3BitvecDestroy(pPager->pInJournal); pPager->pInJournal = 0; + pPager->journalOff = 0; }else{ assert( pPager->eState==PAGER_WRITER_LOCKED ); pPager->eState = PAGER_WRITER_CACHEMOD; @@ -61330,7 +61398,7 @@ SQLITE_PRIVATE int wx_sqlite3PagerGetJournalMode(Pager *pPager){ SQLITE_PRIVATE int wx_sqlite3PagerOkToChangeJournalMode(Pager *pPager){ assert( assert_pager_state(pPager) ); if( pPager->eState>=PAGER_WRITER_CACHEMOD ) return 0; - if( NEVER(isOpen(pPager->jfd) && pPager->journalOff>0) ) return 0; + if( isOpen(pPager->jfd) && pPager->journalOff>0 ) return 0; return 1; } @@ -68445,7 +68513,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); sz += sz2; - }else if( NEVER(iFree+sz>usableSize) ){ + }else if( iFree+sz>usableSize ){ return SQLITE_CORRUPT_PAGE(pPage); } @@ -74801,8 +74869,6 @@ static int balance_nonroot( Pgno pgno; /* Temp var to store a page number in */ u8 abDone[NB+2]; /* True after i'th new page is populated */ Pgno aPgno[NB+2]; /* Page numbers of new pages before shuffling */ - Pgno aPgOrder[NB+2]; /* Copy of aPgno[] used for sorting pages */ - u16 aPgFlags[NB+2]; /* flags field of new pages before shuffling */ CellArray b; /* Parsed information on cells being balanced */ memset(abDone, 0, sizeof(abDone)); @@ -75226,42 +75292,39 @@ static int balance_nonroot( ** of the table is closer to a linear scan through the file. That in turn ** helps the operating system to deliver pages from the disk more rapidly. ** - ** An O(n^2) insertion sort algorithm is used, but since n is never more - ** than (NB+2) (a small constant), that should not be a problem. + ** An O(N*N) sort algorithm is used, but since N is never more than NB+2 + ** (5), that is not a performance concern. ** ** When NB==3, this one optimization makes the database about 25% faster ** for large insertions and deletions. */ for(i=0; ipgno; - aPgFlags[i] = apNew[i]->pDbPage->flags; - for(j=0; jpgno; + assert( apNew[i]->pDbPage->flags & PGHDR_WRITEABLE ); + assert( apNew[i]->pDbPage->flags & PGHDR_DIRTY ); } - for(i=0; ipgno < apNew[iB]->pgno ) iB = j; } - pgno = aPgOrder[iBest]; - aPgOrder[iBest] = 0xffffffff; - if( iBest!=i ){ - if( iBest>i ){ - wx_sqlite3PagerRekey(apNew[iBest]->pDbPage, pBt->nPage+iBest+1, 0); - } - wx_sqlite3PagerRekey(apNew[i]->pDbPage, pgno, aPgFlags[iBest]); - apNew[i]->pgno = pgno; + + /* If apNew[i] has a page number that is bigger than any of the + ** subsequence apNew[i] entries, then swap apNew[i] with the subsequent + ** entry that has the smallest page number (which we know to be + ** entry apNew[iB]). + */ + if( iB!=i ){ + Pgno pgnoA = apNew[i]->pgno; + Pgno pgnoB = apNew[iB]->pgno; + Pgno pgnoTemp = (PENDING_BYTE/pBt->pageSize)+1; + u16 fgA = apNew[i]->pDbPage->flags; + u16 fgB = apNew[iB]->pDbPage->flags; + wx_sqlite3PagerRekey(apNew[i]->pDbPage, pgnoTemp, fgB); + wx_sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); + wx_sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); + apNew[i]->pgno = pgnoB; + apNew[iB]->pgno = pgnoA; } } @@ -81134,6 +81197,7 @@ SQLITE_PRIVATE int wx_sqlite3VdbeAddFunctionCall( addr = wx_sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function, p1, p2, p3, (char*)pCtx, P4_FUNCCTX); wx_sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef); + wx_sqlite3MayAbort(pParse); return addr; } @@ -81469,6 +81533,7 @@ SQLITE_PRIVATE int wx_sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){ || opcode==OP_VDestroy || opcode==OP_VCreate || opcode==OP_ParseSchema + || opcode==OP_Function || opcode==OP_PureFunc || ((opcode==OP_Halt || opcode==OP_HaltIfNull) && ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort)) ){ @@ -132808,6 +132873,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( ** */ case PragTyp_TEMP_STORE_DIRECTORY: { + wx_sqlite3_mutex_enter(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, wx_sqlite3_temp_directory); }else{ @@ -132817,6 +132883,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( rc = wx_sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ wx_sqlite3ErrorMsg(pParse, "not a writable directory"); + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132834,6 +132901,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } @@ -132852,6 +132920,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( ** */ case PragTyp_DATA_STORE_DIRECTORY: { + wx_sqlite3_mutex_enter(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); if( !zRight ){ returnSingleText(v, wx_sqlite3_data_directory); }else{ @@ -132861,6 +132930,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( rc = wx_sqlite3OsAccess(db->pVfs, zRight, SQLITE_ACCESS_READWRITE, &res); if( rc!=SQLITE_OK || res==0 ){ wx_sqlite3ErrorMsg(pParse, "not a writable directory"); + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); goto pragma_out; } } @@ -132872,6 +132942,7 @@ SQLITE_PRIVATE void wx_sqlite3Pragma( } #endif /* SQLITE_OMIT_WSD */ } + wx_sqlite3_mutex_leave(wx_sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_TEMPDIR)); break; } #endif @@ -137317,7 +137388,7 @@ static void generateSortTail( if( addrOnce ) wx_sqlite3VdbeJumpHere(v, addrOnce); addr = 1 + wx_sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak); VdbeCoverage(v); - codeOffset(v, p->iOffset, addrContinue); + assert( p->iLimit==0 && p->iOffset==0 ); wx_sqlite3VdbeAddOp3(v, OP_SorterData, iTab, regSortOut, iSortTab); bSeq = 0; }else{ @@ -137325,6 +137396,9 @@ static void generateSortTail( codeOffset(v, p->iOffset, addrContinue); iSortTab = iTab; bSeq = 1; + if( p->iOffset>0 ){ + wx_sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1); + } } for(i=0, iCol=nKey+bSeq-1; ipPrior ){ - wx_sqlite3SelectDelete(db, pSplit->pPrior); + wx_sqlite3ParserAddCleanup(pParse, + (void(*)(wx_sqlite3*,void*))wx_sqlite3SelectDelete, pSplit->pPrior); } pSplit->pPrior = pPrior; pPrior->pNext = pSplit; @@ -140839,6 +140914,7 @@ static Table *isSimpleCount(Select *p, AggInfo *pAggInfo){ || p->pSrc->nSrc!=1 || p->pSrc->a[0].pSelect || pAggInfo->nFunc!=1 + || p->pHaving ){ return 0; } @@ -144076,6 +144152,23 @@ SQLITE_PRIVATE void wx_sqlite3FinishTrigger( Vdbe *v; char *z; + /* If this is a new CREATE TABLE statement, and if shadow tables + ** are read-only, and the trigger makes a change to a shadow table, + ** then raise an error - do not allow the trigger to be created. */ + if( wx_sqlite3ReadOnlyShadowTables(db) ){ + TriggerStep *pStep; + for(pStep=pTrig->step_list; pStep; pStep=pStep->pNext){ + if( pStep->zTarget!=0 + && wx_sqlite3ShadowTableName(db, pStep->zTarget) + ){ + wx_sqlite3ErrorMsg(pParse, + "trigger \"%s\" may not write to shadow table \"%s\"", + pTrig->zName, pStep->zTarget); + goto triggerfinish_cleanup; + } + } + } + /* Make an entry in the sqlite_schema table */ v = wx_sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; @@ -149887,7 +149980,8 @@ static int codeEqualityTerm( } wx_sqlite3ExprDelete(db, pX); }else{ - aiMap = (int*)wx_sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq); + int n = wx_sqlite3ExprVectorSize(pX->pLeft); + aiMap = (int*)wx_sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n)); eType = wx_sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab); } pX = pExpr; @@ -177045,7 +177139,7 @@ struct Fts3MultiSegReader { int nAdvance; /* How many seg-readers to advance */ Fts3SegFilter *pFilter; /* Pointer to filter object */ char *aBuffer; /* Buffer to merge doclists in */ - int nBuffer; /* Allocated size of aBuffer[] in bytes */ + i64 nBuffer; /* Allocated size of aBuffer[] in bytes */ int iColFilter; /* If >=0, filter for this column */ int bRestart; @@ -179741,7 +179835,7 @@ static int fts3TermSelectMerge( ** ** Similar padding is added in the fts3DoclistOrMerge() function. */ - pTS->aaOutput[0] = wx_sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1); + pTS->aaOutput[0] = wx_sqlite3_malloc64((i64)nDoclist + FTS3_VARINT_MAX + 1); pTS->anOutput[0] = nDoclist; if( pTS->aaOutput[0] ){ memcpy(pTS->aaOutput[0], aDoclist, nDoclist); @@ -181229,7 +181323,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){ nDistance = iPrev - nMaxUndeferred; } - aOut = (char *)wx_sqlite3_malloc(nPoslist+8); + aOut = (char *)wx_sqlite3Fts3MallocZero(nPoslist+FTS3_BUFFER_PADDING); if( !aOut ){ wx_sqlite3_free(aPoslist); return SQLITE_NOMEM; @@ -181598,7 +181692,7 @@ static int fts3EvalIncrPhraseNext( if( bEof==0 ){ int nList = 0; int nByte = a[p->nToken-1].nList; - char *aDoclist = wx_sqlite3_malloc(nByte+FTS3_BUFFER_PADDING); + char *aDoclist = wx_sqlite3_malloc64((i64)nByte+FTS3_BUFFER_PADDING); if( !aDoclist ) return SQLITE_NOMEM; memcpy(aDoclist, a[p->nToken-1].pList, nByte+1); memset(&aDoclist[nByte], 0, FTS3_BUFFER_PADDING); @@ -185834,7 +185928,7 @@ static int porterNext( if( n>c->nAllocated ){ char *pNew; c->nAllocated = n+20; - pNew = wx_sqlite3_realloc(c->zToken, c->nAllocated); + pNew = wx_sqlite3_realloc64(c->zToken, c->nAllocated); if( !pNew ) return SQLITE_NOMEM; c->zToken = pNew; } @@ -186586,7 +186680,7 @@ static int simpleNext( if( n>c->nTokenAllocated ){ char *pNew; c->nTokenAllocated = n+20; - pNew = wx_sqlite3_realloc(c->pToken, c->nTokenAllocated); + pNew = wx_sqlite3_realloc64(c->pToken, c->nTokenAllocated); if( !pNew ) return SQLITE_NOMEM; c->pToken = pNew; } @@ -187748,7 +187842,7 @@ static int fts3PendingListAppendVarint( /* Allocate or grow the PendingList as required. */ if( !p ){ - p = wx_sqlite3_malloc(sizeof(*p) + 100); + p = wx_sqlite3_malloc64(sizeof(*p) + 100); if( !p ){ return SQLITE_NOMEM; } @@ -187757,14 +187851,14 @@ static int fts3PendingListAppendVarint( p->nData = 0; } else if( p->nData+FTS3_VARINT_MAX+1>p->nSpace ){ - int nNew = p->nSpace * 2; - p = wx_sqlite3_realloc(p, sizeof(*p) + nNew); + i64 nNew = p->nSpace * 2; + p = wx_sqlite3_realloc64(p, sizeof(*p) + nNew); if( !p ){ wx_sqlite3_free(*pp); *pp = 0; return SQLITE_NOMEM; } - p->nSpace = nNew; + p->nSpace = (int)nNew; p->aData = (char *)&p[1]; } @@ -188321,7 +188415,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3ReadBlock( int nByte = wx_sqlite3_blob_bytes(p->pSegments); *pnBlob = nByte; if( paBlob ){ - char *aByte = wx_sqlite3_malloc(nByte + FTS3_NODE_PADDING); + char *aByte = wx_sqlite3_malloc64((i64)nByte + FTS3_NODE_PADDING); if( !aByte ){ rc = SQLITE_NOMEM; }else{ @@ -188438,7 +188532,7 @@ static int fts3SegReaderNext( int nTerm = fts3HashKeysize(pElem); if( (nTerm+1)>pReader->nTermAlloc ){ wx_sqlite3_free(pReader->zTerm); - pReader->zTerm = (char*)wx_sqlite3_malloc((nTerm+1)*2); + pReader->zTerm = (char*)wx_sqlite3_malloc64(((i64)nTerm+1)*2); if( !pReader->zTerm ) return SQLITE_NOMEM; pReader->nTermAlloc = (nTerm+1)*2; } @@ -188446,7 +188540,7 @@ static int fts3SegReaderNext( pReader->zTerm[nTerm] = '\0'; pReader->nTerm = nTerm; - aCopy = (char*)wx_sqlite3_malloc(nCopy); + aCopy = (char*)wx_sqlite3_malloc64(nCopy); if( !aCopy ) return SQLITE_NOMEM; memcpy(aCopy, pList->aData, nCopy); pReader->nNode = pReader->nDoclist = nCopy; @@ -188733,7 +188827,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3SegReaderNew( nExtra = nRoot + FTS3_NODE_PADDING; } - pReader = (Fts3SegReader *)wx_sqlite3_malloc(sizeof(Fts3SegReader) + nExtra); + pReader = (Fts3SegReader *)wx_sqlite3_malloc64(sizeof(Fts3SegReader) + nExtra); if( !pReader ){ return SQLITE_NOMEM; } @@ -188825,7 +188919,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3SegReaderPending( if( nElem==nAlloc ){ Fts3HashElem **aElem2; nAlloc += 16; - aElem2 = (Fts3HashElem **)wx_sqlite3_realloc( + aElem2 = (Fts3HashElem **)wx_sqlite3_realloc64( aElem, nAlloc*sizeof(Fts3HashElem *) ); if( !aElem2 ){ @@ -189159,7 +189253,7 @@ static int fts3NodeAddTerm( ** this is not expected to be a serious problem. */ assert( pTree->aData==(char *)&pTree[1] ); - pTree->aData = (char *)wx_sqlite3_malloc(nReq); + pTree->aData = (char *)wx_sqlite3_malloc64(nReq); if( !pTree->aData ){ return SQLITE_NOMEM; } @@ -189177,7 +189271,7 @@ static int fts3NodeAddTerm( if( isCopyTerm ){ if( pTree->nMalloczMalloc, nTerm*2); + char *zNew = wx_sqlite3_realloc64(pTree->zMalloc, (i64)nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } @@ -189203,7 +189297,7 @@ static int fts3NodeAddTerm( ** now. Instead, the term is inserted into the parent of pTree. If pTree ** has no parent, one is created here. */ - pNew = (SegmentNode *)wx_sqlite3_malloc(sizeof(SegmentNode) + p->nNodeSize); + pNew = (SegmentNode *)wx_sqlite3_malloc64(sizeof(SegmentNode) + p->nNodeSize); if( !pNew ){ return SQLITE_NOMEM; } @@ -189341,7 +189435,7 @@ static int fts3SegWriterAdd( ){ int nPrefix; /* Size of term prefix in bytes */ int nSuffix; /* Size of term suffix in bytes */ - int nReq; /* Number of bytes required on leaf page */ + i64 nReq; /* Number of bytes required on leaf page */ int nData; SegmentWriter *pWriter = *ppWriter; @@ -189350,13 +189444,13 @@ static int fts3SegWriterAdd( wx_sqlite3_stmt *pStmt; /* Allocate the SegmentWriter structure */ - pWriter = (SegmentWriter *)wx_sqlite3_malloc(sizeof(SegmentWriter)); + pWriter = (SegmentWriter *)wx_sqlite3_malloc64(sizeof(SegmentWriter)); if( !pWriter ) return SQLITE_NOMEM; memset(pWriter, 0, sizeof(SegmentWriter)); *ppWriter = pWriter; /* Allocate a buffer in which to accumulate data */ - pWriter->aData = (char *)wx_sqlite3_malloc(p->nNodeSize); + pWriter->aData = (char *)wx_sqlite3_malloc64(p->nNodeSize); if( !pWriter->aData ) return SQLITE_NOMEM; pWriter->nSize = p->nNodeSize; @@ -189431,7 +189525,7 @@ static int fts3SegWriterAdd( ** the buffer to make it large enough. */ if( nReq>pWriter->nSize ){ - char *aNew = wx_sqlite3_realloc(pWriter->aData, nReq); + char *aNew = wx_sqlite3_realloc64(pWriter->aData, nReq); if( !aNew ) return SQLITE_NOMEM; pWriter->aData = aNew; pWriter->nSize = nReq; @@ -189456,7 +189550,7 @@ static int fts3SegWriterAdd( */ if( isCopyTerm ){ if( nTerm>pWriter->nMalloc ){ - char *zNew = wx_sqlite3_realloc(pWriter->zMalloc, nTerm*2); + char *zNew = wx_sqlite3_realloc64(pWriter->zMalloc, (i64)nTerm*2); if( !zNew ){ return SQLITE_NOMEM; } @@ -189764,12 +189858,12 @@ static void fts3ColumnFilter( static int fts3MsrBufferData( Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ char *pList, - int nList + i64 nList ){ if( nList>pMsr->nBuffer ){ char *pNew; pMsr->nBuffer = nList*2; - pNew = (char *)wx_sqlite3_realloc(pMsr->aBuffer, pMsr->nBuffer); + pNew = (char *)wx_sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer); if( !pNew ) return SQLITE_NOMEM; pMsr->aBuffer = pNew; } @@ -189825,7 +189919,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3MsrIncrNext( fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp); if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pMsr, pList, nList+1); + rc = fts3MsrBufferData(pMsr, pList, (i64)nList+1); if( rc!=SQLITE_OK ) return rc; assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 ); pList = pMsr->aBuffer; @@ -189962,11 +190056,11 @@ SQLITE_PRIVATE int wx_sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){ return SQLITE_OK; } -static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){ +static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, i64 nReq){ if( nReq>pCsr->nBuffer ){ char *aNew; pCsr->nBuffer = nReq*2; - aNew = wx_sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer); + aNew = wx_sqlite3_realloc64(pCsr->aBuffer, pCsr->nBuffer); if( !aNew ){ return SQLITE_NOMEM; } @@ -190057,7 +190151,8 @@ SQLITE_PRIVATE int wx_sqlite3Fts3SegReaderStep( ){ pCsr->nDoclist = apSegment[0]->nDoclist; if( fts3SegReaderIsPending(apSegment[0]) ){ - rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, pCsr->nDoclist); + rc = fts3MsrBufferData(pCsr, apSegment[0]->aDoclist, + (i64)pCsr->nDoclist); pCsr->aDoclist = pCsr->aBuffer; }else{ pCsr->aDoclist = apSegment[0]->aDoclist; @@ -190110,7 +190205,8 @@ SQLITE_PRIVATE int wx_sqlite3Fts3SegReaderStep( nByte = wx_sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0); - rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist+FTS3_NODE_PADDING); + rc = fts3GrowSegReaderBuffer(pCsr, + (i64)nByte+nDoclist+FTS3_NODE_PADDING); if( rc ) return rc; if( isFirst ){ @@ -190136,7 +190232,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3SegReaderStep( fts3SegReaderSort(apSegment, nMerge, j, xCmp); } if( nDoclist>0 ){ - rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING); + rc = fts3GrowSegReaderBuffer(pCsr, (i64)nDoclist+FTS3_NODE_PADDING); if( rc ) return rc; memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING); pCsr->aDoclist = pCsr->aBuffer; @@ -190849,7 +190945,7 @@ struct NodeReader { static void blobGrowBuffer(Blob *pBlob, int nMin, int *pRc){ if( *pRc==SQLITE_OK && nMin>pBlob->nAlloc ){ int nAlloc = nMin; - char *a = (char *)wx_sqlite3_realloc(pBlob->a, nAlloc); + char *a = (char *)wx_sqlite3_realloc64(pBlob->a, nAlloc); if( a ){ pBlob->nAlloc = nAlloc; pBlob->a = a; @@ -191646,7 +191742,7 @@ static int fts3RepackSegdirLevel( if( nIdx>=nAlloc ){ int *aNew; nAlloc += 16; - aNew = wx_sqlite3_realloc(aIdx, nAlloc*sizeof(int)); + aNew = wx_sqlite3_realloc64(aIdx, nAlloc*sizeof(int)); if( !aNew ){ rc = SQLITE_NOMEM; break; @@ -192020,7 +192116,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){ /* Allocate space for the cursor, filter and writer objects */ const int nAlloc = sizeof(*pCsr) + sizeof(*pFilter) + sizeof(*pWriter); - pWriter = (IncrmergeWriter *)wx_sqlite3_malloc(nAlloc); + pWriter = (IncrmergeWriter *)wx_sqlite3_malloc64(nAlloc); if( !pWriter ) return SQLITE_NOMEM; pFilter = (Fts3SegFilter *)&pWriter[1]; pCsr = (Fts3MultiSegReader *)&pFilter[1]; @@ -192656,7 +192752,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3DeferredTokenList( return SQLITE_OK; } - pRet = (char *)wx_sqlite3_malloc(p->pList->nData); + pRet = (char *)wx_sqlite3_malloc64(p->pList->nData); if( !pRet ) return SQLITE_NOMEM; nSkip = wx_sqlite3Fts3GetVarint(p->pList->aData, &dummy); @@ -192676,7 +192772,7 @@ SQLITE_PRIVATE int wx_sqlite3Fts3DeferToken( int iCol /* Column that token must appear in (or -1) */ ){ Fts3DeferredToken *pDeferred; - pDeferred = wx_sqlite3_malloc(sizeof(*pDeferred)); + pDeferred = wx_sqlite3_malloc64(sizeof(*pDeferred)); if( !pDeferred ){ return SQLITE_NOMEM; } @@ -204255,7 +204351,7 @@ static int geopolyUpdate( wx_sqlite3_free(p); nChange = 1; } - for(jj=1; jjnAux; jj++){ + for(jj=1; jj CODEC_TYPE_MAX +#if CODEC_TYPE < 1 || CODEC_TYPE > CODEC_TYPE_MAX_BUILTIN #error "Invalid codec type selected" #endif +/* +** Define the maximum number of ciphers that can be registered +*/ + +/* Use a reasonable upper limit for the maximum number of ciphers */ +#define CODEC_COUNT_LIMIT 16 + +#ifdef SQLITE3MC_MAX_CODEC_COUNT +/* Allow at least to register all built-in ciphers, but use a reasonable upper limit */ +#if SQLITE3MC_MAX_CODEC_COUNT >= CODEC_TYPE_MAX_BUILTIN && SQLITE3MC_MAX_CODEC_COUNT <= CODEC_COUNT_LIMIT +#define CODEC_COUNT_MAX SQLITE3MC_MAX_CODEC_COUNT +#else +#error "Maximum cipher count not in range [CODEC_TYPE_MAX_BUILTIN .. CODEC_COUNT_LIMIT]" +#endif +#else +#define CODEC_COUNT_MAX CODEC_COUNT_LIMIT +#endif + +#define CIPHER_NAME_MAXLEN 32 +#define CIPHER_PARAMS_COUNT_MAX 64 + #define MAXKEYLENGTH 32 #define KEYLENGTH_AES128 16 #define KEYLENGTH_AES256 32 @@ -261024,6 +261258,13 @@ void RijndaelInvalidate(Rijndael* rijndael) #define CODEC_SHA_ITER 4001 +typedef struct _CodecParameter +{ + char* m_name; + int m_id; + CipherParams* m_params; +} CodecParameter; + typedef struct _Codec { int m_isEncrypted; @@ -261055,53 +261296,11 @@ typedef struct _Codec #define CIPHER_PARAMS_SENTINEL { "", 0, 0, 0, 0 } #define CIPHER_PAGE1_OFFSET 24 -typedef struct _CipherParams -{ - char* m_name; - int m_value; - int m_default; - int m_minValue; - int m_maxValue; -} CipherParams; - -typedef struct _CodecParameter -{ - char* m_name; - int m_id; - CipherParams* m_params; -} CodecParameter; - -typedef void* (*AllocateCipher_t)(wx_sqlite3* db); -typedef void (*FreeCipher_t)(void* cipher); -typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom); -typedef int (*GetLegacy_t)(void* cipher); -typedef int (*GetPageSize_t)(void* cipher); -typedef int (*GetReserved_t)(void* cipher); -typedef unsigned char* (*GetSalt_t)(void* cipher); -typedef void (*GenerateKey_t)(void* cipher, BtShared* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt); -typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved); -typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck); - -typedef struct _CodecDescriptor -{ - char m_name[32]; - AllocateCipher_t m_allocateCipher; - FreeCipher_t m_freeCipher; - CloneCipher_t m_cloneCipher; - GetLegacy_t m_getLegacy; - GetPageSize_t m_getPageSize; - GetReserved_t m_getReserved; - GetSalt_t m_getSalt; - GenerateKey_t m_generateKey; - EncryptPage_t m_encryptPage; - DecryptPage_t m_decryptPage; -} CipherDescriptor; - SQLITE_PRIVATE int wx_sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName); SQLITE_PRIVATE int wx_sqlite3mcGetCipherType(wx_sqlite3* db); -SQLITE_PRIVATE CipherParams* wx_sqlite3mcGetCipherParams(wx_sqlite3* db, int cypherType); +SQLITE_PRIVATE CipherParams* wx_sqlite3mcGetCipherParams(wx_sqlite3* db, const char* cipherName); SQLITE_PRIVATE int wx_sqlite3mcCodecInit(Codec* codec); @@ -261504,6 +261703,8 @@ wx_sqlite3mcConvertHex2Bin(const unsigned char* hex, int len, unsigned char* bin /* --- AES 128-bit cipher (wxSQLite3) --- */ #if HAVE_CIPHER_AES_128_CBC +#define CIPHER_NAME_AES128 "aes128cbc" + /* ** Configuration parameters for "aes128cbc" ** @@ -261554,7 +261755,7 @@ AllocateAES128Cipher(wx_sqlite3* db) } if (aesCipher != NULL) { - CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CODEC_TYPE_AES128); + CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CIPHER_NAME_AES128); aesCipher->m_legacy = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy"); aesCipher->m_legacyPageSize = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); } @@ -261758,16 +261959,17 @@ DecryptPageAES128Cipher(void* cipher, int page, unsigned char* data, int len, in SQLITE_PRIVATE const CipherDescriptor mcAES128Descriptor = { - "aes128cbc", AllocateAES128Cipher, - FreeAES128Cipher, - CloneAES128Cipher, - GetLegacyAES128Cipher, - GetPageSizeAES128Cipher, - GetReservedAES128Cipher, - GetSaltAES128Cipher, - GenerateKeyAES128Cipher, - EncryptPageAES128Cipher, - DecryptPageAES128Cipher + CIPHER_NAME_AES128, + AllocateAES128Cipher, + FreeAES128Cipher, + CloneAES128Cipher, + GetLegacyAES128Cipher, + GetPageSizeAES128Cipher, + GetReservedAES128Cipher, + GetSaltAES128Cipher, + GenerateKeyAES128Cipher, + EncryptPageAES128Cipher, + DecryptPageAES128Cipher }; #endif /*** End of #include "cipher_wxaes128.c" ***/ @@ -261789,6 +261991,8 @@ SQLITE_PRIVATE const CipherDescriptor mcAES128Descriptor = /* --- AES 256-bit cipher (wxSQLite3) --- */ #if HAVE_CIPHER_AES_256_CBC +#define CIPHER_NAME_AES256 "aes256cbc" + /* ** Configuration parameters for "aes256cbc" ** @@ -261843,7 +262047,7 @@ AllocateAES256Cipher(wx_sqlite3* db) } if (aesCipher != NULL) { - CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CODEC_TYPE_AES256); + CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CIPHER_NAME_AES256); aesCipher->m_legacy = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy"); aesCipher->m_legacyPageSize = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); aesCipher->m_kdfIter = wx_sqlite3mcGetCipherParameter(cipherParams, "kdf_iter"); @@ -262011,16 +262215,17 @@ DecryptPageAES256Cipher(void* cipher, int page, unsigned char* data, int len, in SQLITE_PRIVATE const CipherDescriptor mcAES256Descriptor = { - "aes256cbc", AllocateAES256Cipher, - FreeAES256Cipher, - CloneAES256Cipher, - GetLegacyAES256Cipher, - GetPageSizeAES256Cipher, - GetReservedAES256Cipher, - GetSaltAES256Cipher, - GenerateKeyAES256Cipher, - EncryptPageAES256Cipher, - DecryptPageAES256Cipher + CIPHER_NAME_AES256, + AllocateAES256Cipher, + FreeAES256Cipher, + CloneAES256Cipher, + GetLegacyAES256Cipher, + GetPageSizeAES256Cipher, + GetReservedAES256Cipher, + GetSaltAES256Cipher, + GenerateKeyAES256Cipher, + EncryptPageAES256Cipher, + DecryptPageAES256Cipher }; #endif /*** End of #include "cipher_wxaes256.c" ***/ @@ -262042,6 +262247,8 @@ SQLITE_PRIVATE const CipherDescriptor mcAES256Descriptor = /* --- ChaCha20-Poly1305 cipher (plus sqleet variant) --- */ #if HAVE_CIPHER_CHACHA20 +#define CIPHER_NAME_CHACHA20 "chacha20" + /* ** Configuration parameters for "chacha20" ** @@ -262098,7 +262305,7 @@ AllocateChaCha20Cipher(wx_sqlite3* db) } if (chacha20Cipher != NULL) { - CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CODEC_TYPE_CHACHA20); + CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CIPHER_NAME_CHACHA20); chacha20Cipher->m_legacy = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy"); chacha20Cipher->m_legacyPageSize = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); chacha20Cipher->m_kdfIter = wx_sqlite3mcGetCipherParameter(cipherParams, "kdf_iter"); @@ -262394,16 +262601,17 @@ DecryptPageChaCha20Cipher(void* cipher, int page, unsigned char* data, int len, SQLITE_PRIVATE const CipherDescriptor mcChaCha20Descriptor = { - "chacha20", AllocateChaCha20Cipher, - FreeChaCha20Cipher, - CloneChaCha20Cipher, - GetLegacyChaCha20Cipher, - GetPageSizeChaCha20Cipher, - GetReservedChaCha20Cipher, - GetSaltChaCha20Cipher, - GenerateKeyChaCha20Cipher, - EncryptPageChaCha20Cipher, - DecryptPageChaCha20Cipher + CIPHER_NAME_CHACHA20, + AllocateChaCha20Cipher, + FreeChaCha20Cipher, + CloneChaCha20Cipher, + GetLegacyChaCha20Cipher, + GetPageSizeChaCha20Cipher, + GetReservedChaCha20Cipher, + GetSaltChaCha20Cipher, + GenerateKeyChaCha20Cipher, + EncryptPageChaCha20Cipher, + DecryptPageChaCha20Cipher }; #endif /*** End of #include "cipher_chacha20.c" ***/ @@ -262425,6 +262633,8 @@ SQLITE_PRIVATE const CipherDescriptor mcChaCha20Descriptor = /* --- SQLCipher AES256CBC-HMAC cipher --- */ #if HAVE_CIPHER_SQLCIPHER +#define CIPHER_NAME_SQLCIPHER "sqlcipher" + /* ** Configuration parameters for "sqlcipher" ** @@ -262540,7 +262750,7 @@ AllocateSQLCipherCipher(wx_sqlite3* db) } if (sqlCipherCipher != NULL) { - CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CODEC_TYPE_SQLCIPHER); + CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CIPHER_NAME_SQLCIPHER); sqlCipherCipher->m_legacy = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy"); sqlCipherCipher->m_legacyPageSize = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); sqlCipherCipher->m_kdfIter = wx_sqlite3mcGetCipherParameter(cipherParams, "kdf_iter"); @@ -262913,16 +263123,17 @@ DecryptPageSQLCipherCipher(void* cipher, int page, unsigned char* data, int len, } SQLITE_PRIVATE const CipherDescriptor mcSQLCipherDescriptor = { - "sqlcipher", AllocateSQLCipherCipher, - FreeSQLCipherCipher, - CloneSQLCipherCipher, - GetLegacySQLCipherCipher, - GetPageSizeSQLCipherCipher, - GetReservedSQLCipherCipher, - GetSaltSQLCipherCipher, - GenerateKeySQLCipherCipher, - EncryptPageSQLCipherCipher, - DecryptPageSQLCipherCipher + CIPHER_NAME_SQLCIPHER, + AllocateSQLCipherCipher, + FreeSQLCipherCipher, + CloneSQLCipherCipher, + GetLegacySQLCipherCipher, + GetPageSizeSQLCipherCipher, + GetReservedSQLCipherCipher, + GetSaltSQLCipherCipher, + GenerateKeySQLCipherCipher, + EncryptPageSQLCipherCipher, + DecryptPageSQLCipherCipher }; #endif /*** End of #include "cipher_sqlcipher.c" ***/ @@ -262944,6 +263155,8 @@ SQLITE_PRIVATE const CipherDescriptor mcSQLCipherDescriptor = /* --- RC4 cipher (System.Data.SQLite) --- */ #if HAVE_CIPHER_RC4 +#define CIPHER_NAME_RC4 "rc4" + /* ** Configuration parameters for "rc4" ** @@ -262984,7 +263197,7 @@ AllocateRC4Cipher(wx_sqlite3* db) } if (rc4Cipher != NULL) { - CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CODEC_TYPE_RC4); + CipherParams* cipherParams = wx_sqlite3mcGetCipherParams(db, CIPHER_NAME_RC4); rc4Cipher->m_legacy = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy"); rc4Cipher->m_legacyPageSize = wx_sqlite3mcGetCipherParameter(cipherParams, "legacy_page_size"); } @@ -263087,16 +263300,17 @@ DecryptPageRC4Cipher(void* cipher, int page, unsigned char* data, int len, int r SQLITE_PRIVATE const CipherDescriptor mcRC4Descriptor = { - "rc4", AllocateRC4Cipher, - FreeRC4Cipher, - CloneRC4Cipher, - GetLegacyRC4Cipher, - GetPageSizeRC4Cipher, - GetReservedRC4Cipher, - GetSaltRC4Cipher, - GenerateKeyRC4Cipher, - EncryptPageRC4Cipher, - DecryptPageRC4Cipher + CIPHER_NAME_RC4, + AllocateRC4Cipher, + FreeRC4Cipher, + CloneRC4Cipher, + GetLegacyRC4Cipher, + GetPageSizeRC4Cipher, + GetReservedRC4Cipher, + GetSaltRC4Cipher, + GenerateKeyRC4Cipher, + EncryptPageRC4Cipher, + DecryptPageRC4Cipher }; #endif /*** End of #include "cipher_sds_rc4.c" ***/ @@ -263108,7 +263322,7 @@ SQLITE_PRIVATE const CipherDescriptor mcRC4Descriptor = ** Purpose: Implementation of SQLite codecs ** Author: Ulrich Telle ** Created: 2020-02-02 -** Copyright: (c) 2006-2021 Ulrich Telle +** Copyright: (c) 2006-2022 Ulrich Telle ** License: MIT */ @@ -263129,21 +263343,26 @@ static unsigned char padding[] = static CipherParams commonParams[] = { - { "cipher", CODEC_TYPE, CODEC_TYPE, 1, CODEC_TYPE_MAX }, - { "hmac_check", 1, 1, 0, 1 }, - { "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 }, + { "cipher", CODEC_TYPE_UNKNOWN, CODEC_TYPE_UNKNOWN, 1, CODEC_COUNT_MAX }, + { "hmac_check", 1, 1, 0, 1 }, + { "mc_legacy_wal", SQLITE3MC_LEGACY_WAL, SQLITE3MC_LEGACY_WAL, 0, 1 }, CIPHER_PARAMS_SENTINEL }; +#define CIPHER_NAME_GLOBAL "global" + +static CodecParameter globalCommonParams = { CIPHER_NAME_GLOBAL, CODEC_TYPE_UNKNOWN, commonParams }; +static CodecParameter globalSentinelParams = { "", CODEC_TYPE_UNKNOWN, NULL }; + SQLITE_PRIVATE int wx_sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName) { int value = -1; - for (; strlen(cipherParams->m_name) > 0; ++cipherParams) + for (; cipherParams->m_name[0] != 0; ++cipherParams) { if (wx_sqlite3_stricmp(paramName, cipherParams->m_name) == 0) break; } - if (strlen(cipherParams->m_name) > 0) + if (cipherParams->m_name[0] != 0) { value = cipherParams->m_value; cipherParams->m_value = cipherParams->m_default; @@ -263151,26 +263370,15 @@ wx_sqlite3mcGetCipherParameter(CipherParams* cipherParams, const char* paramName return value; } -static CodecParameter globalCodecParameterTable[] = +typedef struct _CipherName { - { "global", CODEC_TYPE_UNKNOWN, commonParams }, -#if HAVE_CIPHER_AES_128_CBC - { "aes128cbc", CODEC_TYPE_AES128, mcAES128Params }, -#endif -#if HAVE_CIPHER_AES_256_CBC - { "aes256cbc", CODEC_TYPE_AES256, mcAES256Params }, -#endif -#if HAVE_CIPHER_CHACHA20 - { "chacha20", CODEC_TYPE_CHACHA20, mcChaCha20Params }, -#endif -#if HAVE_CIPHER_SQLCIPHER - { "sqlcipher", CODEC_TYPE_SQLCIPHER, mcSQLCipherParams }, -#endif -#if HAVE_CIPHER_RC4 - { "rc4", CODEC_TYPE_RC4, mcRC4Params }, -#endif - { "", CODEC_TYPE_UNKNOWN, NULL } -}; + char m_name[CIPHER_NAME_MAXLEN]; +} CipherName; + +static int globalCipherCount = 0; +static char* globalSentinelName = ""; +static CipherName globalCipherNameTable[CODEC_COUNT_LIMIT + 2] = { 0 }; +static CodecParameter globalCodecParameterTable[CODEC_COUNT_LIMIT + 2]; SQLITE_PRIVATE CodecParameter* wx_sqlite3mcCloneCodecParameterTable() @@ -263182,10 +263390,10 @@ wx_sqlite3mcCloneCodecParameterTable() CipherParams* cloneCipherParams; CodecParameter* cloneCodecParams; - for (j = 0; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 0; globalCodecParameterTable[j].m_name[0] != 0; ++j) { CipherParams* params = globalCodecParameterTable[j].m_params; - for (k = 0; strlen(params[k].m_name) > 0; ++k); + for (k = 0; params[k].m_name[0] != 0; ++k); nParams += k; } nTables = j; @@ -263204,7 +263412,7 @@ wx_sqlite3mcCloneCodecParameterTable() cloneCodecParams[j].m_name = globalCodecParameterTable[j].m_name; cloneCodecParams[j].m_id = globalCodecParameterTable[j].m_id; cloneCodecParams[j].m_params = &cloneCipherParams[offset]; - for (n = 0; strlen(params[n].m_name) > 0; ++n); + for (n = 0; params[n].m_name[0] != 0; ++n); /* Copy all parameters of the current table (including sentinel) */ for (k = 0; k <= n; ++k) { @@ -263244,35 +263452,7 @@ static const CipherDescriptor mcDummyDescriptor = "@dummy@", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; -static const CipherDescriptor* codecDescriptorTable[] = -{ -#if HAVE_CIPHER_AES_128_CBC - &mcAES128Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_AES_256_CBC - &mcAES256Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_CHACHA20 - &mcChaCha20Descriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_SQLCIPHER - &mcSQLCipherDescriptor, -#else - &mcDummyDescriptor, -#endif -#if HAVE_CIPHER_RC4 - &mcRC4Descriptor, -#else - &mcDummyDescriptor, -#endif - &mcSentinelDescriptor -}; +static CipherDescriptor globalCodecDescriptorTable[CODEC_COUNT_MAX + 1]; /* --- Codec --- */ @@ -263286,11 +263466,11 @@ wx_sqlite3mcGetCipherType(wx_sqlite3* db) CipherParams* cipherParamTable = (codecParams != NULL) ? codecParams[0].m_params : commonParams; int cipherType = CODEC_TYPE; CipherParams* cipher = cipherParamTable; - for (; strlen(cipher->m_name) > 0; ++cipher) + for (; cipher->m_name[0] != 0; ++cipher) { if (wx_sqlite3_stricmp("cipher", cipher->m_name) == 0) break; } - if (strlen(cipher->m_name) > 0) + if (cipher->m_name[0] != 0) { cipherType = cipher->m_value; cipher->m_value = cipher->m_default; @@ -263299,19 +263479,20 @@ wx_sqlite3mcGetCipherType(wx_sqlite3* db) } SQLITE_PRIVATE CipherParams* -wx_sqlite3mcGetCipherParams(wx_sqlite3* db, int cypherType) +wx_sqlite3mcGetCipherParams(wx_sqlite3* db, const char* cipherName) { int j = 0; + int cipherType = wx_sqlite3mc_cipher_index(cipherName); CodecParameter* codecParams = (db != NULL) ? wx_sqlite3mcGetCodecParams(db) : globalCodecParameterTable; if (codecParams == NULL) { codecParams = globalCodecParameterTable; } - if (cypherType > 0) + if (cipherType > 0) { for (j = 1; codecParams[j].m_id > 0; ++j) { - if (cypherType == codecParams[j].m_id) break; + if (cipherType == codecParams[j].m_id) break; } } CipherParams* cipherParamTable = codecParams[j].m_params; @@ -263361,12 +263542,12 @@ wx_sqlite3mcCodecTerm(Codec* codec) { if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType - 1]->m_freeCipher(codec->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType - 1].m_freeCipher(codec->m_readCipher); codec->m_readCipher = NULL; } if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType - 1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_freeCipher(codec->m_writeCipher); codec->m_writeCipher = NULL; } memset(codec, 0, sizeof(Codec)); @@ -263383,14 +263564,14 @@ SQLITE_PRIVATE int wx_sqlite3mcCodecSetup(Codec* codec, int cipherType, char* userPassword, int passwordLength) { int rc = SQLITE_OK; - CipherParams* globalParams = wx_sqlite3mcGetCipherParams(codec->m_db, 0); + CipherParams* globalParams = wx_sqlite3mcGetCipherParams(codec->m_db, CIPHER_NAME_GLOBAL); codec->m_isEncrypted = 1; codec->m_hmacCheck = wx_sqlite3mcGetCipherParameter(globalParams, "hmac_check"); codec->m_walLegacy = wx_sqlite3mcGetCipherParameter(globalParams, "mc_legacy_wal"); codec->m_hasReadCipher = 1; codec->m_hasWriteCipher = 1; codec->m_readCipherType = cipherType; - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType-1].m_allocateCipher(codec->m_db); if (codec->m_readCipher != NULL) { unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL; @@ -263408,17 +263589,17 @@ SQLITE_PRIVATE int wx_sqlite3mcSetupWriteCipher(Codec* codec, int cipherType, char* userPassword, int passwordLength) { int rc = SQLITE_OK; - CipherParams* globalParams = wx_sqlite3mcGetCipherParams(codec->m_db, 0); + CipherParams* globalParams = wx_sqlite3mcGetCipherParams(codec->m_db, CIPHER_NAME_GLOBAL); if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_freeCipher(codec->m_writeCipher); } codec->m_isEncrypted = 1; codec->m_hmacCheck = wx_sqlite3mcGetCipherParameter(globalParams, "hmac_check"); codec->m_walLegacy = wx_sqlite3mcGetCipherParameter(globalParams, "mc_legacy_wal"); codec->m_hasWriteCipher = 1; codec->m_writeCipherType = cipherType; - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType-1].m_allocateCipher(codec->m_db); if (codec->m_writeCipher != NULL) { unsigned char* keySalt = (codec->m_hasKeySalt != 0) ? codec->m_keySalt : NULL; @@ -263539,57 +263720,57 @@ wx_sqlite3mcGetPageBuffer(Codec* codec) SQLITE_PRIVATE int wx_sqlite3mcGetLegacyReadCipher(Codec* codec) { - int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getLegacy(codec->m_readCipher) : 0; + int legacy = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType - 1].m_getLegacy(codec->m_readCipher) : 0; return legacy; } SQLITE_PRIVATE int wx_sqlite3mcGetLegacyWriteCipher(Codec* codec) { - int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getLegacy(codec->m_writeCipher) : -1; + int legacy = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getLegacy(codec->m_writeCipher) : -1; return legacy; } SQLITE_PRIVATE int wx_sqlite3mcGetPageSizeReadCipher(Codec* codec) { - int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType - 1]->m_getPageSize(codec->m_readCipher) : 0; + int pageSize = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType - 1].m_getPageSize(codec->m_readCipher) : 0; return pageSize; } SQLITE_PRIVATE int wx_sqlite3mcGetPageSizeWriteCipher(Codec* codec) { - int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getPageSize(codec->m_writeCipher) : -1; + int pageSize = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getPageSize(codec->m_writeCipher) : -1; return pageSize; } SQLITE_PRIVATE int wx_sqlite3mcGetReservedReadCipher(Codec* codec) { - int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1; + int reserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1; return reserved; } SQLITE_PRIVATE int wx_sqlite3mcGetReservedWriteCipher(Codec* codec) { - int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1; + int reserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1; return reserved; } SQLITE_PRIVATE int wx_sqlite3mcReservedEqual(Codec* codec) { - int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? codecDescriptorTable[codec->m_readCipherType-1]->m_getReserved(codec->m_readCipher) : -1; - int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType-1]->m_getReserved(codec->m_writeCipher) : -1; + int readReserved = (codec->m_hasReadCipher && codec->m_readCipher != NULL) ? globalCodecDescriptorTable[codec->m_readCipherType-1].m_getReserved(codec->m_readCipher) : -1; + int writeReserved = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType-1].m_getReserved(codec->m_writeCipher) : -1; return (readReserved == writeReserved); } SQLITE_PRIVATE unsigned char* wx_sqlite3mcGetSaltWriteCipher(Codec* codec) { - unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? codecDescriptorTable[codec->m_writeCipherType - 1]->m_getSalt(codec->m_writeCipher) : NULL; + unsigned char* salt = (codec->m_hasWriteCipher && codec->m_writeCipher != NULL) ? globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_getSalt(codec->m_writeCipher) : NULL; return salt; } @@ -263611,10 +263792,10 @@ wx_sqlite3mcCodecCopy(Codec* codec, Codec* other) if (codec->m_hasReadCipher) { - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType - 1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType - 1].m_allocateCipher(codec->m_db); if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType - 1]->m_cloneCipher(codec->m_readCipher, other->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType - 1].m_cloneCipher(codec->m_readCipher, other->m_readCipher); } else { @@ -263624,10 +263805,10 @@ wx_sqlite3mcCodecCopy(Codec* codec, Codec* other) if (codec->m_hasWriteCipher) { - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType - 1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_allocateCipher(codec->m_db); if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType - 1]->m_cloneCipher(codec->m_writeCipher, other->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType - 1].m_cloneCipher(codec->m_writeCipher, other->m_writeCipher); } else { @@ -263650,17 +263831,17 @@ wx_sqlite3mcCopyCipher(Codec* codec, int read2write) { if (codec->m_writeCipher != NULL && codec->m_writeCipherType != codec->m_readCipherType) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_freeCipher(codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_freeCipher(codec->m_writeCipher); codec->m_writeCipher = NULL; } if (codec->m_writeCipher == NULL) { codec->m_writeCipherType = codec->m_readCipherType; - codec->m_writeCipher = codecDescriptorTable[codec->m_writeCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_writeCipher = globalCodecDescriptorTable[codec->m_writeCipherType-1].m_allocateCipher(codec->m_db); } if (codec->m_writeCipher != NULL) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_cloneCipher(codec->m_writeCipher, codec->m_readCipher); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_cloneCipher(codec->m_writeCipher, codec->m_readCipher); } else { @@ -263671,17 +263852,17 @@ wx_sqlite3mcCopyCipher(Codec* codec, int read2write) { if (codec->m_readCipher != NULL && codec->m_readCipherType != codec->m_writeCipherType) { - codecDescriptorTable[codec->m_readCipherType-1]->m_freeCipher(codec->m_readCipher); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_freeCipher(codec->m_readCipher); codec->m_readCipher = NULL; } if (codec->m_readCipher == NULL) { codec->m_readCipherType = codec->m_writeCipherType; - codec->m_readCipher = codecDescriptorTable[codec->m_readCipherType-1]->m_allocateCipher(codec->m_db); + codec->m_readCipher = globalCodecDescriptorTable[codec->m_readCipherType-1].m_allocateCipher(codec->m_db); } if (codec->m_readCipher != NULL) { - codecDescriptorTable[codec->m_readCipherType-1]->m_cloneCipher(codec->m_readCipher, codec->m_writeCipher); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_cloneCipher(codec->m_readCipher, codec->m_writeCipher); } else { @@ -263712,13 +263893,13 @@ wx_sqlite3mcPadPassword(char* password, int pswdlen, unsigned char pswd[32]) SQLITE_PRIVATE void wx_sqlite3mcGenerateReadKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - codecDescriptorTable[codec->m_readCipherType-1]->m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt); + globalCodecDescriptorTable[codec->m_readCipherType-1].m_generateKey(codec->m_readCipher, codec->m_btShared, userPassword, passwordLength, 0, cipherSalt); } SQLITE_PRIVATE void wx_sqlite3mcGenerateWriteKey(Codec* codec, char* userPassword, int passwordLength, unsigned char* cipherSalt) { - codecDescriptorTable[codec->m_writeCipherType-1]->m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt); + globalCodecDescriptorTable[codec->m_writeCipherType-1].m_generateKey(codec->m_writeCipher, codec->m_btShared, userPassword, passwordLength, 1, cipherSalt); } SQLITE_PRIVATE int @@ -263728,7 +263909,7 @@ wx_sqlite3mcEncrypt(Codec* codec, int page, unsigned char* data, int len, int us void* cipher = (useWriteKey) ? codec->m_writeCipher : codec->m_readCipher; int reserved = (useWriteKey) ? (codec->m_writeReserved >= 0) ? codec->m_writeReserved : codec->m_reserved : (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved; - return codecDescriptorTable[cipherType-1]->m_encryptPage(cipher, page, data, len, reserved); + return globalCodecDescriptorTable[cipherType-1].m_encryptPage(cipher, page, data, len, reserved); } SQLITE_PRIVATE int @@ -263737,7 +263918,7 @@ wx_sqlite3mcDecrypt(Codec* codec, int page, unsigned char* data, int len) int cipherType = codec->m_readCipherType; void* cipher = codec->m_readCipher; int reserved = (codec->m_readReserved >= 0) ? codec->m_readReserved : codec->m_reserved; - return codecDescriptorTable[cipherType-1]->m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck); + return globalCodecDescriptorTable[cipherType-1].m_decryptPage(cipher, page, data, len, reserved, codec->m_hmacCheck); } #if HAVE_CIPHER_SQLCIPHER @@ -263820,6 +264001,8 @@ SQLITE_PRIVATE int wx_sqlite3mcHandleMainKey(wx_sqlite3* db, const char* zPath); /* --- Codec --- */ +SQLITE_PRIVATE int +wx_sqlite3mcGetGlobalCipherCount(); SQLITE_PRIVATE Codec* wx_sqlite3mcGetCodec(wx_sqlite3* db, const char* zDbName); @@ -263888,28 +264071,30 @@ wx_sqlite3mc_config(wx_sqlite3* db, const char* paramName, int newValue) } param = codecParams[0].m_params; - for (; strlen(param->m_name) > 0; ++param) + for (; param->m_name[0] != 0; ++param) { if (wx_sqlite3_stricmp(paramName, param->m_name) == 0) break; } - if (strlen(param->m_name) > 0) + if (param->m_name[0] != 0) { + int cipherCount = wx_sqlite3mcGetGlobalCipherCount(); if (db != NULL) { wx_sqlite3_mutex_enter(db->mutex); } else { - wx_sqlite3_mutex_enter(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + wx_sqlite3_mutex_enter(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); } value = (hasDefaultPrefix) ? param->m_default : (hasMinPrefix) ? param->m_minValue : (hasMaxPrefix) ? param->m_maxValue : param->m_value; if (!hasMinPrefix && !hasMaxPrefix && newValue >= 0 && newValue >= param->m_minValue && newValue <= param->m_maxValue) { int allowChange = 1; + /* Allow cipher change only if new cipher is actually available */ if (wx_sqlite3_stricmp(paramName, "cipher") == 0) { - allowChange = (codecDescriptorTable[newValue - 1] != &mcDummyDescriptor); + allowChange = newValue > 0 && newValue <= cipherCount; } if (allowChange) @@ -263929,12 +264114,52 @@ wx_sqlite3mc_config(wx_sqlite3* db, const char* paramName, int newValue) } else { - wx_sqlite3_mutex_leave(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); + wx_sqlite3_mutex_leave(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); } } return value; } +SQLITE_API int +wx_sqlite3mc_cipher_count() +{ + return wx_sqlite3mcGetGlobalCipherCount(); +} + +SQLITE_API int +wx_sqlite3mc_cipher_index(const char* cipherName) +{ + int count = wx_sqlite3mcGetGlobalCipherCount(); + int j = 0; + for (j = 0; j < count && globalCodecDescriptorTable[j].m_name[0] != 0; ++j) + { + if (wx_sqlite3_stricmp(cipherName, globalCodecDescriptorTable[j].m_name) == 0) break; + } + return (j < count && globalCodecDescriptorTable[j].m_name[0] != 0) ? j + 1 : -1; +} + +SQLITE_API const char* +wx_sqlite3mc_cipher_name(int cipherIndex) +{ + static char cipherName[CIPHER_NAME_MAXLEN] = ""; + int count = wx_sqlite3mcGetGlobalCipherCount(); + int j = 0; + cipherName[0] = '\0'; + if (cipherIndex > 0 && cipherIndex <= count) + { + for (j = 0; j < count && globalCodecDescriptorTable[j].m_name[0] != 0; ++j) + { + if (cipherIndex == j + 1) break; + } + if (j < count && globalCodecDescriptorTable[j].m_name[0] != 0) + { + strncpy(cipherName, globalCodecDescriptorTable[j].m_name, CIPHER_NAME_MAXLEN - 1); + cipherName[CIPHER_NAME_MAXLEN - 1] = '\0'; + } + } + return cipherName; +} + SQLITE_API int wx_sqlite3mc_config_cipher(wx_sqlite3* db, const char* cipherName, const char* paramName, int newValue) { @@ -263966,11 +264191,11 @@ wx_sqlite3mc_config_cipher(wx_sqlite3* db, const char* cipherName, const char* p return value; } - for (j = 0; strlen(codecParams[j].m_name) > 0; ++j) + for (j = 0; codecParams[j].m_name[0] != 0; ++j) { if (wx_sqlite3_stricmp(cipherName, codecParams[j].m_name) == 0) break; } - if (strlen(codecParams[j].m_name) > 0) + if (codecParams[j].m_name[0] != 0) { cipherParamTable = codecParams[j].m_params; } @@ -264020,11 +264245,11 @@ wx_sqlite3mc_config_cipher(wx_sqlite3* db, const char* cipherName, const char* p } #endif - for (; strlen(param->m_name) > 0; ++param) + for (; param->m_name[0] != 0; ++param) { if (wx_sqlite3_stricmp(paramName, param->m_name) == 0) break; } - if (strlen(param->m_name) > 0) + if (param->m_name[0] != 0) { if (db != NULL) { @@ -264200,11 +264425,11 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value param1 = codecParams[0].m_params; cipherParamTable = NULL; - for (; strlen(param1->m_name) > 0; ++param1) + for (; param1->m_name[0] != 0; ++param1) { if (wx_sqlite3_stricmp(nameParam1, param1->m_name) == 0) break; } - isCommonParam1 = strlen(param1->m_name) > 0; + isCommonParam1 = param1->m_name[0] != 0; /* Check first argument whether it is a cipher name, if it wasn't a common parameter */ /* If the first argument is a cipher name, cipherParamTable will point to the corresponding cipher parameter table */ @@ -264213,11 +264438,11 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value if (!hasDefaultPrefix && !hasMinPrefix && !hasMaxPrefix) { int j = 0; - for (j = 0; strlen(codecParams[j].m_name) > 0; ++j) + for (j = 0; codecParams[j].m_name[0] != 0; ++j) { if (wx_sqlite3_stricmp(nameParam1, codecParams[j].m_name) == 0) break; } - isCipherParam1 = strlen(codecParams[j].m_name) > 0; + isCipherParam1 = codecParams[j].m_name[0] != 0; if (isCipherParam1) { cipherParamTable = codecParams[j].m_params; @@ -264239,7 +264464,7 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value int value = (hasDefaultPrefix) ? param1->m_default : (hasMinPrefix) ? param1->m_minValue : (hasMaxPrefix) ? param1->m_maxValue : param1->m_value; if (wx_sqlite3_stricmp(nameParam1, "cipher") == 0) { - wx_sqlite3_result_text(context, codecDescriptorTable[value - 1]->m_name, -1, SQLITE_STATIC); + wx_sqlite3_result_text(context, globalCodecDescriptorTable[value - 1].m_name, -1, SQLITE_STATIC); } else { @@ -264252,7 +264477,7 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value int nParams = 0; int lenTotal = 0; int j; - for (j = 0; strlen(cipherParamTable[j].m_name) > 0; ++j) + for (j = 0; cipherParamTable[j].m_name[0] != 0; ++j) { ++nParams; lenTotal += (int) strlen(cipherParamTable[j].m_name); @@ -264298,18 +264523,18 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value { const char* nameCipher = (const char*)wx_sqlite3_value_text(argv[1]); int j = 0; - for (j = 0; strlen(codecDescriptorTable[j]->m_name) > 0; ++j) + for (j = 0; globalCodecDescriptorTable[j].m_name[0] != 0; ++j) { - if (wx_sqlite3_stricmp(nameCipher, codecDescriptorTable[j]->m_name) == 0) break; + if (wx_sqlite3_stricmp(nameCipher, globalCodecDescriptorTable[j].m_name) == 0) break; } - if (strlen(codecDescriptorTable[j]->m_name) > 0) + if (globalCodecDescriptorTable[j].m_name[0] != 0) { if (hasDefaultPrefix) { param1->m_default = j + 1; } param1->m_value = j + 1; - wx_sqlite3_result_text(context, codecDescriptorTable[j]->m_name, -1, SQLITE_STATIC); + wx_sqlite3_result_text(context, globalCodecDescriptorTable[j].m_name, -1, SQLITE_STATIC); } else { @@ -264371,7 +264596,7 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value hasMaxPrefix = 1; nameParam2 += 4; } - for (; strlen(param2->m_name) > 0; ++param2) + for (; param2->m_name[0] != 0; ++param2) { if (wx_sqlite3_stricmp(nameParam2, param2->m_name) == 0) break; } @@ -264394,7 +264619,7 @@ wx_sqlite3mcConfigParams(wx_sqlite3_context* context, int argc, wx_sqlite3_value } #endif - if (strlen(param2->m_name) > 0) + if (param2->m_name[0] != 0) { if (argc == 2) { @@ -264458,13 +264683,13 @@ wx_sqlite3mcConfigureFromUri(wx_sqlite3* db, const char *zDbName, int configDefa CipherParams* cipherParams = NULL; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (wx_sqlite3_stricmp(cipherName, globalCodecParameterTable[j].m_name) == 0) break; } /* j is the index of the cipher name, if found */ - cipherParams = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_params : NULL; + cipherParams = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_params : NULL; if (cipherParams != NULL) { /* @@ -264504,7 +264729,7 @@ wx_sqlite3mcConfigureFromUri(wx_sqlite3* db, const char *zDbName, int configDefa #endif /* Check all cipher specific parameters */ - for (j = 0; strlen(cipherParams[j].m_name) > 0; ++j) + for (j = 0; cipherParams[j].m_name[0] != 0; ++j) { if (skipLegacy && wx_sqlite3_stricmp(cipherParams[j].m_name, "legacy") == 0) continue; @@ -264581,15 +264806,15 @@ wx_sqlite3mcFileControlPragma(wx_sqlite3* db, const char* zDbName, int op, void* { int j = 1; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (wx_sqlite3_stricmp(pragmaValue, globalCodecParameterTable[j].m_name) == 0) break; } - cipherId = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_id : CODEC_TYPE_UNKNOWN; + cipherId = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_id : CODEC_TYPE_UNKNOWN; } /* cipherId is the numeric id of the cipher name, if found */ - if ((cipherId == -1) || (cipherId > 0 && cipherId <= CODEC_TYPE_MAX)) + if ((cipherId == -1) || (cipherId > 0 && cipherId <= CODEC_COUNT_MAX)) { int value; if (configDefault) @@ -264601,7 +264826,7 @@ wx_sqlite3mcFileControlPragma(wx_sqlite3* db, const char* zDbName, int op, void* value = wx_sqlite3mc_config(db, "cipher", cipherId); } rc = SQLITE_OK; - ((char**)pArg)[0] = wx_sqlite3_mprintf("%s", codecDescriptorTable[value - 1]->m_name); + ((char**)pArg)[0] = wx_sqlite3_mprintf("%s", globalCodecDescriptorTable[value - 1].m_name); } else { @@ -264645,10 +264870,10 @@ wx_sqlite3mcFileControlPragma(wx_sqlite3* db, const char* zDbName, int op, void* else if (wx_sqlite3StrICmp(pragmaName, "hexkey") == 0) { int nValue = wx_sqlite3Strlen30(pragmaValue); - if (((nValue & 1) == 0) && (wx_sqlite3mcIsHexKey(pragmaValue, nValue) != 0)) + if (((nValue & 1) == 0) && (wx_sqlite3mcIsHexKey((const unsigned char*) pragmaValue, nValue) != 0)) { - char* zHexKey = wx_sqlite3_malloc(nValue/2); - wx_sqlite3mcConvertHex2Bin(pragmaValue, nValue, zHexKey); + unsigned char* zHexKey = wx_sqlite3_malloc(nValue/2); + wx_sqlite3mcConvertHex2Bin((const unsigned char*) pragmaValue, nValue, zHexKey); rc = wx_sqlite3_key_v2(db, zDbName, zHexKey, nValue/2); wx_sqlite3_free(zHexKey); if (rc == SQLITE_OK) @@ -264695,10 +264920,10 @@ wx_sqlite3mcFileControlPragma(wx_sqlite3* db, const char* zDbName, int op, void* else if (wx_sqlite3StrICmp(pragmaName, "hexrekey") == 0) { int nValue = wx_sqlite3Strlen30(pragmaValue); - if (((nValue & 1) == 0) && (wx_sqlite3mcIsHexKey(pragmaValue, nValue) != 0)) + if (((nValue & 1) == 0) && (wx_sqlite3mcIsHexKey((const unsigned char*) pragmaValue, nValue) != 0)) { - char* zHexKey = wx_sqlite3_malloc(nValue/2); - wx_sqlite3mcConvertHex2Bin(pragmaValue, nValue, zHexKey); + unsigned char* zHexKey = wx_sqlite3_malloc(nValue/2); + wx_sqlite3mcConvertHex2Bin((const unsigned char*) pragmaValue, nValue, zHexKey); rc = wx_sqlite3_rekey_v2(db, zDbName, zHexKey, nValue/2); wx_sqlite3_free(zHexKey); if (rc == SQLITE_OK) @@ -264734,21 +264959,21 @@ wx_sqlite3mcFileControlPragma(wx_sqlite3* db, const char* zDbName, int op, void* CipherParams* cipherParams = NULL; /* Try to locate the cipher name */ - for (j = 1; strlen(globalCodecParameterTable[j].m_name) > 0; ++j) + for (j = 1; globalCodecParameterTable[j].m_name[0] != 0; ++j) { if (cipher == globalCodecParameterTable[j].m_id) break; } /* j is the index of the cipher name, if found */ - cipherParams = (strlen(globalCodecParameterTable[j].m_name) > 0) ? globalCodecParameterTable[j].m_params : NULL; + cipherParams = (globalCodecParameterTable[j].m_name[0] != 0) ? globalCodecParameterTable[j].m_params : NULL; if (cipherParams != NULL) { const char* cipherName = globalCodecParameterTable[j].m_name; - for (j = 0; strlen(cipherParams[j].m_name) > 0; ++j) + for (j = 0; cipherParams[j].m_name[0] != 0; ++j) { if (wx_sqlite3_stricmp(pragmaName, cipherParams[j].m_name) == 0) break; } - if (strlen(cipherParams[j].m_name) > 0) + if (cipherParams[j].m_name[0] != 0) { char* param = (configDefault) ? wx_sqlite3_mprintf("default:%s", pragmaName) : pragmaName; if (isIntValue) @@ -264949,7 +265174,7 @@ wx_sqlite3mcBtreeSetPageSize(Btree* p, int pageSize, int nReserve, int iFix) ** Change 4: Call wx_sqlite3mcBtreeSetPageSize instead of wx_sqlite3BtreeSetPageSize for main database ** (wx_sqlite3mcBtreeSetPageSize allows to reduce the number of reserved bytes) ** -** This code is generated by the script rekeyvacuum.sh from SQLite version 3.39.2 amalgamation. +** This code is generated by the script rekeyvacuum.sh from SQLite version 3.39.4 amalgamation. */ SQLITE_PRIVATE SQLITE_NOINLINE int wx_sqlite3mcRunVacuumForRekey( char **pzErrMsg, /* Write error message here */ @@ -265626,6 +265851,10 @@ wx_sqlite3_rekey_v2(wx_sqlite3* db, const char* zDbName, const void* zKey, int n wx_sqlite3mcSetReadReserved(codec, nReserved); wx_sqlite3mcSetWriteReserved(codec, nReservedWriteCipher); rc = wx_sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, nReservedWriteCipher); + if (rc != SQLITE_OK && err != NULL) + { + wx_sqlite3ErrorWithMsg(db, rc, err); + } goto leave_rekey; } } @@ -265654,6 +265883,10 @@ wx_sqlite3_rekey_v2(wx_sqlite3* db, const char* zDbName, const void* zKey, int n wx_sqlite3mcSetReadReserved(codec, nReserved); wx_sqlite3mcSetWriteReserved(codec, 0); rc = wx_sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, 0); + if (rc != SQLITE_OK && err != NULL) + { + wx_sqlite3ErrorWithMsg(db, rc, err); + } goto leave_rekey; } } @@ -265675,6 +265908,10 @@ wx_sqlite3_rekey_v2(wx_sqlite3* db, const char* zDbName, const void* zKey, int n wx_sqlite3mcSetReadReserved(codec, nReserved); wx_sqlite3mcSetWriteReserved(codec, nReservedWriteCipher); rc = wx_sqlite3mcRunVacuumForRekey(&err, db, dbIndex, NULL, nReservedWriteCipher); + if (rc != SQLITE_OK && err != NULL) + { + wx_sqlite3ErrorWithMsg(db, rc, err); + } goto leave_rekey; } } @@ -288758,16 +288995,262 @@ wx_sqlite3_extfunc_init(wx_sqlite3 *db, char **pzErrMsg, const wx_sqlite3_api_ro } #endif +static int +mcCheckValidName(char* name) +{ + size_t nl; + if (!name) + return SQLITE_ERROR; + + /* Check for valid cipher name length */ + nl = strlen(name); + if (nl < 1 || nl >= CIPHER_NAME_MAXLEN) + return SQLITE_ERROR; + + /* Check for already registered names */ + CipherName* cipherNameTable = &globalCipherNameTable[0]; + for (; cipherNameTable->m_name[0] != 0; ++cipherNameTable) + { + if (wx_sqlite3_stricmp(name, cipherNameTable->m_name) == 0) break; + } + if (cipherNameTable->m_name[0] != 0) + return SQLITE_ERROR; + + /* Check for valid character set (1st char = alpha, rest = alpha-numeric or underscore) */ + if (wx_sqlite3Isalpha(name[0])) + { + size_t j; + for (j = 1; j < nl && (name[j] == '_' || wx_sqlite3Isalnum(name[j])); ++j) {} + if (j == nl) + return SQLITE_OK; + } + return SQLITE_ERROR; +} + +SQLITE_PRIVATE int +wx_sqlite3mcGetGlobalCipherCount() +{ + int cipherCount = 0; + wx_sqlite3_mutex_enter(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + cipherCount = globalCipherCount; + wx_sqlite3_mutex_leave(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + return cipherCount; +} + +static int +wx_sqlite3mcRegisterCipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault) +{ + int rc; + int np; + CipherParams* cipherParams; + + /* Sanity checks */ + + /* Cipher description AND parameter are required */ + if (!desc || !params) + return SQLITE_ERROR; + + /* ALL methods of the cipher descriptor need to be defined */ + if (!desc->m_name || + !desc->m_allocateCipher || + !desc->m_freeCipher || + !desc->m_cloneCipher || + !desc->m_getLegacy || + !desc->m_getPageSize || + !desc->m_getReserved || + !desc->m_getSalt || + !desc->m_generateKey || + !desc->m_encryptPage || + !desc->m_decryptPage) + return SQLITE_ERROR; + + /* Check for valid cipher name */ + if (mcCheckValidName(desc->m_name) != SQLITE_OK) + return SQLITE_ERROR; + + /* Check cipher parameters */ + for (np = 0; np < CIPHER_PARAMS_COUNT_MAX; ++np) + { + CipherParams entry = params[np]; + /* Check for sentinel parameter */ + if (entry.m_name == 0 || entry.m_name[0] == 0) + break; + /* Check for valid parameter name */ + if (mcCheckValidName(entry.m_name) != SQLITE_OK) + return SQLITE_ERROR; + /* Check for valid parameter specification */ + if (!(entry.m_minValue >= 0 && entry.m_maxValue >= 0 && entry.m_minValue <= entry.m_maxValue && + entry.m_value >= entry.m_minValue && entry.m_value <= entry.m_maxValue && + entry.m_default >= entry.m_minValue && entry.m_default <= entry.m_maxValue)) + return SQLITE_ERROR; + } + + /* Check for parameter count in valid range and valid sentinel parameter */ + if (np >= CIPHER_PARAMS_COUNT_MAX || params[np].m_name == 0) + return SQLITE_ERROR; + + /* Sanity checks were successful, now register cipher */ + + cipherParams = (CipherParams*) wx_sqlite3_malloc((np+1) * sizeof(CipherParams)); + if (!cipherParams) + return SQLITE_NOMEM; + + wx_sqlite3_mutex_enter(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + + /* Check for */ + if (globalCipherCount < CODEC_COUNT_MAX) + { + int n; + char* cipherName; + ++globalCipherCount; + cipherName = globalCipherNameTable[globalCipherCount].m_name; + strcpy(cipherName, desc->m_name); + + globalCodecDescriptorTable[globalCipherCount - 1] = *desc; + globalCodecDescriptorTable[globalCipherCount - 1].m_name = cipherName; + + globalCodecParameterTable[globalCipherCount].m_name = cipherName; + globalCodecParameterTable[globalCipherCount].m_id = globalCipherCount; + globalCodecParameterTable[globalCipherCount].m_params = cipherParams; + + /* Copy parameters */ + for (n = 0; n < np; ++n) + { + cipherParams[n] = params[n]; + cipherParams[n].m_name = (char*) wx_sqlite3_malloc(strlen(params[n].m_name) + 1); + strcpy(cipherParams[n].m_name, params[n].m_name); + } + /* Add sentinel */ + cipherParams[n] = params[n]; + cipherParams[n].m_name = globalSentinelName; + + /* Make cipher default, if requested */ + if (makeDefault) + { + CipherParams* param = globalCodecParameterTable[0].m_params; + for (; param->m_name[0] != 0; ++param) + { + if (wx_sqlite3_stricmp("cipher", param->m_name) == 0) break; + } + if (param->m_name[0] != 0) + { + param->m_value = param->m_default = globalCipherCount; + } + } + + rc = SQLITE_OK; + } + else + { + rc = SQLITE_NOMEM; + } + + wx_sqlite3_mutex_leave(wx_sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN)); + + return rc; +} + +SQLITE_API int +wx_sqlite3mc_register_cipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault) +{ + int rc; +#ifndef SQLITE_OMIT_AUTOINIT + rc = wx_sqlite3_initialize(); + if (rc) return rc; +#endif + return wx_sqlite3mcRegisterCipher(desc, params, makeDefault); +} + +SQLITE_PRIVATE int +wx_sqlite3mcInitCipherTables() +{ + size_t n; + + /* Initialize cipher name table */ + strcpy(globalCipherNameTable[0].m_name, "global"); + for (n = 1; n < CODEC_COUNT_MAX + 2; ++n) + { + strcpy(globalCipherNameTable[n].m_name, ""); + } + + /* Initialize cipher descriptor table */ + for (n = 0; n < CODEC_COUNT_MAX + 1; ++n) + { + globalCodecDescriptorTable[n] = mcSentinelDescriptor; + } + + /* Initialize cipher parameter table */ + globalCodecParameterTable[0] = globalCommonParams; + for (n = 1; n < CODEC_COUNT_MAX + 2; ++n) + { + globalCodecParameterTable[n] = globalSentinelParams; + } + + return SQLITE_OK; +} + +SQLITE_PRIVATE void +wx_sqlite3mcTermCipherTables() +{ + size_t n; + for (n = CODEC_COUNT_MAX+1; n > 0; --n) + { + if (globalCodecParameterTable[n].m_name[0] != 0) + { + int k; + CipherParams* params = globalCodecParameterTable[n].m_params; + for (k = 0; params[k].m_name[0] != 0; ++k) + { + wx_sqlite3_free(params[k].m_name); + } + wx_sqlite3_free(globalCodecParameterTable[n].m_params); + } + } +} + int wx_sqlite3mc_initialize(const char* arg) { - int rc = SQLITE_OK; + int rc = wx_sqlite3mcInitCipherTables(); +#if HAVE_CIPHER_AES_128_CBC + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mcRegisterCipher(&mcAES128Descriptor, mcAES128Params, (CODEC_TYPE_AES128 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_AES_256_CBC + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mcRegisterCipher(&mcAES256Descriptor, mcAES256Params, (CODEC_TYPE_AES256 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_CHACHA20 + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mcRegisterCipher(&mcChaCha20Descriptor, mcChaCha20Params, (CODEC_TYPE_CHACHA20 == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_SQLCIPHER + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mcRegisterCipher(&mcSQLCipherDescriptor, mcSQLCipherParams, (CODEC_TYPE_SQLCIPHER == CODEC_TYPE)); + } +#endif +#if HAVE_CIPHER_RC4 + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mcRegisterCipher(&mcRC4Descriptor, mcRC4Params, (CODEC_TYPE_RC4 == CODEC_TYPE)); + } +#endif /* ** Initialize and register MultiCipher VFS as default VFS ** if it isn't already registered */ - rc = wx_sqlite3mc_vfs_create(NULL, 1); + if (rc == SQLITE_OK) + { + rc = wx_sqlite3mc_vfs_create(NULL, 1); + } /* ** Register Multi Cipher extension @@ -288855,6 +289338,7 @@ void wx_sqlite3mc_shutdown(void) { wx_sqlite3mc_vfs_shutdown(); + wx_sqlite3mcTermCipherTables(); } /* diff --git a/Plugins/DbSqliteWx/wxsqlite3.h b/Plugins/DbSqliteWx/wxsqlite3.h index e40dfe06d2..be295b448a 100644 --- a/Plugins/DbSqliteWx/wxsqlite3.h +++ b/Plugins/DbSqliteWx/wxsqlite3.h @@ -3,7 +3,7 @@ ** Purpose: Header file for SQLite3 Multiple Ciphers support ** Author: Ulrich Telle ** Created: 2020-03-01 -** Copyright: (c) 2019-2021 Ulrich Telle +** Copyright: (c) 2019-2022 Ulrich Telle ** License: MIT */ @@ -30,10 +30,10 @@ #define SQLITE3MC_VERSION_H_ #define SQLITE3MC_VERSION_MAJOR 1 -#define SQLITE3MC_VERSION_MINOR 4 -#define SQLITE3MC_VERSION_RELEASE 8 +#define SQLITE3MC_VERSION_MINOR 5 +#define SQLITE3MC_VERSION_RELEASE 3 #define SQLITE3MC_VERSION_SUBRELEASE 0 -#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.4.8" +#define SQLITE3MC_VERSION_STRING "SQLite3 Multiple Ciphers 1.5.3" #endif /* SQLITE3MC_VERSION_H_ */ /*** End of #include "wx_sqlite3mc_version.h" ***/ @@ -192,9 +192,9 @@ extern "C" { ** [wx_sqlite3_libversion_number()], [wx_sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.39.2" -#define SQLITE_VERSION_NUMBER 3039002 -#define SQLITE_SOURCE_ID "2022-07-21 15:24:47 698edb77537b67c41adc68f9b892db56bcf9a55e00371a61420f3ddd668e6603" +#define SQLITE_VERSION "3.39.4" +#define SQLITE_VERSION_NUMBER 3039004 +#define SQLITE_SOURCE_ID "2022-09-29 15:55:41 a29f9949895322123f7c38fbe94c649a9d6e6c9cd0c3b41c96d694552f26b309" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -12989,13 +12989,13 @@ int wx_sqlite3_user_delete( /* ** Symbols for ciphers */ -#define CODEC_TYPE_UNKNOWN 0 -#define CODEC_TYPE_AES128 1 -#define CODEC_TYPE_AES256 2 -#define CODEC_TYPE_CHACHA20 3 -#define CODEC_TYPE_SQLCIPHER 4 -#define CODEC_TYPE_RC4 5 -#define CODEC_TYPE_MAX 5 +#define CODEC_TYPE_UNKNOWN 0 +#define CODEC_TYPE_AES128 1 +#define CODEC_TYPE_AES256 2 +#define CODEC_TYPE_CHACHA20 3 +#define CODEC_TYPE_SQLCIPHER 4 +#define CODEC_TYPE_RC4 5 +#define CODEC_TYPE_MAX_BUILTIN 5 /* ** Definition of API functions @@ -13064,6 +13064,9 @@ SQLITE_API void wx_sqlite3_activate_see(const char* zPassPhrase); /* ** Define functions for the configuration of the wxSQLite3 encryption extension */ +SQLITE_API int wx_sqlite3mc_cipher_count(); +SQLITE_API int wx_sqlite3mc_cipher_index(const char* cipherName); +SQLITE_API const char* wx_sqlite3mc_cipher_name(int cipherIndex); SQLITE_API int wx_sqlite3mc_config(wx_sqlite3* db, const char* paramName, int newValue); SQLITE_API int wx_sqlite3mc_config_cipher(wx_sqlite3* db, const char* cipherName, const char* paramName, int newValue); SQLITE_API unsigned char* wx_sqlite3mc_codec_data(wx_sqlite3* db, const char* zDbName, const char* paramName); @@ -13075,6 +13078,88 @@ SQLITE_API int wxwx_sqlite3_config_cipher(wx_sqlite3* db, const char* cipherName SQLITE_API unsigned char* wxwx_sqlite3_codec_data(wx_sqlite3* db, const char* zDbName, const char* paramName); #endif +/* +** Structures and functions to dynamically register a cipher +*/ + +/* +** Structure for a single cipher configuration parameter +** +** Components: +** m_name - name of parameter (1st char = alpha, rest = alphanumeric or underscore, max 63 characters) +** m_value - current/transient parameter value +** m_default - default parameter value +** m_minValue - minimum valid parameter value +** m_maxValue - maximum valid parameter value +*/ +typedef struct _CipherParams +{ + char* m_name; + int m_value; + int m_default; + int m_minValue; + int m_maxValue; +} CipherParams; + +/* +** Structure for a cipher API +** +** Components: +** m_name - name of cipher (1st char = alpha, rest = alphanumeric or underscore, max 63 characters) +** m_allocateCipher - Function pointer for function AllocateCipher +** m_freeCipher - Function pointer for function FreeCipher +** m_cloneCipher - Function pointer for function CloneCipher +** m_getLegacy - Function pointer for function GetLegacy +** m_getPageSize - Function pointer for function GetPageSize +** m_getReserved - Function pointer for function GetReserved +** m_getSalt - Function pointer for function GetSalt +** m_generateKey - Function pointer for function GenerateKey +** m_encryptPage - Function pointer for function EncryptPage +** m_decryptPage - Function pointer for function DecryptPage +*/ + +typedef struct BtShared BtSharedMC; + +typedef void* (*AllocateCipher_t)(wx_sqlite3* db); +typedef void (*FreeCipher_t)(void* cipher); +typedef void (*CloneCipher_t)(void* cipherTo, void* cipherFrom); +typedef int (*GetLegacy_t)(void* cipher); +typedef int (*GetPageSize_t)(void* cipher); +typedef int (*GetReserved_t)(void* cipher); +typedef unsigned char* (*GetSalt_t)(void* cipher); +typedef void (*GenerateKey_t)(void* cipher, BtSharedMC* pBt, char* userPassword, int passwordLength, int rekey, unsigned char* cipherSalt); +typedef int (*EncryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved); +typedef int (*DecryptPage_t)(void* cipher, int page, unsigned char* data, int len, int reserved, int hmacCheck); + +typedef struct _CipherDescriptor +{ + char* m_name; + AllocateCipher_t m_allocateCipher; + FreeCipher_t m_freeCipher; + CloneCipher_t m_cloneCipher; + GetLegacy_t m_getLegacy; + GetPageSize_t m_getPageSize; + GetReserved_t m_getReserved; + GetSalt_t m_getSalt; + GenerateKey_t m_generateKey; + EncryptPage_t m_encryptPage; + DecryptPage_t m_decryptPage; +} CipherDescriptor; + +/* +** Register a cipher +** +** Arguments: +** desc - Cipher descriptor structure +** params - Cipher configuration parameter table +** makeDefault - flag whether to make the cipher the default cipher +** +** Returns: +** SQLITE_OK - the cipher could be registered successfully +** SQLITE_ERROR - the cipher could not be registered +*/ +SQLITE_API int wx_sqlite3mc_register_cipher(const CipherDescriptor* desc, const CipherParams* params, int makeDefault); + #ifdef __cplusplus } #endif