mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve WallFilter
This commit is contained in:
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 1999-2011 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.sql.dialect.sqlserver.visitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
|
||||
|
||||
public class SQLServerEvalVisitor extends SQLServerASTVisitorAdapter implements SQLEvalVisitor {
|
||||
|
||||
private List<Object> parameters = new ArrayList<Object>();
|
||||
|
||||
private int variantIndex = -1;
|
||||
|
||||
private boolean markVariantIndex = true;
|
||||
|
||||
public SQLServerEvalVisitor(){
|
||||
this(new ArrayList<Object>(1));
|
||||
}
|
||||
|
||||
public SQLServerEvalVisitor(List<Object> parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(List<Object> parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public boolean visit(SQLCharExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public int incrementAndGetVariantIndex() {
|
||||
return ++variantIndex;
|
||||
}
|
||||
|
||||
public int getVariantIndex() {
|
||||
return variantIndex;
|
||||
}
|
||||
|
||||
public boolean visit(SQLVariantRefExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLIntegerExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLNumberExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCaseExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLNullExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLMethodInvokeExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLQueryExpr x) {
|
||||
return SQLEvalVisitorUtils.visit(this, x);
|
||||
}
|
||||
|
||||
public boolean isMarkVariantIndex() {
|
||||
return markVariantIndex;
|
||||
}
|
||||
|
||||
public void setMarkVariantIndex(boolean markVariantIndex) {
|
||||
this.markVariantIndex = markVariantIndex;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,6 +50,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleEvalVisitor;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGEvalVisitor;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerEvalVisitor;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.wall.spi.WallVisitorUtils;
|
||||
import com.alibaba.druid.wall.spi.WallVisitorUtils.WallConditionContext;
|
||||
@@ -113,10 +114,14 @@ public class SQLEvalVisitorUtils {
|
||||
if (JdbcUtils.POSTGRESQL.equals(dbType)) {
|
||||
return new PGEvalVisitor();
|
||||
}
|
||||
|
||||
if (JdbcUtils.SQL_SERVER.equals(dbType)) {
|
||||
return new SQLServerEvalVisitor();
|
||||
}
|
||||
|
||||
return new SQLEvalVisitorImpl();
|
||||
}
|
||||
|
||||
|
||||
public static boolean visit(SQLEvalVisitor visitor, SQLMethodInvokeExpr x) {
|
||||
String methodName = x.getMethodName().toLowerCase();
|
||||
|
||||
@@ -260,7 +265,7 @@ public class SQLEvalVisitorUtils {
|
||||
String result = strValue.trim();
|
||||
|
||||
x.putAttribute(EVAL_VALUE, result);
|
||||
} else if ("length".equals(methodName)) {
|
||||
} else if ("length".equals(methodName) || "len".equals(methodName)) {
|
||||
if (x.getParameters().size() != 1) {
|
||||
return false;
|
||||
}
|
||||
@@ -753,6 +758,11 @@ public class SQLEvalVisitorUtils {
|
||||
}
|
||||
|
||||
public static boolean visit(SQLEvalVisitor visitor, SQLQueryExpr x) {
|
||||
if (WallVisitorUtils.isSimpleCountTableSource(((SQLQueryExpr) x).getSubQuery())) {
|
||||
x.putAttribute(EVAL_VALUE, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (x.getSubQuery().getQuery() instanceof SQLSelectQueryBlock) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getSubQuery().getQuery();
|
||||
|
||||
@@ -809,6 +819,23 @@ public class SQLEvalVisitorUtils {
|
||||
}
|
||||
}
|
||||
|
||||
Object leftValue = left.getAttribute(EVAL_VALUE);
|
||||
Object rightValue = right.getAttributes().get(EVAL_VALUE);
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.Like) {
|
||||
if (isAlwayTrueLikePattern(x.getRight())) {
|
||||
x.putAttribute(EVAL_VALUE, Boolean.TRUE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (x.getOperator() == SQLBinaryOperator.NotLike) {
|
||||
if (isAlwayTrueLikePattern(x)) {
|
||||
x.putAttribute(EVAL_VALUE, Boolean.FALSE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!left.getAttributes().containsKey(EVAL_VALUE)) {
|
||||
return false;
|
||||
}
|
||||
@@ -832,8 +859,6 @@ public class SQLEvalVisitorUtils {
|
||||
}
|
||||
|
||||
Object value = null;
|
||||
Object leftValue = left.getAttribute(EVAL_VALUE);
|
||||
Object rightValue = right.getAttributes().get(EVAL_VALUE);
|
||||
switch (x.getOperator()) {
|
||||
case Add:
|
||||
value = add(leftValue, rightValue);
|
||||
@@ -872,6 +897,10 @@ public class SQLEvalVisitorUtils {
|
||||
value = eq(leftValue, rightValue);
|
||||
x.putAttribute(EVAL_VALUE, value);
|
||||
break;
|
||||
case NotEqual:
|
||||
value = !eq(leftValue, rightValue);
|
||||
x.putAttribute(EVAL_VALUE, value);
|
||||
break;
|
||||
case IsNot:
|
||||
value = !eq(leftValue, rightValue);
|
||||
x.putAttribute(EVAL_VALUE, value);
|
||||
@@ -918,6 +947,22 @@ public class SQLEvalVisitorUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isAlwayTrueLikePattern(SQLExpr x) {
|
||||
if (x instanceof SQLCharExpr) {
|
||||
String text = ((SQLCharExpr) x).getText();
|
||||
|
||||
if (text.length() >= 0) {
|
||||
for (char ch : text.toCharArray()) {
|
||||
if (ch != '%') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean visit(SQLEvalVisitor visitor, SQLNumericLiteralExpr x) {
|
||||
x.getAttributes().put(EVAL_VALUE, x.getNumber());
|
||||
return false;
|
||||
@@ -1564,5 +1609,6 @@ public class SQLEvalVisitorUtils {
|
||||
String regexpr = regexprBuilder.toString();
|
||||
return Pattern.matches(regexpr, input);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public abstract class WallProvider {
|
||||
public WallProvider(WallConfig config){
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
||||
public WallProvider(WallConfig config, String dbType){
|
||||
this.config = config;
|
||||
this.dbType = dbType;
|
||||
@@ -136,9 +136,17 @@ public abstract class WallProvider {
|
||||
public abstract ExportParameterVisitor createExportParameterVisitor();
|
||||
|
||||
public boolean checkValid(String sql) {
|
||||
WallContext.createIfNotExists(dbType);
|
||||
WallCheckResult result = check(sql);
|
||||
return result.getViolations().isEmpty();
|
||||
WallContext originalContext = WallContext.current();
|
||||
|
||||
try {
|
||||
WallContext.createIfNotExists(dbType);
|
||||
WallCheckResult result = check(sql);
|
||||
return result.getViolations().isEmpty();
|
||||
} finally {
|
||||
if (originalContext == null) {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void incrementCommentDeniedCount() {
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2011 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;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.wall.spi.WallVisitorUtils;
|
||||
|
||||
public class CountTest extends TestCase {
|
||||
|
||||
public void test_isTrue() throws Exception {
|
||||
|
||||
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) > 0")));
|
||||
Assert.assertEquals(Boolean.TRUE,
|
||||
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) >= 0")));
|
||||
Assert.assertEquals(Boolean.FALSE,
|
||||
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("(select count(*) from t) < 0")));
|
||||
Assert.assertEquals(Boolean.TRUE,
|
||||
WallVisitorUtils.getValue(SQLUtils.toSQLExpr("NOT (select count(*) from t) < 0")));
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 1999-2011 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;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.wall.spi.WallVisitorUtils;
|
||||
|
||||
public class LikeTest extends TestCase {
|
||||
|
||||
public void test_isTrue() throws Exception {
|
||||
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("f1 like '%'")));
|
||||
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("f1 like '%%'")));
|
||||
Assert.assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 AND f1 like '%%'")));
|
||||
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 OR f1 like '%%'")));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import com.alibaba.druid.wall.WallUtils;
|
||||
|
||||
/**
|
||||
@@ -31,27 +30,13 @@ import com.alibaba.druid.wall.WallUtils;
|
||||
*/
|
||||
public class MySqlWallTest2 extends TestCase {
|
||||
|
||||
public void test_true() throws Exception {
|
||||
WallConfig config = new WallConfig();
|
||||
config.setConstArithmeticAllow(true);
|
||||
public void test_stuff() throws Exception {
|
||||
Assert.assertTrue(WallUtils.isValidateMySql(//
|
||||
"select * from person_qingjia " + //
|
||||
"where isxiao=1 " + //
|
||||
"and ((starttime between 2013-01-15 and 2013-01-15)" + //
|
||||
" or (endtime between 2013-01- 15 and 2013-01-15)" + //
|
||||
") " + //
|
||||
"order by xiaojiatime desc", config));
|
||||
}
|
||||
|
||||
public void test_false() throws Exception {
|
||||
WallConfig config = new WallConfig();
|
||||
config.setConstArithmeticAllow(true);
|
||||
Assert.assertFalse(WallUtils.isValidateMySql(//
|
||||
"select * from person_qingjia " + //
|
||||
"where isxiao=1 " + //
|
||||
"and ((starttime between 2013-01-15 and 2013-01-15)" + //
|
||||
" or (endtime between 2013-01- 15 and 2013-01-15)" + //
|
||||
") " + //
|
||||
"order by xiaojiatime desc", config));
|
||||
"order by xiaojiatime desc"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user