diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/resolve.c | 28 | ||||
-rw-r--r-- | src/sqlite.h.in | 19 | ||||
-rw-r--r-- | src/sqliteInt.h | 24 |
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, \ |