diff --git a/manifest b/manifest index 1a81415783..dd4d4bcc90 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Provide\sthe\s-innocuous\soption\sto\sthe\s"db\sfunc"\smethod\sin\sthe\sTCL\sinterface. -D 2020-01-08T15:44:10.295 +C Check\sfor\swhether\sor\snot\sit\sis\ssafe\sto\suse\snon-innocuous\sfunctions\sas\sthe\nfunction\sis\sbeing\scoded,\snot\swhen\sits\sname\sis\sresolved. +D 2020-01-08T17:28:19.750 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -481,7 +481,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 0f55297469d4244ab7df395849e1af98eb5e95816af7c661e7d2d8402dea23da F src/delete.c a5c59b9c0251cf7682bc52af0d64f09b1aefc6781a63592c8f1136f7b73c66e4 -F src/expr.c 631b1f24d07114066c756984b8bc7be64529afb2ea3a5da4e3e262792f320dfa +F src/expr.c bea12b33808867bb8f336d4bd70ebedfef72bb96bd453adcb068e578417b5e46 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 92a248ec0fa4ed8ab60c98d9b188ce173aaf218f32e7737ba77deb2a684f9847 F src/func.c 259496e4856bd0a3215d16804992f3339f3e8db29f129a5a7285c341488bbe9c @@ -527,14 +527,14 @@ F src/pragma.h 9f86a3a3a0099e651189521c8ad03768df598974e7bbdc21c7f9bb6125592fbd F src/prepare.c 6049beb71385f017af6fc320d2c75a4e50b75e280c54232442b785fbb83df057 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c 894397f372b5c23fb68e0c534d3682f45285f228bb335d713344a7ed37f0ba45 +F src/resolve.c 5200d014fa78412f6189777cde3ac71b2dde55260c620be095610afe03fe9354 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93 F src/select.c fbae5d6db63959aa1ecb34efe93caf5399444ca3c78d6f1ef4620b0ee5c37707 F src/shell.c.in 43d3cfbee97d78ca5782dc53e4c1e22d3cc15c91beff20889dc60551f47eab9f F src/sqlite.h.in 06452043348e35cf6108345a35574a2faa4d1c2829beefb1e73c73d6bfb2fa80 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 72af51aa4e912e14cd495fb6e7fac65f0940db80ed950d90911aff292cc47ce2 -F src/sqliteInt.h 8c1fcdad7418c87cd482d2868610ed299e0201091e247598495e92e9c5d8e884 +F src/sqliteInt.h 0ca99e207087851fd27c6e1314fc52d273caa424ff2bafa3f1daf6d5eb63b35a F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -930,7 +930,7 @@ F test/fts3al.test 07d64326e79bbdbab20ee87fc3328fbf01641c9f F test/fts3am.test 218aa6ba0dfc50c7c16b2022aac5c6be593d08d8 F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18 F test/fts3ao.test 266989148fec6d9f1bb6c5382f7aa3dcea0e9cd444576e28dd2b9287ac7dd220 -F test/fts3atoken.test 2b2b0d7943eccf76e7a4887b557d4abcbb9279fbbb88e2bc2eba31c1817d11c7 +F test/fts3atoken.test dc2078ce464914efe3a8dfc545dd034a0fc14f2ab425c240471d5a5f1c721400 F test/fts3auto.test bfe0857bd0b69d68dd685a931b58486411a69f5794a7f6d6fe808bfa31a99614 F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6 F test/fts3aux2.test 2459e7fa3e22734aed237d1e2ae192f5541c4d8b218956ad2d90754977bf907f @@ -998,7 +998,7 @@ F test/fts4rename.test 15fd9985c2bce6dea20da2245b22029ec89bd4710ed317c4c53abbe3c F test/fts4umlaut.test fcaca4471de7e78c9d1f7e8976e3e8704d7d8ad979d57a739d00f3f757380429 F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95 F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d -F test/func.test 7d425f9a6eaa2c50baa751bef6b0c6c6af1751e0e0e1eb4863d426bb4c886788 +F test/func.test 93d692f6427bd01b39c6ddb1e2d728f5264abefdbdd56e2f95c9dc1fa7dbcb53 F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f F test/func3.test 2bb0f31ab7baaed690b962a88544d7be6b34fa389364bc36a44e441ed3e3f1e6 F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f @@ -1592,6 +1592,7 @@ F test/triggerD.test 8e7f3921a92a5797d472732108109e44575fa650 F test/triggerE.test ede2e4bce4ba802337bd69d39447fa04a938e06d84a8bfc53c76850fc36ed86d F test/triggerF.test 5d76f0a8c428ff87a4d5ed52da06f6096a2c787a1e21b846111dfac4123de3ad F test/triggerG.test d5caeef6144ede2426dd13211fd72248241ff2ebc68e12a4c0bf30f5faa21499 +F test/trustschema1.test b337ef2d006c3c02ca822eca45bbc10d711ba96d12486cb0fa8e7beb5e0d7660 F test/tt3_checkpoint.c 9e75cf7c1c364f52e1c47fd0f14c4340a9db0fe1 F test/tt3_index.c 39eec10a35f57672225be4d182862152896dee4a F test/tt3_lookaside1.c 0377e202c3c2a50d688cb65ba203afeda6fafeb9 @@ -1854,7 +1855,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P a679122ca8ec95d5c8afba3a1a50170db9dd519a3810e56877b8f56e858d0175 -R 9fbba3111d220dbea3ef9c5770ac6cef +P 0138652b6c2f21fd67e59a23a396a5b9d6a16ee9b44701cddfc49b23fddfce5b +R ce4061dc1b633cb47a4ee9d471ef9c80 U drh -Z fc531ff60387ab6488432d4541dd29bf +Z 1c75c43008bf3984bb39f61126a3891e diff --git a/manifest.uuid b/manifest.uuid index 0381fd8065..3ce3dd07e0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0138652b6c2f21fd67e59a23a396a5b9d6a16ee9b44701cddfc49b23fddfce5b \ No newline at end of file +1da802d54b689a462e1fe899c6ffa08ef14d34f36728b14b055b5a76b1edc274 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 4e8703e552..7d712ad674 100644 --- a/src/expr.c +++ b/src/expr.c @@ -973,6 +973,41 @@ Expr *sqlite3ExprFunction( return pNew; } +/* +** Check to see if a function is usable according to current access +** rules: +** +** SQLITE_FUNC_DIRECT - Only usable from top-level SQL +** +** SQLITE_FUNC_UNSAFE - Usable if TRUSTED_SCHEMA or from +** top-level SQL +** +** If the function is not usable, create an error. +*/ +void sqlite3ExprFunctionUsable( + Parse *pParse, /* Parsing and code generating context */ + Expr *pExpr, /* The function invocation */ + FuncDef *pDef /* The function being invoked */ +){ + assert( !IN_RENAME_OBJECT ); + if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 + && ExprHasProperty(pExpr, EP_FromDDL) + ){ + if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 + || (pParse->db->flags & SQLITE_TrustedSchema)==0 + ){ + /* Functions prohibited in triggers and views if: + ** (1) tagged with SQLITE_DIRECTONLY + ** (2) not tagged with SQLITE_INNOCUOUS (which means it + ** is tagged with SQLITE_FUNC_UNSAFE) and + ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning + ** that the schema is possibly tainted). + */ + sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName); + } + } +} + /* ** Assign a variable number to an expression that encodes a wildcard ** in the original SQL statement. @@ -4073,9 +4108,12 @@ expr_code_doover: break; } if( pDef->funcFlags & SQLITE_FUNC_INLINE ){ + assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 ); + assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 ); return exprCodeInlineFunction(pParse, pFarg, SQLITE_PTR_TO_INT(pDef->pUserData), target); } + sqlite3ExprFunctionUsable(pParse, pExpr, pDef); for(i=0; ia[i].pExpr) ){ @@ -5740,6 +5778,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ }else{ pItem->iDistinct = -1; } + sqlite3ExprFunctionUsable(pParse, pExpr, pItem->pFunc); } } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry diff --git a/src/resolve.c b/src/resolve.c index 929c8743f5..16546ada4b 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -876,33 +876,18 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ }else{ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */ pExpr->op2 = pNC->ncFlags & NC_SelfRef; + if( pExpr->op2 ) ExprSetProperty(pExpr, EP_FromDDL); } if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0 && pParse->nested==0 && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0 ){ /* Internal-use-only functions are disallowed unless the - ** SQL is being compiled using sqlite3NestedParse() */ + ** SQL is being compiled using sqlite3NestedParse() or + ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be + ** used to activate internal functionsn for testing purposes */ no_such_func = 1; pDef = 0; - }else - if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 - && ExprHasProperty(pExpr, EP_FromDDL) - && !IN_RENAME_OBJECT - ){ - if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0 - || (pParse->db->flags & SQLITE_TrustedSchema)==0 - ){ - /* Functions prohibited in triggers and views if: - ** (1) tagged with SQLITE_DIRECTONLY - ** (2) not tagged with SQLITE_INNOCUOUS (which means it - ** is tagged with SQLITE_FUNC_UNSAFE) and - ** SQLITE_DBCONFIG_UNTRUSTED_SCHEMA is off (meaning - ** that the schema is fully trustworthy). - */ - sqlite3ErrorMsg(pParse, "%s() prohibited in triggers and views", - pDef->zName); - } } } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 455403637a..e56a4b3d54 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4056,6 +4056,7 @@ void sqlite3PExprAddSelect(Parse*, Expr*, Select*); Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*); Expr *sqlite3ExprSimplifiedAndOr(Expr*); Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int); +void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*); void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32); void sqlite3ExprDelete(sqlite3*, Expr*); void sqlite3ExprUnmapAndDelete(Parse*, Expr*); diff --git a/test/fts3atoken.test b/test/fts3atoken.test index 5694dfb9f0..4981480b5e 100644 --- a/test/fts3atoken.test +++ b/test/fts3atoken.test @@ -138,7 +138,7 @@ do_catchsql_test fts3atoken-1.10 { } {0 {}} do_catchsql_test fts3atoken-1.11 { SELECT * FROM v110; -} {1 {fts3_tokenizer() prohibited in triggers and views}} +} {1 {unsafe use of fts3_tokenizer()}} do_catchsql_test fts3atoken-1.12 { CREATE TABLE t110(a,b); CREATE TRIGGER r110 AFTER INSERT ON t110 BEGIN @@ -147,7 +147,7 @@ do_catchsql_test fts3atoken-1.12 { } {0 {}} do_catchsql_test fts3atoken-1.13 { INSERT INTO t110(a,b) VALUES(1,2); -} {1 {fts3_tokenizer() prohibited in triggers and views}} +} {1 {unsafe use of fts3_tokenizer()}} do_catchsql_test fts3atoken-1.14 { SELECT * FROM t110; } {0 {}} diff --git a/test/func.test b/test/func.test index 3bfb1fe8ac..585ae1a14f 100644 --- a/test/func.test +++ b/test/func.test @@ -1430,7 +1430,7 @@ do_test func-33.1 { do_catchsql_test func-33.2 { CREATE VIEW v33(y) AS SELECT testdirectonly(15); SELECT * FROM v33; -} {1 {testdirectonly() prohibited in triggers and views}} +} {1 {unsafe use of testdirectonly()}} do_execsql_test func-33.3 { SELECT * FROM (SELECT testdirectonly(15)) AS v33; } {30} @@ -1441,7 +1441,7 @@ do_execsql_test func-33.4 { do_catchsql_test func-33.5 { WITH c(x) AS (SELECT * FROM v33) SELECT * FROM c; -} {1 {testdirectonly() prohibited in triggers and views}} +} {1 {unsafe use of testdirectonly()}} do_execsql_test func-33.10 { CREATE TABLE t33a(a,b); CREATE TABLE t33b(x,y); @@ -1451,7 +1451,7 @@ do_execsql_test func-33.10 { } {} do_catchsql_test func-33.11 { INSERT INTO t33a VALUES(1,2); -} {1 {testdirectonly() prohibited in triggers and views}} +} {1 {unsafe use of testdirectonly()}} do_execsql_test func-33.20 { ALTER TABLE t33a RENAME COLUMN a TO aaa; SELECT sql FROM sqlite_master WHERE name='r1'; diff --git a/test/trustschema1.test b/test/trustschema1.test new file mode 100644 index 0000000000..d536645397 --- /dev/null +++ b/test/trustschema1.test @@ -0,0 +1,44 @@ +# 2020-01-08 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test cases for managing execution of code snippets found in untrusted +# schemas. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix trustschema1 + + +proc f1 {x} {return $x} +do_test 1.100 { + db function f1 -innocuous -deterministic f1 + db function f2 -deterministic f1 + db function f3 -directonly -deterministic f1 + db eval { + CREATE TABLE t1(a, b AS (f1(a+1)), c AS (f2(a+2))); + INSERT INTO t1 VALUES(100),(200); + } +} {} +do_catchsql_test 1.110 { + SELECT a, b, c FROM t1; +} {0 {100 101 102 200 201 202}} +do_execsql_test 1.120 { + PRAGMA trusted_schema=OFF; +} {} +do_catchsql_test 1.130 { + SELECT a, b FROM t1; +} {0 {100 101 200 201}} +do_catchsql_test 1.140 { + SELECT a, b, c FROM t1; +} {1 {unsafe use of f2()}} + +finish_test