diff --git a/go.mod b/go.mod
index 3e0a02509..efee4f973 100644
--- a/go.mod
+++ b/go.mod
@@ -6,7 +6,7 @@ require (
github.com/blang/semver/v4 v4.0.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.9.0
- github.com/mattn/go-sqlite3 v1.14.47
+ github.com/mattn/go-sqlite3 v1.14.48
github.com/mileusna/useragent v1.3.5
github.com/tebeka/selenium v0.9.9
golang.org/x/sync v0.22.0
diff --git a/go.sum b/go.sum
index 054ff2fbe..28099dd44 100644
--- a/go.sum
+++ b/go.sum
@@ -16,8 +16,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/go-version v1.9.0 h1:CeOIz6k+LoN3qX9Z0tyQrPtiB1DFYRPfCIBtaXPSCnA=
github.com/hashicorp/go-version v1.9.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
-github.com/mattn/go-sqlite3 v1.14.47 h1:jOBI62gS7nKeZv+as1oGEy0+1qISgXwH/QBlR6KbfIo=
-github.com/mattn/go-sqlite3 v1.14.47/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
+github.com/mattn/go-sqlite3 v1.14.48 h1:7XHIgl0a8HwOaiK4E47ozLkST78rR9+OtNGx27D/TFs=
+github.com/mattn/go-sqlite3 v1.14.48/go.mod h1:6JTjA44L93a0QCyJef5YvlPoKXntQPjzWv5gtm9sB6w=
github.com/mileusna/useragent v1.3.5 h1:SJM5NzBmh/hO+4LGeATKpaEX9+b4vcGg2qXGLiNGDws=
github.com/mileusna/useragent v1.3.5/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
github.com/romainmenke/selenium v0.9.15 h1:XTWq5YIg/pn59ItE8SS8LPlXZIHTOKwkUu/L3ooydUo=
diff --git a/vendor/github.com/mattn/go-sqlite3/.coderabbit.yaml b/vendor/github.com/mattn/go-sqlite3/.coderabbit.yaml
new file mode 100644
index 000000000..2c8132562
--- /dev/null
+++ b/vendor/github.com/mattn/go-sqlite3/.coderabbit.yaml
@@ -0,0 +1,15 @@
+# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
+language: en-US
+reviews:
+ # Skip the vendored SQLite amalgamation. These files are copied verbatim from
+ # upstream SQLite (see the License section in README.md) and are not code that
+ # this project authors or reviews.
+ path_filters:
+ - "!sqlite3-binding.c"
+ - "!sqlite3-binding.h"
+ - "!sqlite3ext.h"
+ auto_review:
+ enabled: true
+ drafts: false
+chat:
+ auto_reply: true
diff --git a/vendor/github.com/mattn/go-sqlite3/README.md b/vendor/github.com/mattn/go-sqlite3/README.md
index 4fd391118..16acdb454 100644
--- a/vendor/github.com/mattn/go-sqlite3/README.md
+++ b/vendor/github.com/mattn/go-sqlite3/README.md
@@ -7,6 +7,17 @@ go-sqlite3
[](https://codecov.io/gh/mattn/go-sqlite3)
[](https://goreportcard.com/report/github.com/mattn/go-sqlite3)
+## Sponsors
+
+This project is proudly sponsored by:
+
+
+
+
+
+
+
+
Latest stable version is v1.14 or later, not v2.
# Description
diff --git a/vendor/github.com/mattn/go-sqlite3/callback.go b/vendor/github.com/mattn/go-sqlite3/callback.go
index 293d26dba..8ea17db9d 100644
--- a/vendor/github.com/mattn/go-sqlite3/callback.go
+++ b/vendor/github.com/mattn/go-sqlite3/callback.go
@@ -34,8 +34,8 @@ import (
)
//export callbackTrampoline
-func callbackTrampoline(ctx *C.sqlite3_context, argc int, argv **C.sqlite3_value) {
- args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:argc:argc]
+func callbackTrampoline(ctx *C.sqlite3_context, argc C.int, argv **C.sqlite3_value) {
+ args := (*[(math.MaxInt32 - 1) / unsafe.Sizeof((*C.sqlite3_value)(nil))]*C.sqlite3_value)(unsafe.Pointer(argv))[:int(argc):int(argc)]
fi := lookupHandle(C.sqlite3_user_data(ctx)).(*functionInfo)
fi.Call(ctx, args)
}
@@ -60,9 +60,9 @@ func compareTrampoline(handlePtr unsafe.Pointer, la C.int, a *C.char, lb C.int,
}
//export commitHookTrampoline
-func commitHookTrampoline(handle unsafe.Pointer) int {
+func commitHookTrampoline(handle unsafe.Pointer) C.int {
callback := lookupHandle(handle).(func() int)
- return callback()
+ return C.int(callback())
}
//export rollbackHookTrampoline
@@ -72,23 +72,23 @@ func rollbackHookTrampoline(handle unsafe.Pointer) {
}
//export updateHookTrampoline
-func updateHookTrampoline(handle unsafe.Pointer, op int, db *C.char, table *C.char, rowid int64) {
+func updateHookTrampoline(handle unsafe.Pointer, op C.int, db *C.char, table *C.char, rowid int64) {
callback := lookupHandle(handle).(func(int, string, string, int64))
- callback(op, C.GoString(db), C.GoString(table), rowid)
+ callback(int(op), C.GoString(db), C.GoString(table), rowid)
}
//export authorizerTrampoline
-func authorizerTrampoline(handle unsafe.Pointer, op int, arg1 *C.char, arg2 *C.char, arg3 *C.char) int {
+func authorizerTrampoline(handle unsafe.Pointer, op C.int, arg1 *C.char, arg2 *C.char, arg3 *C.char) C.int {
callback := lookupHandle(handle).(func(int, string, string, string) int)
- return callback(op, C.GoString(arg1), C.GoString(arg2), C.GoString(arg3))
+ return C.int(callback(int(op), C.GoString(arg1), C.GoString(arg2), C.GoString(arg3)))
}
//export preUpdateHookTrampoline
-func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
+func preUpdateHookTrampoline(handle unsafe.Pointer, dbHandle uintptr, op C.int, db *C.char, table *C.char, oldrowid int64, newrowid int64) {
hval := lookupHandleVal(handle)
data := SQLitePreUpdateData{
Conn: hval.db,
- Op: op,
+ Op: int(op),
DatabaseName: C.GoString(db),
TableName: C.GoString(table),
OldRowID: oldrowid,
@@ -260,6 +260,16 @@ func callbackArgGeneric(v *C.sqlite3_value) (reflect.Value, error) {
}
}
+// callbackArgConvert returns conv as-is when the parameter type is the
+// canonical type conv produces, and wraps it with a cast for named types
+// (e.g. time.Duration), which reflect.Call would otherwise panic on.
+func callbackArgConvert(conv callbackArgConverter, typ, canonical reflect.Type) callbackArgConverter {
+ if typ == canonical {
+ return conv
+ }
+ return callbackArgCast{conv, typ}.Run
+}
+
func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
switch typ.Kind() {
case reflect.Interface:
@@ -271,18 +281,18 @@ func callbackArg(typ reflect.Type) (callbackArgConverter, error) {
if typ.Elem().Kind() != reflect.Uint8 {
return nil, errors.New("the only supported slice type is []byte")
}
- return callbackArgBytes, nil
+ return callbackArgConvert(callbackArgBytes, typ, reflect.TypeOf([]byte(nil))), nil
case reflect.String:
- return callbackArgString, nil
+ return callbackArgConvert(callbackArgString, typ, reflect.TypeOf("")), nil
case reflect.Bool:
- return callbackArgBool, nil
+ return callbackArgConvert(callbackArgBool, typ, reflect.TypeOf(false)), nil
case reflect.Int64:
- return callbackArgInt64, nil
+ return callbackArgConvert(callbackArgInt64, typ, reflect.TypeOf(int64(0))), nil
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
c := callbackArgCast{callbackArgInt64, typ}
return c.Run, nil
case reflect.Float64:
- return callbackArgFloat64, nil
+ return callbackArgConvert(callbackArgFloat64, typ, reflect.TypeOf(float64(0))), nil
case reflect.Float32:
c := callbackArgCast{callbackArgFloat64, typ}
return c.Run, nil
@@ -326,8 +336,7 @@ func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int, reflect.Uint:
v = v.Convert(reflect.TypeOf(int64(0)))
case reflect.Bool:
- b := v.Interface().(bool)
- if b {
+ if v.Bool() {
v = reflect.ValueOf(int64(1))
} else {
v = reflect.ValueOf(int64(0))
@@ -336,7 +345,7 @@ func callbackRetInteger(ctx *C.sqlite3_context, v reflect.Value) error {
return fmt.Errorf("cannot convert %s to INTEGER", v.Type())
}
- C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Interface().(int64)))
+ C.sqlite3_result_int64(ctx, C.sqlite3_int64(v.Int()))
return nil
}
@@ -349,7 +358,7 @@ func callbackRetFloat(ctx *C.sqlite3_context, v reflect.Value) error {
return fmt.Errorf("cannot convert %s to FLOAT", v.Type())
}
- C.sqlite3_result_double(ctx, C.double(v.Interface().(float64)))
+ C.sqlite3_result_double(ctx, C.double(v.Float()))
return nil
}
@@ -357,11 +366,10 @@ func callbackRetBlob(ctx *C.sqlite3_context, v reflect.Value) error {
if v.Type().Kind() != reflect.Slice || v.Type().Elem().Kind() != reflect.Uint8 {
return fmt.Errorf("cannot convert %s to BLOB", v.Type())
}
- i := v.Interface()
- if i == nil || len(i.([]byte)) == 0 {
+ bs := v.Bytes()
+ if len(bs) == 0 {
C.sqlite3_result_null(ctx)
} else {
- bs := i.([]byte)
if i64 && len(bs) > math.MaxInt32 {
C.sqlite3_result_error_toobig(ctx)
return nil
@@ -375,7 +383,7 @@ func callbackRetText(ctx *C.sqlite3_context, v reflect.Value) error {
if v.Type().Kind() != reflect.String {
return fmt.Errorf("cannot convert %s to TEXT", v.Type())
}
- s := v.Interface().(string)
+ s := v.String()
if i64 && len(s) > math.MaxInt32 {
C.sqlite3_result_error_toobig(ctx)
return nil
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
index 28c910600..337af9e47 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.c
@@ -1,7 +1,7 @@
#ifndef USE_LIBSQLITE3
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.53.2. By combining all the individual C code files into this
+** version 3.53.3. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -19,7 +19,7 @@
** separate file. This file contains only code for the core SQLite library.
**
** The content in this amalgamation comes from Fossil check-in
-** d6e03d8c777cfa2d35e3b60d8ec3e0187f3e with changes in files:
+** d4c0e51e4aeb96955b99185ab9cde75c339e with changes in files:
**
**
*/
@@ -468,12 +468,12 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.53.2"
-#define SQLITE_VERSION_NUMBER 3053002
-#define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
+#define SQLITE_VERSION "3.53.3"
+#define SQLITE_VERSION_NUMBER 3053003
+#define SQLITE_SOURCE_ID "2026-06-26 20:14:12 d4c0e51e4aeb96955b99185ab9cde75c339e2c29c3f3f12428d364a10d782c62"
#define SQLITE_SCM_BRANCH "branch-3.53"
-#define SQLITE_SCM_TAGS "release version-3.53.2"
-#define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
+#define SQLITE_SCM_TAGS "release version-3.53.3"
+#define SQLITE_SCM_DATETIME "2026-06-26T20:14:12.354Z"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -4688,7 +4688,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or in an ORDER BY or GROUP BY clause.)^
**
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(
SQLITE_LIMIT_EXPR_DEPTH
-** The maximum depth of the parse tree on any expression.)^
+** The maximum depth of the parse tree on any expression and
+** the maximum nesting depth for subqueries and VIEWs)^
**
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(SQLITE_LIMIT_PARSER_DEPTH
** The maximum depth of the LALR(1) parser stack used to analyze
@@ -4719,7 +4720,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(SQLITE_LIMIT_TRIGGER_DEPTH
-** The maximum depth of recursion for triggers.)^
+** The maximum depth of recursion for triggers, and the maximum
+** nesting depth for separate triggers.)^
**
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(SQLITE_LIMIT_WORKER_THREADS
** The maximum number of auxiliary worker threads that a single
@@ -15801,6 +15803,13 @@ SQLITE_PRIVATE void sqlite3HashClear(Hash*);
# define offsetof(ST,M) ((size_t)((char*)&((ST*)0)->M - (char*)0))
#endif
+/*
+** sizeof64() is like sizeof(), but always returns a 64-bit value, even
+** on 32-bit builds. This can help to avoid overflow by ensuring 64-bit
+** arithmetic is used consistently in both 32-bit and 64-bit builds.
+*/
+#define sizeof64(X) ((sqlite3_int64)sizeof(X))
+
/*
** Work around C99 "flex-array" syntax for pre-C99 compilers, so as
** to avoid complaints from -fsanitize=strict-bounds.
@@ -17162,7 +17171,7 @@ SQLITE_PRIVATE int sqlite3BtreeCheckpoint(Btree*, int, int *, int *);
SQLITE_PRIVATE const char *sqlite3BtreeGetFilename(Btree *);
SQLITE_PRIVATE const char *sqlite3BtreeGetJournalname(Btree *);
-SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree *, Btree *);
+SQLITE_PRIVATE int sqlite3BtreeCopyFile(Btree*, Btree*);
SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *);
@@ -20920,6 +20929,7 @@ struct Parse {
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
int iSelfTab; /* Table associated with an index on expr, or negative
** of the base register during check-constraint eval */
+ int nNestSel; /* Number of nested SELECT statements and/or VIEWs */
int nLabel; /* The *negative* of the number of labels used */
int nLabelAlloc; /* Number of slots in aLabel */
int *aLabel; /* Space to hold the labels */
@@ -39576,16 +39586,17 @@ int kvvfsDecode(const char *a, char *aOut, int nOut){
while( 1 ){
c = kvvfsHexValue[aIn[i]];
if( c<0 ){
- int n = 0;
- int mult = 1;
+ sqlite3_int64 n = 0;
+ sqlite3_int64 mult = 1;
c = aIn[i];
if( c==0 ) break;
while( c>='a' && c<='z' ){
n += (c - 'a')*mult;
+ if( n>nOut ) return -1 /* oversized/malformed input */;
mult *= 26;
c = aIn[++i];
}
- if( j+n>nOut ) return -1;
+ if( j+n>nOut ) return -1 /* oversized/malformed input */;
memset(&aOut[j], 0, n);
j += n;
if( c==0 || mult==1 ) break; /* progress stalled if mult==1 */
@@ -39621,7 +39632,7 @@ static void kvvfsDecodeJournal(
i = 0;
mult = 1;
while( (c = zTxt[i++])>='a' && c<='z' ){
- n += (zTxt[i] - 'a')*mult;
+ n += (c - 'a')*mult;
mult *= 26;
}
sqlite3_free(pFile->aJrnl);
@@ -39667,9 +39678,7 @@ static int kvvfsClose(sqlite3_file *pProtoFile){
pFile->isJournal ? "journal" : "db"));
sqlite3_free(pFile->aJrnl);
sqlite3_free(pFile->aData);
-#ifdef SQLITE_WASM
memset(pFile, 0, sizeof(*pFile));
-#endif
return SQLITE_OK;
}
@@ -39699,6 +39708,7 @@ static int kvvfsReadJrnl(
aTxt, szTxt+1);
if( rc>=0 ){
kvvfsDecodeJournal(pFile, aTxt, szTxt);
+ rc = 0;
}
sqlite3_free(aTxt);
if( rc ) return rc;
@@ -49762,10 +49772,8 @@ static struct win_syscall {
#define osWaitForSingleObjectEx ((DWORD(WINAPI*)(HANDLE,DWORD, \
BOOL))aSyscall[63].pCurrent)
- { "GetNativeSystemInfo", (SYSCALL)GetNativeSystemInfo, 0 },
-
-#define osGetNativeSystemInfo ((VOID(WINAPI*)( \
- LPSYSTEM_INFO))aSyscall[64].pCurrent)
+ { "GetNativeSystemInfo", (SYSCALL)0, 0 },
+ /* ^^^^^^^^^^^^^^^^^^^----------------^------- placeholder only */
#if defined(SQLITE_WIN32_HAS_ANSI)
{ "OutputDebugStringA", (SYSCALL)OutputDebugStringA, 0 },
@@ -53020,11 +53028,29 @@ SQLITE_API int sqlite3_win_test_unc_locking = 0;
/*
** Return true if the string passed as the only argument is likely
-** to be a UNC path. In other words, if it starts with "\\".
+** to be a UNC path. Return false if note.
+**
+** Return true if:
+**
+** (1) The name begins with "\\"
+** (2) But does not begin with "\\?\C:\" where C can be any alphabetic
+** character.
+**
+** For testing, also return true in all cases if the global variable
+** sqlite3_win_test_unc_locking is true.
*/
static int winIsUNCPath(const char *zFile){
if( zFile[0]=='\\' && zFile[1]=='\\' ){
- return 1;
+ if( zFile[2]=='?'
+ && zFile[3]=='\\'
+ && sqlite3Isalpha(zFile[4])
+ && zFile[5]==':'
+ && winIsDirSep(zFile[6])
+ ){
+ return sqlite3_win_test_unc_locking;
+ }else{
+ return 1;
+ }
}
return sqlite3_win_test_unc_locking;
}
@@ -56040,7 +56066,7 @@ SQLITE_API unsigned char *sqlite3_serialize(
sqlite3_int64 sz;
int szPage = 0;
sqlite3_stmt *pStmt = 0;
- unsigned char *pOut;
+ unsigned char *pOut = 0;
char *zSql;
int rc;
@@ -56050,12 +56076,13 @@ SQLITE_API unsigned char *sqlite3_serialize(
return 0;
}
#endif
+ sqlite3_mutex_enter(db->mutex);
if( zSchema==0 ) zSchema = db->aDb[0].zDbSName;
p = memdbFromDbSchema(db, zSchema);
iDb = sqlite3FindDbName(db, zSchema);
if( piSize ) *piSize = -1;
- if( iDb<0 ) return 0;
+ if( iDb<0 ) goto serialize_out;
if( p ){
MemStore *pStore = p->pStore;
assert( pStore->pMutex==0 );
@@ -56066,19 +56093,17 @@ SQLITE_API unsigned char *sqlite3_serialize(
pOut = sqlite3_malloc64( pStore->sz );
if( pOut ) memcpy(pOut, pStore->aData, pStore->sz);
}
- return pOut;
+ goto serialize_out;
}
pBt = db->aDb[iDb].pBt;
- if( pBt==0 ) return 0;
+ if( pBt==0 ) goto serialize_out;
szPage = sqlite3BtreeGetPageSize(pBt);
zSql = sqlite3_mprintf("PRAGMA \"%w\".page_count", zSchema);
rc = zSql ? sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0) : SQLITE_NOMEM;
sqlite3_free(zSql);
- if( rc ) return 0;
+ if( rc ) goto serialize_out;
rc = sqlite3_step(pStmt);
- if( rc!=SQLITE_ROW ){
- pOut = 0;
- }else{
+ if( rc==SQLITE_ROW ){
sz = sqlite3_column_int64(pStmt, 0)*szPage;
if( sz==0 ){
sqlite3_reset(pStmt);
@@ -56112,6 +56137,9 @@ SQLITE_API unsigned char *sqlite3_serialize(
}
}
sqlite3_finalize(pStmt);
+
+ serialize_out:
+ sqlite3_mutex_leave(db->mutex);
return pOut;
}
@@ -57965,22 +57993,24 @@ static int pcache1InitBulk(PCache1 *pCache){
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
szBulk = pCache->szAlloc*(i64)pCache->nMax;
}
- zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
- sqlite3EndBenignMalloc();
- if( zBulk ){
- int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
- do{
- PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
- pX->page.pBuf = zBulk;
- pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
- assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
- pX->isBulkLocal = 1;
- pX->isAnchor = 0;
- pX->pNext = pCache->pFree;
- pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
- pCache->pFree = pX;
- zBulk += pCache->szAlloc;
- }while( --nBulk );
+ if( szBulk>=pCache->szAlloc ){
+ zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
+ sqlite3EndBenignMalloc();
+ if( zBulk ){
+ int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
+ do{
+ PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
+ pX->page.pBuf = zBulk;
+ pX->page.pExtra = (u8*)pX + ROUND8(sizeof(*pX));
+ assert( EIGHT_BYTE_ALIGNMENT( pX->page.pExtra ) );
+ pX->isBulkLocal = 1;
+ pX->isAnchor = 0;
+ pX->pNext = pCache->pFree;
+ pX->pLruPrev = 0; /* Initializing this saves a valgrind error */
+ pCache->pFree = pX;
+ zBulk += pCache->szAlloc;
+ }while( --nBulk );
+ }
}
return pCache->pFree!=0;
}
@@ -60878,39 +60908,43 @@ static void checkPage(PgHdr *pPg){
#endif /* SQLITE_CHECK_PAGES */
/*
-** When this is called the journal file for pager pPager must be open.
-** This function attempts to read a super-journal file name from the
-** end of the file and, if successful, copies it into memory supplied
-** by the caller. See comments above writeSuperJournal() for the format
-** used to store a super-journal file name at the end of a journal file.
-**
-** zSuper must point to a buffer of at least nSuper bytes allocated by
-** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
-** enough space to write the super-journal name). If the super-journal
-** name in the journal is longer than nSuper bytes (including a
-** nul-terminator), then this is handled as if no super-journal name
-** were present in the journal.
+** Free a buffer allocated by the readSuperJournal() function.
+*/
+static void freeSuperJournal(char *zSuper){
+ if( zSuper ){
+ sqlite3_free(&zSuper[-4]);
+ }
+}
+
+/*
+** Parameter pJrnl is a file-handle open on a journal file. This function
+** attempts to read a super-journal file name from the end of the journal
+** file. If successful, it sets output parameter (*pzSuper) to point to a
+** buffer containing the super-journal name as a nul-terminated string.
+** The caller is responsible for freeing the buffer using freeSuperJournal().
**
-** If a super-journal file name is present at the end of the journal
-** file, then it is copied into the buffer pointed to by zSuper. A
-** nul-terminator byte is appended to the buffer following the
-** super-journal file name.
+** Refer to comments above writeSuperJournal() for the format used to store
+** a super-journal file name at the end of a journal file.
**
-** If it is determined that no super-journal file name is present
-** zSuper[0] is set to 0 and SQLITE_OK returned.
+** Parameter nSuper is passed the maximum allowable size of the super journal
+** name in bytes. If the super-journal name in the journal is longer than
+** nSuper bytes (including a nul-terminator), then this is handled as if no
+** super-journal name were present in the journal.
**
-** If an error occurs while reading from the journal file, an SQLite
-** error code is returned.
+** If there is no super-journal name at the end of pJrnl, (*pzSuper) is
+** set to 0 and SQLITE_OK is returned. Or, if an error occurs while reading
+** the super-journal name, an SQLite error code is returned and (*pzSuper)
+** is set to 0.
*/
-static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
+static int readSuperJournal(sqlite3_file *pJrnl, u64 nSuper, char **pzSuper){
int rc; /* Return code */
u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
u32 cksum; /* MJ checksum value read from journal */
- u32 u; /* Unsigned loop counter */
unsigned char aMagic[8]; /* A buffer to hold the magic header */
- zSuper[0] = '\0';
+ char *zOut = 0;
+ *pzSuper = 0;
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
@@ -60920,27 +60954,34 @@ static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u64 nSuper){
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
- || SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
){
return rc;
}
- /* See if the checksum matches the super-journal name */
- for(u=0; uzJournal */
+
+ /* Check if this looks like a real super-journal name. If it does not,
+ ** return SQLITE_OK without attempting to delete it. This is to limit
+ ** the degree to which a crafted journal file can be used to cause
+ ** SQLite to delete arbitrary files. */
+ if( pagerIsSuperJrnlName(zSuper)==0 ){
+ return SQLITE_OK;
+ }
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
@@ -62170,9 +62252,8 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
*/
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
- nSuperPtr = 1 + (i64)pVfs->mxPathname;
- assert( nSuperJournal>=0 && nSuperPtr>0 );
- zFree = sqlite3Malloc(4 + nSuperJournal + 2 + nSuperPtr + 2);
+ assert( nSuperJournal>=0 );
+ zFree = sqlite3Malloc(4 + nSuperJournal + 2);
if( !zFree ){
rc = SQLITE_NOMEM_BKPT;
goto delsuper_out;
@@ -62181,7 +62262,6 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
}
zFree[0] = zFree[1] = zFree[2] = zFree[3] = 0;
zSuperJournal = &zFree[4];
- zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
zSuperJournal[nSuperJournal] = 0;
@@ -62189,43 +62269,56 @@ static int pager_delsuper(Pager *pPager, const char *zSuper){
zJournal = zSuperJournal;
while( (zJournal-zSuperJournal)zJournal)==0 ){
+ bSeen = 1;
+ }else{
+ int exists;
+ rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
if( rc!=SQLITE_OK ){
goto delsuper_out;
}
+ if( exists ){
+ char *zSuperPtr = 0;
- rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
- sqlite3OsClose(pJournal);
- if( rc!=SQLITE_OK ){
- goto delsuper_out;
- }
+ /* One of the journals pointed to by the super-journal exists.
+ ** Open it and check if it points at the super-journal. If
+ ** so, return without deleting the super-journal file.
+ ** NB: zJournal is really a MAIN_JOURNAL. But call it a
+ ** SUPER_JOURNAL here so that the VFS will not send the zJournal
+ ** name into sqlite3_database_file_object().
+ */
+ int c;
+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
+ rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
+ if( rc!=SQLITE_OK ){
+ goto delsuper_out;
+ }
- c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
- if( c ){
- /* We have a match. Do not delete the super-journal file. */
- goto delsuper_out;
+ rc = readSuperJournal(pJournal, 1+(u64)pVfs->mxPathname, &zSuperPtr);
+ sqlite3OsClose(pJournal);
+ if( rc!=SQLITE_OK ){
+ assert( zSuperPtr==0 );
+ goto delsuper_out;
+ }
+
+ c = zSuperPtr!=0 && strcmp(zSuperPtr, zSuper)==0;
+ freeSuperJournal(zSuperPtr);
+ if( c ){
+ /* We have a match. Do not delete the super-journal file. */
+ goto delsuper_out;
+ }
}
}
zJournal += (sqlite3Strlen30(zJournal)+1);
}
sqlite3OsClose(pSuper);
- rc = sqlite3OsDelete(pVfs, zSuper, 0);
+ if( bSeen ){
+ /* Only delete the super-journal if bSeen is true - indicating that
+ ** the super-journal contained a pointer to this database's journal
+ ** file. */
+ rc = sqlite3OsDelete(pVfs, zSuper, 0);
+ }
delsuper_out:
sqlite3_free(zFree);
@@ -62430,19 +62523,11 @@ static int pager_playback(Pager *pPager, int isHot){
** If a super-journal file name is specified, but the file is not
** present on disk, then the journal is not hot and does not need to be
** played back.
- **
- ** TODO: Technically the following is an error because it assumes that
- ** buffer Pager.pTmpSpace is (mxPathname+1) bytes or larger. i.e. that
- ** ((pPager->pageSize+8) >= pPager->pVfs->mxPathname+1). Using os_unix.c,
- ** mxPathname is 512, which is the same as the minimum allowable value
- ** for pageSize, and so this assumption holds. But it might not for some
- ** custom VFS. */
- zSuper = pPager->pTmpSpace;
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
- if( rc==SQLITE_OK && zSuper[0] ){
+ */
+ rc = readSuperJournal(pPager->jfd, 1+(i64)pPager->pVfs->mxPathname, &zSuper);
+ if( rc==SQLITE_OK && zSuper ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
- zSuper = 0;
if( rc!=SQLITE_OK || !res ){
goto end_playback;
}
@@ -62571,30 +62656,20 @@ static int pager_playback(Pager *pPager, int isHot){
*/
pPager->changeCountDone = pPager->tempFile;
- if( rc==SQLITE_OK ){
- /* Leave 4 bytes of space before the super-journal filename in memory.
- ** This is because it may end up being passed to sqlite3OsOpen(), in
- ** which case it requires 4 0x00 bytes in memory immediately before
- ** the filename. */
- zSuper = &pPager->pTmpSpace[4];
- rc = readSuperJournal(pPager->jfd, zSuper, 1+(i64)pPager->pVfs->mxPathname);
- testcase( rc!=SQLITE_OK );
- }
if( rc==SQLITE_OK
&& (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
){
rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
- rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
+ rc = pager_end_transaction(pPager, zSuper!=0, 0);
testcase( rc!=SQLITE_OK );
}
- if( rc==SQLITE_OK && zSuper[0] && res ){
+ if( rc==SQLITE_OK && zSuper && res ){
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
- assert( zSuper==&pPager->pTmpSpace[4] );
- memset(pPager->pTmpSpace, 0, 4);
+ assert( memcmp(&zSuper[-4], "\0\0\0\0", 4)==0 );
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
@@ -62607,6 +62682,7 @@ static int pager_playback(Pager *pPager, int isHot){
** back a journal created by a process with a different sector size
** value. Reset it to the correct value for this process.
*/
+ freeSuperJournal(zSuper);
setSectorSize(pPager);
return rc;
}
@@ -68466,6 +68542,12 @@ static int walDecodeFrame(
return 0;
}
+ /* Need a valid page size
+ */
+ if( !pWal->szPage ){
+ return 0;
+ }
+
/* A frame is only valid if a checksum of the WAL header,
** all prior frames, the first 16 bytes of this frame-header,
** and the frame-data matches the checksum in the last 8
@@ -70320,7 +70402,7 @@ static int walBeginShmUnreliable(Wal *pWal, int *pChanged){
/* Allocate a buffer to read frames into */
assert( (pWal->szPage & (pWal->szPage-1))==0 );
- assert( pWal->szPage>=512 && pWal->szPage<=65536 );
+ assert( (pWal->szPage>=512 && pWal->szPage<=65536) || pWal->szPage==0 );
szFrame = pWal->szPage + WAL_FRAME_HDRSIZE;
aFrame = (u8 *)sqlite3_malloc64(szFrame);
if( aFrame==0 ){
@@ -72818,6 +72900,9 @@ struct IntegrityCk {
u32 *heap; /* Min-heap used for analyzing cell coverage */
sqlite3 *db; /* Database connection running the check */
i64 nRow; /* Number of rows visited in current tree */
+#ifdef SQLITE_DEBUG
+ u32 mxHeap; /* Maximum number of entries in the Min-heap */
+#endif
};
/*
@@ -75279,8 +75364,12 @@ static int btreeComputeFreeSpace(MemPage *pPage){
}
next = get2byte(&data[pc]);
size = get2byte(&data[pc+2]);
+ if( size<4 ){
+ /* Minimum freeblock size is 4 */
+ return SQLITE_CORRUPT_PAGE(pPage);
+ }
nFree = nFree + size;
- if( next<=pc+size+3 ) break;
+ if( next0 ){
@@ -79113,14 +79202,14 @@ static int indexCellCompare(
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
- testcase( pCell+nCell+1==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ) return 99;
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
- testcase( pCell+nCell+2==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ) return 99;
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* If the record extends into overflow pages, do not attempt
@@ -79282,14 +79371,17 @@ SQLITE_PRIVATE int sqlite3BtreeIndexMoveto(
/* This branch runs if the record-size field of the cell is a
** single byte varint and the record fits entirely on the main
** b-tree page. */
- testcase( pCell+nCell+1==pPage->aDataEnd );
+ if( pCell + nCell >= pPage->aDataEnd ){
+ rc = SQLITE_CORRUPT_PAGE(pPage);
+ goto moveto_index_finish;
+ }
c = xRecordCompare(nCell, (void*)&pCell[1], pIdxKey);
}else if( !(pCell[1] & 0x80)
&& (nCell = ((nCell&0x7f)<<7) + pCell[1])<=pPage->maxLocal
+ && pCell + nCell < pPage->aDataEnd
){
/* The record-size field is a 2 byte varint and the record
** fits entirely on the main b-tree page. */
- testcase( pCell+nCell+2==pPage->aDataEnd );
c = xRecordCompare(nCell, (void*)&pCell[2], pIdxKey);
}else{
/* The record flows over onto one or more overflow pages. In
@@ -84154,6 +84246,7 @@ static int checkTreePage(
}
}else{
/* Populate the coverage-checking heap for leaf pages */
+ assert( heap[0] < pCheck->mxHeap );
btreeHeapInsert(heap, (pc<<16)|(pc+info.nSize-1));
}
}
@@ -84173,6 +84266,7 @@ static int checkTreePage(
u32 size;
pc = get2byteAligned(&data[cellStart+i*2]);
size = pPage->xCellSize(pPage, &data[pc]);
+ assert( heap[0] < pCheck->mxHeap );
btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
}
}
@@ -84189,6 +84283,7 @@ static int checkTreePage(
assert( (u32)i<=usableSize-4 ); /* Enforced by btreeComputeFreeSpace() */
size = get2byte(&data[i+2]);
assert( (u32)(i+size)<=usableSize ); /* due to btreeComputeFreeSpace() */
+ assert( heap[0] < pCheck->mxHeap );
btreeHeapInsert(heap, (((u32)i)<<16)|(i+size-1));
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
** big-endian integer which is the offset in the b-tree page of the next
@@ -84323,6 +84418,9 @@ SQLITE_PRIVATE int sqlite3BtreeIntegrityCheck(
goto integrity_ck_cleanup;
}
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
+#ifdef SQLITE_DEBUG
+ sCheck.mxHeap = pBt->pageSize/4 - 1;
+#endif
if( sCheck.heap==0 ){
checkOom(&sCheck);
goto integrity_ck_cleanup;
@@ -84740,6 +84838,7 @@ SQLITE_PRIVATE int sqlite3BtreeConnectionCount(Btree *p){
*/
struct sqlite3_backup {
sqlite3* pDestDb; /* Destination database handle */
+ char *zDestDb;
Btree *pDest; /* Destination b-tree file */
u32 iDestSchema; /* Original schema cookie in destination */
int bDestLocked; /* True once a write-transaction is open on pDest */
@@ -84829,10 +84928,8 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
** Attempt to set the page size of the destination to match the page size
** of the source.
*/
-static int setDestPgsz(sqlite3_backup *p){
- int rc;
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
- return rc;
+static int setDestPgsz(Btree *pDest, Btree *pSrc){
+ return sqlite3BtreeSetPageSize(pDest, sqlite3BtreeGetPageSize(pSrc), 0, 0);
}
/*
@@ -84889,27 +84986,37 @@ SQLITE_API sqlite3_backup *sqlite3_backup_init(
);
p = 0;
}else {
+ int nDest = sqlite3Strlen30(zDestDb);
+
/* Allocate space for a new sqlite3_backup object...
** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
** call to sqlite3_backup_init() and is destroyed by a call to
** sqlite3_backup_finish(). */
- p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
+ p = (sqlite3_backup*)sqlite3MallocZero(sizeof(sqlite3_backup)+nDest+1);
if( !p ){
sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
+ }else{
+ p->zDestDb = (char*)&p[1];
+ memcpy(p->zDestDb, zDestDb, nDest);
}
}
/* If the allocation succeeded, populate the new object. */
if( p ){
+ /* Do not store the pointer to the destination b-tree at this point.
+ ** This is because there is nothing preventing it from being detached
+ ** or otherwise freed before the first call to sqlite3_backup_step()
+ ** on this object. The source b-tree does not have this problem, as
+ ** incrementing Btree.nBackup (see below) effectively locks the object. */
+ Btree *pDest = findBtree(pDestDb, pDestDb, zDestDb);
p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
- p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
p->pDestDb = pDestDb;
p->pSrcDb = pSrcDb;
p->iNext = 1;
p->isAttached = 0;
- if( 0==p->pSrc || 0==p->pDest
- || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
+ if( 0==p->pSrc || 0==pDest
+ || checkReadTransaction(pDestDb, pDest)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
@@ -85033,7 +85140,7 @@ static void attachBackupObject(sqlite3_backup *p){
*/
SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
int rc;
- int destMode; /* Destination journal mode */
+ int destMode = 0; /* Destination journal mode */
int pgszSrc = 0; /* Source page size */
int pgszDest = 0; /* Destination page size */
@@ -85049,7 +85156,8 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = p->rc;
if( !isFatalError(rc) ){
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
- Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
+ Btree * pDest = 0; /* Dest btree */
+ Pager * pDestPager = 0; /* Dest pager */
int ii; /* Iterator variable */
int nSrcPage = -1; /* Size of source db in pages */
int bCloseTrans = 0; /* True if src db requires unlocking */
@@ -85063,6 +85171,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
rc = SQLITE_OK;
}
+
/* If there is no open read-transaction on the source database, open
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
@@ -85072,34 +85181,48 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
bCloseTrans = 1;
}
+ /* Locate the destination btree and pager. */
+ if( (pDest = p->pDest)==0 ){
+ pDest = findBtree(p->pDestDb, p->pDestDb, p->zDestDb);
+ }
+ if( pDest==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ pDestPager = sqlite3BtreePager(pDest);
+ }
+
/* If the destination database has not yet been locked (i.e. if this
** is the first call to backup_step() for the current backup operation),
** try to set its page size to the same as the source database. This
** is especially important on ZipVFS systems, as in that case it is
** not possible to create a database file that uses one page size by
** writing to it with another. */
- if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
+ if( p->bDestLocked==0 && rc==SQLITE_OK
+ && setDestPgsz(pDest, p->pSrc)==SQLITE_NOMEM
+ ){
rc = SQLITE_NOMEM;
}
/* Lock the destination database, if it is not locked already. */
if( SQLITE_OK==rc && p->bDestLocked==0
- && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
+ && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(pDest, 2,
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
+ p->pDest = pDest;
}
/* Do not allow backup if the destination database is in WAL mode
** and the page sizes are different between source and destination */
- pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
- pgszDest = sqlite3BtreeGetPageSize(p->pDest);
- destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
- if( SQLITE_OK==rc
- && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
- && pgszSrc!=pgszDest
- ){
- rc = SQLITE_READONLY;
+ if( rc==SQLITE_OK ){
+ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
+ pgszDest = sqlite3BtreeGetPageSize(p->pDest);
+ destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
+ if( (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
+ && pgszSrc!=pgszDest
+ ){
+ rc = SQLITE_READONLY;
+ }
}
/* Now that there is a read-lock on the source database, query the
@@ -85317,7 +85440,9 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
}
/* If a transaction is still open on the Btree, roll it back. */
- sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
+ if( p->pDest ){
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
+ }
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
@@ -93585,8 +93710,14 @@ SQLITE_PRIVATE const char *sqlite3VdbeFuncName(const sqlite3_context *pCtx){
** added or changed.
*/
SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
- Vdbe *p = (Vdbe*)pStmt;
- return p==0 || p->expired;
+ int iRet = 1;
+ if( pStmt ){
+ Vdbe *p = (Vdbe*)pStmt;
+ sqlite3_mutex_enter(p->db->mutex);
+ iRet = p->expired;
+ sqlite3_mutex_leave(p->db->mutex);
+ }
+ return iRet;
}
#endif
@@ -116881,7 +117012,7 @@ static void sqlite3ExprCodeIN(
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
- sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
+ sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+aiMap[i], destStep2);
VdbeCoverage(v);
}
}
@@ -116965,8 +117096,8 @@ static void sqlite3ExprCodeIN(
** ...)" is the collating sequence of x.". */
pColl = sqlite3ExprCollSeq(pParse, p);
}
- sqlite3VdbeAddOp3(v, OP_Column, iTab, i, r3);
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs+i, destNotNull, r3,
+ sqlite3VdbeAddOp3(v, OP_Column, iTab, aiMap[i], r3);
+ sqlite3VdbeAddOp4(v, OP_Ne, rLhs+aiMap[i], destNotNull, r3,
(void*)pColl, P4_COLLSEQ);
VdbeCoverage(v);
sqlite3ReleaseTempReg(pParse, r3);
@@ -125305,9 +125436,9 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
pIdx->mxSample = nSample;
- nByte = ROUND8(sizeof(IndexSample) * nSample);
- nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
- nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
+ nByte = ROUND8(sizeof64(IndexSample) * nSample);
+ nByte += sizeof64(tRowcnt) * nIdxCol * 3 * nSample;
+ nByte += nIdxCol * sizeof64(tRowcnt); /* Space for Index.aAvgEq[] */
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
@@ -125315,7 +125446,7 @@ static int loadStatTbl(
return SQLITE_NOMEM_BKPT;
}
pPtr = (u8*)pIdx->aSample;
- pPtr += ROUND8(nSample*sizeof(pIdx->aSample[0]));
+ pPtr += ROUND8(nSample*sizeof64(pIdx->aSample[0]));
pSpace = (tRowcnt*)pPtr;
assert( EIGHT_BYTE_ALIGNMENT( pSpace ) );
pIdx->aAvgEq = pSpace; pSpace += nIdxCol;
@@ -136787,7 +136918,7 @@ static void percentSort(double *a, unsigned int n){
i++;
}
}while( in/2 ){
+ if( iLt>(int)(n/2) ){
if( n-iGt>=2 ) percentSort(a+iGt, n-iGt);
n = iLt;
}else{
@@ -151304,6 +151435,13 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, c
sqlite3 *db = pParse->db;
u64 savedFlags;
+ pParse->nNestSel++;
+#if SQLITE_MAX_EXPR_DEPTH>0
+ if( pParse->nNestSel >= db->aLimit[SQLITE_LIMIT_EXPR_DEPTH] ){
+ sqlite3ErrorMsg(pParse, "VIEWs and/or subqueries nested too deep");
+ return 0;
+ }
+#endif
savedFlags = db->flags;
db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
@@ -151325,6 +151463,8 @@ SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, c
sqlite3DeleteTable(db, pTab);
return 0;
}
+ pParse->nNestSel--;
+ assert( pParse->nNestSel>=0 );
return pTab;
}
@@ -159268,7 +159408,7 @@ static TriggerPrg *codeRowTrigger(
Table *pTab, /* The table pTrigger is attached to */
int orconf /* ON CONFLICT policy to code trigger program with */
){
- Parse *pTop = sqlite3ParseToplevel(pParse);
+ Parse *pTop; /* Top level Parse object */
sqlite3 *db = pParse->db; /* Database handle */
TriggerPrg *pPrg; /* Value to return */
Expr *pWhen = 0; /* Duplicate of trigger WHEN expression */
@@ -159277,10 +159417,24 @@ static TriggerPrg *codeRowTrigger(
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
+ int nDepth; /* Trigger depth */
+ /* Ensure that triggers are not chained too deep. This test is linear
+ ** in the chaining depth, but sensible code ought not be chaining
+ ** triggers excessively, so that shouldn't be a problem.
+ */
+ pTop = pParse;
+ for(nDepth=0; pTop->pOuterParse; pTop = pTop->pOuterParse, nDepth++){}
+ if( nDepth>=db->aLimit[SQLITE_LIMIT_TRIGGER_DEPTH] ){
+ sqlite3ErrorMsg(pParse, "triggers nested too deep");
+ return 0;
+ }
+
+ pTop = sqlite3ParseToplevel(pParse);
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
+
/* Allocate the TriggerPrg and SubProgram objects. To ensure that they
** are freed if an error occurs, link them into the Parse.pTriggerPrg
** list of the top-level Parse object sooner rather than later. */
@@ -161281,7 +161435,8 @@ SQLITE_PRIVATE void sqlite3UpsertDoUpdate(
/* excluded.* columns of type REAL need to be converted to a hard real */
for(i=0; inCol; i++){
if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
- sqlite3VdbeAddOp1(v, OP_RealAffinity, pTop->regData+i);
+ int iStorage = pTop->regData + sqlite3TableColumnToStorage(pTab, i);
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iStorage);
}
}
sqlite3Update(pParse, pSrc, sqlite3ExprListDup(db,pUpsert->pUpsertSet,0),
@@ -161869,6 +162024,7 @@ SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
+ sqlite3_mutex_enter(db->mutex);
for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){
Module *pMod = (Module*)sqliteHashData(pThis);
pNext = sqliteHashNext(pThis);
@@ -161879,6 +162035,7 @@ SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
}
createModule(db, pMod->zName, 0, 0, 0);
}
+ sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -167253,7 +167410,10 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
pWC->a[iChild].iParent = iParent;
pWC->a[iChild].truthProb = pWC->a[iParent].truthProb;
+ assert( pWC->a[iParent].nChild < UMXV(pWC->a[0].nChild) );
pWC->a[iParent].nChild++;
+ testcase( pWC->a[iParent].nChild == UMXV(pWC->a[0].nChild) );
+
}
/*
@@ -168030,6 +168190,7 @@ static void exprAnalyze(
pList = pExpr->x.pList;
assert( pList!=0 );
assert( pList->nExpr==2 );
+ assert( pWC->a[idxTerm].nChild==0 );
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
@@ -168240,8 +168401,11 @@ static void exprAnalyze(
&& pExpr->x.pSelect->pWin==0
#endif
&& pWC->op==TK_AND
+ && pExpr->x.pSelect->pEList->nExpr <= UMXV(pTerm->nChild)
+ /* ^-- See bug 2026-06-04T10:00:49Z */
){
int i;
+ assert( pTerm->nChild==0 );
for(i=0; ipLeft); i++){
int idxNew;
idxNew = whereClauseInsert(pWC, pExpr, TERM_VIRTUAL|TERM_SLICE);
@@ -188310,13 +188474,17 @@ static int nocaseCollatingFunc(
** Return the ROWID of the most recent insert
*/
SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->lastRowid;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->lastRowid;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
/*
@@ -188338,13 +188506,17 @@ SQLITE_API void sqlite3_set_last_insert_rowid(sqlite3 *db, sqlite3_int64 iRowid)
** Return the number of changes in the most recent call to sqlite3_exec().
*/
SQLITE_API sqlite3_int64 sqlite3_changes64(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->nChange;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->nChange;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_changes(sqlite3 *db){
return (int)sqlite3_changes64(db);
@@ -188354,13 +188526,17 @@ SQLITE_API int sqlite3_changes(sqlite3 *db){
** Return the number of changes since the database handle was opened.
*/
SQLITE_API sqlite3_int64 sqlite3_total_changes64(sqlite3 *db){
+ i64 iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->nTotalChange;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->nTotalChange;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_total_changes(sqlite3 *db){
return (int)sqlite3_total_changes64(db);
@@ -189043,6 +189219,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
+ sqlite3_mutex_enter(db->mutex);
if( ms>0 ){
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
(void*)db);
@@ -189053,6 +189230,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
}else{
sqlite3_busy_handler(db, 0, 0);
}
+ sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
}
@@ -189958,9 +190136,11 @@ SQLITE_API int sqlite3_set_errmsg(sqlite3 *db, int errcode, const char *zMsg){
*/
SQLITE_API int sqlite3_error_offset(sqlite3 *db){
int iOffset = -1;
- if( db && sqlite3SafetyCheckSickOrOk(db) && db->errCode ){
+ if( db && sqlite3SafetyCheckSickOrOk(db) ){
sqlite3_mutex_enter(db->mutex);
- iOffset = db->errByteOffset;
+ if( db->errCode ){
+ iOffset = db->errByteOffset;
+ }
sqlite3_mutex_leave(db->mutex);
}
return iOffset;
@@ -190014,25 +190194,43 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
SQLITE_API int sqlite3_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ int iRet;
+ if( !db ) return SQLITE_NOMEM_BKPT;
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ iRet = SQLITE_NOMEM_BKPT;
+ }else{
+ iRet = db->errCode & db->errMask;
}
- return db->errCode & db->errMask;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
- if( db && !sqlite3SafetyCheckSickOrOk(db) ){
+ int iRet;
+ if( !db ) return SQLITE_NOMEM_BKPT;
+ if( !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
- if( !db || db->mallocFailed ){
- return SQLITE_NOMEM_BKPT;
+ sqlite3_mutex_enter(db->mutex);
+ if( db->mallocFailed ){
+ iRet = SQLITE_NOMEM_BKPT;
+ }else{
+ iRet = db->errCode;
}
- return db->errCode;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
SQLITE_API int sqlite3_system_errno(sqlite3 *db){
- return db ? db->iSysErrno : 0;
+ int iRet = 0;
+ if( db ){
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->iSysErrno;
+ sqlite3_mutex_leave(db->mutex);
+ }
+ return iRet;
}
/*
@@ -190227,6 +190425,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
if( limitId<0 || limitId>=SQLITE_N_LIMIT ){
return -1;
}
+ sqlite3_mutex_enter(db->mutex);
oldLimit = db->aLimit[limitId];
if( newLimit>=0 ){ /* IMP: R-52476-28732 */
if( newLimit>aHardLimit[limitId] ){
@@ -190236,6 +190435,7 @@ SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
}
db->aLimit[limitId] = newLimit;
}
+ sqlite3_mutex_leave(db->mutex);
return oldLimit; /* IMP: R-53341-35419 */
}
@@ -190278,7 +190478,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
const char *zVfs = zDefaultVfs;
char *zFile;
char c;
- int nUri = sqlite3Strlen30(zUri);
+ i64 nUri = strlen(zUri);
assert( *pzErrMsg==0 );
@@ -190288,8 +190488,8 @@ SQLITE_PRIVATE int sqlite3ParseUri(
){
char *zOpt;
int eState; /* Parser state when parsing URI */
- int iIn; /* Input character index */
- int iOut = 0; /* Output character index */
+ i64 iIn; /* Input character index */
+ i64 iOut = 0; /* Output character index */
u64 nByte = nUri+8; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
@@ -190323,7 +190523,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
while( zUri[iIn] && zUri[iIn]!='/' ) iIn++;
if( iIn!=7 && (iIn!=16 || memcmp("localhost", &zUri[7], 9)) ){
*pzErrMsg = sqlite3_mprintf("invalid uri authority: %.*s",
- iIn-7, &zUri[7]);
+ (int)(iIn-7), &zUri[7]);
rc = SQLITE_ERROR;
goto parse_uri_out;
}
@@ -190398,11 +190598,11 @@ SQLITE_PRIVATE int sqlite3ParseUri(
** here. Options that are interpreted here include "vfs" and those that
** correspond to flags that may be passed to the sqlite3_open_v2()
** method. */
- zOpt = &zFile[sqlite3Strlen30(zFile)+1];
+ zOpt = &zFile[strlen(zFile)+1];
while( zOpt[0] ){
- int nOpt = sqlite3Strlen30(zOpt);
+ i64 nOpt = strlen(zOpt);
char *zVal = &zOpt[nOpt+1];
- int nVal = sqlite3Strlen30(zVal);
+ i64 nVal = strlen(zVal);
if( nOpt==3 && memcmp("vfs", zOpt, 3)==0 ){
zVfs = zVal;
@@ -190448,7 +190648,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
int mode = 0;
for(i=0; aMode[i].z; i++){
const char *z = aMode[i].z;
- if( nVal==sqlite3Strlen30(z) && 0==memcmp(zVal, z, nVal) ){
+ if( nVal==(i64)strlen(z) && 0==memcmp(zVal, z, nVal) ){
mode = aMode[i].mode;
break;
}
@@ -191133,13 +191333,17 @@ SQLITE_API int sqlite3_global_recover(void){
** by the next COMMIT or ROLLBACK.
*/
SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
+ int iRet;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- return db->autoCommit;
+ sqlite3_mutex_enter(db->mutex);
+ iRet = db->autoCommit;
+ sqlite3_mutex_leave(db->mutex);
+ return iRet;
}
/*
@@ -192164,17 +192368,19 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
** of range.
*/
SQLITE_API const char *sqlite3_db_name(sqlite3 *db, int N){
+ const char *zRet = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
- if( N<0 || N>=db->nDb ){
- return 0;
- }else{
- return db->aDb[N].zDbSName;
+ sqlite3_mutex_enter(db->mutex);
+ if( N>=0 && NnDb ){
+ zRet = db->aDb[N].zDbSName;
}
+ sqlite3_mutex_leave(db->mutex);
+ return zRet;
}
/*
@@ -195796,8 +196002,13 @@ static void fts3PutDeltaVarint(
sqlite3_int64 iVal /* Write this value to the list */
){
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
- *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
- *piPrev = iVal;
+ if( iVal-(*piPrev)>=0 ){
+ /* Refuse to write a negative delta integer. This only happens with a
+ ** corrupt db (see the assert above) and can cause buffer overwrites
+ ** in some cases. */
+ *pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
+ *piPrev = iVal;
+ }
}
/*
@@ -198151,6 +198362,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
char *p1;
char *p2;
char *aOut;
+ i64 nAlloc = (i64)nPoslist*2 + FTS3_BUFFER_PADDING;
if( nMaxUndeferred>iPrev ){
p1 = aPoslist;
@@ -198162,7 +198374,7 @@ static int fts3EvalDeferredPhrase(Fts3Cursor *pCsr, Fts3Phrase *pPhrase){
nDistance = iPrev - nMaxUndeferred;
}
- aOut = (char *)sqlite3Fts3MallocZero(((i64)nPoslist)+FTS3_BUFFER_PADDING);
+ aOut = (char *)sqlite3Fts3MallocZero(nAlloc);
if( !aOut ){
sqlite3_free(aPoslist);
return SQLITE_NOMEM;
@@ -207217,6 +207429,10 @@ static void fts3ReadEndBlockField(
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
+
+ /* This if() clause is just to avoid an integer overflow. The record is
+ ** corrupt in this case. */
+ if( (i64)iVal==SMALLEST_INT64 ) iMul = 1;
*pnByte = ((i64)iVal * (i64)iMul);
}
}
@@ -208443,7 +208659,7 @@ static int fts3IncrmergeLoad(
return FTS_CORRUPT_VTAB;
}
- pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
+ pWriter->nLeafEst = (int)(((iEnd - iStart)+1)/FTS_MAX_APPENDABLE_HEIGHT);
pWriter->iStart = iStart;
pWriter->iEnd = iEnd;
pWriter->iAbsLevel = iAbsLevel;
@@ -218557,7 +218773,7 @@ struct RtreeCursor {
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
RtreeSearchPoint sPoint; /* Cached next search point */
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
- u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
+ u32 anQueue[RTREE_MAX_DEPTH+2]; /* Number of queued entries by iLevel */
};
/* Return the Rtree of a RtreeCursor */
@@ -219012,6 +219228,9 @@ static int nodeAcquire(
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
+ }else if( iNode<=0 ){
+ RTREE_IS_CORRUPT(pRtree);
+ rc = SQLITE_CORRUPT_VTAB;
}else if( pRtree->iNodeSize==sqlite3_blob_bytes(pRtree->pNodeBlob) ){
pNode = (RtreeNode *)sqlite3_malloc64(sizeof(RtreeNode)+pRtree->iNodeSize);
if( !pNode ){
@@ -219037,7 +219256,7 @@ static int nodeAcquire(
*/
if( rc==SQLITE_OK && pNode && iNode==1 ){
pRtree->iDepth = readInt16(pNode->zData);
- if( pRtree->iDepth>RTREE_MAX_DEPTH ){
+ if( pRtree->iDepth>=RTREE_MAX_DEPTH ){
rc = SQLITE_CORRUPT_VTAB;
RTREE_IS_CORRUPT(pRtree);
}
@@ -226600,16 +226819,26 @@ static unsigned int rbuDeltaGetInt(const char **pz, int *pLen){
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, 36,
-1, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, -1, -1, -1, 63, -1,
+
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
};
unsigned int v = 0;
int c;
unsigned char *z = (unsigned char*)*pz;
- unsigned char *zStart = z;
- while( (c = zValue[0x7f&*(z++)])>=0 ){
- v = (v<<6) + c;
+ unsigned char *zEnd = z + (*pLen);
+ while( z=0 ){
+ v = (v<<6) + c;
+ z++;
}
- z--;
- *pLen -= (int)(z - zStart);
+
+ *pLen -= (int)(z - (unsigned char*)*pz);
*pz = (char*)z;
return v;
}
@@ -226685,7 +226914,7 @@ static int rbuDeltaApply(
#endif
limit = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
+ if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -226693,11 +226922,12 @@ static int rbuDeltaApply(
while( *zDelta && lenDelta>0 ){
unsigned int cnt, ofst;
cnt = rbuDeltaGetInt(&zDelta, &lenDelta);
+ if( lenDelta<=0 ) return -1;
switch( zDelta[0] ){
case '@': {
zDelta++; lenDelta--;
ofst = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( lenDelta>0 && zDelta[0]!=',' ){
+ if( lenDelta>0 || zDelta[0]!=',' ){
/* ERROR: copy command not terminated by ',' */
return -1;
}
@@ -226722,7 +226952,7 @@ static int rbuDeltaApply(
/* ERROR: insert command gives an output larger than predicted */
return -1;
}
- if( (int)cnt>lenDelta ){
+ if( (i64)cnt>(i64)lenDelta ){
/* ERROR: insert count exceeds size of delta */
return -1;
}
@@ -226760,7 +226990,7 @@ static int rbuDeltaApply(
static int rbuDeltaOutputSize(const char *zDelta, int lenDelta){
int size;
size = rbuDeltaGetInt(&zDelta, &lenDelta);
- if( *zDelta!='\n' ){
+ if( lenDelta<=0 || *zDelta!='\n' ){
/* ERROR: size integer not terminated by "\n" */
return -1;
}
@@ -226808,7 +227038,7 @@ static void rbuFossilDeltaFunc(
return;
}
- aOut = sqlite3_malloc(nOut+1);
+ aOut = sqlite3_malloc64((i64)nOut+1);
if( aOut==0 ){
sqlite3_result_error_nomem(context);
}else{
@@ -234987,7 +235217,7 @@ static void sessionAppendStr(
int *pRc
){
int nStr = sqlite3Strlen30(zStr);
- if( 0==sessionBufferGrow(p, nStr+1, pRc) ){
+ if( 0==sessionBufferGrow(p, (i64)nStr+1, pRc) ){
memcpy(&p->aBuf[p->nBuf], zStr, nStr);
p->nBuf += nStr;
p->aBuf[p->nBuf] = 0x00;
@@ -240385,14 +240615,17 @@ static void sessionAppendRecordMerge(
u8 *a2, int n2, /* Record 2 */
int *pRc /* IN/OUT: error code */
){
- sessionBufferGrow(pBuf, n1+n2, pRc);
+ u8 *a1Eof = &a1[n1];
+ u8 *a2Eof = &a2[n2];
+
+ sessionBufferGrow(pBuf, (i64)n1+n2, pRc);
if( *pRc==SQLITE_OK ){
int i;
u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
for(i=0; i0 && (*a1==0 || *a1==0xFF)) ){
memcpy(pOut, a2, nn2);
pOut += nn2;
}else{
@@ -240434,7 +240667,7 @@ static void sessionAppendPartialUpdate(
u8 *aChange, int nChange, /* Record to rebase against */
int *pRc /* IN/OUT: Return Code */
){
- sessionBufferGrow(pBuf, 2+nRec+nChange, pRc);
+ sessionBufferGrow(pBuf, (i64)2+nRec+nChange, pRc);
if( *pRc==SQLITE_OK ){
int bData = 0;
u8 *pOut = &pBuf->aBuf[pBuf->nBuf];
@@ -244774,7 +245007,7 @@ static void fts5SnippetFunction(
int rc = SQLITE_OK; /* Return code */
int iCol; /* 1st argument to snippet() */
const char *zEllips; /* 4th argument to snippet() */
- int nToken; /* 5th argument to snippet() */
+ i64 nToken; /* 5th argument to snippet() */
int nInst = 0; /* Number of instance matches this row */
int i; /* Used to iterate through instances */
int nPhrase; /* Number of phrases in query */
@@ -244799,7 +245032,7 @@ static void fts5SnippetFunction(
ctx.zClose = fts5ValueToText(apVal[2]);
ctx.iRangeEnd = -1;
zEllips = fts5ValueToText(apVal[3]);
- nToken = sqlite3_value_int(apVal[4]);
+ nToken = (int)(MIN( MAX(sqlite3_value_int64(apVal[4]), 0), 64));
iBestCol = (iCol>=0 ? iCol : 0);
nPhrase = pApi->xPhraseCount(pFts);
@@ -247515,7 +247748,7 @@ static int fts5ExprNearIsMatch(int *pRc, Fts5ExprNearset *pNear){
i64 iPos = a[i].reader.iPos;
Fts5PoslistWriter *pWriter = &a[i].writer;
if( a[i].pOut->n==0 || iPos!=pWriter->iPrev ){
- sqlite3Fts5PoslistWriterAppend(a[i].pOut, pWriter, iPos);
+ sqlite3Fts5PoslistSafeAppend(a[i].pOut, &pWriter->iPrev, iPos);
}
}
@@ -248466,10 +248699,10 @@ static int fts5ParseTokenize(
memset(pSyn, 0, (size_t)nByte);
pSyn->pTerm = ((char*)pSyn) + sizeof(Fts5ExprTerm) + sizeof(Fts5Buffer);
pSyn->nFullTerm = pSyn->nQueryTerm = nToken;
+ memcpy(pSyn->pTerm, pToken, nToken);
if( pCtx->pConfig->bTokendata ){
pSyn->nQueryTerm = (int)strlen(pSyn->pTerm);
}
- memcpy(pSyn->pTerm, pToken, nToken);
pSyn->pSynonym = pPhrase->aTerm[pPhrase->nTerm-1].pSynonym;
pPhrase->aTerm[pPhrase->nTerm-1].pSynonym = pSyn;
}
@@ -251752,7 +251985,7 @@ static int fts5StructureDecode(
i += fts5GetVarint32(&pData[i], nTotal);
if( nTotalnMerge ) rc = FTS5_CORRUPT;
pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&rc,
- nTotal * sizeof(Fts5StructureSegment)
+ (i64)nTotal * sizeof(Fts5StructureSegment)
);
nSegment -= nTotal;
}
@@ -252708,7 +252941,7 @@ static void fts5SegIterReverseNewPage(Fts5Index *p, Fts5SegIter *pIter){
while( p->rc==SQLITE_OK && pIter->iLeafPgno>pIter->iTermLeafPgno ){
Fts5Data *pNew;
pIter->iLeafPgno--;
- pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID(
+ pNew = fts5LeafRead(p, FTS5_SEGMENT_ROWID(
pIter->pSeg->iSegid, pIter->iLeafPgno
));
if( pNew ){
@@ -258576,8 +258809,8 @@ static void fts5IndexTombstoneRebuild(
){
const int MINSLOT = 32;
int nSlotPerPage = MAX(MINSLOT, (p->pConfig->pgsz - 8) / szKey);
- int nSlot = 0; /* Number of slots in each output page */
- int nOut = 0;
+ i64 nSlot = 0; /* Number of slots in each output page */
+ i64 nOut = 0;
/* Figure out how many output pages (nOut) and how many slots per
** page (nSlot). There are three possibilities:
@@ -258602,23 +258835,26 @@ static void fts5IndexTombstoneRebuild(
nSlot = MINSLOT;
}else if( pSeg->nPgTombstone==1 ){
/* Case 2. */
- int nElem = (int)fts5GetU32(&pData1->p[4]);
+ u32 nElem = fts5GetU32(&pData1->p[4]);
assert( pData1 && iPg1==0 );
- nOut = 1;
- nSlot = MAX(nElem*4, MINSLOT);
- if( nSlot>nSlotPerPage ) nOut = 0;
+ if( nElem>((u32)nSlotPerPage/4) ){
+ nOut = 0;
+ }else{
+ nOut = 1;
+ nSlot = MAX((i64)nElem*4, MINSLOT);
+ }
}
if( nOut==0 ){
/* Case 3. */
- nOut = (pSeg->nPgTombstone * 2 + 1);
+ nOut = ((i64)pSeg->nPgTombstone * 2 + 1);
nSlot = nSlotPerPage;
}
/* Allocate the required array and output pages */
while( 1 ){
int res = 0;
- int ii = 0;
- int szPage = 0;
+ i64 ii = 0;
+ i64 szPage = 0;
Fts5Data **apOut = 0;
/* Allocate space for the new hash table */
@@ -259123,9 +259359,13 @@ static void fts5IndexIntegrityCheckSegment(
FTS5_CORRUPT_ROWID(p, iRow);
}else{
iOff += fts5GetVarint32(&pLeaf->p[iOff], nTerm);
- res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
- if( res==0 ) res = nTerm - nIdxTerm;
- if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
+ if( iOff+nTerm>pLeaf->szLeaf ){
+ FTS5_CORRUPT_ROWID(p, iRow);
+ }else{
+ res = fts5Memcmp(&pLeaf->p[iOff], zIdxTerm, MIN(nTerm, nIdxTerm));
+ if( res==0 ) res = nTerm - nIdxTerm;
+ if( res<0 ) FTS5_CORRUPT_ROWID(p, iRow);
+ }
}
fts5IntegrityCheckPgidx(p, iRow, pLeaf);
@@ -259156,7 +259396,7 @@ static void fts5IndexIntegrityCheckSegment(
/* Check any rowid-less pages that occur before the current leaf. */
for(iPg=iPrevLeaf+1; iPgeContent==FTS5_CONTENT_NORMAL
|| pConfig->eContent==FTS5_CONTENT_UNINDEXED
){
- int nDefn = 32 + pConfig->nCol*10;
- char *zDefn = sqlite3_malloc64(32 + (sqlite3_int64)pConfig->nCol * 20);
- if( zDefn==0 ){
- rc = SQLITE_NOMEM;
- }else{
- int i;
- int iOff;
- sqlite3_snprintf(nDefn, zDefn, "id INTEGER PRIMARY KEY");
- iOff = (int)strlen(zDefn);
- for(i=0; inCol; i++){
- if( pConfig->eContent==FTS5_CONTENT_NORMAL
- || pConfig->abUnindexed[i]
- ){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", c%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
- }
+ int i = 0;
+ char *zDefn = 0;
+ sqlite3_str *pDefn = sqlite3_str_new(pConfig->db);
+
+ sqlite3_str_appendf(pDefn, "id INTEGER PRIMARY KEY");
+ for(i=0; inCol; i++){
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL || pConfig->abUnindexed[i] ){
+ sqlite3_str_appendf(pDefn, ", c%d", i);
}
- if( pConfig->bLocale ){
- for(i=0; inCol; i++){
- if( pConfig->abUnindexed[i]==0 ){
- sqlite3_snprintf(nDefn-iOff, &zDefn[iOff], ", l%d", i);
- iOff += (int)strlen(&zDefn[iOff]);
- }
+ }
+ if( pConfig->bLocale ){
+ for(i=0; inCol; i++){
+ if( pConfig->abUnindexed[i]==0 ){
+ sqlite3_str_appendf(pDefn, ", l%d", i);
}
}
+ }
+ zDefn = sqlite3_str_finish(pDefn);
+
+ if( zDefn ){
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
+ sqlite3_free(zDefn);
+ }else{
+ rc = SQLITE_NOMEM;
}
- sqlite3_free(zDefn);
}
if( rc==SQLITE_OK && pConfig->bColumnsize ){
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
index 7ea576038..9417bce8d 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3-binding.h
@@ -147,12 +147,12 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.53.2"
-#define SQLITE_VERSION_NUMBER 3053002
-#define SQLITE_SOURCE_ID "2026-06-03 19:12:13 d6e03d8c777cfa2d35e3b60d8ec3e0187f3e9f99d8e2ee9cac695fd6fcdf1a24"
+#define SQLITE_VERSION "3.53.3"
+#define SQLITE_VERSION_NUMBER 3053003
+#define SQLITE_SOURCE_ID "2026-06-26 20:14:12 d4c0e51e4aeb96955b99185ab9cde75c339e2c29c3f3f12428d364a10d782c62"
#define SQLITE_SCM_BRANCH "branch-3.53"
-#define SQLITE_SCM_TAGS "release version-3.53.2"
-#define SQLITE_SCM_DATETIME "2026-06-03T19:12:13.350Z"
+#define SQLITE_SCM_TAGS "release version-3.53.3"
+#define SQLITE_SCM_DATETIME "2026-06-26T20:14:12.354Z"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -4367,7 +4367,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** or in an ORDER BY or GROUP BY clause.)^
**
** [[SQLITE_LIMIT_EXPR_DEPTH]] ^(SQLITE_LIMIT_EXPR_DEPTH
-** The maximum depth of the parse tree on any expression.)^
+** The maximum depth of the parse tree on any expression and
+** the maximum nesting depth for subqueries and VIEWs)^
**
** [[SQLITE_LIMIT_PARSER_DEPTH]] ^(SQLITE_LIMIT_PARSER_DEPTH
** The maximum depth of the LALR(1) parser stack used to analyze
@@ -4398,7 +4399,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** The maximum index number of any [parameter] in an SQL statement.)^
**
** [[SQLITE_LIMIT_TRIGGER_DEPTH]] ^(SQLITE_LIMIT_TRIGGER_DEPTH
-** The maximum depth of recursion for triggers.)^
+** The maximum depth of recursion for triggers, and the maximum
+** nesting depth for separate triggers.)^
**
** [[SQLITE_LIMIT_WORKER_THREADS]] ^(SQLITE_LIMIT_WORKER_THREADS
** The maximum number of auxiliary worker threads that a single
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3.go b/vendor/github.com/mattn/go-sqlite3/sqlite3.go
index 656d2dc67..c30bb8f1e 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3.go
@@ -445,12 +445,12 @@ type SQLiteDriver struct {
// SQLiteConn implements driver.Conn.
type SQLiteConn struct {
- mu sync.Mutex
- db *C.sqlite3
- loc *time.Location
- txlock string
- funcs []*functionInfo
- aggregators []*aggInfo
+ mu sync.Mutex
+ db *C.sqlite3
+ loc *time.Location
+ txlock string
+ funcs []*functionInfo
+ aggregators []*aggInfo
// Prepared-statement cache. The slice is allocated at Open with a
// fixed capacity equal to the configured cache size; cap bounds the
// cache, len is the live count, and entries are ordered LRU-first
@@ -1595,6 +1595,20 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
return nil, errors.New("sqlite succeeded without returning a database")
}
+ // Create connection to SQLite
+ conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
+ if stmtCacheSize > 0 {
+ conn.stmtCache = make([]*SQLiteStmt, 0, stmtCacheSize)
+ conn.stmtCacheEnabled = true
+ }
+
+ // fail closes the connection so no error path leaks the database
+ // handle or any callback handles registered on it.
+ fail := func(err error) (driver.Conn, error) {
+ conn.Close()
+ return nil, err
+ }
+
exec := func(s string) error {
cs := C.CString(s)
rv := C.sqlite3_exec(db, cs, nil, nil, nil)
@@ -1607,8 +1621,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// Busy timeout
if err := exec(fmt.Sprintf("PRAGMA busy_timeout = %d;", busyTimeout)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
// USER AUTHENTICATION
@@ -1633,66 +1646,59 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// NO => Continue
//
- // Create connection to SQLite
- conn := &SQLiteConn{db: db, loc: loc, txlock: txlock}
- if stmtCacheSize > 0 {
- conn.stmtCache = make([]*SQLiteStmt, 0, stmtCacheSize)
- conn.stmtCacheEnabled = true
- }
-
// Password Cipher has to be registered before authentication
if len(authCrypt) > 0 {
switch strings.ToUpper(authCrypt) {
case "SHA1":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA1, true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSHA1: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSHA1: %s", err))
}
case "SSHA1":
if len(authSalt) == 0 {
- return nil, fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt")
+ return fail(fmt.Errorf("_auth_crypt=ssha1, requires _auth_salt"))
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA1(authSalt), true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSSHA1: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSSHA1: %s", err))
}
case "SHA256":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA256, true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSHA256: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSHA256: %s", err))
}
case "SSHA256":
if len(authSalt) == 0 {
- return nil, fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt")
+ return fail(fmt.Errorf("_auth_crypt=ssha256, requires _auth_salt"))
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA256(authSalt), true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSSHA256: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSSHA256: %s", err))
}
case "SHA384":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA384, true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSHA384: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSHA384: %s", err))
}
case "SSHA384":
if len(authSalt) == 0 {
- return nil, fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt")
+ return fail(fmt.Errorf("_auth_crypt=ssha384, requires _auth_salt"))
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA384(authSalt), true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSSHA384: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSSHA384: %s", err))
}
case "SHA512":
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSHA512, true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSHA512: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSHA512: %s", err))
}
case "SSHA512":
if len(authSalt) == 0 {
- return nil, fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt")
+ return fail(fmt.Errorf("_auth_crypt=ssha512, requires _auth_salt"))
}
if err := conn.RegisterFunc("sqlite_crypt", CryptEncoderSSHA512(authSalt), true); err != nil {
- return nil, fmt.Errorf("CryptEncoderSSHA512: %s", err)
+ return fail(fmt.Errorf("CryptEncoderSSHA512: %s", err))
}
}
}
// Preform Authentication
if err := conn.Authenticate(authUser, authPass); err != nil {
- return nil, err
+ return fail(err)
}
// Register: authenticate
@@ -1710,7 +1716,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// If the SQLITE_USER table is not present in the database file, then
// this interface is a harmless no-op returnning SQLITE_OK.
if err := conn.RegisterFunc("authenticate", conn.authenticate, true); err != nil {
- return nil, err
+ return fail(err)
}
//
// Register: auth_user_add
@@ -1723,7 +1729,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// for any ATTACH-ed databases. Any call to AuthUserAdd by a
// non-admin user results in an error.
if err := conn.RegisterFunc("auth_user_add", conn.authUserAdd, true); err != nil {
- return nil, err
+ return fail(err)
}
//
// Register: auth_user_change
@@ -1733,7 +1739,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// credentials or admin privilege setting. No user may change their own
// admin privilege setting.
if err := conn.RegisterFunc("auth_user_change", conn.authUserChange, true); err != nil {
- return nil, err
+ return fail(err)
}
//
// Register: auth_user_delete
@@ -1743,13 +1749,13 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// the database cannot be converted into a no-authentication-required
// database.
if err := conn.RegisterFunc("auth_user_delete", conn.authUserDelete, true); err != nil {
- return nil, err
+ return fail(err)
}
// Register: auth_enabled
// auth_enabled can be used to check if user authentication is enabled
if err := conn.RegisterFunc("auth_enabled", conn.authEnabled, true); err != nil {
- return nil, err
+ return fail(err)
}
// Auto Vacuum
@@ -1760,8 +1766,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// and activating user authentication creates the internal table `sqlite_user`.
if autoVacuum > -1 {
if err := exec(fmt.Sprintf("PRAGMA auto_vacuum = %d;", autoVacuum)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
@@ -1771,17 +1776,17 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// has provided an username and password within the DSN.
// We are not allowed to continue.
if len(authUser) == 0 {
- return nil, fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'")
+ return fail(fmt.Errorf("Missing '_auth_user' while user authentication was requested with '_auth'"))
}
if len(authPass) == 0 {
- return nil, fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'")
+ return fail(fmt.Errorf("Missing '_auth_pass' while user authentication was requested with '_auth'"))
}
// Check if User Authentication is Enabled
authExists := conn.AuthEnabled()
if !authExists {
if err := conn.AuthUserAdd(authUser, authPass, true); err != nil {
- return nil, err
+ return fail(err)
}
}
}
@@ -1789,40 +1794,35 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// Case Sensitive LIKE
if caseSensitiveLike > -1 {
if err := exec(fmt.Sprintf("PRAGMA case_sensitive_like = %d;", caseSensitiveLike)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Defer Foreign Keys
if deferForeignKeys > -1 {
if err := exec(fmt.Sprintf("PRAGMA defer_foreign_keys = %d;", deferForeignKeys)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Foreign Keys
if foreignKeys > -1 {
if err := exec(fmt.Sprintf("PRAGMA foreign_keys = %d;", foreignKeys)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Ignore CHECK Constraints
if ignoreCheckConstraints > -1 {
if err := exec(fmt.Sprintf("PRAGMA ignore_check_constraints = %d;", ignoreCheckConstraints)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Journal Mode
if journalMode != "" {
if err := exec(fmt.Sprintf("PRAGMA journal_mode = %s;", journalMode)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
@@ -1830,23 +1830,20 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// Because the default is NORMAL and this is not changed in this package
// by using the compile time SQLITE_DEFAULT_LOCKING_MODE this PRAGMA can always be executed
if err := exec(fmt.Sprintf("PRAGMA locking_mode = %s;", lockingMode)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
// Query Only
if queryOnly > -1 {
if err := exec(fmt.Sprintf("PRAGMA query_only = %d;", queryOnly)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Recursive Triggers
if recursiveTriggers > -1 {
if err := exec(fmt.Sprintf("PRAGMA recursive_triggers = %d;", recursiveTriggers)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
@@ -1857,8 +1854,7 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
// you can compile with secure_delete 'ON' and disable it for a specific database connection.
if secureDelete != "DEFAULT" {
if err := exec(fmt.Sprintf("PRAGMA secure_delete = %s;", secureDelete)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
@@ -1866,37 +1862,32 @@ func (d *SQLiteDriver) Open(dsn string) (driver.Conn, error) {
//
// Because default is NORMAL this statement is always executed
if err := exec(fmt.Sprintf("PRAGMA synchronous = %s;", synchronousMode)); err != nil {
- conn.Close()
- return nil, err
+ return fail(err)
}
// Writable Schema
if writableSchema > -1 {
if err := exec(fmt.Sprintf("PRAGMA writable_schema = %d;", writableSchema)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
// Cache Size
if cacheSize != nil {
if err := exec(fmt.Sprintf("PRAGMA cache_size = %d;", *cacheSize)); err != nil {
- C.sqlite3_close_v2(db)
- return nil, err
+ return fail(err)
}
}
if len(d.Extensions) > 0 {
if err := conn.loadExtensions(d.Extensions); err != nil {
- conn.Close()
- return nil, err
+ return fail(err)
}
}
if d.ConnectHook != nil {
if err := d.ConnectHook(conn); err != nil {
- conn.Close()
- return nil, err
+ return fail(err)
}
}
runtime.SetFinalizer(conn, (*SQLiteConn).Close)
@@ -1970,6 +1961,10 @@ func (c *SQLiteConn) putCachedStmt(s *SQLiteStmt) bool {
c.mu.Lock()
defer c.mu.Unlock()
+ return c.putCachedStmtLocked(s)
+}
+
+func (c *SQLiteConn) putCachedStmtLocked(s *SQLiteStmt) bool {
if c.db == nil {
return false
}
@@ -2164,12 +2159,20 @@ func (s *SQLiteStmt) Close() error {
s.c = nil
return nil
}
- if !conn.dbConnOpen() {
+ if s.cacheKey != "" {
+ conn.mu.Lock()
+ if conn.db == nil {
+ conn.mu.Unlock()
+ return errors.New("sqlite statement with already closed database connection")
+ }
+ if conn.putCachedStmtLocked(s) {
+ conn.mu.Unlock()
+ return nil
+ }
+ conn.mu.Unlock()
+ } else if !conn.dbConnOpen() {
return errors.New("sqlite statement with already closed database connection")
}
- if s.cacheKey != "" && conn.putCachedStmt(s) {
- return nil
- }
s.s = nil
s.c = nil
rv := C.sqlite3_finalize(stmt)
@@ -2282,6 +2285,17 @@ func stmtArgs(args []driver.NamedValue, start, na int) []driver.NamedValue {
return stmtArgs
}
+// bindError converts a non-OK return code from bindValue into an error.
+// The synthetic SQLITE_MISUSE returned for unsupported Go types is never
+// recorded in the database handle, so lastError may report no error; fall
+// back to an explicit message instead of silently ignoring the failure.
+func (s *SQLiteStmt) bindError(v driver.Value) error {
+ if err := s.c.lastError(); err != nil {
+ return err
+ }
+ return fmt.Errorf("sqlite3: unsupported bind type %T", v)
+}
+
func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
rv := C._sqlite3_reset_clear(s.s)
if rv != C.SQLITE_ROW && rv != C.SQLITE_OK && rv != C.SQLITE_DONE {
@@ -2301,7 +2315,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
n := C.int(arg.Ordinal)
rv = bindValue(s.s, n, arg.Value)
if rv != C.SQLITE_OK {
- return s.c.lastError()
+ return s.bindError(arg.Value)
}
}
return nil
@@ -2311,7 +2325,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
if arg.Name == "" {
rv = bindValue(s.s, C.int(arg.Ordinal), arg.Value)
if rv != C.SQLITE_OK {
- return s.c.lastError()
+ return s.bindError(arg.Value)
}
continue
}
@@ -2322,7 +2336,7 @@ func (s *SQLiteStmt) bind(args []driver.NamedValue) error {
}
rv = bindValue(s.s, C.int(idx), arg.Value)
if rv != C.SQLITE_OK {
- return s.c.lastError()
+ return s.bindError(arg.Value)
}
}
}
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
index 03cbc8b68..fbbb64939 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_load_extension.go
@@ -74,11 +74,11 @@ func (c *SQLiteConn) loadExtension(lib string, entry *string) error {
}
var errMsg *C.char
- defer C.sqlite3_free(unsafe.Pointer(errMsg))
-
rv := C.sqlite3_load_extension(c.db, clib, centry, &errMsg)
if rv != C.SQLITE_OK {
- return errors.New(C.GoString(errMsg))
+ err := errors.New(C.GoString(errMsg))
+ C.sqlite3_free(unsafe.Pointer(errMsg))
+ return err
}
return nil
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go
index 8cce278fd..37e048ffd 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_preupdate_hook.go
@@ -59,13 +59,17 @@ func (d *SQLitePreUpdateData) row(dest []any, new bool) error {
for i := 0; i < d.Count() && i < len(dest); i++ {
var val *C.sqlite3_value
var src any
+ var rc C.int
// Initially I tried making this just a function pointer argument, but
// it's absurdly complicated to pass C function pointers.
if new {
- C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
+ rc = C.sqlite3_preupdate_new(d.Conn.db, C.int(i), &val)
} else {
- C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
+ rc = C.sqlite3_preupdate_old(d.Conn.db, C.int(i), &val)
+ }
+ if rc != C.SQLITE_OK {
+ return Error{Code: ErrNo(rc)}
}
switch C.sqlite3_value_type(val) {
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_serialize.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_serialize.go
index 51dd9c8f0..60019bd5e 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_serialize.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_serialize.go
@@ -60,6 +60,9 @@ func (c *SQLiteConn) Deserialize(b []byte, schema string) error {
defer C.free(unsafe.Pointer(zSchema))
tmpBuf := (*C.uchar)(C.sqlite3_malloc64(C.sqlite3_uint64(len(b))))
+ if tmpBuf == nil && len(b) > 0 {
+ return fmt.Errorf("deserialize failed: out of memory")
+ }
copy(unsafe.Slice((*byte)(unsafe.Pointer(tmpBuf)), len(b)), b)
rc := C.sqlite3_deserialize(c.db, zSchema, tmpBuf, C.sqlite3_int64(len(b)),
diff --git a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go
index 7c2ae58e5..9e916ea8c 100644
--- a/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go
+++ b/vendor/github.com/mattn/go-sqlite3/sqlite3_opt_vtable.go
@@ -113,6 +113,9 @@ uintptr_t goVOpen(void *pVTab, char **pzErr);
static int cXOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor) {
void *vTabCursor = (void *)goVOpen(((goVTab*)pVTab)->vTab, &(pVTab->zErrMsg));
+ if (!vTabCursor) {
+ return SQLITE_ERROR;
+ }
goVTabCursor *pCursor = (goVTabCursor *)sqlite3_malloc(sizeof(goVTabCursor));
if (!pCursor) {
return SQLITE_NOMEM;
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0b5a68200..3e909e432 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -10,7 +10,7 @@ github.com/google/uuid
# github.com/hashicorp/go-version v1.9.0
## explicit
github.com/hashicorp/go-version
-# github.com/mattn/go-sqlite3 v1.14.47
+# github.com/mattn/go-sqlite3 v1.14.48
## explicit; go 1.21
github.com/mattn/go-sqlite3
# github.com/mileusna/useragent v1.3.5