diff --git a/Makefile.in b/Makefile.in
index 7926aa84dd..91135edba3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -135,6 +135,9 @@ ENABLE_LIB_STATIC = @ENABLE_LIB_STATIC@
HAVE_WASI_SDK = @HAVE_WASI_SDK@
libsqlite3.DLL.install-rules = @SQLITE_DLL_INSTALL_RULES@
+# -fsanitize flags for the fuzzcheck-asap app
+CFLAGS.fuzzcheck.fsanitize = @CFLAGS_FUZZCHECK_FSANITIZE@
+
T.cc.sqlite = $(T.cc) @TARGET_DEBUG@
#
@@ -261,6 +264,7 @@ AS_AUTORECONFIG = @SQLITE_AUTORECONFIG@
USE_AMALGAMATION ?= @USE_AMALGAMATION@
LINK_TOOLS_DYNAMICALLY ?= @LINK_TOOLS_DYNAMICALLY@
AMALGAMATION_GEN_FLAGS ?= --linemacros=@AMALGAMATION_LINE_MACROS@
+EXTRA_SRC ?= @AMALGAMATION_EXTRA_SRC@
#
# CFLAGS for sqlite3$(T.exe)
@@ -322,13 +326,7 @@ misspell: ./custom.rws has_tclsh84
# perform cleanup known to be relevant to (only) the autosetup-driven
# build.
#
-#clean-autosetup:
-# -if [ -f ext/wasm/GNUmakefile ]; then \
-# gmake --no-print-directory --ignore-errors -C ext/wasm clean; \
-# fi >/dev/null 2>&1; true
-#clean: clean-autosetup
-
-distclean-autosetup: clean
+distclean-autosetup:
rm -f sqlite_cfg.h config.log config.status config.defines.* Makefile sqlite3.pc
rm -f $(TOP)/tool/emcc.sh
rm -f libsqlite3*$(T.dll)
diff --git a/auto.def b/auto.def
index e0f8be7bde..dcc7371ec0 100644
--- a/auto.def
+++ b/auto.def
@@ -25,7 +25,7 @@ sqlite-configure canonical {
# -------------^^^^^^^ intentionally using [get-env] instead of
# [proj-get-env] here because [sqlite-setup-default-cflags] uses
# [proj-get-env] and we want this to supercede that.
- sqlite-munge-cflags
+ sqlite-munge-cflags; # straighten out -DSQLITE_ENABLE/OMIT flags
}
sqlite-check-common-bins ;# must come before [sqlite-handle-wasi-sdk]
sqlite-handle-wasi-sdk ;# must run relatively early, as it changes the environment
@@ -41,8 +41,14 @@ sqlite-configure canonical {
proj-define-for-opt linemacros AMALGAMATION_LINE_MACROS \
"Use #line macros in the amalgamation:"
+ define AMALGAMATION_EXTRA_SRC \
+ [join [opt-val amalgamation-extra-src ""] " "]
+
define LINK_TOOLS_DYNAMICALLY [proj-opt-was-provided dynlink-tools]
+ define CFLAGS_FUZZCHECK_FSANITIZE [proj-check-fsanitize {address bounds-strict}]
+
sqlite-handle-tcl
sqlite-handle-emsdk
+
}
diff --git a/autoconf/Makefile.in b/autoconf/Makefile.in
index f74c71d674..e59864a20b 100644
--- a/autoconf/Makefile.in
+++ b/autoconf/Makefile.in
@@ -220,7 +220,7 @@ install-lib-0 install-lib-:
install-lib: install-lib-$(ENABLE_LIB_STATIC)
install: install-lib
-
+#
# Flags to link the shell app either directly against sqlite3.c
# (ENABLE_STATIC_SHELL==1) or libsqlite3.so (ENABLE_STATIC_SHELL==0).
#
@@ -269,8 +269,10 @@ DIST_FILES := \
sqlite3.rc sqlite3rc.h Replace.cs \
sqlite3.pc.in sqlite3.1
+#
# Maintenance note: dist_name must be sqlite-$(PACKAGE_VERSION) so
# that tool/mkautoconfamal.sh knows how to find it.
+#
dist_name = sqlite-$(PACKAGE_VERSION)
dist_tarball = $(dist_name).tar.gz
dist:
diff --git a/autosetup/proj.tcl b/autosetup/proj.tcl
index adf31a1ad6..f367b01567 100644
--- a/autosetup/proj.tcl
+++ b/autosetup/proj.tcl
@@ -183,6 +183,8 @@ proc proj-lshift_ {listVar {count 1}} {
}
########################################################################
+# @proj-strip-hash-comments value
+#
# Expects to receive string input, which it splits on newlines, strips
# out any lines which begin with any number of whitespace followed by
# a '#', and returns a value containing the [append]ed results of each
@@ -1031,6 +1033,29 @@ proc proj-check-soname {{libname "libfoo.so.0"}} {
}
}
+########################################################################
+# @proj-check-fsanitize ?list-of-opts?
+#
+# Checks whether CC supports -fsanitize=X, where X is each entry of
+# the given list of flags. If any of those flags are supported, it
+# returns the string "-fsanitize=X..." where X... is a comma-separated
+# list of all supported flags. If none of the given options are
+# supported then it returns an empty string.
+proc proj-check-fsanitize {{opts {address bounds-strict}}} {
+ set sup {}
+ foreach opt $opts {
+ cc-with {} {
+ if {[cc-check-flags "-fsanitize=$opt"]} {
+ lappend sup $opt
+ }
+ }
+ }
+ if {[llength $sup] > 0} {
+ return "-fsanitize=[join $sup ,]"
+ }
+ return ""
+}
+
########################################################################
# Internal helper for proj-dump-defs-json. Expects to be passed a
# [define] name and the variadic $args which are passed to
diff --git a/autosetup/sqlite-config.tcl b/autosetup/sqlite-config.tcl
index 54daf7c8a3..3644b4872a 100644
--- a/autosetup/sqlite-config.tcl
+++ b/autosetup/sqlite-config.tcl
@@ -61,13 +61,21 @@ array set sqliteConfig [proj-strip-hash-comments {
set sqliteConfig(is-cross-compiling) [proj-is-cross-compiling]
########################################################################
-# Processes all configure --flags for this build $buildMode must be
-# either "canonical" or "autoconf", and others may be added in the
+# Processes all configure --flags for this build, run build-specific
+# config checks, then finalize the configure process. $buildMode must
+# be either "canonical" or "autoconf", and others may be added in the
# future. After bootstrapping, $configScript is eval'd in the caller's
# scope, then post-configuration finalization is run. $configScript is
# intended to hold configure code which is specific to the given
# $buildMode, with the caveat that _some_ build-specific code is
# encapsulated in the configuration finalization step.
+#
+# The intent is that all build-mode-specific configuration goes inside
+# the $configScript argument to this function, and that an auto.def file
+# contains only two commands:
+#
+# use sqlite-config
+# sqlite-configure BUILD_NAME { build-specific configure script }
proc sqlite-configure {buildMode configScript} {
set allBuildModes {canonical autoconf}
if {$buildMode ni $allBuildModes} {
@@ -89,6 +97,7 @@ proc sqlite-configure {buildMode configScript} {
# boolopt => "a boolean option which defaults to disabled"
# boolopt2=1 => "a boolean option which defaults to enabled"
# stringopt: => "an option which takes an argument, e.g. --stringopt=value"
+ # stringopt:DESCR => As for stringopt: with a description for the value
# stringopt2:=value => "an option where the argument is optional and defaults to 'value'"
# optalias booltopt3 => "a boolean with a hidden alias. --optalias is not shown in --help"
#
@@ -130,7 +139,7 @@ proc sqlite-configure {buildMode configScript} {
########################################################################
set allFlags {
# Structure: a list of M {Z} pairs, where M is a descriptive
- # option group name and Z is a list of X Y pairs. X is a list of
+ # option group name and Z is a list of X Y pairs. X is a list of
# $buildMode name(s) to which the Y flags apply, or {*} to apply
# to all builds. Y is a {block} in the form expected by
# autosetup's [options] command. Each block which is applicable
@@ -167,8 +176,8 @@ proc sqlite-configure {buildMode configScript} {
largefile=1
=> {This legacy flag has no effect on the library but may influence
the contents of the generated sqlite_cfg.h}
- # ^^^ It's not clear that this actually does anything, as
- # HAVE_LFS is not checked anywhere in the .c/.h/.in files.
+ # ^^^ It's not clear that LFS support actually does anything,
+ # as HAVE_LFS is not checked anywhere in the .c/.h/.in files.
load-extension=1 => {Disable loading of external extensions}
math=1 => {Disable math functions}
json=1 => {Disable JSON functions}
@@ -259,6 +268,10 @@ proc sqlite-configure {buildMode configScript} {
with-emsdk:=auto
=> {Top-most dir of the Emscripten SDK installation.
Needed only by ext/wasm. Default=EMSDK env var.}
+
+ amalgamation-extra-src:FILES
+ => {Space-separated list of soure files to append as-is to the resulting
+ sqlite3.c amalgamation file. May be provided multiple times.}
}
}
@@ -360,12 +373,13 @@ proc sqlite-configure {buildMode configScript} {
}; # sqlite-configure
########################################################################
-# Performs late-stage config steps common to both the canonical and
-# autoconf bundle builds.
+# Performs late-stage config steps common to all supported
+# $::sqliteConfig(build-mode) values.
proc sqlite-configure-finalize {} {
set buildMode $::sqliteConfig(build-mode)
set isCanonical [expr {$buildMode eq "canonical"}]
set isAutoconf [expr {$buildMode eq "autoconf"}]
+ proj-assert {$isCanonical || $isAutoconf} "Unknown build mode: $buildMode"
define HAVE_LFS 0
if {[opt-bool largefile]} {
@@ -412,6 +426,13 @@ proc sqlite-configure-finalize {} {
sqlite-handle-math
sqlite-handle-icu
sqlite-handle-env-quirks
+ sqlite-handle-common-feature-flags
+ sqlite-finalize-feature-flags
+ ########################################################################
+ # When cross-compiling, we have to avoid using the -s flag to
+ # /usr/bin/install:
+ # https://sqlite.org/forum/forumpost/9a67df63eda9925c
+ define IS_CROSS_COMPILING $::sqliteConfig(is-cross-compiling)
sqlite-process-dot-in-files
sqlite-post-config-validation
sqlite-dump-defines
@@ -428,12 +449,10 @@ proc sqlite-post-options-init {} {
define PACKAGE_URL {https://sqlite.org}
define PACKAGE_BUGREPORT [get-define PACKAGE_URL]/forum
define PACKAGE_STRING "[get-define PACKAGE_NAME] [get-define PACKAGE_VERSION]"
- #
- # Carry values from hidden --flag aliases over to their canonical
- # flag forms. This list must include only options which are common
- # to both the top-level auto.def and autoconf/auto.def.
- #
proj-xfer-options-aliases {
+ # Carry values from hidden --flag aliases over to their canonical
+ # flag forms. This list must include only options which are common
+ # to all build modes supported by [sqlite-configure].
with-readline-inc => with-readline-cflags
with-readline-lib => with-readline-ldflags
with-debug => debug
@@ -463,11 +482,9 @@ proc msg-debug {msg} {
########################################################################
# Sets up the SQLITE_AUTORECONFIG define.
proc sqlite-autoreconfig {} {
- #
# SQLITE_AUTORECONFIG contains make target rules for re-running the
# configure script with the same arguments it was initially invoked
- # with. This can be used to automatically reconfigure
- #
+ # with. This can be used to automatically reconfigure.
set squote {{arg} {
# Wrap $arg in single-quotes if it looks like it might need that
# to avoid mis-handling as a shell argument. We assume that $arg
@@ -502,6 +519,8 @@ proc sqlite-add-feature-flag {args} {
define-append OPT_FEATURE_FLAGS {*}$args
}
}
+
+########################################################################
# Appends $args, if not empty, to OPT_SHELL.
proc sqlite-add-shell-opt {args} {
if {"" ne $args} {
@@ -540,13 +559,11 @@ proc sqlite-check-common-bins {} {
# Run checks for system-level includes and libs which are common to
# both the canonical build and the "autoconf" bundle.
proc sqlite-check-common-system-deps {} {
- #
# Check for needed/wanted data types
cc-with {-includes stdint.h} \
{cc-check-types int8_t int16_t int32_t int64_t intptr_t \
uint8_t uint16_t uint32_t uint64_t uintptr_t}
- #
# Check for needed/wanted functions
cc-check-functions gmtime_r isnan localtime_r localtime_s \
malloc_usable_size strchrnul usleep utime pread pread64 pwrite pwrite64
@@ -561,7 +578,6 @@ proc sqlite-check-common-system-deps {} {
}
define LDFLAGS_RT [join [lsort -unique $ldrt] ""]
- #
# Check for needed/wanted headers
cc-check-includes \
sys/types.h sys/stat.h dlfcn.h unistd.h \
@@ -583,7 +599,6 @@ proc sqlite-check-common-system-deps {} {
########################################################################
# Move -DSQLITE_OMIT... and -DSQLITE_ENABLE... flags from CFLAGS and
# CPPFLAGS to OPT_FEATURE_FLAGS and remove them from BUILD_CFLAGS.
-# This is derived from the legacy build but is still practical.
proc sqlite-munge-cflags {} {
# Move CFLAGS and CPPFLAGS entries matching -DSQLITE_OMIT* and
# -DSQLITE_ENABLE* to OPT_FEATURE_FLAGS. This behavior is derived
@@ -730,6 +745,10 @@ proc sqlite-finalize-feature-flags {} {
define OPT_SHELL [lsort -unique $oFF]
msg-result "Shell options: [get-define OPT_SHELL]"
}
+ if {"" ne [set extraSrc [get-define AMALGAMATION_EXTRA_SRC ""]]} {
+ proj-assert {"canonical" eq $::sqliteConfig(build-mode)}
+ msg-result "Appending source files to amalgamation: $extraSrc"
+ }
}
########################################################################
@@ -1464,7 +1483,8 @@ proc sqlite-handle-out-implib {} {
#
# It does not distinguish between msys and msys2, returning msys for
# both. The build does not, as of this writing, specifically support
-# msys v1.
+# msys v1. Similarly, this function returns "mingw" for both "mingw32"
+# and "mingw64".
proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
if {"" eq $envTuple} {
set envTuple [get-define host]
@@ -1475,7 +1495,7 @@ proc sqlite-env-is-unix-on-windows {{envTuple ""}} {
*-*-ming* { set name mingw }
*-*-msys { set name msys }
}
- return $name;
+ return $name
}
########################################################################
@@ -1551,18 +1571,6 @@ proc sqlite-handle-env-quirks {} {
# Perform some late-stage work and generate the configure-process
# output file(s).
proc sqlite-process-dot-in-files {} {
- ########################################################################
- # When cross-compiling, we have to avoid using the -s flag to
- # /usr/bin/install:
- # https://sqlite.org/forum/forumpost/9a67df63eda9925c
- define IS_CROSS_COMPILING $::sqliteConfig(is-cross-compiling)
-
- # Finish up handling of the various feature flags here because it's
- # convenient for both the canonical build and autoconf bundles that
- # it be done here.
- sqlite-handle-common-feature-flags
- sqlite-finalize-feature-flags
-
########################################################################
# "Re-export" the autoconf-conventional --XYZdir flags into something
# which is more easily overridable from a make invocation. See the docs
@@ -1831,16 +1839,20 @@ proc sqlite-check-tcl {} {
if {"" eq $with_tclsh && $cfg ne ""} {
# We have tclConfig.sh but no tclsh. Attempt to locate a tclsh
# based on info from tclConfig.sh.
- proj-assert {"" ne [get-define TCL_EXEC_PREFIX]}
- set with_tclsh [get-define TCL_EXEC_PREFIX]/bin/tclsh[get-define TCL_VERSION]
- if {![file-isexec $with_tclsh]} {
- set with_tclsh2 [get-define TCL_EXEC_PREFIX]/bin/tclsh
- if {![file-isexec $with_tclsh2]} {
- proj-warn "Cannot find a usable tclsh (tried: $with_tclsh $with_tclsh2)"
- } else {
- set with_tclsh $with_tclsh2
+ set tclExecPrefix [get-define TCL_EXEC_PREFIX]
+ proj-assert {"" ne $tclExecPrefix}
+ set tryThese [list \
+ $tclExecPrefix/bin/tclsh[get-define TCL_VERSION] \
+ $tclExecPrefix/bin/tclsh ]
+ foreach trySh $tryThese {
+ if {[file-isexec $trySh]} {
+ set with_tclsh $trySh
+ break
}
}
+ if {![file-isexec $with_tclsh]} {
+ proj-warn "Cannot find a usable tclsh (tried: $tryThese)
+ }
}
define TCLSH_CMD $with_tclsh
if {$use_tcl} {
diff --git a/ext/fts3/README.syntax b/ext/fts3/README.syntax
index 0cab8fa048..d32ae384c5 100644
--- a/ext/fts3/README.syntax
+++ b/ext/fts3/README.syntax
@@ -62,20 +62,20 @@
matches rows that contain both the "engineering" and "consultancy" tokens
in the same column with not more than 10 other words between them. It does
not matter which of the two terms occurs first in the document, only that
- they be seperated by only 10 tokens or less. The user may also specify
+ they be separated by only 10 tokens or less. The user may also specify
a different required proximity by adding "/N" immediately after the NEAR
operator, where N is an integer. For example:
MATCH 'engineering NEAR/5 consultancy'
- searches for a row containing an instance of each specified token seperated
+ searches for a row containing an instance of each specified token separated
by not more than 5 other tokens. More than one NEAR operator can be used
in as sequence. For example this query:
MATCH 'reliable NEAR/2 engineering NEAR/5 consultancy'
searches for a row that contains an instance of the token "reliable"
- seperated by not more than two tokens from an instance of "engineering",
+ separated by not more than two tokens from an instance of "engineering",
which is in turn separated by not more than 5 other tokens from an
instance of the term "consultancy". Phrases enclosed in quotes may
also be used as arguments to the NEAR operator.
diff --git a/ext/fts3/fts3Int.h b/ext/fts3/fts3Int.h
index 06f3c6efec..a53ecdf17c 100644
--- a/ext/fts3/fts3Int.h
+++ b/ext/fts3/fts3Int.h
@@ -202,6 +202,19 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
#define deliberate_fall_through
+/*
+** Macros needed to provide flexible arrays in a portable way
+*/
+#ifndef offsetof
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
+
+
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
@@ -431,9 +444,13 @@ struct Fts3Phrase {
*/
int nToken; /* Number of tokens in the phrase */
int iColumn; /* Index of column this phrase must match */
- Fts3PhraseToken aToken[1]; /* One entry for each token in the phrase */
+ Fts3PhraseToken aToken[FLEXARRAY]; /* One for each token in the phrase */
};
+/* Size (in bytes) of an Fts3Phrase object large enough to hold N tokens */
+#define SZ_FTS3PHRASE(N) \
+ (offsetof(Fts3Phrase,aToken)+(N)*sizeof(Fts3PhraseToken))
+
/*
** A tree of these objects forms the RHS of a MATCH operator.
**
diff --git a/ext/fts3/fts3_expr.c b/ext/fts3/fts3_expr.c
index ca857835e2..681d4e8625 100644
--- a/ext/fts3/fts3_expr.c
+++ b/ext/fts3/fts3_expr.c
@@ -161,6 +161,23 @@ int sqlite3Fts3OpenTokenizer(
*/
static int fts3ExprParse(ParseContext *, const char *, int, Fts3Expr **, int *);
+/*
+** Search buffer z[], size n, for a '"' character. Or, if enable_parenthesis
+** is defined, search for '(' and ')' as well. Return the index of the first
+** such character in the buffer. If there is no such character, return -1.
+*/
+static int findBarredChar(const char *z, int n){
+ int ii;
+ for(ii=0; iiiLangid, z, i, &pCursor);
+ *pnConsumed = n;
+ rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
@@ -202,7 +212,18 @@ static int getNextToken(
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
- nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
+ /* Check that this tokenization did not gobble up any " characters. Or,
+ ** if enable_parenthesis is true, that it did not gobble up any
+ ** open or close parenthesis characters either. If it did, call
+ ** getNextToken() again, but pass only that part of the input buffer
+ ** up to the first such character. */
+ int iBarred = findBarredChar(z, iEnd);
+ if( iBarred>=0 ){
+ pModule->xClose(pCursor);
+ return getNextToken(pParse, iCol, z, iBarred, ppExpr, pnConsumed);
+ }
+
+ nByte = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1) + nToken;
pRet = (Fts3Expr *)sqlite3Fts3MallocZero(nByte);
if( !pRet ){
rc = SQLITE_NOMEM;
@@ -212,7 +233,7 @@ static int getNextToken(
pRet->pPhrase->nToken = 1;
pRet->pPhrase->iColumn = iCol;
pRet->pPhrase->aToken[0].n = nToken;
- pRet->pPhrase->aToken[0].z = (char *)&pRet->pPhrase[1];
+ pRet->pPhrase->aToken[0].z = (char*)&pRet->pPhrase->aToken[1];
memcpy(pRet->pPhrase->aToken[0].z, zToken, nToken);
if( iEnd=0 ){
+ *pnConsumed = iBarred;
+ }
rc = SQLITE_OK;
}
@@ -285,7 +310,7 @@ static int getNextString(
char *zTemp = 0;
i64 nTemp = 0;
- const int nSpace = sizeof(Fts3Expr) + sizeof(Fts3Phrase);
+ const int nSpace = sizeof(Fts3Expr) + SZ_FTS3PHRASE(1);
int nToken = 0;
/* The final Fts3Expr data structure, including the Fts3Phrase,
@@ -1239,7 +1264,6 @@ static void fts3ExprTestCommon(
}
if( rc!=SQLITE_OK && rc!=SQLITE_NOMEM ){
- sqlite3Fts3ExprFree(pExpr);
sqlite3_result_error(context, "Error parsing expression", -1);
}else if( rc==SQLITE_NOMEM || !(zBuf = exprToString(pExpr, 0)) ){
sqlite3_result_error_nomem(context);
diff --git a/ext/fts3/fts3_snippet.c b/ext/fts3/fts3_snippet.c
index 9ec7df3802..36ee94a48b 100644
--- a/ext/fts3/fts3_snippet.c
+++ b/ext/fts3/fts3_snippet.c
@@ -108,9 +108,13 @@ struct MatchinfoBuffer {
int nElem;
int bGlobal; /* Set if global data is loaded */
char *zMatchinfo;
- u32 aMatchinfo[1];
+ u32 aMI[FLEXARRAY];
};
+/* Size (in bytes) of a MatchinfoBuffer sufficient for N elements */
+#define SZ_MATCHINFOBUFFER(N) \
+ (offsetof(MatchinfoBuffer,aMI)+(((N)+1)/2)*sizeof(u64))
+
/*
** The snippet() and offsets() functions both return text values. An instance
@@ -135,13 +139,13 @@ struct StrBuffer {
static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
MatchinfoBuffer *pRet;
sqlite3_int64 nByte = sizeof(u32) * (2*(sqlite3_int64)nElem + 1)
- + sizeof(MatchinfoBuffer);
+ + SZ_MATCHINFOBUFFER(1);
sqlite3_int64 nStr = strlen(zMatchinfo);
pRet = sqlite3Fts3MallocZero(nByte + nStr+1);
if( pRet ){
- pRet->aMatchinfo[0] = (u8*)(&pRet->aMatchinfo[1]) - (u8*)pRet;
- pRet->aMatchinfo[1+nElem] = pRet->aMatchinfo[0]
+ pRet->aMI[0] = (u8*)(&pRet->aMI[1]) - (u8*)pRet;
+ pRet->aMI[1+nElem] = pRet->aMI[0]
+ sizeof(u32)*((int)nElem+1);
pRet->nElem = (int)nElem;
pRet->zMatchinfo = ((char*)pRet) + nByte;
@@ -155,10 +159,10 @@ static MatchinfoBuffer *fts3MIBufferNew(size_t nElem, const char *zMatchinfo){
static void fts3MIBufferFree(void *p){
MatchinfoBuffer *pBuf = (MatchinfoBuffer*)((u8*)p - ((u32*)p)[-1]);
- assert( (u32*)p==&pBuf->aMatchinfo[1]
- || (u32*)p==&pBuf->aMatchinfo[pBuf->nElem+2]
+ assert( (u32*)p==&pBuf->aMI[1]
+ || (u32*)p==&pBuf->aMI[pBuf->nElem+2]
);
- if( (u32*)p==&pBuf->aMatchinfo[1] ){
+ if( (u32*)p==&pBuf->aMI[1] ){
pBuf->aRef[1] = 0;
}else{
pBuf->aRef[2] = 0;
@@ -175,18 +179,18 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
if( p->aRef[1]==0 ){
p->aRef[1] = 1;
- aOut = &p->aMatchinfo[1];
+ aOut = &p->aMI[1];
xRet = fts3MIBufferFree;
}
else if( p->aRef[2]==0 ){
p->aRef[2] = 1;
- aOut = &p->aMatchinfo[p->nElem+2];
+ aOut = &p->aMI[p->nElem+2];
xRet = fts3MIBufferFree;
}else{
aOut = (u32*)sqlite3_malloc64(p->nElem * sizeof(u32));
if( aOut ){
xRet = sqlite3_free;
- if( p->bGlobal ) memcpy(aOut, &p->aMatchinfo[1], p->nElem*sizeof(u32));
+ if( p->bGlobal ) memcpy(aOut, &p->aMI[1], p->nElem*sizeof(u32));
}
}
@@ -196,7 +200,7 @@ static void (*fts3MIBufferAlloc(MatchinfoBuffer *p, u32 **paOut))(void*){
static void fts3MIBufferSetGlobal(MatchinfoBuffer *p){
p->bGlobal = 1;
- memcpy(&p->aMatchinfo[2+p->nElem], &p->aMatchinfo[1], p->nElem*sizeof(u32));
+ memcpy(&p->aMI[2+p->nElem], &p->aMI[1], p->nElem*sizeof(u32));
}
/*
diff --git a/ext/fts5/fts5Int.h b/ext/fts5/fts5Int.h
index 832f9ad477..2da347862e 100644
--- a/ext/fts5/fts5Int.h
+++ b/ext/fts5/fts5Int.h
@@ -75,6 +75,18 @@ typedef sqlite3_uint64 u64;
# define EIGHT_BYTE_ALIGNMENT(X) ((((uptr)(X) - (uptr)0)&7)==0)
#endif
+/*
+** Macros needed to provide flexible arrays in a portable way
+*/
+#ifndef offsetof
+# define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
+
#endif
/* Truncate very long tokens to this many bytes. Hard limit is
@@ -147,10 +159,11 @@ typedef struct Fts5Colset Fts5Colset;
*/
struct Fts5Colset {
int nCol;
- int aiCol[1];
+ int aiCol[FLEXARRAY];
};
-
+/* Size (int bytes) of a complete Fts5Colset object with N columns. */
+#define SZ_FTS5COLSET(N) (sizeof(i64)*((N+2)/2))
/**************************************************************************
** Interface to code in fts5_config.c. fts5_config.c contains contains code
diff --git a/ext/fts5/fts5_expr.c b/ext/fts5/fts5_expr.c
index dc2f7fb39c..d7574aec52 100644
--- a/ext/fts5/fts5_expr.c
+++ b/ext/fts5/fts5_expr.c
@@ -86,9 +86,13 @@ struct Fts5ExprNode {
/* Child nodes. For a NOT node, this array always contains 2 entries. For
** AND or OR nodes, it contains 2 or more entries. */
int nChild; /* Number of child nodes */
- Fts5ExprNode *apChild[1]; /* Array of child nodes */
+ Fts5ExprNode *apChild[FLEXARRAY]; /* Array of child nodes */
};
+/* Size (in bytes) of an Fts5ExprNode object that holds up to N children */
+#define SZ_FTS5EXPRNODE(N) \
+ (offsetof(Fts5ExprNode,apChild) + (N)*sizeof(Fts5ExprNode*))
+
#define Fts5NodeIsString(p) ((p)->eType==FTS5_TERM || (p)->eType==FTS5_STRING)
/*
@@ -119,9 +123,13 @@ struct Fts5ExprPhrase {
Fts5ExprNode *pNode; /* FTS5_STRING node this phrase is part of */
Fts5Buffer poslist; /* Current position list */
int nTerm; /* Number of entries in aTerm[] */
- Fts5ExprTerm aTerm[1]; /* Terms that make up this phrase */
+ Fts5ExprTerm aTerm[FLEXARRAY]; /* Terms that make up this phrase */
};
+/* Size (in bytes) of an Fts5ExprPhrase object that holds up to N terms */
+#define SZ_FTS5EXPRPHRASE(N) \
+ (offsetof(Fts5ExprPhrase,aTerm) + (N)*sizeof(Fts5ExprTerm))
+
/*
** One or more phrases that must appear within a certain token distance of
** each other within each matching document.
@@ -130,9 +138,12 @@ struct Fts5ExprNearset {
int nNear; /* NEAR parameter */
Fts5Colset *pColset; /* Columns to search (NULL -> all columns) */
int nPhrase; /* Number of entries in aPhrase[] array */
- Fts5ExprPhrase *apPhrase[1]; /* Array of phrase pointers */
+ Fts5ExprPhrase *apPhrase[FLEXARRAY]; /* Array of phrase pointers */
};
+/* Size (in bytes) of an Fts5ExprNearset object covering up to N phrases */
+#define SZ_FTS5EXPRNEARSET(N) \
+ (offsetof(Fts5ExprNearset,apPhrase)+(N)*sizeof(Fts5ExprPhrase*))
/*
** Parse context.
@@ -292,7 +303,7 @@ int sqlite3Fts5ExprNew(
/* If the LHS of the MATCH expression was a user column, apply the
** implicit column-filter. */
if( sParse.rc==SQLITE_OK && iColnCol ){
- int n = sizeof(Fts5Colset);
+ int n = SZ_FTS5COLSET(1);
Fts5Colset *pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&sParse.rc, n);
if( pColset ){
pColset->nCol = 1;
@@ -1650,7 +1661,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
if( pParse->rc==SQLITE_OK ){
if( pNear==0 ){
sqlite3_int64 nByte;
- nByte = sizeof(Fts5ExprNearset) + SZALLOC * sizeof(Fts5ExprPhrase*);
+ nByte = SZ_FTS5EXPRNEARSET(SZALLOC+1);
pRet = sqlite3_malloc64(nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
@@ -1661,7 +1672,7 @@ Fts5ExprNearset *sqlite3Fts5ParseNearset(
int nNew = pNear->nPhrase + SZALLOC;
sqlite3_int64 nByte;
- nByte = sizeof(Fts5ExprNearset) + nNew * sizeof(Fts5ExprPhrase*);
+ nByte = SZ_FTS5EXPRNEARSET(nNew+1);
pRet = (Fts5ExprNearset*)sqlite3_realloc64(pNear, nByte);
if( pRet==0 ){
pParse->rc = SQLITE_NOMEM;
@@ -1752,12 +1763,12 @@ static int fts5ParseTokenize(
int nNew = SZALLOC + (pPhrase ? pPhrase->nTerm : 0);
pNew = (Fts5ExprPhrase*)sqlite3_realloc64(pPhrase,
- sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
+ SZ_FTS5EXPRPHRASE(nNew+1)
);
if( pNew==0 ){
rc = SQLITE_NOMEM;
}else{
- if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
+ if( pPhrase==0 ) memset(pNew, 0, SZ_FTS5EXPRPHRASE(1));
pCtx->pPhrase = pPhrase = pNew;
pNew->nTerm = nNew - SZALLOC;
}
@@ -1865,7 +1876,7 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
if( sCtx.pPhrase==0 ){
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, sizeof(Fts5ExprPhrase));
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&pParse->rc, SZ_FTS5EXPRPHRASE(1));
}else if( sCtx.pPhrase->nTerm ){
sCtx.pPhrase->aTerm[sCtx.pPhrase->nTerm-1].bPrefix = (u8)bPrefix;
}
@@ -1900,19 +1911,18 @@ int sqlite3Fts5ExprClonePhrase(
sizeof(Fts5ExprPhrase*));
}
if( rc==SQLITE_OK ){
- pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNode));
+ pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRNODE(1));
}
if( rc==SQLITE_OK ){
- pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
- sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
+ pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
+ SZ_FTS5EXPRNEARSET(2));
}
if( rc==SQLITE_OK && ALWAYS(pOrig!=0) ){
Fts5Colset *pColsetOrig = pOrig->pNode->pNear->pColset;
if( pColsetOrig ){
sqlite3_int64 nByte;
Fts5Colset *pColset;
- nByte = sizeof(Fts5Colset) + (pColsetOrig->nCol-1) * sizeof(int);
+ nByte = SZ_FTS5COLSET(pColsetOrig->nCol);
pColset = (Fts5Colset*)sqlite3Fts5MallocZero(&rc, nByte);
if( pColset ){
memcpy(pColset, pColsetOrig, (size_t)nByte);
@@ -1940,7 +1950,7 @@ int sqlite3Fts5ExprClonePhrase(
}else{
/* This happens when parsing a token or quoted phrase that contains
** no token characters at all. (e.g ... MATCH '""'). */
- sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
+ sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, SZ_FTS5EXPRPHRASE(1));
}
}
@@ -2034,7 +2044,7 @@ static Fts5Colset *fts5ParseColset(
assert( pParse->rc==SQLITE_OK );
assert( iCol>=0 && iColpConfig->nCol );
- pNew = sqlite3_realloc64(p, sizeof(Fts5Colset) + sizeof(int)*nCol);
+ pNew = sqlite3_realloc64(p, SZ_FTS5COLSET(nCol+1));
if( pNew==0 ){
pParse->rc = SQLITE_NOMEM;
}else{
@@ -2069,7 +2079,7 @@ Fts5Colset *sqlite3Fts5ParseColsetInvert(Fts5Parse *pParse, Fts5Colset *p){
int nCol = pParse->pConfig->nCol;
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(&pParse->rc,
- sizeof(Fts5Colset) + sizeof(int)*nCol
+ SZ_FTS5COLSET(nCol+1)
);
if( pRet ){
int i;
@@ -2130,7 +2140,7 @@ Fts5Colset *sqlite3Fts5ParseColset(
static Fts5Colset *fts5CloneColset(int *pRc, Fts5Colset *pOrig){
Fts5Colset *pRet;
if( pOrig ){
- sqlite3_int64 nByte = sizeof(Fts5Colset) + (pOrig->nCol-1) * sizeof(int);
+ sqlite3_int64 nByte = SZ_FTS5COLSET(pOrig->nCol);
pRet = (Fts5Colset*)sqlite3Fts5MallocZero(pRc, nByte);
if( pRet ){
memcpy(pRet, pOrig, (size_t)nByte);
@@ -2298,7 +2308,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
assert( pNear->nPhrase==1 );
assert( pParse->bPhraseToAnd );
- nByte = sizeof(Fts5ExprNode) + nTerm*sizeof(Fts5ExprNode*);
+ nByte = SZ_FTS5EXPRNODE(nTerm+1);
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
if( pRet ){
pRet->eType = FTS5_AND;
@@ -2308,7 +2318,7 @@ static Fts5ExprNode *fts5ParsePhraseToAnd(
pParse->nPhrase--;
for(ii=0; iirc, sizeof(Fts5ExprPhrase)
+ &pParse->rc, SZ_FTS5EXPRPHRASE(1)
);
if( pPhrase ){
if( parseGrowPhraseArray(pParse) ){
@@ -2377,7 +2387,7 @@ Fts5ExprNode *sqlite3Fts5ParseNode(
if( pRight->eType==eType ) nChild += pRight->nChild-1;
}
- nByte = sizeof(Fts5ExprNode) + sizeof(Fts5ExprNode*)*(nChild-1);
+ nByte = SZ_FTS5EXPRNODE(nChild);
pRet = (Fts5ExprNode*)sqlite3Fts5MallocZero(&pParse->rc, nByte);
if( pRet ){
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 70a4752e26..63840de1fb 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -422,9 +422,13 @@ struct Fts5Structure {
u64 nOriginCntr; /* Origin value for next top-level segment */
int nSegment; /* Total segments in this structure */
int nLevel; /* Number of levels in this index */
- Fts5StructureLevel aLevel[1]; /* Array of nLevel level objects */
+ Fts5StructureLevel aLevel[FLEXARRAY]; /* Array of nLevel level objects */
};
+/* Size (in bytes) of an Fts5Structure object holding up to N levels */
+#define SZ_FTS5STRUCTURE(N) \
+ (offsetof(Fts5Structure,aLevel) + (N)*sizeof(Fts5StructureLevel))
+
/*
** An object of type Fts5SegWriter is used to write to segments.
*/
@@ -554,11 +558,15 @@ struct Fts5SegIter {
** Array of tombstone pages. Reference counted.
*/
struct Fts5TombstoneArray {
- int nRef; /* Number of pointers to this object */
+ int nRef; /* Number of pointers to this object */
int nTombstone;
- Fts5Data *apTombstone[1]; /* Array of tombstone pages */
+ Fts5Data *apTombstone[FLEXARRAY]; /* Array of tombstone pages */
};
+/* Size (in bytes) of an Fts5TombstoneArray holding up to N tombstones */
+#define SZ_FTS5TOMBSTONEARRAY(N) \
+ (offsetof(Fts5TombstoneArray,apTombstone)+(N)*sizeof(Fts5Data*))
+
/*
** Argument is a pointer to an Fts5Data structure that contains a
** leaf page.
@@ -627,9 +635,12 @@ struct Fts5Iter {
i64 iSwitchRowid; /* Firstest rowid of other than aFirst[1] */
Fts5CResult *aFirst; /* Current merge state (see above) */
- Fts5SegIter aSeg[1]; /* Array of segment iterators */
+ Fts5SegIter aSeg[FLEXARRAY]; /* Array of segment iterators */
};
+/* Size (in bytes) of an Fts5Iter object holding up to N segment iterators */
+#define SZ_FTS5ITER(N) (offsetof(Fts5Iter,aSeg)+(N)*sizeof(Fts5SegIter))
+
/*
** An instance of the following type is used to iterate through the contents
** of a doclist-index record.
@@ -656,9 +667,13 @@ struct Fts5DlidxLvl {
struct Fts5DlidxIter {
int nLvl;
int iSegid;
- Fts5DlidxLvl aLvl[1];
+ Fts5DlidxLvl aLvl[FLEXARRAY];
};
+/* Size (in bytes) of an Fts5DlidxIter object with up to N levels */
+#define SZ_FTS5DLIDXITER(N) \
+ (offsetof(Fts5DlidxIter,aLvl)+(N)*sizeof(Fts5DlidxLvl))
+
static void fts5PutU16(u8 *aOut, u16 iVal){
aOut[0] = (iVal>>8);
aOut[1] = (iVal&0xFF);
@@ -1026,7 +1041,7 @@ int sqlite3Fts5StructureTest(Fts5Index *p, void *pStruct){
static void fts5StructureMakeWritable(int *pRc, Fts5Structure **pp){
Fts5Structure *p = *pp;
if( *pRc==SQLITE_OK && p->nRef>1 ){
- i64 nByte = sizeof(Fts5Structure)+(p->nLevel-1)*sizeof(Fts5StructureLevel);
+ i64 nByte = SZ_FTS5STRUCTURE(p->nLevel);
Fts5Structure *pNew;
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(pRc, nByte);
if( pNew ){
@@ -1100,10 +1115,7 @@ static int fts5StructureDecode(
){
return FTS5_CORRUPT;
}
- nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel-1) /* aLevel[] array */
- );
+ nByte = SZ_FTS5STRUCTURE(nLevel);
pRet = (Fts5Structure*)sqlite3Fts5MallocZero(&rc, nByte);
if( pRet ){
@@ -1183,10 +1195,7 @@ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){
if( *pRc==SQLITE_OK ){
Fts5Structure *pStruct = *ppStruct;
int nLevel = pStruct->nLevel;
- sqlite3_int64 nByte = (
- sizeof(Fts5Structure) + /* Main structure */
- sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */
- );
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(nLevel+2);
pStruct = sqlite3_realloc64(pStruct, nByte);
if( pStruct ){
@@ -1725,7 +1734,7 @@ static Fts5DlidxIter *fts5DlidxIterInit(
int bDone = 0;
for(i=0; p->rc==SQLITE_OK && bDone==0; i++){
- sqlite3_int64 nByte = sizeof(Fts5DlidxIter) + i * sizeof(Fts5DlidxLvl);
+ sqlite3_int64 nByte = SZ_FTS5DLIDXITER(i+1);
Fts5DlidxIter *pNew;
pNew = (Fts5DlidxIter*)sqlite3_realloc64(pIter, nByte);
@@ -1943,7 +1952,7 @@ static void fts5SegIterSetNext(Fts5Index *p, Fts5SegIter *pIter){
static void fts5SegIterAllocTombstone(Fts5Index *p, Fts5SegIter *pIter){
const int nTomb = pIter->pSeg->nPgTombstone;
if( nTomb>0 ){
- int nByte = nTomb * sizeof(Fts5Data*) + sizeof(Fts5TombstoneArray);
+ int nByte = SZ_FTS5TOMBSTONEARRAY(nTomb+1);
Fts5TombstoneArray *pNew;
pNew = (Fts5TombstoneArray*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pNew ){
@@ -3404,8 +3413,7 @@ static Fts5Iter *fts5MultiIterAlloc(
for(nSlot=2; nSlotaSeg[] */
+ SZ_FTS5ITER(nSlot) + /* pNew + pNew->aSeg[] */
sizeof(Fts5CResult) * nSlot /* pNew->aFirst[] */
);
if( pNew ){
@@ -5771,7 +5779,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
Fts5Structure *pStruct
){
Fts5Structure *pNew = 0;
- sqlite3_int64 nByte = sizeof(Fts5Structure);
+ sqlite3_int64 nByte = SZ_FTS5STRUCTURE(1);
int nSeg = pStruct->nSegment;
int i;
@@ -5801,6 +5809,7 @@ static Fts5Structure *fts5IndexOptimizeStruct(
}
nByte += (((i64)pStruct->nLevel)+1) * sizeof(Fts5StructureLevel);
+ assert( nByte==SZ_FTS5STRUCTURE(pStruct->nLevel+2) );
pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte);
if( pNew ){
@@ -6377,9 +6386,13 @@ struct Fts5TokenDataIter {
int nIterAlloc;
Fts5PoslistReader *aPoslistReader;
int *aPoslistToIter;
- Fts5Iter *apIter[1];
+ Fts5Iter *apIter[FLEXARRAY];
};
+/* Size in bytes of an Fts5TokenDataIter object holding up to N iterators */
+#define SZ_FTS5TOKENDATAITER(N) \
+ (offsetof(Fts5TokenDataIter,apIter) + (N)*sizeof(Fts5Iter))
+
/*
** The two input arrays - a1[] and a2[] - are in sorted order. This function
** merges the two arrays together and writes the result to output array
@@ -6642,7 +6655,7 @@ static void fts5SetupPrefixIter(
&& p->pConfig->bPrefixInsttoken
){
s.pTokendata = &s2;
- s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, sizeof(*s2.pT));
+ s2.pT = (Fts5TokenDataIter*)fts5IdxMalloc(p, SZ_FTS5TOKENDATAITER(1));
}
if( p->pConfig->eDetail==FTS5_DETAIL_NONE ){
@@ -6770,15 +6783,17 @@ int sqlite3Fts5IndexRollback(Fts5Index *p){
** and the initial version of the "averages" record (a zero-byte blob).
*/
int sqlite3Fts5IndexReinit(Fts5Index *p){
- Fts5Structure s;
+ Fts5Structure *pTmp;
+ u8 tmpSpace[SZ_FTS5STRUCTURE(1)];
fts5StructureInvalidate(p);
fts5IndexDiscardData(p);
- memset(&s, 0, sizeof(Fts5Structure));
+ pTmp = (Fts5Structure*)tmpSpace;
+ memset(pTmp, 0, SZ_FTS5STRUCTURE(1));
if( p->pConfig->bContentlessDelete ){
- s.nOriginCntr = 1;
+ pTmp->nOriginCntr = 1;
}
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
- fts5StructureWrite(p, &s);
+ fts5StructureWrite(p, pTmp);
return fts5IndexReturn(p);
}
@@ -6986,7 +7001,7 @@ static Fts5TokenDataIter *fts5AppendTokendataIter(
if( p->rc==SQLITE_OK ){
if( pIn==0 || pIn->nIter==pIn->nIterAlloc ){
int nAlloc = pIn ? pIn->nIterAlloc*2 : 16;
- int nByte = nAlloc * sizeof(Fts5Iter*) + sizeof(Fts5TokenDataIter);
+ int nByte = SZ_FTS5TOKENDATAITER(nAlloc+1);
Fts5TokenDataIter *pNew = (Fts5TokenDataIter*)sqlite3_realloc(pIn, nByte);
if( pNew==0 ){
@@ -7502,7 +7517,8 @@ static int fts5SetupPrefixIterTokendata(
fts5BufferGrow(&p->rc, &token, nToken+1);
assert( token.p!=0 || p->rc!=SQLITE_OK );
- ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*ctx.pT));
+ ctx.pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
+ SZ_FTS5TOKENDATAITER(1));
if( p->rc==SQLITE_OK ){
@@ -7633,7 +7649,8 @@ int sqlite3Fts5IndexIterWriteTokendata(
if( pIter->nSeg>0 ){
/* This is a prefix term iterator. */
if( pT==0 ){
- pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc, sizeof(*pT));
+ pT = (Fts5TokenDataIter*)sqlite3Fts5MallocZero(&p->rc,
+ SZ_FTS5TOKENDATAITER(1));
pIter->pTokenDataIter = pT;
}
if( pT ){
diff --git a/ext/fts5/fts5_main.c b/ext/fts5/fts5_main.c
index 4d5e3cd4f3..e888abf215 100644
--- a/ext/fts5/fts5_main.c
+++ b/ext/fts5/fts5_main.c
@@ -170,9 +170,11 @@ struct Fts5Sorter {
i64 iRowid; /* Current rowid */
const u8 *aPoslist; /* Position lists for current row */
int nIdx; /* Number of entries in aIdx[] */
- int aIdx[1]; /* Offsets into aPoslist for current row */
+ int aIdx[FLEXARRAY]; /* Offsets into aPoslist for current row */
};
+/* Size (int bytes) of an Fts5Sorter object with N indexes */
+#define SZ_FTS5SORTER(N) (offsetof(Fts5Sorter,nIdx)+((N+2)/2)*sizeof(i64))
/*
** Virtual-table cursor object.
@@ -1050,7 +1052,7 @@ static int fts5CursorFirstSorted(
const char *zRankArgs = pCsr->zRankArgs;
nPhrase = sqlite3Fts5ExprPhraseCount(pCsr->pExpr);
- nByte = sizeof(Fts5Sorter) + sizeof(int) * (nPhrase-1);
+ nByte = SZ_FTS5SORTER(nPhrase);
pSorter = (Fts5Sorter*)sqlite3_malloc64(nByte);
if( pSorter==0 ) return SQLITE_NOMEM;
memset(pSorter, 0, (size_t)nByte);
diff --git a/ext/misc/completion.c b/ext/misc/completion.c
index 54abc0ae15..0a6db1a224 100644
--- a/ext/misc/completion.c
+++ b/ext/misc/completion.c
@@ -41,6 +41,11 @@ SQLITE_EXTENSION_INIT1
#ifndef SQLITE_OMIT_VIRTUALTABLE
+#ifndef IsAlnum
+#define IsAlnum(X) isalnum((unsigned char)X)
+#endif
+
+
/* completion_vtab is a subclass of sqlite3_vtab which will
** serve as the underlying representation of a completion virtual table
*/
@@ -377,7 +382,7 @@ static int completionFilter(
}
if( pCur->zLine!=0 && pCur->zPrefix==0 ){
int i = pCur->nLine;
- while( i>0 && (isalnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
+ while( i>0 && (IsAlnum(pCur->zLine[i-1]) || pCur->zLine[i-1]=='_') ){
i--;
}
pCur->nPrefix = pCur->nLine - i;
diff --git a/ext/misc/decimal.c b/ext/misc/decimal.c
index b0eeb96e33..60488a0012 100644
--- a/ext/misc/decimal.c
+++ b/ext/misc/decimal.c
@@ -27,6 +27,9 @@ SQLITE_EXTENSION_INIT1
# define UNUSED_PARAMETER(X) (void)(X)
#endif
+#ifndef IsSpace
+#define IsSpace(X) isspace((unsigned char)X)
+#endif
/* A decimal object */
typedef struct Decimal Decimal;
@@ -76,7 +79,7 @@ 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++){}
+ for(i=0; IsSpace(zIn[i]); i++){}
if( zIn[i]=='-' ){
p->sign = 1;
i++;
diff --git a/ext/misc/series.c b/ext/misc/series.c
index d500842d56..04644dd603 100644
--- a/ext/misc/series.c
+++ b/ext/misc/series.c
@@ -519,8 +519,7 @@ static int seriesFilter(
pCur->ss.iBase += ((d+szStep-1)/szStep)*szStep;
}
if( pCur->ss.iTerm>iMax ){
- sqlite3_uint64 d = pCur->ss.iTerm - iMax;
- pCur->ss.iTerm -= ((d+szStep-1)/szStep)*szStep;
+ pCur->ss.iTerm = iMax;
}
}else{
sqlite3_int64 szStep = -pCur->ss.iStep;
@@ -530,8 +529,7 @@ static int seriesFilter(
pCur->ss.iBase -= ((d+szStep-1)/szStep)*szStep;
}
if( pCur->ss.iTermss.iTerm;
- pCur->ss.iTerm += ((d+szStep-1)/szStep)*szStep;
+ pCur->ss.iTerm = iMin;
}
}
}
diff --git a/ext/recover/recoverslowidx.test b/ext/recover/recoverslowidx.test
index 269105113d..36842b8a64 100644
--- a/ext/recover/recoverslowidx.test
+++ b/ext/recover/recoverslowidx.test
@@ -39,6 +39,7 @@ do_test 1.2 {
} [list {*}{
{BEGIN}
{PRAGMA writable_schema = on}
+ {PRAGMA foreign_keys = off}
{PRAGMA encoding = 'UTF-8'}
{PRAGMA page_size = '1024'}
{PRAGMA auto_vacuum = '0'}
@@ -67,6 +68,7 @@ do_test 1.4 {
} [list {*}{
{BEGIN}
{PRAGMA writable_schema = on}
+ {PRAGMA foreign_keys = off}
{PRAGMA encoding = 'UTF-8'}
{PRAGMA page_size = '1024'}
{PRAGMA auto_vacuum = '0'}
diff --git a/ext/recover/sqlite3recover.c b/ext/recover/sqlite3recover.c
index 58d726f599..d50aa25ea0 100644
--- a/ext/recover/sqlite3recover.c
+++ b/ext/recover/sqlite3recover.c
@@ -33,6 +33,16 @@ typedef unsigned int u32;
typedef unsigned char u8;
typedef sqlite3_int64 i64;
+/*
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
+** to avoid complaints from -fsanitize=strict-bounds.
+*/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
+
typedef struct RecoverTable RecoverTable;
typedef struct RecoverColumn RecoverColumn;
@@ -140,9 +150,12 @@ struct RecoverColumn {
typedef struct RecoverBitmap RecoverBitmap;
struct RecoverBitmap {
i64 nPg; /* Size of bitmap */
- u32 aElem[1]; /* Array of 32-bit bitmasks */
+ u32 aElem[FLEXARRAY]; /* Array of 32-bit bitmasks */
};
+/* Size in bytes of a RecoverBitmap object sufficient to cover 32 pages */
+#define SZ_RECOVERBITMAP_32 (16)
+
/*
** State variables (part of the sqlite3_recover structure) used while
** recovering data for tables identified in the recovered schema (state
@@ -382,7 +395,7 @@ static int recoverError(
*/
static RecoverBitmap *recoverBitmapAlloc(sqlite3_recover *p, i64 nPg){
int nElem = (nPg+1+31) / 32;
- int nByte = sizeof(RecoverBitmap) + nElem*sizeof(u32);
+ int nByte = SZ_RECOVERBITMAP_32 + nElem*sizeof(u32);
RecoverBitmap *pRet = (RecoverBitmap*)recoverMalloc(p, nByte);
if( pRet ){
@@ -2574,37 +2587,53 @@ static void recoverUninstallWrapper(sqlite3_recover *p){
static void recoverStep(sqlite3_recover *p){
assert( p && p->errCode==SQLITE_OK );
switch( p->eState ){
- case RECOVER_STATE_INIT:
+ case RECOVER_STATE_INIT: {
+ int bUseWrapper = 1;
/* This is the very first call to sqlite3_recover_step() on this object.
*/
recoverSqlCallback(p, "BEGIN");
recoverSqlCallback(p, "PRAGMA writable_schema = on");
+ recoverSqlCallback(p, "PRAGMA foreign_keys = off");
recoverEnterMutex();
- recoverInstallWrapper(p);
/* Open the output database. And register required virtual tables and
** user functions with the new handle. */
recoverOpenOutput(p);
- /* Open transactions on both the input and output databases. */
- sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
- recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
- recoverExec(p, p->dbIn, "BEGIN");
- if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
- recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
- recoverTransferSettings(p);
- recoverOpenRecovery(p);
- recoverCacheSchema(p);
+ /* Attempt to open a transaction and read page 1 of the input database.
+ ** Two attempts may be made - one with a wrapper installed to ensure
+ ** that the database header is sane, and then if that attempt returns
+ ** SQLITE_NOTADB, then again with no wrapper. The second attempt is
+ ** required for encrypted databases. */
+ if( p->errCode==SQLITE_OK ){
+ do{
+ p->errCode = SQLITE_OK;
+ if( bUseWrapper ) recoverInstallWrapper(p);
+
+ /* Open a transaction on the input database. */
+ sqlite3_file_control(p->dbIn, p->zDb, SQLITE_FCNTL_RESET_CACHE, 0);
+ recoverExec(p, p->dbIn, "PRAGMA writable_schema = on");
+ recoverExec(p, p->dbIn, "BEGIN");
+ if( p->errCode==SQLITE_OK ) p->bCloseTransaction = 1;
+ recoverExec(p, p->dbIn, "SELECT 1 FROM sqlite_schema");
+ recoverTransferSettings(p);
+ recoverOpenRecovery(p);
+ recoverCacheSchema(p);
+
+ if( bUseWrapper ) recoverUninstallWrapper(p);
+ }while( p->errCode==SQLITE_NOTADB
+ && (bUseWrapper--)
+ && SQLITE_OK==sqlite3_exec(p->dbIn, "ROLLBACK", 0, 0, 0)
+ );
+ }
- recoverUninstallWrapper(p);
recoverLeaveMutex();
-
recoverExec(p, p->dbOut, "BEGIN");
-
recoverWriteSchema1(p);
p->eState = RECOVER_STATE_WRITING;
break;
+ }
case RECOVER_STATE_WRITING: {
if( p->w1.pTbls==0 ){
diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c
index 21c87bdc76..5e9fa6996e 100644
--- a/ext/rtree/rtree.c
+++ b/ext/rtree/rtree.c
@@ -94,6 +94,14 @@ typedef unsigned int u32;
# define ALWAYS(X) (X)
# define NEVER(X) (X)
#endif
+#ifndef offsetof
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
#endif /* !defined(SQLITE_AMALGAMATION) */
/* Macro to check for 4-byte alignment. Only used inside of assert() */
@@ -414,9 +422,13 @@ struct RtreeMatchArg {
RtreeGeomCallback cb; /* Info about the callback functions */
int nParam; /* Number of parameters to the SQL function */
sqlite3_value **apSqlParam; /* Original SQL parameter values */
- RtreeDValue aParam[1]; /* Values for parameters to the SQL function */
+ RtreeDValue aParam[FLEXARRAY]; /* Values for parameters to the SQL function */
};
+/* Size of an RtreeMatchArg object with N parameters */
+#define SZ_RTREEMATCHARG(N) \
+ (offsetof(RtreeMatchArg,aParam)+(N)*sizeof(RtreeDValue))
+
#ifndef MAX
# define MAX(x,y) ((x) < (y) ? (y) : (x))
#endif
@@ -4369,8 +4381,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
sqlite3_int64 nBlob;
int memErr = 0;
- nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
- + nArg*sizeof(sqlite3_value*);
+ nBlob = SZ_RTREEMATCHARG(nArg) + nArg*sizeof(sqlite3_value*);
pBlob = (RtreeMatchArg *)sqlite3_malloc64(nBlob);
if( !pBlob ){
sqlite3_result_error_nomem(ctx);
diff --git a/main.mk b/main.mk
index 14f3232d81..e0ed6a1b80 100644
--- a/main.mk
+++ b/main.mk
@@ -22,10 +22,10 @@ all:
#
# $(TOP) =
#
-# The toplevel directory of the source tree. For canonical builds
+# The top-level directory of the source tree. For canonical builds
# this is the directory that contains this "Makefile.in" and the
-# "configure.in" script. For out-of-tree builds, this will differ
-# from $(PWD).
+# "auto.def" script. For out-of-tree builds, this will differ from
+# $(PWD).
#
TOP ?= $(PWD)
#
@@ -115,8 +115,8 @@ JIMSH ?= ./jimsh$(T.exe)
#
# The TCL interpreter for in-tree code generation. May be either the
# in-tree JimTCL ($(JIMSH)) or the canonical TCL ($(TCLSH_CMD). If
-# it's JimTCL, it must be compiled with -DHAVE_REALPATH or
-# -DHAVE__FULLPATH.
+# it's JimTCL, it must be compiled with -DHAVE_REALPATH (Unix) or
+# -DHAVE__FULLPATH (Windows).
#
B.tclsh ?= $(JIMSH)
@@ -231,6 +231,13 @@ LINK_TOOLS_DYNAMICALLY ?= 0
# Optional flags for the amalgamation generator.
#
AMALGAMATION_GEN_FLAGS ?= --linemacros=0
+#
+# EXTRA_SRC = list of C files to append as-is to the generated
+# amalgamation. It should arguably be called AMALGAMATION_EXTRA_SRC
+# but this older name is already in use by clients.
+#
+EXTRA_SRC ?=
+
#
# $(OPT_FEATURE_FLAGS) =
#
@@ -448,8 +455,9 @@ $(install-dir.all):
# to an empty string.
#
# 2) Ensure that it is built with -DJIM_COMPAT (which may be
-# hard-coded into jimsh0.c). Without this, the [expr] command
-# accepts only a single argument.
+# hard-coded into jimsh0.c). Without this, the [expr] command accepts
+# only a single argument. (That said: the real fix for that is to
+# update any scripts which still pass multiple arguments to [expr].)
#
$(JIMSH): $(TOP)/autosetup/jimsh0.c
$(B.cc) -o $@ $(CFLAGS.jimsh) $(TOP)/autosetup/jimsh0.c
@@ -1102,7 +1110,7 @@ sqlite3.h: $(MAKE_SANITY_CHECK) $(TOP)/src/sqlite.h.in \
$(B.tclsh) $(TOP)/tool/mksqlite3h.tcl $(TOP) -o sqlite3.h
sqlite3.c: .target_source sqlite3.h $(TOP)/tool/mksqlite3c.tcl src-verify$(B.exe) \
- $(B.tclsh)
+ $(B.tclsh) $(EXTRA_SRC)
$(B.tclsh) $(TOP)/tool/mksqlite3c.tcl $(AMALGAMATION_GEN_FLAGS) $(EXTRA_SRC)
cp tsrc/sqlite3ext.h .
cp $(TOP)/ext/session/sqlite3session.h .
@@ -2163,8 +2171,11 @@ fuzzcheck$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP)
fuzzy: fuzzcheck$(T.exe)
xbin: fuzzcheck$(T.exe)
+# -fsanitize=... flags for fuzzcheck-asan.
+CFLAGS.fuzzcheck.fsanitize ?= -fsanitize=address
+
fuzzcheck-asan$(T.exe): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP)
- $(T.link) -o $@ -fsanitize=address $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) \
+ $(T.link) -o $@ $(CFLAGS.fuzzcheck.fsanitize) $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) \
sqlite3.c $(LDFLAGS.libsqlite3)
fuzzy: fuzzcheck-asan$(T.exe)
xbin: fuzzcheck-asan$(T.exe)
@@ -2336,6 +2347,9 @@ stmt.o: $(TOP)/ext/misc/stmt.c $(DEPS_EXT_COMMON)
#
# Windows section
#
+# 2025-03-03: sqlite3.def and sqlite3.dll might no longer be relevant
+# in this particular build, but that's difficult to verify.
+#
dll: sqlite3.dll
sqlite3.def: $(LIBOBJ)
echo 'EXPORTS' >sqlite3.def
@@ -2348,6 +2362,7 @@ sqlite3.dll: $(LIBOBJ) sqlite3.def
#
# Emit a list of commonly-used targets
+#
help:
@echo; echo "Frequently-used high-level make targets:"; echo; \
echo " - all [default] = builds most components"; \
@@ -2370,14 +2385,15 @@ help:
echo
+#
# Remove build products sufficient so that subsequent makes will recompile
# everything from scratch. Do not remove:
#
# * test results and test logs
# * output from ./configure
#
-tidy-.:
-tidy: tidy-.
+#
+tidy:
rm -f *.o *.c *.da *.bb *.bbg gmon.* *.rws sqlite3$(T.exe)
rm -f fts5.h keywordhash.h opcodes.h sqlite3.h sqlite3ext.h sqlite3session.h
rm -rf .libs .deps tsrc .target_source
@@ -2409,16 +2425,23 @@ tidy: tidy-.
#
# Removes build products and test logs. Retains ./configure outputs.
#
-clean-.:
-clean: clean-. tidy
+clean: tidy
rm -rf omittest* testrunner* testdir*
-# Clean up everything. No exceptions.
-distclean-.:
-distclean: distclean-. clean
+#
+# Clean up everything. No exceptions. From an out-of-tree build which
+# starts in an empty directory, this should result in an empty
+# directory (assuming the user does not create new files in this
+# directory).
+#
+# The main distclean rules are in Makefile.in.
+#
+distclean: clean
+#
# Show important variable settings.
+#
show-variables:
@echo "CC = $(CC)"
@echo "B.cc = $(B.cc)"
diff --git a/manifest b/manifest
index dd9082c0d7..0779c866c5 100644
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Update\sLemon\sso\sthat\sit\saccepts\sfilename\sarguments\sto\sdirectives\slike\n"%include".\s\sEx:\s\s"%include\s<./subdir/file-to-include.txt>".\nThis\swas\scapability\sneeded\sby\spikchr\sand\sbackported\shere\sfor\ssafe\skeeping.\nSQLite\sdoes\snot\sneed\sthis\scapability,\sthough\sit\sdoesn't\shurt\sto\shave\sit\sin\stree.
-D 2025-03-05T13:39:33.597
+C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sreuse-schema\sbranch.
+D 2025-03-15T20:35:24.375
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md e108e1e69ae8e8a59e93c455654b8ac9356a11720d3345df2a4743e9590fb20d
-F Makefile.in 4ff9b301b59c66ef9d11c8d133cc62e09173bad4abc7d5eb801e45d5527f8fe6
+F Makefile.in 2788f5a3c36e26817707003170871936d44f46c5b45f8cbefe07c9f1a51a8988
F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
F Makefile.msc 40a852813c2c84efd579f34b881f9169020284ac80d3d56463b88158e2f1c00e
F README.md a953c0cffd6e4f2501a306c00ee2b6e1e6630c25031e094629307fe99dd003d1
@@ -14,9 +14,9 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F art/sqlite370.svg 40b7e2fe8aac3add5d56dd86ab8d427a4eca5bcb3fe4f8946cb3794e1821d531
-F auto.def f39c4f3e58c8c2853555c7ec65c20701f8a42554d23dcb175a346a4f5ee5a36d
+F auto.def 619383263dfd0ee31df6a9d3e9828f65943d9fbcd274084046680641e5de53cb
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
-F autoconf/Makefile.in c9a7007181df2a07d08bd63c6ba395ed38705aa218789726951aabebec32ee27
+F autoconf/Makefile.in 6c98c82f52aa27a5c586080cf7c61c811174c2b6d8b8de33fd657d78d541dd7d
F autoconf/Makefile.msc 5bc67d3912444c40c6f96d003e5c90663e51abb83d204a520110b1b2038dcd8b
F autoconf/README.first f1d3876e9a7852c22f275a6f06814e64934cecbc0b5b9617d64849094c1fd136
F autoconf/README.txt 1a32296d8bbdd67110c79d224c92c05545a0b5bd0c272950025fe3c7c7b49580
@@ -49,8 +49,8 @@ F autosetup/cc-shared.tcl 4f024e94a47f427ba61de1739f6381ef0080210f9fae89112d5c1d
F autosetup/cc.tcl c0fcc50ca91deff8741e449ddad05bcd08268bc31177e613a6343bbd1fd3e45f
F autosetup/jimsh0.c a57c16e65dcffc9c76e496757cb3f7fb47e01ecbd1631a0a5e01751fc856f049
F autosetup/pkg-config.tcl 4e635bf39022ff65e0d5434339dd41503ea48fc53822c9c5bde88b02d3d952ba
-F autosetup/proj.tcl e69b91f814ea510057ce7663845de703c3746d71cff9a0db6b2563ee3e7fd25e
-F autosetup/sqlite-config.tcl 1d0c70f372c464c9849dde898b5e778f73c72d8183c6e62634a45ee123e37f89
+F autosetup/proj.tcl bacaf1ed827067942a6d33f2a5c95bd649ceacae2a8ddc584d0f74456fb9167e
+F autosetup/sqlite-config.tcl a7f4d093d63bc1da9ec3d44f392f377ce4c86aa7e48532ae51619e55558f5fbe
F autosetup/system.tcl 51d4be76cd9a9074704b584e5c9cbba616202c8468cf9ba8a4f8294a7ab1dba9
F configure 9a00b21dfd13757bbfb8d89b30660a89ec1f8f3a79402b8f9f9b6fc475c3303a x
F contrib/sqlitecon.tcl eb4c6578e08dd353263958da0dc620f8400b869a50d06e271ab0be85a51a08d3
@@ -76,19 +76,19 @@ F ext/expert/sqlite3expert.c cf4b1e5584862f486a4c6014ddb081831f1c512065dcf356446
F ext/expert/sqlite3expert.h ca81efc2679a92373a13a3e76a6138d0310e32be53d6c3bfaedabd158ea8969b
F ext/expert/test_expert.c b767b2039a0df707eb3147e86bcf68b252d8455d9a41774b1a836cd052ceca70
F ext/fts3/README.content b9078d0843a094d86af0d48dffbff13c906702b4c3558012e67b9c7cc3bf59ee
-F ext/fts3/README.syntax 6d0cbd8caa7ea34ecb0f0ae8278217180a8b7f24a1ea50ddf765383669f494a9
+F ext/fts3/README.syntax b72477722e9b4fe43f8403227d790a1c94221bfad15c27863a4b36d1052e892b
F ext/fts3/README.tokenizers b92bdeb8b46503f0dd301d364efc5ef59ef9fa8e2758b8e742f39fa93a2e422d
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c fd2a8642fa4701ef5dd6bce7947ecb3c7ae472e1d44022772454a8b74a13155d
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
-F ext/fts3/fts3Int.h 75b9cf37c93d3c56d8e569d64527c927cb54a5279afb3823740ca1e29e481c15
+F ext/fts3/fts3Int.h ad51347fa5a5a49f6c3bd40a961eafd08f1e410f60b64dea06f115697a2ad9fe
F ext/fts3/fts3_aux.c 7eab82a9cf0830f6551ba3abfdbe73ed39e322a4d3940ee82fbf723674ecd9f3
-F ext/fts3/fts3_expr.c 673bf600655f5080239ff0e1e80eaae0176389f7e7d3af54c6d51491280ca360
+F ext/fts3/fts3_expr.c 5c13796638d8192c388777166075cdc8bc4b6712024cd5b72c31acdbefce5984
F ext/fts3/fts3_hash.c d9dba473741445789330c7513d4f65737c92df23c3212784312931641814672a
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c 305ce7fb6036484085b5556a9c8e62acdc7763f0f4cdf5fd538212a9f3720116
F ext/fts3/fts3_porter.c 024417020c57dd1ab39816f5fe6cf45222a857b78a1f6412f040ada1ceabd4ff
-F ext/fts3/fts3_snippet.c ac402ba81ce9503a54238f975d870384f8b9fb3680f6b86eb7a1be44829a1cee
+F ext/fts3/fts3_snippet.c 55506af9c656d06ad6acef0735b67749d199617421f2e66c5b7101745b9cf1ba
F ext/fts3/fts3_term.c 6a96027ad364001432545fe43322b6af04ed28bb5619ec51af1f59d0710d6d69
F ext/fts3/fts3_test.c 7a9cb3d61774134211bf4bfdf1adcb581a1a0377f2d050a121ae7ab44baef0e3
F ext/fts3/fts3_tokenize_vtab.c 7fd9ef364f257b97218b9c331f2378e307375c592f70fd541f714e747d944962
@@ -107,14 +107,14 @@ F ext/fts3/unicode/mkunicode.tcl cbf5f7b5c8ce8014bad731f246f2e520eece908465de477
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl 009cf59c77afa86d137b0cca3e3b1a5efbe2264faa2df233f9a7aa8563926d15
F ext/fts5/fts5.h ff5d3cc88b29e41612bfb29eb723e29e38973de62ca75ba3e8f94ccb67f5b5f2
-F ext/fts5/fts5Int.h 6abff7dd770dc5969c994c281e6e77fc277ce414d56cc4a62c145cc7036b0b67
+F ext/fts5/fts5Int.h bffbd0acdcdf509899681f4e1cfeef1c955030acd9fe15ff9082410f80c3bead
F ext/fts5/fts5_aux.c da4a7a9a11ec15c6df0699d908915a209bcde48f0b04101461316b59f71abffb
F ext/fts5/fts5_buffer.c f1e6d0324d7c55329d340673befc26681a372a4d36086caa8d1ec7d7c53066c7
F ext/fts5/fts5_config.c e7d8dd062b44a66cd77e5a0f74f23a2354cd1f3f8575afb967b2773c3384f7f8
-F ext/fts5/fts5_expr.c 4a35c6edc4a36862597532ace43db20f5dfd4a2f789d4fa1dd7786b677b73036
+F ext/fts5/fts5_expr.c 887a611b34094c828ff5fb19bbc50a6b1bbfd28791db01b0c8bf722e3c9f437a
F ext/fts5/fts5_hash.c a6266cedd801ab7964fa9e74ebcdda6d30ec6a96107fa24148ec6b7b5b80f6e0
-F ext/fts5/fts5_index.c 2f35dd8408946f0e0bfea8f3bfbe8dfaafe90a5345885b43d678546c19266673
-F ext/fts5/fts5_main.c b0e95a793f3c649d313c536269403e1a413ee665223adb5f8196edd2bc1146f7
+F ext/fts5/fts5_index.c d171f2a507abccb3d524bf461b01f0d3971a9bf221be622ac7c671a991cb62ee
+F ext/fts5/fts5_main.c 57933c18efe1058d8871199875c7a59744dabc3904f3aefbf9ff4a4e11fc79e2
F ext/fts5/fts5_storage.c 1ad05dab4830a4e2eaf2900bb143477f93bc17437093582f36f4b818809e88d8
F ext/fts5/fts5_tcl.c 7fb5a3d3404099075aaa2457307cb459bbc257c0de3dbd52b1e80a5b503e0329
F ext/fts5/fts5_test_mi.c d35fdd50db99a775a040fb57127a45adc968e97da94ae784eec664256ac86db2
@@ -410,11 +410,11 @@ F ext/misc/carray.c 34fac63770971611c5285de0a9f0ac67d504eaf66be891f637add9290f1c
F ext/misc/carray.h 503209952ccf2431c7fd899ebb92bf46bf7635b38aace42ec8aa1b8d7b6e98a5
F ext/misc/cksumvfs.c 3a7931dd30667be6348af919f3f9e6188dfd7646b42af8e399a499b327f5bd63
F ext/misc/closure.c 87e0967772e0087e709887ce7ca9cf13aa32d2096e33b5d3382c8b8d477c6cb1
-F ext/misc/completion.c cb978c88d5577821323617a8ea775ce1b920e02dcdb593858f02044a4d008eea
+F ext/misc/completion.c c3c8b3cc1293c34f04f8746a3adfbfedb43f00d113f8c984a1ed09433317e507
F ext/misc/compress.c 2c79a74330e0e0ba6cb3f7397f8ba5af12d46377ef5d3ee075e12dd8a6ed57f0
F ext/misc/csv.c 7cae8c2666a058a58fb8994ed2457339a06c97d31c251d9a8445cdd966629890
F ext/misc/dbdump.c b8592f6f2da292c62991a13864a60d6c573c47a9cc58362131b9e6a64f823e01
-F ext/misc/decimal.c 0e6edab8b055230e0ad0787d2e4b84b01f302168c7621042f7e6d7a3c1d98230
+F ext/misc/decimal.c 228d47e9ef4de60daf5851da19e3ac9ac1eda9e94432816914469501db6a1129
F ext/misc/eval.c 04bc9aada78c888394204b4ed996ab834b99726fb59603b0ee3ed6e049755dc1
F ext/misc/explain.c 606100185fb90d6a1eade1ed0414d53503c86820d8956a06e3b0a56291894f2b
F ext/misc/fileio.c 07cf3109ec6452789e3a989a010234e2a17b599ce82ea29212c948572456abac
@@ -437,7 +437,7 @@ F ext/misc/regexp.c 388e7f237307c7dfbfb8dde44e097946f6c437801d63f0d7ad63f3320d4e
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
F ext/misc/scrub.c 2a44b0d44c69584c0580ad2553f6290a307a49df4668941d2812135bfb96a946
-F ext/misc/series.c 13c13768db923313c561851c7feb0adf5c456a40d01bf7c57051895f3e4b81c7
+F ext/misc/series.c 69e0d2b5d193c67bdfee5baf79c10ec24a61a40212c7ca9c219edf7afa24305f
F ext/misc/sha1.c cb5002148c2661b5946f34561701e9105e9d339b713ec8ac057fd888b196dcb9
F ext/misc/shathree.c fd22d70620f86a0467acfdd3acd8435d5cb54eb1e2d9ff36ae44e389826993df
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
@@ -522,9 +522,9 @@ F ext/recover/recoverfault2.test 730e7371bcda769554d15460cb23126abba1be8eca9539c
F ext/recover/recoverold.test 68db3d6f85dd2b98e785b6c4da4f5eea4bbe52ccf6674d9a94c7506dc92596aa
F ext/recover/recoverpgsz.test 88766fcb810e52ee05335c456d4e5fb06d02b73d3ccb48c52bf293434305e2b1
F ext/recover/recoverrowid.test f948bf4024a5f41b0e21b8af80c60564c5b5d78c05a8d64fc00787715ff9f45f
-F ext/recover/recoverslowidx.test 5205a9742dd9490ee99950dabb622307355ef1662dea6a3a21030057bfd81411
+F ext/recover/recoverslowidx.test c90d59c46bb8924a973ac6fbc38f3163cee38cc240256addcab1cf1a322c37dc
F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e41e4b8eab20486
-F ext/recover/sqlite3recover.c 788438a6735108d14ca82cf39c59abf8cde2ee384b962fb93e975eb24f2732fe
+F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
F ext/recover/test_recover.c 072260d7452a3b81aba995b2b3269e7ec2aa7f06725544ba4c25b1b0a1dbc61a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
@@ -538,7 +538,7 @@ F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c3350
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
F ext/rtree/geopoly.c f0573d5109fdc658a180db0db6eec86ab2a1cf5ce58ec66cbf3356167ea757eb
-F ext/rtree/rtree.c 980f84e9fecfa99f80ae066e13b198505790449542f802d6b6466ed839149af4
+F ext/rtree/rtree.c 99dade93b5ca1c1fa4a5ba1381140d88b27a52573a92897827d9eb2a8059a460
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
F ext/rtree/rtree1.test e0608db762b2aadca0ecb6f97396cf66244490adc3ba88f2a292b27be3e1da3e
F ext/rtree/rtree2.test 9d9deddbb16fd0c30c36e6b4fdc3ee3132d765567f0f9432ee71e1303d32603d
@@ -706,7 +706,7 @@ F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36
F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
F ext/wasm/wasmfs.make 68999f5bd8c489239592d59a420f8c627c99169bbd6fa16a404751f757b9f702
F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk 178381be0b2cdcb14f49af1e0b0b679b6626089df9da097563333a265c67db32
+F main.mk 00e3e96c95693a2f9db99470a5ad733b82b6293f8ea6a03c7f9a4921b94bf1a3
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
F mptest/crash01.test 61e61469e257df0850df4293d7d4d6c2af301421
@@ -716,7 +716,7 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 acdff36db796e2d00225b911d3047d580cd136547298435426ce9d40347973cc
F sqlite3.pc.in 0977c03a4da7c4204bd60e784a0efb8d51a190448aba78a4e973fe7192bdaf03
-F src/alter.c 4b855e10b66524fe39f3cc0fc19500593e0a0d7e9c77c17a5a8ad689356230e4
+F src/alter.c 14f2cc098a78f0dce00fa1e101ec288de25d021cf372cda200037df7251a8d63
F src/analyze.c b8662a13798064f01eef20d3f59e83f9f5b1860de131b526aec298180601f2de
F src/attach.c 82a709d96b7043d9c9c52589e77ee5420415809d765405b0cc2f35894dd3fb13
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
@@ -726,14 +726,14 @@ F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 00fcee37947641f48d4b529d96143e74d056b7afa8f26d61292c90ee59c056b2
F src/btree.h 18e5e7b2124c23426a283523e5f31a4bff029131b795bb82391f9d2f3136fc50
F src/btreeInt.h 9c0f9ea5c9b5f4dcaea18111d43efe95f2ac276cd86d770dce10fd99ccc93886
-F src/build.c 259abd6d09b8692553bfa7670ff807091af1219d44d3ee467e283b99656878e0
+F src/build.c 058ce32d3f0cb72d740f18227934aeb32e90c021b293ed453c37525b1998be8d
F src/callback.c dd68d54c81989e9ba846464ffc5cc122ac83fe6686fabc6cf38d9e0f480c6879
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/date.c 9db4d604e699a73e10b8e85a44db074a1f04c0591a77e2abfd77703f50dce1e9
F src/dbpage.c 2e677acb658a29965e55398bbc61161cb7819da538057c8032adac7ab8e4a8c0
F src/dbstat.c 73362c0df0f40ad5523a6f5501224959d0976757b511299bf892313e79d14f5c
F src/delete.c 03a77ba20e54f0f42ebd8eddf15411ed6bdb06a2c472ac4b6b336521bf7cea42
-F src/expr.c f27e2692e65f0600cf4c989ec2af36bdfab52ada6365c0cc0f434630157b877f
+F src/expr.c 61c3baab38f1b50eb4696e1f37c8f7ae1d1ecbfc1a35d446cfd1886624784131
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 928ed2517e8732113d2b9821aa37af639688d752f4ea9ac6e0e393d713eeb76f
F src/func.c 7686ea382b20e8bfe2ab9de76150c99ee7b6e83523561f3c7787e0f68cb435c2
@@ -746,7 +746,7 @@ F src/insert.c a5f0366266be993ebf533808f22cb7a788624805b55bc45424ceed3f48c54a16
F src/json.c 81e2012796a0e139b18c50ee3444c8ef86a020ab360511882216f5b610657e0c
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
F src/loadext.c 7432c944ff197046d67a1207790a1b13eec4548c85a9457eb0896bb3641dfb36
-F src/main.c 65ffb80350bf390245de6222bade5fcc69a4a93b8b70b880ec68b7776dd21ca0
+F src/main.c a3f2f92765ace08ec85aaac7982606d38043aa50e03a6178069c02a42429ec4b
F src/malloc.c 410e570b30c26cc36e3372577df50f7a96ee3eed5b2b161c6b6b48773c650c5e
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c 3bb59158c38e05f6270e761a9f435bf19827a264c13d1631c58b84bdc96d73b2
@@ -775,23 +775,23 @@ F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
F src/parse.y e426d7323311554c75b0aebc426d0fe3c88d9777ffefed236f343ad9e661dc4c
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
-F src/pcache1.c 78d4935e510f7bed0fdd1a3f742c0e663b36a795f9dc7411161dc22bdae1245e
+F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
F src/pragma.c 22c184ba97a2d5880aae074edbcf3f862a0198b9d8f5ef1ee7ee96d883858f88
F src/prepare.c 64fb8aaf3c0ad0a5a12472bd7f5ec8d2e569f186c555e6ad4bf962d751e30325
F src/printf.c 33fc0d7643c848a098afdcb6e1db6de12379d47084b1cd0912cfce1d09345e44
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
-F src/resolve.c 626c24b258b111f75c22107aa5614ad89810df3026f5ca071116d3fe75925c75
+F src/resolve.c 20e1fbe8f840ffc0cd835e33f68a802a22e34faa918d7a269f3de242fda02f99
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c a076f7db3a0fcbd9f710d7746cfc07e0b3baadee45eb3136bedc29c598ef8f1c
-F src/shell.c.in a363e56e095003a31a5b6cadb369883682456f80147307a395b5c7babcd0f018
-F src/sqlite.h.in 7c58f9f9f7ed6d30d0783162f7d9f12ede11e833bac77b176aaa28aeca77bb12
+F src/select.c 8c273248e38a8a7286abe3f41c1931cc65eff602fef128acc0cc0484e1b7abb3
+F src/shell.c.in 4ef33d12944dca85d08732426fcd3e1c45f4ed7c0fa0de7fc3bf0e59317bb257
+F src/sqlite.h.in 6051a203938c432762c79ea1a2a812f4ad251ebc64e0dc1123eca32aa94e236b
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 3f046c04ea3595d6bfda99b781926b17e672fd6d27da2ba6d8d8fc39981dcb54
-F src/sqliteInt.h b6c47ecbe197adb620ce3d43415ff2d2519e53a5d634ec9c055ee193df72776c
+F src/sqliteInt.h d6d6946eb8cee2465632ac28767bc457a9c061b178b1e6223b64f80b699667ea
F src/sqliteLimit.h 6d817c28a8f19af95e6f4921933b7fbbca48a962bce0eb0ec81e8bb3ef38e68b
F src/status.c 9adeef15f9b2bd4a72ccd22b1f29e34dea6ca898baf420016332ba7e63f55539
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
-F src/tclsqlite.c 09d33ad9a35929f997d7152e9aa1d4d62757ce6e73d237dbe33f11261e4778ae
+F src/tclsqlite.c 9e4e8708e3832d86d4c62687d2d853d6ff59417ef1955f85a7e7c5680d63a313
F src/tclsqlite.h 65e2c761446e1c9fa0342b7d2612a703483643c8b6a316d12a65b745a4727395
F src/test1.c ba7b93478a6a7a3f48ec5507f28bc662636ac5d9f9791700d3648a8e788f0bb2
F src/test2.c 7ebc518e6735939d8979273a6f7b1d9b5702babf059f6ad62499f7f60a9eb9a3
@@ -844,32 +844,32 @@ F src/test_windirent.h da2e5b73c32d09905fbdd00f27cd802212a32a58ead882736fe4f5eb7
F src/test_window.c 6d80e11fba89a1796525e6f0048ff0c7789aa2c6b0b11c80827dc1437bd8ea72
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
-F src/tokenize.c 375a772e2342274f4bf73605a70633237da09deed00a9bf4c4816a56777ea7c9
+F src/tokenize.c 3e37ac2b6cbb9b0abe33827b0153c27595269afd7152b48019808974481aca2c
F src/treeview.c d85ce76e6d1498d781957c07cb234da6d77ce0ed2d196480d516f54dabc62279
-F src/trigger.c 24e5859e35eb5214ccea0da6924f0f90d41095091b0fc7247b6803e7d9a700f1
+F src/trigger.c 968330bc57239db219ec4828890d0981f470ae2a59a788a6b0282ca4b7a9f888
F src/update.c 3e5e7ff66fa19ebe4d1b113d480639a24cc1175adbefabbd1a948a07f28e37cf
F src/upsert.c 215328c3f91623c520ec8672c44323553f12caeb4f01b1090ebdca99fdf7b4f1
F src/utf.c d4d55ca95106a2029ec1cdbd2497a34e69ea1d338f1a9d80ef15ebf4ff01690d
F src/util.c 36fb1150062957280777655976f3f9a75db236cb8207a0770ceae8d5ec17fcd3
-F src/vacuum.c 38577d6f45e10a984720b5219be09ca8649a0e600c2e5c11993900446caca609
-F src/vdbe.c dac8b4bf8e0a2451690aeb3a8384202e6498c8ec45477be0d0440b23fb52bce2
-F src/vdbe.h e56df3f84b08dfb60120796591af7d36fba8513a7df2605425189253f5a76d5f
-F src/vdbeInt.h 078b1c15b26587b54c1c1879d0d2f4dec812b9de4c337fed9faf73fbcc3bf091
-F src/vdbeapi.c cb8eb9e41a16f5fa3ce5b8f3910edfbba336d10156cfb7a79f92cf7bf443977b
-F src/vdbeaux.c 57b1ec1862d5d081294e3f266a20128837f21774215134b96a883b5d3cf8a70f
-F src/vdbeblob.c e14d9eca0cce3ec4fbef69cea8cc4caefb9f8d642cc4703123a56c43dfa470d3
+F src/vacuum.c b2486d14abfae09830e214d942e804b041efa2d30a8c568bcfb52b131bf24537
+F src/vdbe.c a40fe0860bf510cacae3c02ceaef893d96016e654e5d0dd28785a4e5447f1e4e
+F src/vdbe.h ba31115371f311763bb138991ca73c953e28facb2db81cbc38fb460d4913687c
+F src/vdbeInt.h 5446f60e89b2aa7cdf3ab0ec4e7b01b8732cd9d52d9092a0b8b1bf700768f784
+F src/vdbeapi.c a9ad72afed9aaec2acdde4daa5caa2f342b298f8c8859704143f6e3b78cb9966
+F src/vdbeaux.c add2fbdc28ae6ca1d67b56a6f99a6b677052806c2b117f55bae813db8850b04a
+F src/vdbeblob.c cdaded7d7581e4b2fd3f7a40c4bfe542688eb692d00760fcc2206c721681ea19
F src/vdbemem.c 571ae3116dbf840a62c4aaa6bc09d577dfef8ad4d3978cf37275bb5f9653217b
-F src/vdbesort.c f7ce6eb4c0e8b0273329d2f43b8b6e5ebe8f2d853fc323d5787dada702ea0b66
+F src/vdbesort.c 49e366d0216c782eba287bf602384e4330d2526a22f1275492d2785ce103c79b
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c fc46b9cbd759dc013f0b3724549cc0d71379183c667df3a5988f7e2f1bd485f3
F src/vtab.c 0c2567d6caa2f1df28362eedcd29a2fbc9f4d7a7ff6b13086cc23f4e6ab239c5
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
-F src/wal.c 2c69a5f92270429db72d853691b0640c76c671d5b2465396dadb9d9873e1efce
+F src/wal.c 554a6b1afaaecb98cb47bb598bccf1374c9d3b624e5c4c3c4eb2ad364cc579f8
F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
F src/walker.c d5006d6b005e4ea7302ad390957a8d41ed83faa177e412f89bc5600a7462a014
-F src/where.c 4ef72b4d791fb1b6725d6fbebd17e5a9487105864c7828a7b0311136c08786ce
-F src/whereInt.h d20cddddb1d61b18d5cb1fcfa9b77fbeebbc4afe44d996e603452a23b3009ee1
-F src/wherecode.c 5baa06f0daae7d38aca1d4814030b82ad4f127fe6bad18f0644776a474f6088b
+F src/where.c d71673580b3a02a442838967d7b97061353bf1784bfb00e63b05370c4ba715e9
+F src/whereInt.h ecdbfb5551cf394f04ec7f0bc7ad963146d80eee3071405ac29aa84950128b8e
+F src/wherecode.c 0d3de258d7922aede028841c6e0060633c50be26737c92cc62ce8be280535430
F src/whereexpr.c 2415c8eee5ff89a8b709d7d83d71c1ff986cd720d0520057e1d8a5371339012a
F src/window.c d01227141f622f24fbe36ca105fbe6ef023f9fd98f1ccd65da95f88886565db5
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
@@ -1280,7 +1280,7 @@ F test/fuzz3.test 70ba57260364b83e964707b9d4b5625284239768ab907dd387c740c0370ce3
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl b7197de6ed1ee8250a4f82d67876f4561b42ee8cbbfc6160dcb66331bad3f830
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
-F test/fuzzcheck.c 97eab1b916d576a0f734b921598bdac05ff04d1f15c494dbe40ca71a772c56bb
+F test/fuzzcheck.c e94511f5f5b8c134c83535b4799004b85ead69ed8375d74e9af90e41549a82ad
F test/fuzzdata1.db 3e86d9cf5aea68ddb8e27c02d7dfdaa226347426c7eb814918e4d95475bf8517
F test/fuzzdata2.db 128b3feeb78918d075c9b14b48610145a0dd4c8d6f1ca7c2870c7e425f5bf31f
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
@@ -1562,7 +1562,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
F test/readonly.test 69a7ccec846cad2e000b3539d56360d02f327061dc5e41f7f9a3e01f19719952
F test/readonly2.test 4f4c451adf06e314c3eeed5c5e01e5df8fa10fb3cd5f537a77a48ef50ed97b84
F test/readonlyfault.test 2b9c98ed3ac47e3f3cb00db3850b4d7fc7c857be1502a7b74985fecf50837b1e
-F test/recover.test a163a156ea9f2beea63fa83c4dcd8dea6e57b8a569fc647155e3d2754eaac1b5
+F test/recover.test c76d05f33f0271fba0f0752170e03b0ab5952dc61dcea7ab3ba40df03c4c42de
F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1
F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5
F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d
@@ -1637,7 +1637,7 @@ F test/selectH.test 0b54599f1917d99568c9b929df22ec6261ed7b6d2f02a46b5945ef81b787
F test/session.test 78fa2365e93d3663a6e933f86e7afc395adf18be
F test/sessionfuzz-data1.db 1f8d5def831f19b1c74571037f0d53a588ea49a6c4ca2a028fc0c27ef896dbcb
F test/sessionfuzz.c f693b8827034a3bed7616d89c65fb4fe8b7ff3c0f000c6ea6beda69b7f1aced3
-F test/shared.test f022874d9d299fe913529dc10f52ad5a386e4e7ff709270b9b1111b3a0f3420a
+F test/shared.test c99510b83a6ad650d7335e4733568b9d7b4f5ee88f4f2167b6138950a795b537
F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test f8cd07c1a2b7cdb315c01671a0b2f8e3830b11ef31da6baa9a9cd8da88965403
F test/shared4.test c75f476804e76e26bf6fa0e7b421fb0ca7d07558
@@ -1728,9 +1728,9 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a067468b43b8cb2305e9f9fe414e5f40c875bb5d2cba5f00b8154396e95fcf37
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
-F test/tabfunc01.test 7be82bd50c7ede7f01b2dd17cd1b84f352c516078222d0b067d858f081e3f9a7
+F test/tabfunc01.test 66d1ea27289c19317bf111744a4d5fda901759945d22ddb5bc964641fc38c185
F test/table.test 7862a00b58b5541511a26757ea9c5c7c3f8298766e98aa099deec703d9c0a8e0
-F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
+F test/tableapi.test e37c33e6be2276e3a96bb54b00eea7f321277115d10e5b30fdb52a112b432750
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
F test/tclsqlite.test 350536a4233914aa437b6735e3e8e683e921a71ced8fa9fb5396057a04dbea33
F test/tempdb.test 4cdaa23ddd8acb4d79cbb1b68ccdfd09b0537aaba909ca69a876157c2a2cbd08
@@ -1740,7 +1740,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptable2.test 76821347810ecc88203e6ef0dd6897b6036ac788e9dd3e6b04fd4d1631311a16
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
-F test/tester.tcl d067f95c685087f9e66efa2c4cefa5d99cd72ebeab2a7dceae89cba100ad61f7
+F test/tester.tcl 33733fbe8e7be1004d5eed5808ba397b3cf9c4f34240267ca3dae540baae4d88
F test/testrunner.tcl fafc60461c165a6b53a879f090423eef7005d95f9692c7df798651b55e339fe6 x
F test/testrunner_data.tcl 6aea1cb5865f005986037c9dad4dfe48a5281ec7aa214104e8ada3199332242b
F test/thread001.test a0985c117eab62c0c65526e9fa5d1360dd1cac5b03bde223902763274ce21899
@@ -2040,7 +2040,7 @@ F test/walro.test cb438d05ba0d191f10b688e39c4f0cd5b71569a1d1f4440e5bdf3c6880e08c
F test/walro2.test 33955a6fd874dd9724005e17f77fef89d334b3171454a1256fe4941a96766cdc
F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cfd51af68
F test/walseh1.test bae700eb99519b6d5cd3f893c04759accc5a59c391d4189fe4dd6995a533442b
-F test/walsetlk.test 9c5b92f9a20252540fedf9ffa6ee3d1b8af08ea4b80d0144d9b88e6c0c1de80d
+F test/walsetlk.test aaa418dc2c11002b3e270f8128235a3bbb846796907095a0a02bf0f0bbf8512e
F test/walsetlk2.test 9097083633cdf55bf1098b694fb8651d0356d38fef28b869481d18029d7ceaf4
F test/walsetlk3.test 1b82bd92dea7e58f498b4399b0b3d26773dd8ac5c74205ce4a23c207cb8e85fe
F test/walshared.test 42e3808582504878af237ea02c42ca793e8a0efaa19df7df26ac573370dbc7a3
@@ -2205,7 +2205,7 @@ F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
F tool/spellsift.tcl 52b4b04dc4333c7ab024f09d9d66ed6b6f7c6eb00b38497a09f338fa55d40618 x
F tool/split-sqlite3c.tcl 07e18a1d8cc3f6b3a4a1f3528e63c9b29a5c8a7bca0b8d394b231da464ce1247
F tool/sqldiff.c 134be7866be19f8beb32043d5aea5657f01aaeae2df8d33d758ff722c78666b9
-F tool/sqlite3_analyzer.c.in fc7735c499d226a49d843d8209b2543e4e5229eeb71a674c331323a2217b65b4
+F tool/sqlite3_analyzer.c.in 5a2984ac457a49c7ad4f0924c738df55aafdc97661e912fd99c5cfcdfd4725fd
F tool/sqlite3_rsync.c 9a1cca2ab1271c59b37a6493c15dc1bcd0ab9149197a9125926bc08dd26b83fb
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
@@ -2225,8 +2225,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
F tool/warnings.sh 49a486c5069de041aedcbde4de178293e0463ae9918ecad7539eedf0ec77a139
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 559560da45d0e22ccc6f47dd9eb5ba16851ea444da7e4e951f07b8aa6f6b3753
-R 07ddd929d7c988ac87c481e6c4cfbbbc
+P 52b97a7ad5d944e44240f624b30a76398d10ef945d8edc4b7d7b36ed2e515327 d4307a0d43f42e96ec06ad2c1d8d0f5c8ecae759bae8231b1998633089809f49
+R e7d3d5e6b947d70f26ddd6da2233849d
U drh
-Z c7f5ed8a6a37ec5d454f01999c7e18cd
+Z 23267b5f236cf4d85e561175d3335b1b
# Remove this line to create a well-formed Fossil manifest.
diff --git a/manifest.uuid b/manifest.uuid
index eadf04136e..ce0e299e5c 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-52b97a7ad5d944e44240f624b30a76398d10ef945d8edc4b7d7b36ed2e515327
+271e0373a812d8da153a0e74adec2605d4d8b71e4f8f0ffee8707db501861487
diff --git a/src/alter.c b/src/alter.c
index 9cd12f6592..b966f91db8 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -1136,6 +1136,7 @@ static int renameParseSql(
int bTemp /* True if SQL is from temp schema */
){
int rc;
+ u64 flags;
sqlite3ParseObjectInit(p, db);
if( zSql==0 ){
@@ -1154,7 +1155,11 @@ static int renameParseSql(
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
+ flags = db->flags;
+ testcase( (db->flags & SQLITE_Comments)==0 && strstr(zSql," /* ")!=0 );
+ db->flags |= SQLITE_Comments;
rc = sqlite3RunParser(p, zSql);
+ db->flags = flags;
if( db->mallocFailed ) rc = SQLITE_NOMEM;
if( rc==SQLITE_OK
&& NEVER(p->pNewTable==0 && p->pNewIndex==0 && p->pNewTrigger==0)
@@ -2050,7 +2055,7 @@ static void renameTableTest(
u64 flags = db->flags;
if( bNoDQS ) db->flags &= ~(SQLITE_DqsDML|SQLITE_DqsDDL);
rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
- db->flags |= (flags & (SQLITE_DqsDML|SQLITE_DqsDDL));
+ db->flags = flags;
if( rc==SQLITE_OK ){
if( isLegacy==0 && sParse.pNewTable && IsView(sParse.pNewTable) ){
NameContext sNC;
diff --git a/src/build.c b/src/build.c
index f101ee7c61..1719891015 100644
--- a/src/build.c
+++ b/src/build.c
@@ -3660,7 +3660,7 @@ void sqlite3CreateForeignKey(
}else{
nCol = pFromCol->nExpr;
}
- nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
+ nByte = SZ_FKEY(nCol) + pTo->n + 1;
if( pToCol ){
for(i=0; inExpr; i++){
nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
@@ -4720,12 +4720,11 @@ IdList *sqlite3IdListAppend(Parse *pParse, IdList *pList, Token *pToken){
sqlite3 *db = pParse->db;
int i;
if( pList==0 ){
- pList = sqlite3DbMallocZero(db, sizeof(IdList) );
+ pList = sqlite3DbMallocZero(db, SZ_IDLIST(1));
if( pList==0 ) return 0;
}else{
IdList *pNew;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(IdList) + pList->nId*sizeof(pList->a));
+ pNew = sqlite3DbRealloc(db, pList, SZ_IDLIST(pList->nId+1));
if( pNew==0 ){
sqlite3IdListDelete(db, pList);
return 0;
@@ -4824,8 +4823,7 @@ SrcList *sqlite3SrcListEnlarge(
return 0;
}
if( nAlloc>SQLITE_MAX_SRCLIST ) nAlloc = SQLITE_MAX_SRCLIST;
- pNew = sqlite3DbRealloc(db, pSrc,
- sizeof(*pSrc) + (nAlloc-1)*sizeof(pSrc->a[0]) );
+ pNew = sqlite3DbRealloc(db, pSrc, SZ_SRCLIST(nAlloc));
if( pNew==0 ){
assert( db->mallocFailed );
return 0;
@@ -4900,7 +4898,7 @@ SrcList *sqlite3SrcListAppend(
assert( pParse->db!=0 );
db = pParse->db;
if( pList==0 ){
- pList = sqlite3DbMallocRawNN(pParse->db, sizeof(SrcList) );
+ pList = sqlite3DbMallocRawNN(pParse->db, SZ_SRCLIST(1));
if( pList==0 ) return 0;
pList->nAlloc = 1;
pList->nSrc = 1;
@@ -5786,10 +5784,9 @@ With *sqlite3WithAdd(
}
if( pWith ){
- sqlite3_int64 nByte = sizeof(*pWith) + (sizeof(pWith->a[1]) * pWith->nCte);
- pNew = sqlite3DbRealloc(db, pWith, nByte);
+ pNew = sqlite3DbRealloc(db, pWith, SZ_WITH(pWith->nCte+1));
}else{
- pNew = sqlite3DbMallocZero(db, sizeof(*pWith));
+ pNew = sqlite3DbMallocZero(db, SZ_WITH(1));
}
assert( (pNew!=0 && zName!=0) || db->mallocFailed );
diff --git a/src/expr.c b/src/expr.c
index a3c41a1f57..dd5ea20383 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1738,7 +1738,7 @@ static Expr *exprDup(
With *sqlite3WithDup(sqlite3 *db, With *p){
With *pRet = 0;
if( p ){
- sqlite3_int64 nByte = sizeof(*p) + sizeof(p->a[0]) * (p->nCte-1);
+ sqlite3_int64 nByte = SZ_WITH(p->nCte);
pRet = sqlite3DbMallocZero(db, nByte);
if( pRet ){
int i;
@@ -1865,11 +1865,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, const ExprList *p, int flags){
SrcList *sqlite3SrcListDup(sqlite3 *db, const SrcList *p, int flags){
SrcList *pNew;
int i;
- int nByte;
assert( db!=0 );
if( p==0 ) return 0;
- nByte = sizeof(*p) + (p->nSrc>0 ? sizeof(p->a[0]) * (p->nSrc-1) : 0);
- pNew = sqlite3DbMallocRawNN(db, nByte );
+ pNew = sqlite3DbMallocRawNN(db, SZ_SRCLIST(p->nSrc) );
if( pNew==0 ) return 0;
pNew->nSrc = pNew->nAlloc = p->nSrc;
for(i=0; inSrc; i++){
@@ -1931,7 +1929,7 @@ IdList *sqlite3IdListDup(sqlite3 *db, const IdList *p){
int i;
assert( db!=0 );
if( p==0 ) return 0;
- pNew = sqlite3DbMallocRawNN(db, sizeof(*pNew)+(p->nId-1)*sizeof(p->a[0]) );
+ pNew = sqlite3DbMallocRawNN(db, SZ_IDLIST(p->nId));
if( pNew==0 ) return 0;
pNew->nId = p->nId;
for(i=0; inId; i++){
@@ -2015,7 +2013,7 @@ SQLITE_NOINLINE ExprList *sqlite3ExprListAppendNew(
struct ExprList_item *pItem;
ExprList *pList;
- pList = sqlite3DbMallocRawNN(db, sizeof(ExprList)+sizeof(pList->a[0])*4 );
+ pList = sqlite3DbMallocRawNN(db, SZ_EXPRLIST(4));
if( pList==0 ){
sqlite3ExprDelete(db, pExpr);
return 0;
@@ -2035,8 +2033,7 @@ SQLITE_NOINLINE ExprList *sqlite3ExprListAppendGrow(
struct ExprList_item *pItem;
ExprList *pNew;
pList->nAlloc *= 2;
- pNew = sqlite3DbRealloc(db, pList,
- sizeof(*pList)+(pList->nAlloc-1)*sizeof(pList->a[0]));
+ pNew = sqlite3DbRealloc(db, pList, SZ_EXPRLIST(pList->nAlloc));
if( pNew==0 ){
sqlite3ExprListDelete(db, pList);
sqlite3ExprDelete(db, pExpr);
diff --git a/src/main.c b/src/main.c
index 7cab51b6f3..b9433b1a02 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3857,7 +3857,7 @@ int sqlite3_set_clientdata(
return SQLITE_OK;
}else{
size_t n = strlen(zName);
- p = sqlite3_malloc64( sizeof(DbClientData)+n+1 );
+ p = sqlite3_malloc64( SZ_DBCLIENTDATA(n+1) );
if( p==0 ){
if( xDestructor ) xDestructor(pData);
sqlite3_mutex_leave(db->mutex);
diff --git a/src/pcache1.c b/src/pcache1.c
index 88a7b3a0b4..39607328f3 100644
--- a/src/pcache1.c
+++ b/src/pcache1.c
@@ -232,10 +232,6 @@ static SQLITE_WSD struct PCacheGlobal {
sqlite3_mutex *mutex; /* Mutex for accessing the following: */
PgFreeslot *pFree; /* Free page blocks */
int nFreeSlot; /* Number of unused pcache slots */
- /* The following value requires a mutex to change. We skip the mutex on
- ** reading because (1) most platforms read a 32-bit integer atomically and
- ** (2) even if an incorrect value is read, no great harm is done since this
- ** is really just an optimization. */
int bUnderPressure; /* True if low on PAGECACHE memory */
} pcache1_g;
@@ -283,7 +279,7 @@ void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
pcache1.nReserve = n>90 ? 10 : (n/10 + 1);
pcache1.pStart = pBuf;
pcache1.pFree = 0;
- pcache1.bUnderPressure = 0;
+ AtomicStore(&pcache1.bUnderPressure,0);
while( n-- ){
p = (PgFreeslot*)pBuf;
p->pNext = pcache1.pFree;
@@ -351,7 +347,7 @@ static void *pcache1Alloc(int nByte){
if( p ){
pcache1.pFree = pcache1.pFree->pNext;
pcache1.nFreeSlot--;
- pcache1.bUnderPressure = pcache1.nFreeSlot=0 );
sqlite3StatusHighwater(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
@@ -390,7 +386,7 @@ static void pcache1Free(void *p){
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
pcache1.nFreeSlot++;
- pcache1.bUnderPressure = pcache1.nFreeSlotszPage+pCache->szExtra)<=pcache1.szSlot ){
- return pcache1.bUnderPressure;
+ return AtomicLoad(&pcache1.bUnderPressure);
}else{
return sqlite3HeapNearlyFull();
}
diff --git a/src/resolve.c b/src/resolve.c
index 54ce4fb1ea..c3ab2d557c 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -2277,20 +2277,22 @@ int sqlite3ResolveSelfReference(
Expr *pExpr, /* Expression to resolve. May be NULL. */
ExprList *pList /* Expression list to resolve. May be NULL. */
){
- SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
+ SrcList *pSrc; /* Fake SrcList for pParse->pNewTable */
NameContext sNC; /* Name context for pParse->pNewTable */
int rc;
+ u8 srcSpace[SZ_SRCLIST_1]; /* Memory space for the fake SrcList */
assert( type==0 || pTab!=0 );
assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
|| type==NC_GenCol || pTab==0 );
memset(&sNC, 0, sizeof(sNC));
- memset(&sSrc, 0, sizeof(sSrc));
+ pSrc = (SrcList*)srcSpace;
+ memset(pSrc, 0, SZ_SRCLIST_1);
if( pTab ){
- sSrc.nSrc = 1;
- sSrc.a[0].zName = pTab->zName;
- sSrc.a[0].pSTab = pTab;
- sSrc.a[0].iCursor = -1;
+ pSrc->nSrc = 1;
+ pSrc->a[0].zName = pTab->zName;
+ pSrc->a[0].pSTab = pTab;
+ pSrc->a[0].iCursor = -1;
if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
/* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
** schema elements */
@@ -2298,7 +2300,7 @@ int sqlite3ResolveSelfReference(
}
}
sNC.pParse = pParse;
- sNC.pSrcList = &sSrc;
+ sNC.pSrcList = pSrc;
sNC.ncFlags = type | NC_IsDDL;
if( (rc = sqlite3ResolveExprNames(&sNC, pExpr))!=SQLITE_OK ) return rc;
if( pList ) rc = sqlite3ResolveExprListNames(&sNC, pList);
diff --git a/src/select.c b/src/select.c
index e7db195333..eedbd82818 100644
--- a/src/select.c
+++ b/src/select.c
@@ -154,7 +154,7 @@ Select *sqlite3SelectNew(
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
- if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
+ if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
@@ -1537,8 +1537,8 @@ static void selectInnerLoop(
** X extra columns.
*/
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
- int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
- KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
+ int nExtra = (N+X)*(sizeof(CollSeq*)+1);
+ KeyInfo *p = sqlite3DbMallocRawNN(db, SZ_KEYINFO(0) + nExtra);
if( p ){
p->aSortFlags = (u8*)&p->aColl[N+X];
p->nKeyField = (u16)N;
@@ -1546,7 +1546,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
p->enc = ENC(db);
p->db = db;
p->nRef = 1;
- memset(&p[1], 0, nExtra);
+ memset(p->aColl, 0, nExtra);
}else{
return (KeyInfo*)sqlite3OomFault(db);
}
@@ -6062,7 +6062,7 @@ static int selectExpander(Walker *pWalker, Select *p){
pEList = p->pEList;
if( pParse->pWith && (p->selFlags & SF_View) ){
if( p->pWith==0 ){
- p->pWith = (With*)sqlite3DbMallocZero(db, sizeof(With));
+ p->pWith = (With*)sqlite3DbMallocZero(db, SZ_WITH(1) );
if( p->pWith==0 ){
return WRC_Abort;
}
@@ -7201,6 +7201,7 @@ static void agginfoFree(sqlite3 *db, void *pArg){
** * There is no WHERE or GROUP BY or HAVING clauses on the subqueries
** * The outer query is a simple count(*) with no WHERE clause or other
** extraneous syntax.
+** * None of the subqueries are DISTINCT (forumpost/a860f5fb2e 2025-03-10)
**
** Return TRUE if the optimization is undertaken.
*/
@@ -7233,7 +7234,11 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */
if( pSub->pWhere ) return 0; /* No WHERE clause */
if( pSub->pLimit ) return 0; /* No LIMIT clause */
- if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */
+ if( pSub->selFlags & (SF_Aggregate|SF_Distinct) ){
+ testcase( pSub->selFlags & SF_Aggregate );
+ testcase( pSub->selFlags & SF_Distinct );
+ return 0; /* Not an aggregate nor DISTINCT */
+ }
assert( pSub->pHaving==0 ); /* Due to the previous */
pSub = pSub->pPrior; /* Repeat over compound */
}while( pSub );
@@ -7245,7 +7250,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
pExpr = 0;
pSub = sqlite3SubqueryDetach(db, pFrom);
sqlite3SrcListDelete(db, p->pSrc);
- p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*p->pSrc));
+ p->pSrc = sqlite3DbMallocZero(pParse->db, SZ_SRCLIST_1);
while( pSub ){
Expr *pTerm;
pPrior = pSub->pPrior;
diff --git a/src/shell.c.in b/src/shell.c.in
index 9d56240a66..5b7bbca6d4 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -2742,6 +2742,8 @@ static int shell_callback(
char cEnd = 0;
char c;
int nLine = 0;
+ int isIndex;
+ int isWhere = 0;
assert( nArg==1 );
if( azArg[0]==0 ) break;
if( sqlite3_strlike("CREATE VIEW%", azArg[0], 0)==0
@@ -2750,6 +2752,8 @@ static int shell_callback(
sqlite3_fprintf(p->out, "%s;\n", azArg[0]);
break;
}
+ isIndex = sqlite3_strlike("CREATE INDEX%", azArg[0], 0)==0
+ || sqlite3_strlike("CREATE UNIQUE INDEX%", azArg[0], 0)==0;
z = sqlite3_mprintf("%s", azArg[0]);
shell_check_oom(z);
j = 0;
@@ -2779,14 +2783,26 @@ static int shell_callback(
nParen++;
}else if( c==')' ){
nParen--;
- if( nLine>0 && nParen==0 && j>0 ){
+ if( nLine>0 && nParen==0 && j>0 && !isWhere ){
printSchemaLineN(p->out, z, j, "\n");
j = 0;
}
+ }else if( (c=='w' || c=='W')
+ && nParen==0 && isIndex
+ && sqlite3_strnicmp("WHERE",&z[i],5)==0
+ && !IsAlnum(z[i+5]) && z[i+5]!='_' ){
+ isWhere = 1;
+ }else if( isWhere && (c=='A' || c=='a')
+ && nParen==0
+ && sqlite3_strnicmp("AND",&z[i],3)==0
+ && !IsAlnum(z[i+3]) && z[i+3]!='_' ){
+ printSchemaLineN(p->out, z, j, "\n ");
+ j = 0;
}
z[j++] = c;
if( nParen==1 && cEnd==0
&& (c=='(' || c=='\n' || (c==',' && !wsToEol(z+i+1)))
+ && !isWhere
){
if( c=='\n' ) j--;
printSchemaLineN(p->out, z, j, "\n ");
@@ -8448,6 +8464,7 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids);
sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist);
+ sqlite3_fprintf(pState->out, ".dbconfig defensive off\n");
sqlite3_recover_run(p);
if( sqlite3_recover_errcode(p)!=SQLITE_OK ){
const char *zErr = sqlite3_recover_errmsg(p);
@@ -12546,7 +12563,7 @@ static int line_is_command_terminator(char *zLine){
** out of the build if compiling with SQLITE_OMIT_COMPLETE.
*/
#ifdef SQLITE_OMIT_COMPLETE
-# error the CLI application is incompatable with SQLITE_OMIT_COMPLETE.
+# error the CLI application is incompatible with SQLITE_OMIT_COMPLETE.
#endif
/*
@@ -13750,6 +13767,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
** the database filename.
*/
for(i=0; iFIELD))
+#define offsetof(STRUCTURE,FIELD) ((size_t)((char*)&((STRUCTURE*)0)->FIELD))
+#endif
+
+/*
+** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
+** to avoid complaints from -fsanitize=strict-bounds.
+*/
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
#endif
/*
@@ -2597,9 +2607,13 @@ struct FKey {
struct sColMap { /* Mapping of columns in pFrom to columns in zTo */
int iFrom; /* Index of column in pFrom */
char *zCol; /* Name of column in zTo. If NULL use PRIMARY KEY */
- } aCol[1]; /* One entry for each of nCol columns */
+ } aCol[FLEXARRAY]; /* One entry for each of nCol columns */
};
+/* The size (in bytes) of an FKey object holding N columns. The answer
+** does NOT include space to hold the zTo name. */
+#define SZ_FKEY(N) (offsetof(FKey,aCol)+(N)*sizeof(struct sColMap))
+
/*
** SQLite supports many different ways to resolve a constraint
** error. ROLLBACK processing means that a constraint violation
@@ -2661,9 +2675,12 @@ struct KeyInfo {
u16 nAllField; /* Total columns, including key plus others */
sqlite3 *db; /* The database connection */
u8 *aSortFlags; /* Sort order for each column. */
- CollSeq *aColl[1]; /* Collating sequence for each term of the key */
+ CollSeq *aColl[FLEXARRAY]; /* Collating sequence for each term of the key */
};
+/* The size (in bytes) of a KeyInfo object with up to N fields */
+#define SZ_KEYINFO(N) (offsetof(KeyInfo,aColl) + (N)*sizeof(CollSeq*))
+
/*
** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
*/
@@ -3236,9 +3253,14 @@ struct ExprList {
int iConstExprReg; /* Register in which Expr value is cached. Used only
** by Parse.pConstExpr */
} u;
- } a[1]; /* One slot for each expression in the list */
+ } a[FLEXARRAY]; /* One slot for each expression in the list */
};
+/* The size (in bytes) of an ExprList object that is big enough to hold
+** as many as N expressions. */
+#define SZ_EXPRLIST(N) \
+ (offsetof(ExprList,a) + (N)*sizeof(struct ExprList_item))
+
/*
** Allowed values for Expr.a.eEName
*/
@@ -3266,9 +3288,12 @@ struct IdList {
int nId; /* Number of identifiers on the list */
struct IdList_item {
char *zName; /* Name of the identifier */
- } a[1];
+ } a[FLEXARRAY];
};
+/* The size (in bytes) of an IdList object that can hold up to N IDs. */
+#define SZ_IDLIST(N) (offsetof(IdList,a)+(N)*sizeof(struct IdList_item))
+
/*
** Allowed values for IdList.eType, which determines which value of the a.u4
** is valid.
@@ -3388,11 +3413,19 @@ struct OnOrUsing {
**
*/
struct SrcList {
- int nSrc; /* Number of tables or subqueries in the FROM clause */
- u32 nAlloc; /* Number of entries allocated in a[] below */
- SrcItem a[1]; /* One entry for each identifier on the list */
+ int nSrc; /* Number of tables or subqueries in the FROM clause */
+ u32 nAlloc; /* Number of entries allocated in a[] below */
+ SrcItem a[FLEXARRAY]; /* One entry for each identifier on the list */
};
+/* Size (in bytes) of a SrcList object that can hold as many as N
+** SrcItem objects. */
+#define SZ_SRCLIST(N) (offsetof(SrcList,a)+(N)*sizeof(SrcItem))
+
+/* Size (in bytes( of a SrcList object that holds 1 SrcItem. This is a
+** special case of SZ_SRCITEM(1) that comes up often. */
+#define SZ_SRCLIST_1 (offsetof(SrcList,a)+sizeof(SrcItem))
+
/*
** Permitted values of the SrcList.a.jointype field
*/
@@ -4460,9 +4493,13 @@ struct With {
int nCte; /* Number of CTEs in the WITH clause */
int bView; /* Belongs to the outermost Select of a view */
With *pOuter; /* Containing WITH clause, or NULL */
- Cte a[1]; /* For each CTE in the WITH clause.... */
+ Cte a[FLEXARRAY]; /* For each CTE in the WITH clause.... */
};
+/* The size (in bytes) of a With object that can hold as many
+** as N different CTEs. */
+#define SZ_WITH(N) (offsetof(With,a) + (N)*sizeof(Cte))
+
/*
** The Cte object is not guaranteed to persist for the entire duration
** of code generation. (The query flattener or other parser tree
@@ -4491,9 +4528,13 @@ struct DbClientData {
DbClientData *pNext; /* Next in a linked list */
void *pData; /* The data */
void (*xDestructor)(void*); /* Destructor. Might be NULL */
- char zName[1]; /* Name of this client data. MUST BE LAST */
+ char zName[FLEXARRAY]; /* Name of this client data. MUST BE LAST */
};
+/* The size (in bytes) of a DbClientData object that can has a name
+** that is N bytes long, including the zero-terminator. */
+#define SZ_DBCLIENTDATA(N) (offsetof(DbClientData,zName)+(N))
+
#ifdef SQLITE_DEBUG
/*
** An instance of the TreeView object is used for printing the content of
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index e9b8598965..e681e0060b 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -1232,6 +1232,7 @@ static int auth_callback(
}
#endif /* SQLITE_OMIT_AUTHORIZATION */
+#if 0
/*
** This routine reads a line of text from FILE in, stores
** the text in memory obtained from malloc() and returns a pointer
@@ -1276,6 +1277,7 @@ static char *local_getline(char *zPrompt, FILE *in){
zLine = realloc( zLine, n+1 );
return zLine;
}
+#endif
/*
@@ -2057,7 +2059,7 @@ static int SQLITE_TCLAPI DbObjCmd(
** (4) Name of the database (ex: "main", "temp")
** (5) Name of trigger that is doing the access
**
- ** The callback should return on of the following strings: SQLITE_OK,
+ ** The callback should return one of the following strings: SQLITE_OK,
** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error.
**
** If this method is invoked with no arguments, the current authorization
@@ -2520,9 +2522,10 @@ static int SQLITE_TCLAPI DbObjCmd(
char *zLine; /* A single line of input from the file */
char **azCol; /* zLine[] broken up into columns */
const char *zCommit; /* How to commit changes */
- FILE *in; /* The input file */
+ Tcl_Channel in; /* The input file */
int lineno = 0; /* Line number of input file */
char zLineNum[80]; /* Line number print buffer */
+ Tcl_DString str;
Tcl_Obj *pResult; /* interp result */
const char *zSep;
@@ -2601,23 +2604,24 @@ static int SQLITE_TCLAPI DbObjCmd(
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
- in = fopen(zFile, "rb");
+ in = Tcl_OpenFileChannel(interp, zFile, "rb", 0666);
if( in==0 ){
- Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, (char*)0);
sqlite3_finalize(pStmt);
return TCL_ERROR;
}
azCol = malloc( sizeof(azCol[0])*(nCol+1) );
if( azCol==0 ) {
Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
- fclose(in);
+ Tcl_Close(interp, in);
return TCL_ERROR;
}
+ Tcl_DStringInit(&str);
(void)sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);
zCommit = "COMMIT";
- while( (zLine = local_getline(0, in))!=0 ){
+ while( Tcl_Gets(in, &str)>=0 ) {
char *z;
lineno++;
+ zLine = Tcl_DStringValue(&str);
azCol[0] = zLine;
for(i=0, z=zLine; *z; z++){
if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
@@ -2655,15 +2659,16 @@ static int SQLITE_TCLAPI DbObjCmd(
}
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
- free(zLine);
+ Tcl_DStringSetLength(&str, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);
zCommit = "ROLLBACK";
break;
}
}
+ Tcl_DStringFree(&str);
free(azCol);
- fclose(in);
+ Tcl_Close(interp, in);
sqlite3_finalize(pStmt);
(void)sqlite3_exec(pDb->db, zCommit, 0, 0, 0);
diff --git a/src/tokenize.c b/src/tokenize.c
index fe300ca529..e4d9f53718 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -692,7 +692,11 @@ int sqlite3RunParser(Parse *pParse, const char *zSql){
assert( n==6 );
tokenType = analyzeFilterKeyword((const u8*)&zSql[6], lastTokenParsed);
#endif /* SQLITE_OMIT_WINDOWFUNC */
- }else if( tokenType==TK_COMMENT && (db->flags & SQLITE_Comments)!=0 ){
+ }else if( tokenType==TK_COMMENT
+ && (db->init.busy || (db->flags & SQLITE_Comments)!=0)
+ ){
+ /* Ignore SQL comments if either (1) we are reparsing the schema or
+ ** (2) SQLITE_DBCONFIG_ENABLE_COMMENTS is turned on (the default). */
zSql += n;
continue;
}else if( tokenType!=TK_QNUMBER ){
diff --git a/src/trigger.c b/src/trigger.c
index 3cb9331fa1..f5fa59435f 100644
--- a/src/trigger.c
+++ b/src/trigger.c
@@ -1070,7 +1070,8 @@ static void codeReturningTrigger(
ExprList *pNew;
Returning *pReturning;
Select sSelect;
- SrcList sFrom;
+ SrcList *pFrom;
+ u8 fromSpace[SZ_SRCLIST_1];
assert( v!=0 );
if( !pParse->bReturning ){
@@ -1086,13 +1087,14 @@ static void codeReturningTrigger(
return;
}
memset(&sSelect, 0, sizeof(sSelect));
- memset(&sFrom, 0, sizeof(sFrom));
+ pFrom = (SrcList*)fromSpace;
+ memset(pFrom, 0, SZ_SRCLIST_1);
sSelect.pEList = sqlite3ExprListDup(db, pReturning->pReturnEL, 0);
- sSelect.pSrc = &sFrom;
- sFrom.nSrc = 1;
- sFrom.a[0].pSTab = pTab;
- sFrom.a[0].zName = pTab->zName; /* tag-20240424-1 */
- sFrom.a[0].iCursor = -1;
+ sSelect.pSrc = pFrom;
+ pFrom->nSrc = 1;
+ pFrom->a[0].pSTab = pTab;
+ pFrom->a[0].zName = pTab->zName; /* tag-20240424-1 */
+ pFrom->a[0].iCursor = -1;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( pParse->nErr==0 ){
assert( db->mallocFailed==0 );
diff --git a/src/vacuum.c b/src/vacuum.c
index 2ec8e88d0a..b93ef1019e 100644
--- a/src/vacuum.c
+++ b/src/vacuum.c
@@ -196,7 +196,7 @@ SQLITE_NOINLINE int sqlite3RunVacuum(
saved_nChange = db->nChange;
saved_nTotalChange = db->nTotalChange;
saved_mTrace = db->mTrace;
- db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
+ db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks | SQLITE_Comments;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
diff --git a/src/vdbe.c b/src/vdbe.c
index 1d53d0d888..0e74f7fcd2 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -278,9 +278,9 @@ static VdbeCursor *allocateCursor(
i64 nByte;
VdbeCursor *pCx = 0;
- nByte =
- ROUND8P(sizeof(VdbeCursor)) + 2*sizeof(u32)*nField +
- (eCurType==CURTYPE_BTREE?sqlite3BtreeCursorSize():0);
+ nByte = SZ_VDBECURSOR(nField);
+ assert( ROUND8(nByte)==nByte );
+ if( eCurType==CURTYPE_BTREE ) nByte += sqlite3BtreeCursorSize();
assert( iCur>=0 && iCurnCursor );
if( p->apCsr[iCur] ){ /*OPTIMIZATION-IF-FALSE*/
@@ -313,8 +313,8 @@ static VdbeCursor *allocateCursor(
pCx->nField = nField;
pCx->aOffset = &pCx->aType[nField];
if( eCurType==CURTYPE_BTREE ){
- pCx->uc.pCursor = (BtCursor*)
- &pMem->z[ROUND8P(sizeof(VdbeCursor))+2*sizeof(u32)*nField];
+ assert( ROUND8(SZ_VDBECURSOR(nField))==SZ_VDBECURSOR(nField) );
+ pCx->uc.pCursor = (BtCursor*)&pMem->z[SZ_VDBECURSOR(nField)];
sqlite3BtreeCursorZero(pCx->uc.pCursor);
}
return pCx;
@@ -6056,7 +6056,7 @@ case OP_RowData: {
/* The OP_RowData opcodes always follow OP_NotExists or
** OP_SeekRowid or OP_Rewind/Op_Next with no intervening instructions
** that might invalidate the cursor.
- ** If this where not the case, on of the following assert()s
+ ** If this were not the case, one of the following assert()s
** would fail. Should this ever change (because of changes in the code
** generator) then the fix would be to insert a call to
** sqlite3VdbeCursorMoveto().
@@ -7705,7 +7705,7 @@ case OP_AggStep: {
**
** Note: We could avoid this by using a regular memory cell from aMem[] for
** the accumulator, instead of allocating one here. */
- nAlloc = ROUND8P( sizeof(pCtx[0]) + (n-1)*sizeof(sqlite3_value*) );
+ nAlloc = ROUND8P( SZ_CONTEXT(n) );
pCtx = sqlite3DbMallocRawNN(db, nAlloc + sizeof(Mem));
if( pCtx==0 ) goto no_mem;
pCtx->pOut = (Mem*)((u8*)pCtx + nAlloc);
diff --git a/src/vdbe.h b/src/vdbe.h
index ab25380010..1f663081f8 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -319,8 +319,8 @@ int sqlite3NotPureFunc(sqlite3_context*);
int sqlite3VdbeBytecodeVtabInit(sqlite3*);
#endif
-/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
-** each VDBE opcode.
+/* Use SQLITE_ENABLE_EXPLAIN_COMMENTS to enable generation of extra
+** comments on each VDBE opcode.
**
** Use the SQLITE_ENABLE_MODULE_COMMENTS macro to see some extra no-op
** comments in VDBE programs that show key decision points in the code
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 12af827268..13262cd4e2 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -133,12 +133,19 @@ struct VdbeCursor {
#endif
VdbeTxtBlbCache *pCache; /* Cache of large TEXT or BLOB values */
- /* 2*nField extra array elements allocated for aType[], beyond the one
- ** static element declared in the structure. nField total array slots for
- ** aType[] and nField+1 array slots for aOffset[] */
- u32 aType[1]; /* Type values record decode. MUST BE LAST */
+ /* Space is allocated for aType to hold at least 2*nField+1 entries:
+ ** nField slots for aType[] and nField+1 array slots for aOffset[] */
+ u32 aType[FLEXARRAY]; /* Type values record decode. MUST BE LAST */
};
+/*
+** The size (in bytes) of a VdbeCursor object that has an nField value of N
+** or less. The value of SZ_VDBECURSOR(n) is guaranteed to be a multiple
+** of 8.
+*/
+#define SZ_VDBECURSOR(N) \
+ (ROUND8(offsetof(VdbeCursor,aType)) + ((N)+1)*sizeof(u64))
+
/* Return true if P is a null-only cursor
*/
#define IsNullCursor(P) \
@@ -395,9 +402,16 @@ struct sqlite3_context {
u8 enc; /* Encoding to use for results */
u8 skipFlag; /* Skip accumulator loading if true */
u16 argc; /* Number of arguments */
- sqlite3_value *argv[1]; /* Argument set */
+ sqlite3_value *argv[FLEXARRAY]; /* Argument set */
};
+/*
+** The size (in bytes) of an sqlite3_context object that holds N
+** argv[] arguments.
+*/
+#define SZ_CONTEXT(N) \
+ (offsetof(sqlite3_context,argv)+(N)*sizeof(sqlite3_value*))
+
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
@@ -531,7 +545,7 @@ struct PreUpdate {
VdbeCursor *pCsr; /* Cursor to read old values from */
int op; /* One of SQLITE_INSERT, UPDATE, DELETE */
u8 *aRecord; /* old.* database record */
- KeyInfo keyinfo;
+ KeyInfo *pKeyinfo; /* Key information */
UnpackedRecord *pUnpacked; /* Unpacked version of aRecord[] */
UnpackedRecord *pNewUnpacked; /* Unpacked version of new.* record */
int iNewReg; /* Register for new.* values */
@@ -543,6 +557,7 @@ struct PreUpdate {
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
sqlite3_value **apDflt; /* Array of default values, if required */
+ u8 keyinfoSpace[SZ_KEYINFO(0)]; /* Space to hold pKeyinfo[0] content */
};
/*
diff --git a/src/vdbeapi.c b/src/vdbeapi.c
index 31880d85b5..523f80097d 100644
--- a/src/vdbeapi.c
+++ b/src/vdbeapi.c
@@ -2216,7 +2216,7 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
if( !aRec ) goto preupdate_old_out;
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
if( rc==SQLITE_OK ){
- p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
+ p->pUnpacked = vdbeUnpackRecord(p->pKeyinfo, nRec, aRec);
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
}
if( rc!=SQLITE_OK ){
@@ -2281,7 +2281,7 @@ int sqlite3_preupdate_count(sqlite3 *db){
#else
p = db->pPreUpdate;
#endif
- return (p ? p->keyinfo.nKeyField : 0);
+ return (p ? p->pKeyinfo->nKeyField : 0);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
@@ -2364,7 +2364,7 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
Mem *pData = &p->v->aMem[p->iNewReg];
rc = ExpandBlob(pData);
if( rc!=SQLITE_OK ) goto preupdate_new_out;
- pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
+ pUnpack = vdbeUnpackRecord(p->pKeyinfo, pData->n, pData->z);
if( !pUnpack ){
rc = SQLITE_NOMEM;
goto preupdate_new_out;
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 6c889c2438..61ede7800f 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -445,12 +445,10 @@ int sqlite3VdbeAddFunctionCall(
int eCallCtx /* Calling context */
){
Vdbe *v = pParse->pVdbe;
- int nByte;
int addr;
sqlite3_context *pCtx;
assert( v );
- nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
- pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
+ pCtx = sqlite3DbMallocRawNN(pParse->db, SZ_CONTEXT(nArg));
if( pCtx==0 ){
assert( pParse->db->mallocFailed );
freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
@@ -5528,10 +5526,11 @@ void sqlite3VdbePreUpdateHook(
preupdate.pCsr = pCsr;
preupdate.op = op;
preupdate.iNewReg = iReg;
- preupdate.keyinfo.db = db;
- preupdate.keyinfo.enc = ENC(db);
- preupdate.keyinfo.nKeyField = pTab->nCol;
- preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
+ preupdate.pKeyinfo = (KeyInfo*)&preupdate.keyinfoSpace;
+ preupdate.pKeyinfo->db = db;
+ preupdate.pKeyinfo->enc = ENC(db);
+ preupdate.pKeyinfo->nKeyField = pTab->nCol;
+ preupdate.pKeyinfo->aSortFlags = (u8*)&fakeSortOrder;
preupdate.iKey1 = iKey1;
preupdate.iKey2 = iKey2;
preupdate.pTab = pTab;
@@ -5541,8 +5540,8 @@ void sqlite3VdbePreUpdateHook(
db->xPreUpdateCallback(db->pPreUpdateArg, db, op, zDb, zTbl, iKey1, iKey2);
db->pPreUpdate = 0;
sqlite3DbFree(db, preupdate.aRecord);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
- vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pUnpacked);
+ vdbeFreeUnpacked(db, preupdate.pKeyinfo->nKeyField+1,preupdate.pNewUnpacked);
sqlite3VdbeMemRelease(&preupdate.oldipk);
if( preupdate.aNew ){
int i;
diff --git a/src/vdbeblob.c b/src/vdbeblob.c
index 50cb431473..8756566336 100644
--- a/src/vdbeblob.c
+++ b/src/vdbeblob.c
@@ -133,6 +133,7 @@ int sqlite3_blob_open(
char *zErr = 0;
Table *pTab;
Incrblob *pBlob = 0;
+ int iDb;
Parse sParse;
int bUnlock; /* True to unlock reusable schemas before returning */
@@ -180,7 +181,10 @@ int sqlite3_blob_open(
sqlite3ErrorMsg(&sParse, "cannot open view: %s", zTable);
}
#endif
- if( !pTab ){
+ if( pTab==0
+ || ((iDb = sqlite3SchemaToIndex(db, pTab->pSchema))==1 &&
+ sqlite3OpenTempDatabase(&sParse))
+ ){
if( sParse.zErrMsg ){
sqlite3DbFree(db, zErr);
zErr = sParse.zErrMsg;
@@ -191,7 +195,7 @@ int sqlite3_blob_open(
goto blob_open_out;
}
pBlob->pTab = pTab;
- pBlob->zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
+ pBlob->zDb = db->aDb[iDb].zDbSName;
/* Now search pTab for the exact column. */
iCol = sqlite3ColumnIndex(pTab, zColumn);
@@ -275,7 +279,6 @@ int sqlite3_blob_open(
{OP_Halt, 0, 0, 0}, /* 5 */
};
Vdbe *v = (Vdbe *)pBlob->pStmt;
- int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
VdbeOp *aOp;
sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, wrFlag,
diff --git a/src/vdbesort.c b/src/vdbesort.c
index c9da88f6e1..9a7e0760c6 100644
--- a/src/vdbesort.c
+++ b/src/vdbesort.c
@@ -332,9 +332,12 @@ struct VdbeSorter {
u8 iPrev; /* Previous thread used to flush PMA */
u8 nTask; /* Size of aTask[] array */
u8 typeMask;
- SortSubtask aTask[1]; /* One or more subtasks */
+ SortSubtask aTask[FLEXARRAY]; /* One or more subtasks */
};
+/* Size (in bytes) of a VdbeSorter object that works with N or fewer subtasks */
+#define SZ_VDBESORTER(N) (offsetof(VdbeSorter,aTask)+(N)*sizeof(SortSubtask))
+
#define SORTER_TYPE_INTEGER 0x01
#define SORTER_TYPE_TEXT 0x02
@@ -966,8 +969,8 @@ int sqlite3VdbeSorterInit(
assert( pCsr->eCurType==CURTYPE_SORTER );
assert( sizeof(KeyInfo) + UMXV(pCsr->pKeyInfo->nKeyField)*sizeof(CollSeq*)
< 0x7fffffff );
- szKeyInfo = sizeof(KeyInfo) + (pCsr->pKeyInfo->nKeyField-1)*sizeof(CollSeq*);
- sz = sizeof(VdbeSorter) + nWorker * sizeof(SortSubtask);
+ szKeyInfo = SZ_KEYINFO(pCsr->pKeyInfo->nKeyField+1);
+ sz = SZ_VDBESORTER(nWorker+1);
pSorter = (VdbeSorter*)sqlite3DbMallocZero(db, sz + szKeyInfo);
pCsr->uc.pSorter = pSorter;
diff --git a/src/wal.c b/src/wal.c
index d374d6eb4d..7f091a48cf 100644
--- a/src/wal.c
+++ b/src/wal.c
@@ -597,9 +597,13 @@ struct WalIterator {
u32 *aPgno; /* Array of page numbers. */
int nEntry; /* Nr. of entries in aPgno[] and aIndex[] */
int iZero; /* Frame number associated with aPgno[0] */
- } aSegment[1]; /* One for every 32KB page in the wal-index */
+ } aSegment[FLEXARRAY]; /* One for every 32KB page in the wal-index */
};
+/* Size (in bytes) of a WalIterator object suitable for N or fewer segments */
+#define SZ_WALITERATOR(N) \
+ (offsetof(WalIterator,aSegment)*(N)*sizeof(struct WalSegment))
+
/*
** Define the parameters of the hash tables in the wal-index file. There
** is a hash-table following every HASHTABLE_NPAGE page numbers in the
@@ -1960,8 +1964,7 @@ static int walIteratorInit(Wal *pWal, u32 nBackfill, WalIterator **pp){
/* Allocate space for the WalIterator object. */
nSegment = walFramePage(iLast) + 1;
- nByte = sizeof(WalIterator)
- + (nSegment-1)*sizeof(struct WalSegment)
+ nByte = SZ_WALITERATOR(nSegment)
+ iLast*sizeof(ht_slot);
p = (WalIterator *)sqlite3_malloc64(nByte
+ sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
diff --git a/src/where.c b/src/where.c
index 945adcea8c..de177e6592 100644
--- a/src/where.c
+++ b/src/where.c
@@ -35,11 +35,16 @@ struct HiddenIndexInfo {
int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
u32 mIn; /* Mask of terms that are IN (...) */
u32 mHandleIn; /* Terms that vtab will handle as IN (...) */
- sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
- ** because extra space is allocated to hold up
- ** to nTerm such values */
+ sqlite3_value *aRhs[FLEXARRAY]; /* RHS values for constraints. MUST BE LAST
+ ** Extra space is allocated to hold up
+ ** to nTerm such values */
};
+/* Size (in bytes) of a HiddenIndeInfo object sufficient to hold as
+** many as N constraints */
+#define SZ_HIDDENINDEXINFO(N) \
+ (offsetof(HiddenIndexInfo,aRhs) + (N)*sizeof(sqlite3_value*))
+
/* Forward declaration of methods */
static int whereLoopResize(sqlite3*, WhereLoop*, int);
@@ -1517,8 +1522,8 @@ static sqlite3_index_info *allocateIndexInfo(
*/
pIdxInfo = sqlite3DbMallocZero(pParse->db, sizeof(*pIdxInfo)
+ (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm
- + sizeof(*pIdxOrderBy)*nOrderBy + sizeof(*pHidden)
- + sizeof(sqlite3_value*)*nTerm );
+ + sizeof(*pIdxOrderBy)*nOrderBy
+ + SZ_HIDDENINDEXINFO(nTerm) );
if( pIdxInfo==0 ){
sqlite3ErrorMsg(pParse, "out of memory");
return 0;
@@ -6712,10 +6717,7 @@ WhereInfo *sqlite3WhereBegin(
** field (type Bitmask) it must be aligned on an 8-byte boundary on
** some architectures. Hence the ROUND8() below.
*/
- nByteWInfo = ROUND8P(sizeof(WhereInfo));
- if( nTabList>1 ){
- nByteWInfo = ROUND8P(nByteWInfo + (nTabList-1)*sizeof(WhereLevel));
- }
+ nByteWInfo = SZ_WHEREINFO(nTabList);
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
if( db->mallocFailed ){
sqlite3DbFree(db, pWInfo);
diff --git a/src/whereInt.h b/src/whereInt.h
index 8ba8a7072d..40a720ab9e 100644
--- a/src/whereInt.h
+++ b/src/whereInt.h
@@ -501,9 +501,14 @@ struct WhereInfo {
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
WhereClause sWC; /* Decomposition of the WHERE clause */
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
- WhereLevel a[1]; /* Information about each nest loop in WHERE */
+ WhereLevel a[FLEXARRAY]; /* Information about each nest loop in WHERE */
};
+/*
+** The size (in bytes) of a WhereInfo object that holds N WhereLevels.
+*/
+#define SZ_WHEREINFO(N) ROUND8(offsetof(WhereInfo,a)+(N)*sizeof(WhereLevel))
+
/*
** Private interfaces - callable only by other where.c routines.
**
diff --git a/src/wherecode.c b/src/wherecode.c
index 1a0cdc6d71..5fe2308137 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -2313,8 +2313,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
int nNotReady; /* The number of notReady tables */
SrcItem *origSrc; /* Original list of tables */
nNotReady = pWInfo->nLevel - iLevel - 1;
- pOrTab = sqlite3DbMallocRawNN(db,
- sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0]));
+ pOrTab = sqlite3DbMallocRawNN(db, SZ_SRCLIST(nNotReady+1));
if( pOrTab==0 ) return notReady;
pOrTab->nAlloc = (u8)(nNotReady + 1);
pOrTab->nSrc = pOrTab->nAlloc;
@@ -2857,7 +2856,8 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
WhereInfo *pSubWInfo;
WhereLoop *pLoop = pLevel->pWLoop;
SrcItem *pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
- SrcList sFrom;
+ SrcList *pFrom;
+ u8 fromSpace[SZ_SRCLIST_1];
Bitmask mAll = 0;
int k;
@@ -2901,13 +2901,14 @@ SQLITE_NOINLINE void sqlite3WhereRightJoinLoop(
sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
}
}
- sFrom.nSrc = 1;
- sFrom.nAlloc = 1;
- memcpy(&sFrom.a[0], pTabItem, sizeof(SrcItem));
- sFrom.a[0].fg.jointype = 0;
+ pFrom = (SrcList*)fromSpace;
+ pFrom->nSrc = 1;
+ pFrom->nAlloc = 1;
+ memcpy(&pFrom->a[0], pTabItem, sizeof(SrcItem));
+ pFrom->a[0].fg.jointype = 0;
assert( pParse->withinRJSubrtn < 100 );
pParse->withinRJSubrtn++;
- pSubWInfo = sqlite3WhereBegin(pParse, &sFrom, pSubWhere, 0, 0, 0,
+ pSubWInfo = sqlite3WhereBegin(pParse, pFrom, pSubWhere, 0, 0, 0,
WHERE_RIGHT_JOIN, 0);
if( pSubWInfo ){
int iCur = pLevel->iTabCur;
diff --git a/test/fuzzcheck.c b/test/fuzzcheck.c
index 140ad6944d..7d5da2ce27 100644
--- a/test/fuzzcheck.c
+++ b/test/fuzzcheck.c
@@ -88,6 +88,11 @@
#include "sqlite3recover.h"
#define ISSPACE(X) isspace((unsigned char)(X))
#define ISDIGIT(X) isdigit((unsigned char)(X))
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
+# define FLEXARRAY
+#else
+# define FLEXARRAY 1
+#endif
#ifdef __unix__
@@ -129,9 +134,12 @@ struct Blob {
int id; /* Id of this Blob */
int seq; /* Sequence number */
int sz; /* Size of this Blob in bytes */
- unsigned char a[1]; /* Blob content. Extra space allocated as needed. */
+ unsigned char a[FLEXARRAY]; /* Blob content. Allocated as needed. */
};
+/* Size in bytes of a Blob object sufficient to store N byte of content */
+#define SZ_BLOB(N) (offsetof(Blob,a) + (((N)+7)&~7))
+
/*
** Maximum number of files in the in-memory virtual filesystem.
*/
@@ -512,13 +520,15 @@ static void blobListLoadFromDb(
int *pN, /* OUT: Write number of blobs loaded here */
Blob **ppList /* OUT: Write the head of the blob list here */
){
- Blob head;
+ Blob *head;
Blob *p;
sqlite3_stmt *pStmt;
int n = 0;
int rc;
char *z2;
+ unsigned char tmp[SZ_BLOB(8)];
+ head = (Blob*)tmp;
if( firstId>0 ){
z2 = sqlite3_mprintf("%s WHERE rowid BETWEEN %d AND %d", zSql,
firstId, lastId);
@@ -528,11 +538,11 @@ static void blobListLoadFromDb(
rc = sqlite3_prepare_v2(db, z2, -1, &pStmt, 0);
sqlite3_free(z2);
if( rc ) fatalError("%s", sqlite3_errmsg(db));
- head.pNext = 0;
- p = &head;
+ head->pNext = 0;
+ p = head;
while( SQLITE_ROW==sqlite3_step(pStmt) ){
int sz = sqlite3_column_bytes(pStmt, 1);
- Blob *pNew = safe_realloc(0, sizeof(*pNew)+sz );
+ Blob *pNew = safe_realloc(0, SZ_BLOB(sz+1));
pNew->id = sqlite3_column_int(pStmt, 0);
pNew->sz = sz;
pNew->seq = n++;
@@ -544,7 +554,7 @@ static void blobListLoadFromDb(
}
sqlite3_finalize(pStmt);
*pN = n;
- *ppList = head.pNext;
+ *ppList = head->pNext;
}
/*
diff --git a/test/recover.test b/test/recover.test
index 268d3a55b0..ad6b7298dc 100644
--- a/test/recover.test
+++ b/test/recover.test
@@ -47,6 +47,9 @@ proc recover_with_opts {opts} {
set sql [read $fd]
close $fd
+ # Remove the ".dbconfig defensive off" line
+ set sql [string map {".dbconfig defensive off" ""} $sql]
+
forcedelete test.db2
sqlite3 db2 test.db2
execsql $sql db2
diff --git a/test/shared.test b/test/shared.test
index a0cd0a6696..146830e56a 100644
--- a/test/shared.test
+++ b/test/shared.test
@@ -312,7 +312,7 @@ do_test shared-$av.4.1.3 {
} {2}
# Sanity check: Create a table in ./test.db via handle db, and test that handle
-# db2 can "see" the new table immediately. A handle using a seperate pager
+# db2 can "see" the new table immediately. A handle using a separate pager
# cache would have to reload the database schema before this were possible.
#
do_test shared-$av.4.2.1 {
diff --git a/test/tabfunc01.test b/test/tabfunc01.test
index b6797171e0..cbf9865eda 100644
--- a/test/tabfunc01.test
+++ b/test/tabfunc01.test
@@ -181,6 +181,19 @@ do_execsql_test tabfunc01-4.4 {
SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10;
} {1 3 5}
+# 2025-03-13 forum post bf2dc8e909983511
+#
+do_execsql_test tabfunc01-5.1 {
+ SELECT value
+ FROM generate_series(60,73,6)
+ WHERE value=66;
+} 66
+do_execsql_test tabfunc01-5.2 {
+ SELECT value
+ FROM generate_series(73,60,-6)
+ WHERE value=67;
+} 67
+
# The next series of tests is verifying that virtual table are able
# to optimize the IN operator, even on terms that are not marked "omit".
# When the generate_series virtual table is compiled for the testfixture,
diff --git a/test/tableapi.test b/test/tableapi.test
index 02633cdcac..7720737474 100644
--- a/test/tableapi.test
+++ b/test/tableapi.test
@@ -230,7 +230,7 @@ ifcapable schema_pragmas {
}
# do_malloc_test closes and deletes the usual db connections and files on
-# each iteration. $::dbx is a seperate connection, and on Windows, will
+# each iteration. $::dbx is a separate connection, and on Windows, will
# cause the file deletion of test.db to fail, so we move the close of $::dbx
# up to here before the do_malloc_test.
do_test tableapi-99.0 {
diff --git a/test/tester.tcl b/test/tester.tcl
index a3ad09a454..70b666e234 100644
--- a/test/tester.tcl
+++ b/test/tester.tcl
@@ -1724,7 +1724,7 @@ proc ifcapable {expr code {else ""} {elsecode ""}} {
return -code $c $r
}
-# This proc execs a seperate process that crashes midway through executing
+# This proc execs a separate process that crashes midway through executing
# the SQL script $sql on database test.db.
#
# The crash occurs during a sync() of file $crashfile. When the crash
diff --git a/test/walsetlk.test b/test/walsetlk.test
index d3fd050a63..b65eb9ab68 100644
--- a/test/walsetlk.test
+++ b/test/walsetlk.test
@@ -315,6 +315,7 @@ testfixture_nb done {
db eval {
COMMIT
}
+ db close
}
after 500 {set ok 1}
diff --git a/tool/sqlite3_analyzer.c.in b/tool/sqlite3_analyzer.c.in
index 9c11752b81..945c3c5b90 100644
--- a/tool/sqlite3_analyzer.c.in
+++ b/tool/sqlite3_analyzer.c.in
@@ -61,6 +61,7 @@ static int subst_puts(
}
sqlite3_fputs(zOut, pOut);
if( addNewLine ) sqlite3_fputs("\n", pOut);
+ fflush(pOut);
return TCL_OK;
}
#endif /* defined(_WIN32) */