Skip to content

Commit e3bf59a

Browse files
authored
Update to SQLite 3.51.2 and SQLCipher 4.13.0 (#13)
1 parent 02649e1 commit e3bf59a

3 files changed

Lines changed: 115 additions & 68 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ jobs:
1717
sudo rm -rf /usr/share/dotnet /opt/ghc /opt/hostedtoolcache/CodeQL
1818
docker image prune --all --force
1919
docker builder prune -a
20-
- uses: actions/checkout@v4
20+
- uses: actions/checkout@v6
2121
- name: "Test Swift Package Android"
2222
uses: skiptools/swift-android-action@v2
2323
- name: "Test Swift Package Linux"
2424
run: swift test
2525
macos-ios:
2626
runs-on: macos-latest
2727
steps:
28-
- uses: actions/checkout@v4
28+
- uses: actions/checkout@v6
2929
- name: "Test Swift Package macOS"
3030
run: swift test
3131
- name: "Test Swift Package iOS"
@@ -37,6 +37,6 @@ jobs:
3737
with:
3838
branch: swift-6.2-release
3939
tag: 6.2-RELEASE
40-
- uses: actions/checkout@v4
40+
- uses: actions/checkout@v6
4141
- run: swift test
4242

Sources/SQLCipher/sqlite/sqlite3.c

Lines changed: 107 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
#pragma GCC diagnostic ignored "-Wambiguous-macro"
99
/******************************************************************************
1010
** This file is an amalgamation of many separate C source files from SQLite
11-
** version 3.51.1. By combining all the individual C code files into this
11+
** version 3.51.2. By combining all the individual C code files into this
1212
** single large file, the entire code can be compiled as a single translation
1313
** unit. This allows many compilers to do optimizations that would not be
1414
** possible if the files were compiled separately. Performance improvements
@@ -26,7 +26,7 @@
2626
** separate file. This file contains only code for the core SQLite library.
2727
**
2828
** The content in this amalgamation comes from Fossil check-in
29-
** 281fc0e9afc38674b9b0991943b9e9d1e64c with changes in files:
29+
** b270f8339eb13b504d0b2ba154ebca966b7d with changes in files:
3030
**
3131
** .fossil-settings/binary-glob
3232
** .fossil-settings/empty-dirs
@@ -504,12 +504,12 @@ extern "C" {
504504
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
505505
** [sqlite_version()] and [sqlite_source_id()].
506506
*/
507-
#define SQLITE_VERSION "3.51.1"
508-
#define SQLITE_VERSION_NUMBER 3051001
509-
#define SQLITE_SOURCE_ID "2025-11-28 17:28:25 281fc0e9afc38674b9b0991943b9e9d1e64c6cbdb133d35f6f5c87ff6af3alt1"
507+
#define SQLITE_VERSION "3.51.2"
508+
#define SQLITE_VERSION_NUMBER 3051002
509+
#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cbalt1"
510510
#define SQLITE_SCM_BRANCH "branch-3.51"
511-
#define SQLITE_SCM_TAGS "release version-3.51.1"
512-
#define SQLITE_SCM_DATETIME "2025-11-28T17:28:25.933Z"
511+
#define SQLITE_SCM_TAGS "release version-3.51.2"
512+
#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z"
513513

514514
/*
515515
** CAPI3REF: Run-Time Library Version Numbers
@@ -41367,12 +41367,18 @@ static int unixLock(sqlite3_file *id, int eFileLock){
4136741367
pInode->nLock++;
4136841368
pInode->nShared = 1;
4136941369
}
41370-
}else if( (eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1)
41371-
|| unixIsSharingShmNode(pFile)
41372-
){
41370+
}else if( eFileLock==EXCLUSIVE_LOCK && pInode->nShared>1 ){
4137341371
/* We are trying for an exclusive lock but another thread in this
4137441372
** same process is still holding a shared lock. */
4137541373
rc = SQLITE_BUSY;
41374+
}else if( unixIsSharingShmNode(pFile) ){
41375+
/* We are in WAL mode and attempting to delete the SHM and WAL
41376+
** files due to closing the connection or changing out of WAL mode,
41377+
** but another process still holds locks on the SHM file, thus
41378+
** indicating that database locks have been broken, perhaps due
41379+
** to a rogue close(open(dbFile)) or similar.
41380+
*/
41381+
rc = SQLITE_BUSY;
4137641382
}else{
4137741383
/* The request was for a RESERVED or EXCLUSIVE lock. It is
4137841384
** assumed that there is a SHARED or greater lock on the file
@@ -44011,26 +44017,21 @@ static int unixFcntlExternalReader(unixFile *pFile, int *piOut){
4401144017
** still not a disaster.
4401244018
*/
4401344019
static int unixIsSharingShmNode(unixFile *pFile){
44014-
int rc;
4401544020
unixShmNode *pShmNode;
44021+
struct flock lock;
4401644022
if( pFile->pShm==0 ) return 0;
4401744023
if( pFile->ctrlFlags & UNIXFILE_EXCL ) return 0;
4401844024
pShmNode = pFile->pShm->pShmNode;
44019-
rc = 1;
44020-
unixEnterMutex();
44021-
if( ALWAYS(pShmNode->nRef==1) ){
44022-
struct flock lock;
44023-
lock.l_whence = SEEK_SET;
44024-
lock.l_start = UNIX_SHM_DMS;
44025-
lock.l_len = 1;
44026-
lock.l_type = F_WRLCK;
44027-
osFcntl(pShmNode->hShm, F_GETLK, &lock);
44028-
if( lock.l_type==F_UNLCK ){
44029-
rc = 0;
44030-
}
44031-
}
44032-
unixLeaveMutex();
44033-
return rc;
44025+
#if SQLITE_ATOMIC_INTRINSICS
44026+
assert( AtomicLoad(&pShmNode->nRef)==1 );
44027+
#endif
44028+
memset(&lock, 0, sizeof(lock));
44029+
lock.l_whence = SEEK_SET;
44030+
lock.l_start = UNIX_SHM_DMS;
44031+
lock.l_len = 1;
44032+
lock.l_type = F_WRLCK;
44033+
osFcntl(pShmNode->hShm, F_GETLK, &lock);
44034+
return (lock.l_type!=F_UNLCK);
4403444035
}
4403544036

4403644037
/*
@@ -109502,7 +109503,7 @@ SQLITE_API void sqlite3pager_reset(Pager *pPager);
109502109503
#define CIPHER_STR(s) #s
109503109504

109504109505
#ifndef CIPHER_VERSION_NUMBER
109505-
#define CIPHER_VERSION_NUMBER 4.12.0
109506+
#define CIPHER_VERSION_NUMBER 4.13.0
109506109507
#endif
109507109508

109508109509
#ifndef CIPHER_VERSION_BUILD
@@ -109819,7 +109820,7 @@ static void (*const sqlcipher_fini_func)(void) __attribute__((used, section(".fi
109819109820
static void sqlcipher_exportFunc(sqlite3_context*, int, sqlite3_value**);
109820109821

109821109822
static int sqlcipher_export_init(sqlite3* db, const char** errmsg, const struct sqlite3_api_routines* api) {
109822-
sqlite3_create_function_v2(db, "sqlcipher_export", -1, SQLITE_TEXT, 0, sqlcipher_exportFunc, 0, 0, 0);
109823+
sqlite3_create_function_v2(db, "sqlcipher_export", -1, SQLITE_UTF8, 0, sqlcipher_exportFunc, 0, 0, 0);
109823109824
return SQLITE_OK;
109824109825
}
109825109826

@@ -120420,9 +120421,22 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
120420120421
pParse->nMem += nReg;
120421120422
if( pExpr->op==TK_SELECT ){
120422120423
dest.eDest = SRT_Mem;
120423-
dest.iSdst = dest.iSDParm;
120424+
if( (pSel->selFlags&SF_Distinct) && pSel->pLimit && pSel->pLimit->pRight ){
120425+
/* If there is both a DISTINCT and an OFFSET clause, then allocate
120426+
** a separate dest.iSdst array for sqlite3Select() and other
120427+
** routines to populate. In this case results will be copied over
120428+
** into the dest.iSDParm array only after OFFSET processing. This
120429+
** ensures that in the case where OFFSET excludes all rows, the
120430+
** dest.iSDParm array is not left populated with the contents of the
120431+
** last row visited - it should be all NULLs if all rows were
120432+
** excluded by OFFSET. */
120433+
dest.iSdst = pParse->nMem+1;
120434+
pParse->nMem += nReg;
120435+
}else{
120436+
dest.iSdst = dest.iSDParm;
120437+
}
120424120438
dest.nSdst = nReg;
120425-
sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, dest.iSDParm+nReg-1);
120439+
sqlite3VdbeAddOp3(v, OP_Null, 0, dest.iSDParm, pParse->nMem);
120426120440
VdbeComment((v, "Init subquery result"));
120427120441
}else{
120428120442
dest.eDest = SRT_Exists;
@@ -153441,9 +153455,14 @@ static void selectInnerLoop(
153441153455
assert( nResultCol<=pDest->nSdst );
153442153456
pushOntoSorter(
153443153457
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
153458+
pDest->iSDParm = regResult;
153444153459
}else{
153445153460
assert( nResultCol==pDest->nSdst );
153446-
assert( regResult==iParm );
153461+
if( regResult!=iParm ){
153462+
/* This occurs in cases where the SELECT had both a DISTINCT and
153463+
** an OFFSET clause. */
153464+
sqlite3VdbeAddOp3(v, OP_Copy, regResult, iParm, nResultCol-1);
153465+
}
153447153466
/* The LIMIT clause will jump out of the loop for us */
153448153467
}
153449153468
break;
@@ -159458,12 +159477,24 @@ static SQLITE_NOINLINE void existsToJoin(
159458159477
&& (pSub->selFlags & SF_Aggregate)==0
159459159478
&& !pSub->pSrc->a[0].fg.isSubquery
159460159479
&& pSub->pLimit==0
159480+
&& pSub->pPrior==0
159461159481
){
159482+
/* Before combining the sub-select with the parent, renumber the
159483+
** cursor used by the subselect. This is because the EXISTS expression
159484+
** might be a copy of another EXISTS expression from somewhere
159485+
** else in the tree, and in this case it is important that it use
159486+
** a unique cursor number. */
159487+
sqlite3 *db = pParse->db;
159488+
int *aCsrMap = sqlite3DbMallocZero(db, (pParse->nTab+2)*sizeof(int));
159489+
if( aCsrMap==0 ) return;
159490+
aCsrMap[0] = (pParse->nTab+1);
159491+
renumberCursors(pParse, pSub, -1, aCsrMap);
159492+
sqlite3DbFree(db, aCsrMap);
159493+
159462159494
memset(pWhere, 0, sizeof(*pWhere));
159463159495
pWhere->op = TK_INTEGER;
159464159496
pWhere->u.iValue = 1;
159465159497
ExprSetProperty(pWhere, EP_IntValue);
159466-
159467159498
assert( p->pWhere!=0 );
159468159499
pSub->pSrc->a[0].fg.fromExists = 1;
159469159500
pSub->pSrc->a[0].fg.jointype |= JT_CROSS;
@@ -179271,6 +179302,9 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
179271179302
sqlite3 *db = pParse->db;
179272179303
int iEnd = sqlite3VdbeCurrentAddr(v);
179273179304
int nRJ = 0;
179305+
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
179306+
int addrSeek = 0;
179307+
#endif
179274179308

179275179309
/* Generate loop termination code.
179276179310
*/
@@ -179283,7 +179317,10 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
179283179317
** the RIGHT JOIN table */
179284179318
WhereRightJoin *pRJ = pLevel->pRJ;
179285179319
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
179286-
pLevel->addrCont = 0;
179320+
/* Replace addrCont with a new label that will never be used, just so
179321+
** the subsequent call to resolve pLevel->addrCont will have something
179322+
** to resolve. */
179323+
pLevel->addrCont = sqlite3VdbeMakeLabel(pParse);
179287179324
pRJ->endSubrtn = sqlite3VdbeCurrentAddr(v);
179288179325
sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
179289179326
VdbeCoverage(v);
@@ -179292,7 +179329,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
179292179329
pLoop = pLevel->pWLoop;
179293179330
if( pLevel->op!=OP_Noop ){
179294179331
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
179295-
int addrSeek = 0;
179296179332
Index *pIdx;
179297179333
int n;
179298179334
if( pWInfo->eDistinct==WHERE_DISTINCT_ORDERED
@@ -179315,25 +179351,26 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
179315179351
sqlite3VdbeAddOp2(v, OP_Goto, 1, pLevel->p2);
179316179352
}
179317179353
#endif /* SQLITE_DISABLE_SKIPAHEAD_DISTINCT */
179318-
if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
179319-
/* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
179320-
** loop(s) will be the inner-most loops of the join. There might be
179321-
** multiple EXISTS loops, but they will all be nested, and the join
179322-
** order will not have been changed by the query planner. If the
179323-
** inner-most EXISTS loop sees a single successful row, it should
179324-
** break out of *all* EXISTS loops. But only the inner-most of the
179325-
** nested EXISTS loops should do this breakout. */
179326-
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
179327-
while( nOuter<i ){
179328-
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
179329-
nOuter++;
179330-
}
179331-
testcase( nOuter>0 );
179332-
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
179333-
VdbeComment((v, "EXISTS break"));
179334-
}
179335-
/* The common case: Advance to the next row */
179336-
if( pLevel->addrCont ) sqlite3VdbeResolveLabel(v, pLevel->addrCont);
179354+
}
179355+
if( pTabList->a[pLevel->iFrom].fg.fromExists && i==pWInfo->nLevel-1 ){
179356+
/* If the EXISTS-to-JOIN optimization was applied, then the EXISTS
179357+
** loop(s) will be the inner-most loops of the join. There might be
179358+
** multiple EXISTS loops, but they will all be nested, and the join
179359+
** order will not have been changed by the query planner. If the
179360+
** inner-most EXISTS loop sees a single successful row, it should
179361+
** break out of *all* EXISTS loops. But only the inner-most of the
179362+
** nested EXISTS loops should do this breakout. */
179363+
int nOuter = 0; /* Nr of outer EXISTS that this one is nested within */
179364+
while( nOuter<i ){
179365+
if( !pTabList->a[pLevel[-nOuter-1].iFrom].fg.fromExists ) break;
179366+
nOuter++;
179367+
}
179368+
testcase( nOuter>0 );
179369+
sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel[-nOuter].addrBrk);
179370+
VdbeComment((v, "EXISTS break"));
179371+
}
179372+
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
179373+
if( pLevel->op!=OP_Noop ){
179337179374
sqlite3VdbeAddOp3(v, pLevel->op, pLevel->p1, pLevel->p2, pLevel->p3);
179338179375
sqlite3VdbeChangeP5(v, pLevel->p5);
179339179376
VdbeCoverage(v);
@@ -179346,10 +179383,11 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
179346179383
VdbeCoverage(v);
179347179384
}
179348179385
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
179349-
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
179386+
if( addrSeek ){
179387+
sqlite3VdbeJumpHere(v, addrSeek);
179388+
addrSeek = 0;
179389+
}
179350179390
#endif
179351-
}else if( pLevel->addrCont ){
179352-
sqlite3VdbeResolveLabel(v, pLevel->addrCont);
179353179391
}
179354179392
if( (pLoop->wsFlags & WHERE_IN_ABLE)!=0 && pLevel->u.in.nIn>0 ){
179355179393
struct InLoop *pIn;
@@ -224765,7 +224803,7 @@ static void rtreenode(sqlite3_context *ctx, int nArg, sqlite3_value **apArg){
224765224803
if( node.zData==0 ) return;
224766224804
nData = sqlite3_value_bytes(apArg[1]);
224767224805
if( nData<4 ) return;
224768-
if( nData<NCELL(&node)*tree.nBytesPerCell ) return;
224806+
if( nData<4+NCELL(&node)*tree.nBytesPerCell ) return;
224769224807

224770224808
pOut = sqlite3_str_new(0);
224771224809
for(ii=0; ii<NCELL(&node); ii++){
@@ -243846,7 +243884,13 @@ typedef sqlite3_uint64 u64;
243846243884
# define FLEXARRAY 1
243847243885
#endif
243848243886

243849-
#endif
243887+
#endif /* SQLITE_AMALGAMATION */
243888+
243889+
/*
243890+
** Constants for the largest and smallest possible 32-bit signed integers.
243891+
*/
243892+
# define LARGEST_INT32 ((int)(0x7fffffff))
243893+
# define SMALLEST_INT32 ((int)((-1) - LARGEST_INT32))
243850243894

243851243895
/* Truncate very long tokens to this many bytes. Hard limit is
243852243896
** (65536-1-1-4-9)==65521 bytes. The limiting factor is the 16-bit offset
@@ -258409,7 +258453,7 @@ static int sqlite3Fts5IndexMerge(Fts5Index *p, int nMerge){
258409258453
fts5StructureRelease(pStruct);
258410258454
pStruct = pNew;
258411258455
nMin = 1;
258412-
nMerge = nMerge*-1;
258456+
nMerge = (nMerge==SMALLEST_INT32 ? LARGEST_INT32 : (nMerge*-1));
258413258457
}
258414258458
if( pStruct && pStruct->nLevel ){
258415258459
if( fts5IndexMerge(p, &pStruct, nMerge, nMin) ){
@@ -265616,7 +265660,7 @@ static void fts5SourceIdFunc(
265616265660
){
265617265661
assert( nArg==0 );
265618265662
UNUSED_PARAM2(nArg, apUnused);
265619-
sqlite3_result_text(pCtx, "fts5: 2025-11-28 17:28:25 281fc0e9afc38674b9b0991943b9e9d1e64c6cbdb133d35f6f5c87ff6af38a88", -1, SQLITE_TRANSIENT);
265663+
sqlite3_result_text(pCtx, "fts5: 2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cb2075", -1, SQLITE_TRANSIENT);
265620265664
}
265621265665

265622265666
/*
@@ -271251,6 +271295,9 @@ SQLITE_API int sqlite3_stmt_init(
271251271295
//
271252271296
// This file was obtained from the last known release:
271253271297
// https://raw.githubusercontent.com/sqlcipher/sqlcipher/refs/tags/v4.11.0/src/crypto_libtomcrypt.c
271298+
//
271299+
// Note that this file is not compiled directly, but instead is
271300+
// added to the SQLite amalgamation by scripts/build_sqlcipher.sh
271254271301

271255271302
/* BEGIN SQLCIPHER */
271256271303
#ifdef SQLITE_HAS_CODEC

Sources/SQLCipher/sqlite/sqlite3.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ extern "C" {
146146
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
147147
** [sqlite_version()] and [sqlite_source_id()].
148148
*/
149-
#define SQLITE_VERSION "3.51.1"
150-
#define SQLITE_VERSION_NUMBER 3051001
151-
#define SQLITE_SOURCE_ID "2025-11-28 17:28:25 281fc0e9afc38674b9b0991943b9e9d1e64c6cbdb133d35f6f5c87ff6af3alt1"
149+
#define SQLITE_VERSION "3.51.2"
150+
#define SQLITE_VERSION_NUMBER 3051002
151+
#define SQLITE_SOURCE_ID "2026-01-09 17:27:48 b270f8339eb13b504d0b2ba154ebca966b7dde08e40c3ed7d559749818cbalt1"
152152
#define SQLITE_SCM_BRANCH "branch-3.51"
153-
#define SQLITE_SCM_TAGS "release version-3.51.1"
154-
#define SQLITE_SCM_DATETIME "2025-11-28T17:28:25.933Z"
153+
#define SQLITE_SCM_TAGS "release version-3.51.2"
154+
#define SQLITE_SCM_DATETIME "2026-01-09T17:27:48.405Z"
155155

156156
/*
157157
** CAPI3REF: Run-Time Library Version Numbers

0 commit comments

Comments
 (0)