git: c81e5aa8a52e - stable/15 - sqlite3: Vendor import of sqlite3 3.53.3
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 31 Aug 2026 16:35:21 UTC
The branch stable/15 has been updated by cy:
URL: https://cgit.FreeBSD.org/src/commit/?id=c81e5aa8a52e524eb7e6be2016025ebc910e10de
commit c81e5aa8a52e524eb7e6be2016025ebc910e10de
Author: Cy Schubert <cy@FreeBSD.org>
AuthorDate: 2026-08-16 03:24:45 +0000
Commit: Cy Schubert <cy@FreeBSD.org>
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( k<i/2 ){
+ if( k<i/2 && i/2>0 ){
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; i<n && IsSpace(zIn[i]); i++){}
+ if( i<n && zIn[i]=='-' ){
p->sign = 1;
i++;
- }else if( zIn[i]=='+' ){
+ }else if( i<n && zIn[i]=='+' ){
i++;
}
while( i<n && zIn[i]=='0' ) i++;
@@ -6042,28 +6045,37 @@ static void decimal_result(sqlite3_context *pCtx, Decimal *p){
sqlite3_result_text(pCtx, z, i, sqlite3_free);
}
+/* Forward declaration */
+static void decimal_expand(Decimal *p, int nDigit, int nFrac);
+
/*
** Round a decimal value to N significant digits. N must be positive.
*/
static void decimal_round(Decimal *p, int N){
int i;
- int nZero;
+ int nZero; /* Number of leading zeros */
if( N<1 ) return;
if( p==0 ) return;
if( p->nDigit<=N ) return;
for(nZero=0; nZero<p->nDigit && 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; i<N && p->a[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<X or value<=X */
+ if( idxNum & 0x3000 ){ /* value<X (0x2000) or value<=X (0x1000) */
if( sqlite3_value_numeric_type(argv[iArg])==SQLITE_FLOAT ){
double r = sqlite3_value_double(argv[iArg++]);
- if( r>(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)<nByte ){
u8 *aNew;
- sqlite3_int64 nNew = pBuf->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( nNew<nReq ) nNew = nNew*2;
aNew = sqlite3_realloc64(pBuf->a, 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.</dd>)^
**
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(<dt>SQLITE_LIMIT_EXPR_DEPTH</dt>
-** <dd>The maximum depth of the parse tree on any expression.</dd>)^
+** <dd>The maximum depth of the parse tree on any expression and
+** the maximum nesting depth for subqueries and VIEWs</dd>)^
**
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(<dt>SQLITE_LIMIT_PARSER_DEPTH</dt>
** <dd>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);
** <dd>The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(<dt>SQLITE_LIMIT_TRIGGER_DEPTH</dt>
-** <dd>The maximum depth of recursion for triggers.</dd>)^
+** <dd>The maximum depth of recursion for triggers, and the maximum
+** nesting depth for separate triggers.</dd>)^
**
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(<dt>SQLITE_LIMIT_WORKER_THREADS</dt>
** <dd>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.
+**
+** <dt>SQLITE_CHANGESETAPPLY_NOUPDATELOOP <dd>
+** 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.
+** <p>
+** 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<i; k++){
if( escarg[k]=='\\' ){
nBack++;
@@ -39555,16 +39585,17 @@ int kvvfsDecode(const char *a, char *aOut, int nOut){
while( 1 ){
c = kvvfsHexValue[aIn[i]];
if( c<0 ){
- int n = 0;
- int mult = 1;
+ sqlite3_int64 n = 0;
+ sqlite3_int64 mult = 1;
c = aIn[i];
if( c==0 ) break;
while( c>='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->nRegion<nReqRegion ){
- char **apNew; /* New apRegion[] array */
- int nByte = nReqRegion*szRegion; /* Minimum required file size */
- struct stat sStat; /* Used by fstat() */
+ char **apNew; /* New apRegion[] array */
+ i64 nByte = nReqRegion*(i64)szRegion; /* Minimum required file size */
+ struct stat sStat; /* Used by fstat() */
pShmNode->szRegion = 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->nRegion<nReqRegion ){
- int nMap = szRegion*nShmPerMap;
- int i;
+ i64 nMap = (i64)szRegion*(i64)nShmPerMap;
+ i64 i;
void *pMem;
if( pShmNode->hShm>=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<len; u++){
- cksum -= zSuper[u];
- }
- if( cksum ){
- /* If the checksum doesn't add up, then one or more of the disk sectors
- ** containing the super-journal filename is corrupted. This means
- ** definitely roll back, so just return SQLITE_OK and report a (nul)
- ** super-journal filename.
- */
- len = 0;
+ zOut = (char*)sqlite3MallocZero(4 + len + 2);
+ if( !zOut ){
+ rc = SQLITE_NOMEM_BKPT;
+ }else{
+ zOut = &zOut[4];
+ if( SQLITE_OK==(rc = sqlite3OsRead(pJrnl, zOut, len, szJ-16-len)) ){
+ u32 u; /* Unsigned loop counter */
+ /* See if the checksum matches the super-journal name */
+ for(u=0; u<len; u++){
+ cksum -= zOut[u];
+ }
+ }
+ if( rc!=SQLITE_OK || cksum ){
+ /* If the checksum doesn't add up, then one or more of the disk sectors
+ ** containing the super-journal filename is corrupted. This means
+ ** definitely roll back, so just return SQLITE_OK and report a (nul)
+ ** super-journal filename. */
+ freeSuperJournal(zOut);
+ zOut = 0;
+ }
}
- zSuper[len] = '\0';
- zSuper[len+1] = '\0';
- return SQLITE_OK;
+ *pzSuper = zOut;
+ return rc;
}
/*
@@ -62074,6 +62134,40 @@ static int pager_playback_one_page(
return rc;
}
+/*
+** Check if zSuper is a valid super-journal name. There are two valid
+** formats:
+**
+** + The 3rd and 4th last bytes of the filename are ".9", and the
+** following 2 bytes are hex digits. This is a file created in 8.3
+** filenames mode.
+**
+** + The 3rd last byte of the filename is "9" and the filename
+** contains the string "-mj" starting at the 12th last byte.
+** All bytes following the "-mj" are hex digits.
+**
+** If the filename matches either of these patterns, return non-zero.
+** Otherwise, return zero.
+*/
+static int pagerIsSuperJrnlName(const char *zSuper){
+ const int nSuper = sqlite3Strlen30(zSuper);
+ int ii;
+
+ if( nSuper<4 ) return 0;
+ if( zSuper[nSuper-3]!='9' ) return 0;
+#ifdef SQLITE_ENABLE_8_3_NAMES
+ if( sqlite3Isxdigit(zSuper[nSuper-2])==0 ) return 0;
+ if( sqlite3Isxdigit(zSuper[nSuper-1])==0 ) return 0;
+ if( zSuper[nSuper-4]=='.' ) return 1;
+#endif
+ if( nSuper<12 ) return 0;
+ if( memcmp(&zSuper[nSuper-12], "-mj", 3) ) return 0;
+ for(ii=nSuper-9; ii<nSuper; ii++){
+ if( sqlite3Isxdigit(zSuper[ii])==0 ) return 0;
+ }
*** 2677 LINES SKIPPED ***