improve WallFilter

This commit is contained in:
wenshao
2013-03-18 23:23:23 +08:00
parent 434b11695a
commit 0223e5d13c
6 changed files with 256 additions and 25 deletions
@@ -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"));
}
}