From 64117f739877dd0e07de38475ee8d0e2fa768104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=AB=98=E9=93=81?= Date: Sat, 12 Jun 2021 16:29:07 +0800 Subject: [PATCH] improved oracle sql wall support, fix #4325 --- .../druid/wall/spi/WallVisitorUtils.java | 50 ++++++++++------ .../druid/wall/oracle/permit-function.txt | 4 ++ .../filter/wall/oracle/OracleWallTest10.java | 60 +++++++++++++++++++ 3 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest10.java diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 94ff7808e6..e6048f9d1b 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -1711,44 +1711,56 @@ public class WallVisitorUtils { } public static void checkFunction(WallVisitor visitor, SQLMethodInvokeExpr x) { - final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get(); if (topStatementContext != null && (topStatementContext.fromSysSchema || topStatementContext.fromSysTable)) { return; } - checkSchema(visitor, x.getOwner()); + String methodName = x.getMethodName().toLowerCase(); + SQLExpr owner = x.getOwner(); + + WallProvider provider = visitor.getProvider(); if (!visitor.getConfig().isFunctionCheck()) { return; } - String methodName = x.getMethodName().toLowerCase(); - WallContext context = WallContext.current(); if (context != null) { context.incrementFunctionInvoke(methodName); } - if (!visitor.getProvider().checkDenyFunction(methodName)) { - boolean isTopNoneFrom = isTopNoneFromSelect(visitor, x); - if (isTopNoneFrom) { + if (owner != null) { + String fullName = (owner.toString() + '.' + methodName).toLowerCase(); + if (provider.getConfig().getPermitFunctions().contains(fullName)) { return; } - if (isTopFromDenySchema(visitor, x)) { - return; - } - - boolean isShow = x.getParent() instanceof MySqlShowGrantsStatement; - if (isShow) { - return; - } - - if (isWhereOrHaving(x) || checkSqlExpr(x)) { - addViolation(visitor, ErrorCode.FUNCTION_DENY, "deny function : " + methodName, x); - } + checkSchema(visitor, owner); } + + if (provider.checkDenyFunction(methodName)) { + return; + } + + boolean isTopNoneFrom = isTopNoneFromSelect(visitor, x); + if (isTopNoneFrom) { + return; + } + + if (isTopFromDenySchema(visitor, x)) { + return; + } + + boolean isShow = x.getParent() instanceof MySqlShowGrantsStatement; + if (isShow) { + return; + } + + if (isWhereOrHaving(x) || checkSqlExpr(x)) { + addViolation(visitor, ErrorCode.FUNCTION_DENY, "deny function : " + methodName, x); + } + } public static SQLSelectQueryBlock getQueryBlock(SQLObject x) { diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt b/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt index 525d9e01bf..17f9939d21 100644 --- a/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt +++ b/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt @@ -157,3 +157,7 @@ NULLIF NVL NVL2 +DBMS_LOB.SUBSTR +DBMS_LOB.TRIM +DBMS_LOB.INSTR +DBMS_LOB.COMPARE \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest10.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest10.java new file mode 100644 index 0000000000..0173a623a3 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/oracle/OracleWallTest10.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2018 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.filter.wall.oracle; + +import com.alibaba.druid.wall.WallUtils; +import junit.framework.TestCase; +import org.junit.Assert; + +public class OracleWallTest10 extends TestCase { + + public void test_true() throws Exception { + String sql = // + "select\n" + + "tpl.projectname as 项目名称,\n" + + "tpl.address as 项目地址,\n" + + "tpl.transactor as 联系人,\n" + + "tpl.transactor_tel as 联系人电话,\n" + + "dbms_lob.substr(wmsys.wm_concat(\n" + + "case when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '4') then '4月份'\n" + + "when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '5') then '5月份'\n" + + "when (tap.type = 'LESS_THIS_MONTH_SALARY' AND tap.month = '6') then '6月份'\n" + + "else null end\n" + + ")) as YA,\n" + + "dbms_lob.substr(wmsys.wm_concat(\n" + + "case when tap.type = 'NO_PAY_MONTH' AND tap.month = '4' then '4月份'\n" + + "when tap.type = 'NO_PAY_MONTH' AND tap.month = '5' then '5月份'\n" + + "when tap.type = 'NO_PAY_MONTH' AND tap.month = '6' then '6月份'\n" + + "else null end\n" + + ")) as YB,\n" + + "dbms_lob.substr(wmsys.wm_concat(\n" + + "case when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '4' then '4月份'\n" + + "when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '5' then '5月份'\n" + + "when tap.type = 'SALARY_DATA_MONTH' AND tap.month = '6' then '6月份'\n" + + "else null end\n" + + ")) as YC\n" + + "from t_alert_project tap\n" + + "inner join t_project_list tpl on tpl.projectid = tap.projectid\n" + + "where tap.month in ('4','5','6')\n" + + "group by\n" + + "tpl.projectname,\n" + + "tpl.address,\n" + + "tpl.transactor,\n" + + "tpl.transactor_tel\n" + + "order by tpl.projectname"; + Assert.assertTrue(WallUtils.isValidateOracle(sql)); + } +}