aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c4
-rw-r--r--src/resolve.c28
-rw-r--r--src/sqlite.h.in19
-rw-r--r--src/sqliteInt.h24
4 files changed, 48 insertions, 27 deletions
diff --git a/src/main.c b/src/main.c
index 9838b3419..5e6ff1654 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1760,7 +1760,9 @@ int sqlite3CreateFunc(
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
- extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|SQLITE_SUBTYPE);
+ assert( SQLITE_FUNC_SAFE==SQLITE_INNOCUOUS );
+ extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
+ SQLITE_SUBTYPE|SQLITE_INNOCUOUS);
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
#ifndef SQLITE_OMIT_UTF16
diff --git a/src/resolve.c b/src/resolve.c
index 4587540d3..f934cf602 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -866,16 +866,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
** constant because they are constant for the duration of one query.
** This allows them to be factored out of inner loops. */
ExprSetProperty(pExpr,EP_ConstFunc);
- }else{
- if( ExprHasProperty(pExpr, EP_Indirect)
- && !IN_RENAME_OBJECT
- && (pParse->db->flags & SQLITE_UnsafeInView)==0
- ){
- /* If SQLITE_DBCONFIG_UNSAFE_IN_VIEW is off, then functions with
- ** side effects are not allowed inside triggers and views. */
- sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
- pDef->zName);
- }
}
if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
/* Date/time functions that use 'now', and other functions like
@@ -896,14 +886,22 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
no_such_func = 1;
pDef = 0;
}else
- if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
+ if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_SAFE))
+ != SQLITE_FUNC_SAFE
&& ExprHasProperty(pExpr, EP_Indirect)
&& !IN_RENAME_OBJECT
){
- /* Functions tagged with SQLITE_DIRECTONLY may not be used
- ** inside of triggers and views */
- sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
- pDef->zName);
+ if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
+ || (pParse->db->flags & SQLITE_UnsafeInView)==0
+ ){
+ /* Functions prohibited in triggers and views if:
+ ** (1) tagged with SQLITE_DIRECTONLY
+ ** (2) not tagged with SQLITE_INNOCUOUS and
+ ** SQLITE_DBCONFIG_UNSAFE_IN_VIEW is off
+ */
+ sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views",
+ pDef->zName);
+ }
}
}
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 03e92a4c3..dc8bf4a38 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -5025,12 +5025,26 @@ int sqlite3_create_window_function(
** [sqlite3_create_function_v2()].
**
** The SQLITE_DETERMINISTIC flag means that the new function always gives
-** the same output when the input parameters are the same. The abs() function
-** is deterministic, for example, but randomblob() is not. Functions must
+** the same output when the input parameters are the same.
+** The [abs|abs() function] is deterministic, for example, but
+** [randomblob|randomblob()] is not. Functions must
** be deterministic in order to be used in certain contexts such as
** [CHECK constraints] or [generated columns]. SQLite might also optimize
** deterministic functions by factoring them out of inner loops.
**
+** The SQLITE_INNOCUOUS flag means that the new function is unlikely
+** to cause problems even if misused. An innocuous function should have
+** no side effects and consume few resources. The [abs|abs() function]
+** is an example of an innocuous function.
+** The [load_extension() SQL function] is not innocuous because of its
+** side effects. Some heightened security settings
+** ([SQLITE_DBCONFIG_UNSAFE_FUNC_IN_VIEW])
+** disable the use of SQLlfunctions inside views and triggers unless
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
+** are innocuous. Developers are advised to avoid using the
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
+** function is specifically intended for use inside of views and triggers.
+**
** The SQLITE_DIRECTONLY flag means that the function may only be invoked
** from top-level SQL, and cannot be used in VIEWs or TRIGGERs. This is
** a security feature which is recommended for all
@@ -5050,6 +5064,7 @@ int sqlite3_create_window_function(
#define SQLITE_DETERMINISTIC 0x000000800
#define SQLITE_DIRECTONLY 0x000080000
#define SQLITE_SUBTYPE 0x000100000
+#define SQLITE_INNOCUOUS 0x000200000
/*
** CAPI3REF: Deprecated Functions
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 24b656d9a..34dd74ac5 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -1740,6 +1740,7 @@ struct FuncDestructor {
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
+** SQLITE_FUNC_SAFE == SQLITE_INNOCUOUS
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
*/
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
@@ -1762,7 +1763,11 @@ struct FuncDestructor {
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
-#define SQLITE_FUNC_INLINE 0x00200000 /* Functions implemented in-line */
+#define SQLITE_FUNC_SAFE 0x00200000 /* Function has no side effects */
+#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
+
+/* Combination flags */
+#define SQLITE_FUNC_PURE (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SAFE)
/* Identifier numbers for each in-line function */
#define INLINEFUNC_coalesce 0
@@ -1836,7 +1841,7 @@ struct FuncDestructor {
** parameter.
*/
#define FUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_PURE|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
@@ -1845,26 +1850,27 @@ struct FuncDestructor {
{nArg, SQLITE_UTF8|SQLITE_DIRECTONLY, \
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
- {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_PURE|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define TEST_FUNC(zName, nArg, iArg, mFlags) \
{nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
- SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
+ SQLITE_FUNC_INLINE|(mFlags), \
SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_FUNC_SAFE|SQLITE_UTF8, \
0, 0, xFunc, 0, 0, 0, #zName, {0} }
#define PURE_DATE(zName, nArg, iArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_CONSTANT, \
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|SQLITE_FUNC_PURE, \
(void*)&sqlite3Config, 0, xFunc, 0, 0, 0, #zName, {0} }
#define FUNCTION2(zName, nArg, iArg, bNC, xFunc, extraFlags) \
- {nArg,SQLITE_FUNC_CONSTANT|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
+ {nArg,SQLITE_FUNC_PURE|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL)|extraFlags,\
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
#define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \
- {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
+ {nArg, SQLITE_FUNC_SLOCHNG|SQLITE_FUNC_SAFE| \
+ SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
pArg, 0, xFunc, 0, 0, 0, #zName, }
#define LIKEFUNC(zName, nArg, arg, flags) \
- {nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
+ {nArg, SQLITE_FUNC_PURE|SQLITE_UTF8|flags, \
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \