aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/alter.c17
-rw-r--r--src/global.c1
-rw-r--r--src/main.c17
-rw-r--r--src/pragma.c1
-rw-r--r--src/resolve.c9
-rw-r--r--src/shell.c.in2
-rw-r--r--src/sqlite.h.in1
-rw-r--r--src/sqliteInt.h11
-rw-r--r--src/test1.c17
9 files changed, 51 insertions, 25 deletions
diff --git a/src/alter.c b/src/alter.c
index e299e6537..1280e9055 100644
--- a/src/alter.c
+++ b/src/alter.c
@@ -1188,15 +1188,8 @@ static void renameParseCleanup(Parse *pParse){
** into zNew. The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
-** Though accessible to application code, it is not intended for use by
-** applications. The existance of this function, and the way it works,
-** is subject to change without notice.
-**
-** If any of the parameters are out-of-bounds, then simply return NULL.
-** An out-of-bounds parameter can only occur when the application calls
-** this function directly. The parameters will always be well-formed when
-** this routine is invoked by the bytecode for a legitimate ALTER TABLE
-** statement.
+** It is only accessible to SQL created using sqlite3NestedParse(). It is
+** not reachable from ordinary SQL passed into sqlite3_prepare().
*/
static void renameColumnFunc(
sqlite3_context *context,
@@ -1604,9 +1597,9 @@ static void renameTableTest(
*/
void sqlite3AlterFunctions(void){
static FuncDef aAlterTableFuncs[] = {
- FUNCTION(sqlite_rename_column, 9, 0, 0, renameColumnFunc),
- FUNCTION(sqlite_rename_table, 7, 0, 0, renameTableFunc),
- FUNCTION(sqlite_rename_test, 5, 0, 0, renameTableTest),
+ INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
+ INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
+ INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
};
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
}
diff --git a/src/global.c b/src/global.c
index f0362d1e0..f1a391248 100644
--- a/src/global.c
+++ b/src/global.c
@@ -240,6 +240,7 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* xTestCallback */
#endif
0, /* bLocaltimeFault */
+ 0, /* bInternalFunctions */
0x7ffffffe, /* iOnceResetThreshold */
SQLITE_DEFAULT_SORTERREF_SIZE /* szSorterRef */
};
diff --git a/src/main.c b/src/main.c
index 1e5598393..46c83463c 100644
--- a/src/main.c
+++ b/src/main.c
@@ -3953,15 +3953,26 @@ int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
**
- ** If parameter onoff is non-zero, configure the wrappers so that all
- ** subsequent calls to localtime() and variants fail. If onoff is zero,
- ** undo this setting.
+ ** If parameter onoff is non-zero, subsequent calls to localtime()
+ ** and its variants fail. If onoff is zero, undo this setting.
*/
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
sqlite3GlobalConfig.bLocaltimeFault = va_arg(ap, int);
break;
}
+ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
+ **
+ ** If parameter onoff is non-zero, internal-use-only SQL functions
+ ** are visible to ordinary SQL. This is useful for testing but is
+ ** unsafe because invalid parameters to those internal-use-only functions
+ ** can result in crashes or segfaults.
+ */
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
+ sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
+ break;
+ }
+
/* sqlite3_test_control(SQLITE_TESTCTRL_NEVER_CORRUPT, int);
**
** Set or clear a flag that indicates that the database file is always well-
diff --git a/src/pragma.c b/src/pragma.c
index 54e219ba6..ada652cf1 100644
--- a/src/pragma.c
+++ b/src/pragma.c
@@ -1239,6 +1239,7 @@ void sqlite3Pragma(
pParse->nMem = 2;
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
+ if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
}
}
diff --git a/src/resolve.c b/src/resolve.c
index 34a051583..0c7dfc0b2 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -771,6 +771,15 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
notValid(pParse, pNC, "non-deterministic functions",
NC_IdxExpr|NC_PartIdx);
}
+ if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
+ && pParse->nested==0
+ && sqlite3Config.bInternalFunctions==0
+ ){
+ /* Internal-use-only functions are disallowed unless the
+ ** SQL is being compiled using sqlite3NestedParse() */
+ no_such_func = 1;
+ pDef = 0;
+ }
}
if( 0==IN_RENAME_OBJECT ){
diff --git a/src/shell.c.in b/src/shell.c.in
index 45a793aa5..ad5a1498b 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -7677,6 +7677,7 @@ static int do_meta_command(char *zLine, ShellState *p){
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
/*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
{ "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
+ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
{ "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
{ "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
@@ -7771,6 +7772,7 @@ static int do_meta_command(char *zLine, ShellState *p){
/* sqlite3_test_control(int, int) */
case SQLITE_TESTCTRL_ASSERT:
case SQLITE_TESTCTRL_ALWAYS:
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
if( nArg==3 ){
int opt = booleanValue(azArg[2]);
rc2 = sqlite3_test_control(testctrl, opt);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index fb8753bd7..69c2b27f7 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -7242,6 +7242,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
+#define SQLITE_TESTCTRL_INTERNAL_FUNCTIONS 17
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d0e4b7385..051aa4038 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1683,8 +1683,9 @@ struct FuncDestructor {
** single query - might change over time */
#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
-#define SQLITE_FUNC_WINDOW 0x10000 /* Built-in window-only function */
-#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
+#define SQLITE_FUNC_WINDOW_SIZE 0x20000 /* Requires partition size as arg. */
+#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
/*
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
@@ -1760,10 +1761,13 @@ struct FuncDestructor {
#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
-
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
+#define INTERNAL_FUNCTION(zName, nArg, xFunc) \
+ {nArg, SQLITE_FUNC_INTERNAL|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ 0, 0, xFunc, 0, 0, 0, #zName, {0} }
+
/*
** All current savepoints are stored in a linked list starting at
@@ -3414,6 +3418,7 @@ struct Sqlite3Config {
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
+ int bInternalFunctions; /* Internal SQL functions are visible */
int iOnceResetThreshold; /* When to reset OP_Once counters */
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
};
diff --git a/src/test1.c b/src/test1.c
index 3d1910f8a..e2048cb38 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -6329,7 +6329,7 @@ static int SQLITE_TCLAPI reset_prng_state(
/*
** tclcmd: database_may_be_corrupt
**
-** Indicate that database files might be corrupt. In other words, set the normal
+** Indicate that database files might be corrupt. In other words, set the normal
** state of operation.
*/
static int SQLITE_TCLAPI database_may_be_corrupt(
@@ -6344,8 +6344,9 @@ static int SQLITE_TCLAPI database_may_be_corrupt(
/*
** tclcmd: database_never_corrupt
**
-** Indicate that database files are always well-formed. This enables extra assert()
-** statements that test conditions that are always true for well-formed databases.
+** Indicate that database files are always well-formed. This enables
+** extra assert() statements that test conditions that are always true
+** for well-formed databases.
*/
static int SQLITE_TCLAPI database_never_corrupt(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
@@ -6711,9 +6712,10 @@ static int SQLITE_TCLAPI test_test_control(
const char *zName;
int i;
} aVerb[] = {
- { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
- { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
- { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
+ { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
+ { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
+ { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
+ { "SQLITE_TESTCTRL_INTERNAL_FUNCTIONS", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS},
};
int iVerb;
int iFlag;
@@ -6731,6 +6733,7 @@ static int SQLITE_TCLAPI test_test_control(
iFlag = aVerb[iVerb].i;
switch( iFlag ){
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
int val;
if( objc!=3 ){
@@ -6738,7 +6741,7 @@ static int SQLITE_TCLAPI test_test_control(
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
- sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
+ sqlite3_test_control(iFlag, val);
break;
}