From nobody Mon Aug 31 16:35:21 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hYZNV0J74z6r2SP for ; Mon, 31 Aug 2026 16:35:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hYZNT6YbMz47D0 for ; Mon, 31 Aug 2026 16:35:21 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788194121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tvl1Sq0cRuFsskGwnlIBtCx8xxDsfluwulqL1BPJbn0=; b=n+5nTC4Lh1JXkMB8LmyGNhDLgJCPkh2aPYy39w2ea7MliwEhe1nsAfHAXJWoUGnM+RTNbh ygY6sTTHAxJuCaTCGys0TuVevsOpkxCtoOhVz6I1qnrx294OpQqyubcsUgATR1TybKRmp9 WX8at+2LEJ5NO7BB2c5IXr4n+936pVtLQiWYBC3Z98T6/+sgS6YtfP3seFBw/6kd/IrnIS 4JZUOTbHQTPRxD6tlY5TUcJn2rflOK+gaYRxNZ9IpGiJ/8VqJiG4FbZxUsSBvxlx07869F i3t32VR/aFZVAtNFjItiTTk7KB02LShRPqVInMkv0B/k1WfFJ8pj+zWJGqKY1w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1788194121; a=rsa-sha256; cv=none; b=TWEl2Kod31q/C4a7k64bjOZnIwJjUPESLx1INro+rXCF4RuQe40LkH4c7JwgguKHyveitm VT8syiP3kN8lGZ2uSSPAZpvNquSYWkrW1TcuLC7Y/eP2jOLpDjqd9AIslj4TaZIpJb1jAJ KkbzKSZ5D5lxo/DkVk/0pyVrjs9oag/e9/i6nBbyyzBaQrcan+92zJFzygVhKaYkSLqPDw LmD6Lh7zspW/qg4QOoptkbNvyd0IraYtwjqwvf9fb9DDsx7sk/QbVNfr/dpXjDNTG10/Jm qU8SN+X173Lr9TQ8I0dfs2wA4dMSn+KEvo9+9rHLLp7gFi3Sy9l1ZaIhgR5cnA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1788194121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=tvl1Sq0cRuFsskGwnlIBtCx8xxDsfluwulqL1BPJbn0=; b=fXOpCaj+jLO6QjnvYXIbxbpoRcIz4o5Nb5dxfz8gK9MklF08e/6kWEO1ItUewdpYthwDiv lU/uPW/f4BEDC3j+FR4wMkJODlye7yZ22datsv9TvuYkQXuT/JKYpOBro5rExCGwsLT/8D YZwHAFIX85kPHMJwUW9PtsbTOYB0KE7SSC895ukxbizhrKixcvOsDQSUIxnjnOQTxnh13O KIGVYqLnLx51aPwoE7B6mPCdmb98bkFEt1bwvaNYJ+HUhjqKxdhPpoyOVRVlWlMg9SSAPX 3givS7HK0M1ixtN9wCFPi3VnOSdgsFigbbrtAS04n+69xf2AqBbPITVwSvH0xA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hYZNT4p2Vz4XQ for ; Mon, 31 Aug 2026 16:35:21 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3289e by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 31 Aug 2026 16:35:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Cy Schubert Subject: git: c81e5aa8a52e - stable/15 - sqlite3: Vendor import of sqlite3 3.53.3 List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: cy X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: c81e5aa8a52e524eb7e6be2016025ebc910e10de Auto-Submitted: auto-generated Date: Mon, 31 Aug 2026 16:35:21 +0000 Message-Id: <6a95ad49.3289e.1a409952@gitrepo.freebsd.org> The branch stable/15 has been updated by cy: URL: https://cgit.FreeBSD.org/src/commit/?id=c81e5aa8a52e524eb7e6be2016025ebc910e10de commit c81e5aa8a52e524eb7e6be2016025ebc910e10de Author: Cy Schubert AuthorDate: 2026-08-16 03:24:45 +0000 Commit: Cy Schubert CommitDate: 2026-08-31 16:34:42 +0000 sqlite3: Vendor import of sqlite3 3.53.3 Release notes at https://www.sqlite.org/releaselog/3_53_3.html. Obtained from: https://www.sqlite.org/2026/sqlite-autoconf-3530300.tar.gz Merge commit 'e698feec080925c6cffa9ec31be884daa5cea536' (cherry picked from commit 14e3daa72db7d6410877481a4ed2791603e2b99f) --- contrib/sqlite3/VERSION | 2 +- contrib/sqlite3/autosetup/sqlite-config.tcl | 8 +- contrib/sqlite3/shell.c | 153 ++- contrib/sqlite3/sqlite3.c | 1621 ++++++++++++++++++++------- contrib/sqlite3/sqlite3.h | 28 +- contrib/sqlite3/sqlite3rc.h | 2 +- 6 files changed, 1325 insertions(+), 489 deletions(-) diff --git a/contrib/sqlite3/VERSION b/contrib/sqlite3/VERSION index 0d767a08f23c..a03878a48a9b 100644 --- a/contrib/sqlite3/VERSION +++ b/contrib/sqlite3/VERSION @@ -1 +1 @@ -3.53.1 +3.53.3 diff --git a/contrib/sqlite3/autosetup/sqlite-config.tcl b/contrib/sqlite3/autosetup/sqlite-config.tcl index 59ecb7192a46..fa36dfb59a4b 100644 --- a/contrib/sqlite3/autosetup/sqlite-config.tcl +++ b/contrib/sqlite3/autosetup/sqlite-config.tcl @@ -1745,8 +1745,12 @@ proc sqlite-handle-env-quirks {} { set autoDll 0; # true if --out-implib/--dll-basename should be implied set host [get-define host] switch -glob -- $host { - *apple* - - *darwin* { set instName darwin } + *-*-darwin* { + set instName darwin + # We don't look for *apple* because: + # https://sqlite.org/forum/forumpost/7b218c3c9f207646 + # There's at least one Linux out there which matches *apple*. + } default { set x [sqlite-env-is-unix-on-windows $host] if {"" ne $x} { diff --git a/contrib/sqlite3/shell.c b/contrib/sqlite3/shell.c index 57faceb4691f..f9bfe1a9dd89 100644 --- a/contrib/sqlite3/shell.c +++ b/contrib/sqlite3/shell.c @@ -1790,7 +1790,7 @@ static void qrfEncodeText(Qrf *p, sqlite3_str *pOut, const char *zTxt){ sqlite3_str_append(pOut, (const char*)z, i); } switch( z[i] ){ - case '>': sqlite3_str_append(pOut, "<", 4); break; + case '>': sqlite3_str_append(pOut, ">", 4); break; case '&': sqlite3_str_append(pOut, "&", 5); break; case '<': sqlite3_str_append(pOut, "<", 4); break; case '"': sqlite3_str_append(pOut, """, 6); break; @@ -2270,7 +2270,7 @@ static void qrfWrapLine( for(k=i-1; k>=i/2; k--){ if( qrfSpace(z[k]) ) break; } - if( k0 ){ for(k=i; k>=i/2; k--){ if( qrfAlnum(z[k-1])!=qrfAlnum(z[k]) && (z[k]&0xc0)!=0x80 ) break; } @@ -5810,6 +5810,9 @@ static void decimal_free(Decimal *p){ /* ** Allocate a new Decimal object initialized to the text in zIn[]. ** Return NULL if any kind of error occurs. +** +** Note that zIn[] is not necessarily zero-terminated. Always +** respect the boundary imposed by the n argument. */ static Decimal *decimalNewFromText(const char *zIn, int n){ Decimal *p = 0; @@ -5827,11 +5830,11 @@ static Decimal *decimalNewFromText(const char *zIn, int n){ p->nFrac = 0; p->a = sqlite3_malloc64( n+1 ); if( p->a==0 ) goto new_from_text_failed; - for(i=0; IsSpace(zIn[i]); i++){} - if( zIn[i]=='-' ){ + for(i=0; isign = 1; i++; - }else if( zIn[i]=='+' ){ + }else if( inDigit<=N ) return; for(nZero=0; nZeronDigit && p->a[nZero]==0; nZero++){} N += nZero; if( p->nDigit<=N ) return; - if( p->a[N]>4 ){ + if( p->a[N]>=5 ){ + /* If all leading digits are 9, increase the number of digits + ** by adding a new 0 to the front */ + for(i=0; ia[i]==9; i++){} + if( i==N ){ + decimal_expand(p, p->nDigit+1, p->nFrac); + if( p->oom ) return; + } + + /* Do the rounding */ p->a[N-1]++; for(i=N-1; i>0 && p->a[i]>9; i--){ p->a[i] = 0; p->a[i-1]++; } - if( p->a[0]>9 ){ - p->a[0] = 1; - p->nFrac--; - } + assert( p->a[0]<=9 ); } memset(&p->a[N], 0, p->nDigit - N); } @@ -6211,6 +6223,7 @@ static void decimal_expand(Decimal *p, int nDigit, int nFrac){ signed char *a; if( p==0 ) return; nAddFrac = nFrac - p->nFrac; + assert( nAddFrac>=0 ); nAddSig = (nDigit - p->nDigit) - nAddFrac; if( nAddFrac==0 && nAddSig==0 ) return; if( nDigit+1>SQLITE_DECIMAL_MAX_DIGIT ){ p->oom = 1; return; } @@ -8219,6 +8232,16 @@ static double seriesFloor(double r){ } #endif +/* Convert a floating point value to its closest integer. Do so in +** a way that avoids 'outside the range of representable values' warnings +** from UBSAN. +*/ +sqlite3_int64 seriesRealToI64(double r){ + if( r<-9223372036854774784.0 ) return SMALLEST_INT64; + if( r>+9223372036854774784.0 ) return LARGEST_INT64; + return (sqlite3_int64)r; +} + /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least @@ -8341,7 +8364,7 @@ static int seriesFilter( && r>=(double)SMALLEST_INT64 && r<=(double)LARGEST_INT64 ){ - iMin = iMax = (sqlite3_int64)r; + iMin = iMax = seriesRealToI64(r); }else{ goto series_no_rows; } @@ -8349,15 +8372,19 @@ static int seriesFilter( iMin = iMax = sqlite3_value_int64(argv[iArg++]); } }else{ - if( idxNum & 0x0300 ){ /* value>X or value>=X */ + if( idxNum & 0x0300 ){ /* value>X (0x200) or value>=X (0x100) */ if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){ double r = sqlite3_value_double(argv[iArg++]); - if( r<(double)SMALLEST_INT64 ){ + if( r<=(double)SMALLEST_INT64 ){ iMin = SMALLEST_INT64; - }else if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){ - iMin = (sqlite3_int64)seriesCeil(r+1.0); + }else if( r>(double)LARGEST_INT64 ){ + goto series_no_rows; }else{ - iMin = (sqlite3_int64)seriesCeil(r); + iMin = seriesRealToI64(seriesCeil(r)); + if( (idxNum & 0x0200)!=0 && r==seriesCeil(r) ){ + if( iMin==LARGEST_INT64 ) goto series_no_rows; + iMin++; + } } }else{ iMin = sqlite3_value_int64(argv[iArg++]); @@ -8370,15 +8397,19 @@ static int seriesFilter( } } } - if( idxNum & 0x3000 ){ /* value(double)LARGEST_INT64 ){ + if( r>=(double)LARGEST_INT64 ){ iMax = LARGEST_INT64; - }else if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ - iMax = (sqlite3_int64)(r-1.0); + }else if( r<=(double)SMALLEST_INT64 ){ + goto series_no_rows; }else{ - iMax = (sqlite3_int64)seriesFloor(r); + iMax = seriesRealToI64(seriesFloor(r)); + if( (idxNum & 0x2000)!=0 && r==seriesFloor(r) ){ + if( iMax==SMALLEST_INT64 ) goto series_no_rows; + iMax--; + } } }else{ iMax = sqlite3_value_int64(argv[iArg++]); @@ -12618,6 +12649,7 @@ static void zipfileResetCursor(ZipfileCsr *pCsr){ pNext = p->pNext; zipfileEntryFree(p); } + pCsr->pFreeEntry = 0; } /* @@ -13020,7 +13052,13 @@ static int zipfileGetEntry( if( rc==SQLITE_OK ){ u32 *pt = &pNew->mUnixTime; - pNew->cds.zFile = sqlite3_mprintf("%.*s", nFile, aRead); + /* aRead[0..nFile-1] might contain embedded \000 characters + ** See Bug 2026-05-31T11:43:05Z */ + pNew->cds.zFile = sqlite3_malloc64(nFile+1); + if( pNew->cds.zFile!=0 ){ + memcpy(pNew->cds.zFile, aRead, nFile); + pNew->cds.zFile[nFile] = 0; + } pNew->aExtra = (u8*)&pNew[1]; memcpy(pNew->aExtra, &aRead[nFile], nExtra); if( pNew->cds.zFile==0 ){ @@ -14124,10 +14162,10 @@ struct ZipfileCtx { }; static int zipfileBufferGrow(ZipfileBuffer *pBuf, i64 nByte){ - if( pBuf->n+nByte>pBuf->nAlloc ){ + if( (pBuf->nAlloc-pBuf->n)n ? pBuf->n*2 : 512; - int nReq = pBuf->n + nByte; + i64 nNew = pBuf->n ? (i64)pBuf->n*2 : 512; + i64 nReq = pBuf->n + nByte; while( nNewa, nNew); @@ -14343,7 +14381,7 @@ static void zipfileFinal(sqlite3_context *pCtx){ eocd.nSize = p->cds.n; eocd.iOffset = p->body.n; - nZip = p->body.n + p->cds.n + ZIPFILE_EOCD_FIXED_SZ; + nZip = (i64)p->body.n + (i64)p->cds.n + ZIPFILE_EOCD_FIXED_SZ; aZip = (u8*)sqlite3_malloc64(nZip); if( aZip==0 ){ sqlite3_result_error_nomem(pCtx); @@ -17470,7 +17508,7 @@ static int intckGetToken(const char *z){ } } else if( c=='[' ){ - while( z[iRet++]!=']' && z[iRet] ); + while( z[iRet] && z[iRet++]!=']' ){} } else if( (c>='A' && c<='Z') || (c>='a' && c<='z') ){ while( (z[iRet]>='A' && z[iRet]<='Z') || (z[iRet]>='a' && z[iRet]<='z') ){ @@ -29727,7 +29765,7 @@ struct ArCommand { u8 eCmd; /* An AR_CMD_* value */ u8 bVerbose; /* True if --verbose */ u8 bZip; /* True if the archive is a ZIP */ - u8 bDryRun; /* True if --dry-run */ + u8 bDryRun; /* 1 for --dry-run, 2 for --debug */ u8 bAppend; /* True if --append */ u8 bGlob; /* True if --glob */ u8 fromCmdLine; /* Run from -A instead of .archive */ @@ -29789,6 +29827,7 @@ static int arErrorMsg(ArCommand *pAr, const char *zFmt, ...){ #define AR_SWITCH_APPEND 11 #define AR_SWITCH_DRYRUN 12 #define AR_SWITCH_GLOB 13 +#define AR_SWITCH_DEBUG 14 static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ switch( eSwitch ){ @@ -29806,7 +29845,10 @@ static int arProcessSwitch(ArCommand *pAr, int eSwitch, const char *zArg){ break; case AR_SWITCH_DRYRUN: - pAr->bDryRun = 1; + if( pAr->bDryRun<2 ) pAr->bDryRun = 1; + break; + case AR_SWITCH_DEBUG: + pAr->bDryRun = 2; break; case AR_SWITCH_GLOB: pAr->bGlob = 1; @@ -29857,6 +29899,7 @@ static int arParseCommand( { "append", 'a', AR_SWITCH_APPEND, 1 }, { "directory", 'C', AR_SWITCH_DIRECTORY, 1 }, { "dryrun", 'n', AR_SWITCH_DRYRUN, 0 }, + { "debug", 0, AR_SWITCH_DEBUG, 0 }, { "glob", 'g', AR_SWITCH_GLOB, 0 }, }; int nSwitch = sizeof(aSwitch) / sizeof(struct ArSwitch); @@ -30158,13 +30201,27 @@ static int arRemoveCommand(ArCommand *pAr){ */ static int arExtractCommand(ArCommand *pAr){ const char *zSql1 = - "WITH dest(dpath,dlen) AS (SELECT realpath($dir),length(realpath($dir)))\n" - "SELECT ($dir || name),\n" - " CASE WHEN $dryrun THEN 0\n" - " ELSE writefile($dir||name, %s, mode, mtime) END\n" + "WITH dest(dpath,dlen) AS (\n" +#ifdef _WIN32 + " SELECT realpath($dir) || '\\',\n" +#else + " SELECT realpath($dir) || '/',\n" +#endif + " 1+length(realpath($dir))\n" + ")\n" + "SELECT\n" + " ($dir || name),\n" + " CASE $dryrun\n" + " WHEN 0 THEN writefile($dir||name, %s, mode, mtime)\n" + " WHEN 1 THEN 0\n" + " ELSE shell_putsnl(format('writefile(%%Q,%%s,%%0o,%%d)'," + "$dir||name,quote(%s),mode,mtime)) IS NULL\n" + " END\n" " FROM dest CROSS JOIN %s\n" " WHERE (%s)\n" - " AND (data IS NULL OR $pass==0)\n" /* Dirs both passes */ + " AND (CASE $pass WHEN 0 THEN (mode&0xf000)<>0xa000\n" + " WHEN 1 THEN (mode&0xf000)=0xa000\n" + " ELSE data IS NULL END)\n" " AND dpath=substr(realpath($dir||name),1,dlen)\n" /* No escapes */ " AND name NOT GLOB '*..[/\\]*'\n"; /* No /../ in paths */ @@ -30195,7 +30252,7 @@ static int arExtractCommand(ArCommand *pAr){ } shellPreparePrintf(pAr->db, &rc, &pSql, zSql1, - azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere + azExtraArg[pAr->bZip], azExtraArg[pAr->bZip], pAr->zSrcTable, zWhere ); if( rc==SQLITE_OK ){ @@ -30205,25 +30262,31 @@ static int arExtractCommand(ArCommand *pAr){ sqlite3_bind_int(pSql, j, pAr->bDryRun); /* Run the SELECT statement twice - ** (0) writefile() all files and directories - ** (1) writefile() for directory again - ** The second pass is so that the timestamps for extracted directories + ** (0) writefile() files and directories + ** (1) writefile() symlinks + ** (2) writefile() for directory again + ** The third pass is so that the timestamps for extracted directories ** will be reset to the value in the archive, since populating them ** in the first pass will have changed the timestamp. */ - for(i=0; i<2; i++){ + for(i=0; i<3; i++){ + if( pAr->bDryRun>=2 ){ + cli_printf(pAr->out, "*** BEGIN PASS %d ***\n", i+1); + } j = sqlite3_bind_parameter_index(pSql, "$pass"); sqlite3_bind_int(pSql, j, i); - if( pAr->bDryRun ){ + if( pAr->bDryRun && i==0 ){ cli_printf(pAr->out, "%s\n", sqlite3_sql(pSql)); - if( pAr->bVerbose==0 ) break; } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){ if( i==0 && pAr->bVerbose ){ cli_printf(pAr->out, "%s\n", sqlite3_column_text(pSql, 0)); } } - if( pAr->bDryRun ) break; + if( pAr->bDryRun==1 ) break; shellReset(&rc, pSql); + if( pAr->bDryRun>=2 ){ + cli_printf(pAr->out, "*** END PASS %d ***\n", i+1); + } } shellFinalize(&rc, pSql); } @@ -30738,7 +30801,7 @@ SELECT CASE WHEN (nc < 10) THEN 1 WHEN (nc < 100) THEN 2 \ SELECT\ '('||x'0a'\ || group_concat(\ - cname||' ANY',\ + cname,\ ','||iif((cpos-1)%4>0, ' ', x'0a'||' '))\ ||')' AS ColsSpec \ FROM (\ @@ -36886,8 +36949,10 @@ int SQLITE_CDECL main(int argc, char **argv){ cmdline_option_value(argc,argv,++i)); }else if( cli_strcmp(z,"-header")==0 ){ data.mode.spec.bTitles = QRF_Yes; + data.mode.mFlags |= MFLG_HDR; }else if( cli_strcmp(z,"-noheader")==0 ){ data.mode.spec.bTitles = QRF_No; + data.mode.mFlags |= MFLG_HDR; }else if( cli_strcmp(z,"-echo")==0 ){ data.mode.mFlags |= MFLG_ECHO; }else if( cli_strcmp(z,"-eqp")==0 ){ diff --git a/contrib/sqlite3/sqlite3.c b/contrib/sqlite3/sqlite3.c index dfd557adeda5..09f3e4a9f829 100644 --- a/contrib/sqlite3/sqlite3.c +++ b/contrib/sqlite3/sqlite3.c @@ -1,6 +1,6 @@ /****************************************************************************** ** This file is an amalgamation of many separate C source files from SQLite -** version 3.53.1. By combining all the individual C code files into this +** version 3.53.3. 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 @@ -18,7 +18,7 @@ ** separate file. This file contains only code for the core SQLite library. ** ** The content in this amalgamation comes from Fossil check-in -** c88b22011a54b4f6fbd149e9f8e4de77658c with changes in files: +** d4c0e51e4aeb96955b99185ab9cde75c339e with changes in files: ** ** */ @@ -467,12 +467,12 @@ extern "C" { ** [sqlite3_libversion_number()], [sqlite3_sourceid()], ** [sqlite_version()] and [sqlite_source_id()]. */ -#define SQLITE_VERSION "3.53.1" -#define SQLITE_VERSION_NUMBER 3053001 -#define SQLITE_SOURCE_ID "2026-05-05 10:34:17 c88b22011a54b4f6fbd149e9f8e4de77658ce58143a1af0e3785e4e6475127e9" +#define SQLITE_VERSION "3.53.3" +#define SQLITE_VERSION_NUMBER 3053003 +#define SQLITE_SOURCE_ID "2026-06-26 20:14:12 d4c0e51e4aeb96955b99185ab9cde75c339e2c29c3f3f12428d364a10d782c62" #define SQLITE_SCM_BRANCH "branch-3.53" -#define SQLITE_SCM_TAGS "release version-3.53.1" -#define SQLITE_SCM_DATETIME "2026-05-05T10:34:17.344Z" +#define SQLITE_SCM_TAGS "release version-3.53.3" +#define SQLITE_SCM_DATETIME "2026-06-26T20:14:12.354Z" /* ** CAPI3REF: Run-Time Library Version Numbers @@ -4687,7 +4687,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); ** or in an ORDER BY or GROUP BY clause.)^ ** ** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
-**
The maximum depth of the parse tree on any expression.
)^ +**
The maximum depth of the parse tree on any expression and +** the maximum nesting depth for subqueries and VIEWs
)^ ** ** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(
SQLITE_LIMIT_PARSER_DEPTH
**
The maximum depth of the LALR(1) parser stack used to analyze @@ -4718,7 +4719,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal); **
The maximum index number of any [parameter] in an SQL statement.)^ ** ** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(
SQLITE_LIMIT_TRIGGER_DEPTH
-**
The maximum depth of recursion for triggers.
)^ +**
The maximum depth of recursion for triggers, and the maximum +** nesting depth for separate triggers.
)^ ** ** [[SQLITE_LIMIT_WORKER_THREADS]] ^(
SQLITE_LIMIT_WORKER_THREADS
**
The maximum number of auxiliary worker threads that a single @@ -13174,11 +13176,23 @@ SQLITE_API int sqlite3changeset_apply_v3( ** database behave as if they were declared with "ON UPDATE NO ACTION ON ** DELETE NO ACTION", even if they are actually CASCADE, RESTRICT, SET NULL ** or SET DEFAULT. +** +**
SQLITE_CHANGESETAPPLY_NOUPDATELOOP
+** Sometimes, a changeset contains two or more update statements such that +** although after applying all updates the database will contain no +** constraint violations, no single update can be applied before the others. +** The simplest example of this is a pair of UPDATEs that have "swapped" +** two column values with a UNIQUE constraint. +**

+** Usually, sqlite3changeset_apply() and similar functions work hard to try +** to find a way to apply such a changeset. However, if this flag is set, +** then all such updates are considered CONSTRAINT conflicts. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_INVERT 0x0002 #define SQLITE_CHANGESETAPPLY_IGNORENOOP 0x0004 #define SQLITE_CHANGESETAPPLY_FKNOACTION 0x0008 +#define SQLITE_CHANGESETAPPLY_NOUPDATELOOP 0x0010 /* ** CAPI3REF: Constants Passed To The Conflict Handler @@ -15788,6 +15802,13 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*); # define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0)) #endif +/* +** sizeof64() is like sizeof(), but always returns a 64-bit value, even +** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit +** arithmetic is used consistently in both 32-bit and 64-bit builds. +*/ +#define sizeof64(X) ((sqlite3_int64)sizeof(X)) + /* ** Work around C99 "flex-array" syntax for pre-C99 compilers, so as ** to avoid complaints from -fsanitize=strict-bounds. @@ -17149,7 +17170,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *); SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *); SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *); -SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *); +SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree*, Btree*); SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *); @@ -20907,6 +20928,7 @@ struct Parse { int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int iSelfTab; /* Table associated with an index on expr, or negative ** of the base register during check-constraint eval */ + int nNestSel; /* Number of nested SELECT statements and/or VIEWs */ int nLabel; /* The *negative* of the number of labels used */ int nLabelAlloc; /* Number of slots in aLabel */ int *aLabel; /* Space to hold the labels */ @@ -22448,7 +22470,15 @@ SQLITE_PRIVATE void sqlite3AlterFunctions(void); SQLITE_PRIVATE void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); SQLITE_PRIVATE void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*); -SQLITE_PRIVATE void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int); +SQLITE_PRIVATE void sqlite3AlterAddConstraint( + Parse *pParse, /* Parse context */ + SrcList *pSrc, /* Table to add constraint to */ + Token *pFirst, /* First token of new constraint */ + Token *pName, /* Name of new constraint. NULL if name omitted. */ + const char *zExpr, /* Text of CHECK expression */ + int nExpr, /* Size of pExpr in bytes */ + Expr *pExpr /* The parsed CHECK expression */ +); SQLITE_PRIVATE void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*); SQLITE_PRIVATE i64 sqlite3GetToken(const unsigned char *, int *); SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...); @@ -33257,8 +33287,8 @@ SQLITE_API void sqlite3_str_vappendf( ** all control characters, and for backslash itself. ** For %#Q, do the same but only if there is at least ** one control character. */ - u32 nBack = 0; - u32 nCtrl = 0; + i64 nBack = 0; + i64 nCtrl = 0; for(k=0; k='a' && c<='z' ){ n += (c - 'a')*mult; + if( n>nOut ) return -1 /* oversized/malformed input */; mult *= 26; c = aIn[++i]; } - if( j+n>nOut ) return -1; + if( j+n>nOut ) return -1 /* oversized/malformed input */; memset(&aOut[j], 0, n); j += n; if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */ @@ -39600,7 +39631,7 @@ static void kvvfsDecodeJournal( i = 0; mult = 1; while( (c = zTxt[i++])>='a' && c<='z' ){ - n += (zTxt[i] - 'a')*mult; + n += (c - 'a')*mult; mult *= 26; } sqlite3_free(pFile->aJrnl); @@ -39646,9 +39677,7 @@ static int kvvfsClose(sqlite3_file *pProtoFile){ pFile->isJournal ? "journal" : "db")); sqlite3_free(pFile->aJrnl); sqlite3_free(pFile->aData); -#ifdef SQLITE_WASM memset(pFile, 0, sizeof(*pFile)); -#endif return SQLITE_OK; } @@ -39678,6 +39707,7 @@ static int kvvfsReadJrnl( aTxt, szTxt+1); if( rc>=0 ){ kvvfsDecodeJournal(pFile, aTxt, szTxt); + rc = 0; } sqlite3_free(aTxt); if( rc ) return rc; @@ -45307,9 +45337,9 @@ static int unixShmMap( nReqRegion = ((iRegion+nShmPerMap) / nShmPerMap) * nShmPerMap; if( pShmNode->nRegionszRegion = szRegion; @@ -45340,7 +45370,7 @@ static int unixShmMap( */ else{ static const int pgsz = 4096; - int iPg; + i64 iPg; /* Write to the last byte of each newly allocated or extended page */ assert( (nByte % pgsz)==0 ); @@ -45366,8 +45396,8 @@ static int unixShmMap( } pShmNode->apRegion = apNew; while( pShmNode->nRegionhShm>=0 ){ pMem = osMmap(0, nMap, @@ -49741,10 +49771,8 @@ static struct win_syscall { #define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \ BOOL))aSyscall[63].pCurrent) - { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 }, - -#define osGetNativeSystemInfo ((VOID(WINAPI*)( \ - LPSYSTEM_INFO))aSyscall[64].pCurrent) + { "GetNativeSystemInfo", (SYSCALL)0, 0 }, + /* ^^^^^^^^^^^^^^^^^^^----------------^------- placeholder only */ #if defined(SQLITE_WIN32_HAS_ANSI) { "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 }, @@ -52999,11 +53027,29 @@ SQLITE_API int sqlite3_win_test_unc_locking = 0; /* ** Return true if the string passed as the only argument is likely -** to be a UNC path. In other words, if it starts with "\\". +** to be a UNC path. Return false if note. +** +** Return true if: +** +** (1) The name begins with "\\" +** (2) But does not begin with "\\?\C:\" where C can be any alphabetic +** character. +** +** For testing, also return true in all cases if the global variable +** sqlite3_win_test_unc_locking is true. */ static int winIsUNCPath(const char *zFile){ if( zFile[0]=='\\' && zFile[1]=='\\' ){ - return 1; + if( zFile[2]=='?' + && zFile[3]=='\\' + && sqlite3Isalpha(zFile[4]) + && zFile[5]==':' + && winIsDirSep(zFile[6]) + ){ + return sqlite3_win_test_unc_locking; + }else{ + return 1; + } } return sqlite3_win_test_unc_locking; } @@ -53341,7 +53387,7 @@ static int winShmMap( if( pShmNode->nRegion<=iRegion ){ HANDLE hShared = pShmNode->hSharedShm; struct ShmRegion *apNew; /* New aRegion[] array */ - int nByte = (iRegion+1)*szRegion; /* Minimum required file size */ + i64 nByte = ((i64)iRegion+1)*(i64)szRegion; /* Minimum file size */ sqlite3_int64 sz; /* Current size of wal-index file */ pShmNode->szRegion = szRegion; @@ -53372,7 +53418,7 @@ static int winShmMap( /* Map the requested memory region into this processes address space. */ apNew = (struct ShmRegion*)sqlite3_realloc64( - pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0]) + pShmNode->aRegion, ((i64)iRegion+1)*sizeof(apNew[0]) ); if( !apNew ){ rc = SQLITE_IOERR_NOMEM_BKPT; @@ -53394,15 +53440,14 @@ static int winShmMap( #elif defined(SQLITE_WIN32_HAS_ANSI) && SQLITE_WIN32_CREATEFILEMAPPINGA hMap = osCreateFileMappingA(hShared, NULL, protect, 0, nByte, NULL); #endif - - OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%d, rc=%s\n", + OSTRACE(("SHM-MAP-CREATE pid=%lu, region=%d, size=%lld, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, nByte, hMap ? "ok" : "failed")); if( hMap ){ - int iOffset = pShmNode->nRegion*szRegion; + i64 iOffset = pShmNode->nRegion*szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; pMap = osMapViewOfFile(hMap, flags, - 0, iOffset - iOffsetShift, szRegion + iOffsetShift + 0, iOffset - iOffsetShift, (i64)szRegion + iOffsetShift ); OSTRACE(("SHM-MAP-MAP pid=%lu, region=%d, offset=%d, size=%d, rc=%s\n", osGetCurrentProcessId(), pShmNode->nRegion, iOffset, @@ -53424,7 +53469,7 @@ static int winShmMap( shmpage_out: if( pShmNode->nRegion>iRegion ){ - int iOffset = iRegion*szRegion; + i64 iOffset = (i64)iRegion*(i64)szRegion; int iOffsetShift = iOffset % winSysInfo.dwAllocationGranularity; char *p = (char *)pShmNode->aRegion[iRegion].pMap; *pp = (void *)&p[iOffsetShift]; @@ -56020,7 +56065,7 @@ SQLITE_API unsigned char *sqlite3_serialize( sqlite3_int64 sz; int szPage = 0; sqlite3_stmt *pStmt = 0; - unsigned char *pOut; + unsigned char *pOut = 0; char *zSql; int rc; @@ -56030,12 +56075,13 @@ SQLITE_API unsigned char *sqlite3_serialize( return 0; } #endif + sqlite3_mutex_enter(db->mutex); if( zSchema==0 ) zSchema = db->aDb[0].zDbSName; p = memdbFromDbSchema(db, zSchema); iDb = sqlite3FindDbName(db, zSchema); if( piSize ) *piSize = -1; - if( iDb<0 ) return 0; + if( iDb<0 ) goto serialize_out; if( p ){ MemStore *pStore = p->pStore; assert( pStore->pMutex==0 ); @@ -56046,19 +56092,17 @@ SQLITE_API unsigned char *sqlite3_serialize( pOut = sqlite3_malloc64( pStore->sz ); if( pOut ) memcpy(pOut, pStore->aData, pStore->sz); } - return pOut; + goto serialize_out; } pBt = db->aDb[iDb].pBt; - if( pBt==0 ) return 0; + if( pBt==0 ) goto serialize_out; szPage = sqlite3BtreeGetPageSize(pBt); zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema); rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM; sqlite3_free(zSql); - if( rc ) return 0; + if( rc ) goto serialize_out; rc = sqlite3_step(pStmt); - if( rc!=SQLITE_ROW ){ - pOut = 0; - }else{ + if( rc==SQLITE_ROW ){ sz = sqlite3_column_int64(pStmt, 0)*szPage; if( sz==0 ){ sqlite3_reset(pStmt); @@ -56092,6 +56136,9 @@ SQLITE_API unsigned char *sqlite3_serialize( } } sqlite3_finalize(pStmt); + + serialize_out: + sqlite3_mutex_leave(db->mutex); return pOut; } @@ -57945,22 +57992,24 @@ static int pcache1InitBulk(PCache1 *pCache){ if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){ szBulk = pCache->szAlloc*(i64)pCache->nMax; } - zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); - sqlite3EndBenignMalloc(); - if( zBulk ){ - int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; - do{ - PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; - pX->page.pBuf = zBulk; - pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); - assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); - pX->isBulkLocal = 1; - pX->isAnchor = 0; - pX->pNext = pCache->pFree; - pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ - pCache->pFree = pX; - zBulk += pCache->szAlloc; - }while( --nBulk ); + if( szBulk>=pCache->szAlloc ){ + zBulk = pCache->pBulk = sqlite3Malloc( szBulk ); + sqlite3EndBenignMalloc(); + if( zBulk ){ + int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc; + do{ + PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage]; + pX->page.pBuf = zBulk; + pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX)); + assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) ); + pX->isBulkLocal = 1; + pX->isAnchor = 0; + pX->pNext = pCache->pFree; + pX->pLruPrev = 0; /* Initializing this saves a valgrind error */ + pCache->pFree = pX; + zBulk += pCache->szAlloc; + }while( --nBulk ); + } } return pCache->pFree!=0; } @@ -60858,39 +60907,43 @@ static void checkPage(PgHdr *pPg){ #endif /* SQLITE_CHECK_PAGES */ /* -** When this is called the journal file for pager pPager must be open. -** This function attempts to read a super-journal file name from the -** end of the file and, if successful, copies it into memory supplied -** by the caller. See comments above writeSuperJournal() for the format -** used to store a super-journal file name at the end of a journal file. -** -** zSuper must point to a buffer of at least nSuper bytes allocated by -** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is -** enough space to write the super-journal name). If the super-journal -** name in the journal is longer than nSuper bytes (including a -** nul-terminator), then this is handled as if no super-journal name -** were present in the journal. +** Free a buffer allocated by the readSuperJournal() function. +*/ +static void freeSuperJournal(char *zSuper){ + if( zSuper ){ + sqlite3_free(&zSuper[-4]); + } +} + +/* +** Parameter pJrnl is a file-handle open on a journal file. This function +** attempts to read a super-journal file name from the end of the journal +** file. If successful, it sets output parameter (*pzSuper) to point to a +** buffer containing the super-journal name as a nul-terminated string. +** The caller is responsible for freeing the buffer using freeSuperJournal(). ** -** If a super-journal file name is present at the end of the journal -** file, then it is copied into the buffer pointed to by zSuper. A -** nul-terminator byte is appended to the buffer following the -** super-journal file name. +** Refer to comments above writeSuperJournal() for the format used to store +** a super-journal file name at the end of a journal file. ** -** If it is determined that no super-journal file name is present -** zSuper[0] is set to 0 and SQLITE_OK returned. +** Parameter nSuper is passed the maximum allowable size of the super journal +** name in bytes. If the super-journal name in the journal is longer than +** nSuper bytes (including a nul-terminator), then this is handled as if no +** super-journal name were present in the journal. ** -** If an error occurs while reading from the journal file, an SQLite -** error code is returned. +** If there is no super-journal name at the end of pJrnl, (*pzSuper) is +** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading +** the super-journal name, an SQLite error code is returned and (*pzSuper) +** is set to 0. */ -static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){ +static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){ int rc; /* Return code */ u32 len; /* Length in bytes of super-journal name */ i64 szJ; /* Total size in bytes of journal file pJrnl */ u32 cksum; /* MJ checksum value read from journal */ - u32 u; /* Unsigned loop counter */ unsigned char aMagic[8]; /* A buffer to hold the magic header */ - zSuper[0] = '\0'; + char *zOut = 0; + *pzSuper = 0; if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ)) || szJ<16 || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len)) @@ -60900,27 +60953,34 @@ static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){ || SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum)) || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8)) || memcmp(aMagic, aJournalMagic, 8) - || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len)) ){ return rc; } - /* See if the checksum matches the super-journal name */ - for(u=0; u