improve WallFilter, support conditionOpBitwiseAllow

This commit is contained in:
wenshao
2013-03-19 01:12:11 +08:00
parent 9e12ffb86e
commit 19b24d8022
16 changed files with 235 additions and 44 deletions
@@ -38,7 +38,6 @@ public enum SQLBinaryOperator {
BitwiseAnd("&", 90),
BitwiseOr("|", 100),
InvertBits("~", 100),
GreaterThan(">", 110),
GreaterThanOrEqual(">=", 110),
@@ -28,6 +28,7 @@ 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.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
@@ -76,6 +77,10 @@ public class MySqlEvalVisitorImpl extends MySqlASTVisitorAdapter implements SQLE
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLUnaryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLIntegerExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
@@ -27,6 +27,7 @@ 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.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
@@ -74,6 +75,10 @@ public class OracleEvalVisitor extends OracleASTVisitorAdapter implements SQLEva
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLUnaryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLIntegerExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
@@ -27,6 +27,7 @@ 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.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
@@ -74,6 +75,10 @@ public class PGEvalVisitor extends PGASTVisitorAdapter implements SQLEvalVisitor
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLUnaryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLIntegerExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
@@ -27,6 +27,7 @@ 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.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
@@ -74,6 +75,10 @@ public class SQLServerEvalVisitor extends SQLServerASTVisitorAdapter implements
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLUnaryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLIntegerExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
@@ -126,7 +126,7 @@ public class SQLExprParser extends SQLParser {
}
public final SQLExpr multiplicative() {
SQLExpr expr = primary();
SQLExpr expr = bitXor();
return multiplicativeRest(expr);
}
@@ -798,17 +798,12 @@ public class SQLExprParser extends SQLParser {
SQLExpr rightExp = bitAnd();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.BitwiseOr, rightExp);
expr = bitAndRest(expr);
} else if (lexer.token() == Token.TILDE) {
lexer.nextToken();
SQLExpr rightExp = bitAnd();
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.InvertBits, rightExp);
expr = bitAndRest(expr);
}
return expr;
}
public final SQLExpr equality() {
SQLExpr expr = shift();
SQLExpr expr = bitOr();
return equalityRest(expr);
}
@@ -816,14 +811,14 @@ public class SQLExprParser extends SQLParser {
SQLExpr rightExp;
if (lexer.token() == Token.EQ) {
lexer.nextToken();
rightExp = shift();
rightExp = bitOr();
rightExp = equalityRest(rightExp);
expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp);
} else if (lexer.token() == Token.BANGEQ) {
lexer.nextToken();
rightExp = shift();
rightExp = bitOr();
rightExp = equalityRest(rightExp);
@@ -43,6 +43,8 @@ import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
@@ -114,17 +116,17 @@ 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();
if ("concat".equals(methodName)) {
StringBuilder buf = new StringBuilder();
@@ -762,7 +764,7 @@ public class SQLEvalVisitorUtils {
x.putAttribute(EVAL_VALUE, 1);
return false;
}
if (x.getSubQuery().getQuery() instanceof SQLSelectQueryBlock) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getSubQuery().getQuery();
@@ -801,6 +803,15 @@ public class SQLEvalVisitorUtils {
return false;
}
public static boolean visit(SQLEvalVisitor visitor, SQLUnaryExpr x) {
final WallConditionContext wallConditionContext = WallVisitorUtils.getWallConditionContext();
if (x.getOperator() == SQLUnaryOperator.Compl && wallConditionContext != null) {
wallConditionContext.setBitwise(true);
}
return false;
}
public static boolean visit(SQLEvalVisitor visitor, SQLBinaryOpExpr x) {
SQLExpr left = x.getLeft();
SQLExpr right = x.getRight();
@@ -817,25 +828,36 @@ public class SQLEvalVisitorUtils {
wallConditionContext.setPartAlwayTrue(true);
}
}
} else if (x.getOperator() == SQLBinaryOperator.BooleanXor) {
if (wallConditionContext != null) {
wallConditionContext.setXor(true);
}
} else if (x.getOperator() == SQLBinaryOperator.BitwiseAnd //
|| x.getOperator() == SQLBinaryOperator.BitwiseNot //
|| x.getOperator() == SQLBinaryOperator.BitwiseOr //
|| x.getOperator() == SQLBinaryOperator.BitwiseXor) {
if (wallConditionContext != null) {
wallConditionContext.setBitwise(true);
}
}
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;
}
@@ -845,17 +867,7 @@ public class SQLEvalVisitorUtils {
}
if (wallConditionContext != null) {
switch (x.getOperator()) {
case Add:
case Subtract:
case Multiply:
case Divide:
case Modulus:
wallConditionContext.setConstArithmetic(true);
break;
default:
break;
}
wallConditionContext.setConstArithmetic(true);
}
Object value = null;
@@ -911,30 +923,30 @@ public class SQLEvalVisitorUtils {
String input = castToString(left.getAttributes().get(EVAL_VALUE));
boolean matchResult = Pattern.matches(pattern, input);
x.putAttribute(EVAL_VALUE, matchResult);
}
break;
}
case NotRegExp:
case NotRLike: {
String pattern = castToString(rightValue);
String input = castToString(left.getAttributes().get(EVAL_VALUE));
boolean matchResult = !Pattern.matches(pattern, input);
x.putAttribute(EVAL_VALUE, matchResult);
}
break;
}
case Like: {
String pattern = castToString(rightValue);
String input = castToString(left.getAttributes().get(EVAL_VALUE));
boolean matchResult = like(input, pattern);
x.putAttribute(EVAL_VALUE, matchResult);
}
break;
}
case NotLike: {
String pattern = castToString(rightValue);
String input = castToString(left.getAttributes().get(EVAL_VALUE));
boolean matchResult = !like(input, pattern);
x.putAttribute(EVAL_VALUE, matchResult);
}
break;
}
case Concat: {
String result = leftValue.toString() + rightValue.toString();
x.putAttribute(EVAL_VALUE, result);
@@ -1609,6 +1621,5 @@ public class SQLEvalVisitorUtils {
String regexpr = regexprBuilder.toString();
return Pattern.matches(regexpr, input);
}
}
@@ -51,7 +51,7 @@ public class WallConfig implements WallConfigMBean {
private boolean commentAllow = false;
private boolean strictSyntaxCheck = true;
private boolean constArithmeticAllow = false;
private boolean constArithmeticAllow = true;
private boolean describeAllow = false;
@@ -83,10 +83,29 @@ public class WallConfig implements WallConfigMBean {
private boolean wrapAllow = true;
private boolean metadataAllow = true;
private boolean conditionOpXorAllow = false;
private boolean conditionOpBitwseAllow = false;
public WallConfig(){
}
public boolean isConditionOpXorAllow() {
return conditionOpXorAllow;
}
public void setConditionOpXorAllow(boolean conditionOpXorAllow) {
this.conditionOpXorAllow = conditionOpXorAllow;
}
public boolean isConditionOpBitwseAllow() {
return conditionOpBitwseAllow;
}
public void setConditionOpBitwseAllow(boolean conditionOpBitwseAllow) {
this.conditionOpBitwseAllow = conditionOpBitwseAllow;
}
public String getTenantTablePattern() {
return tenantTablePattern;
}
@@ -464,24 +464,26 @@ public class WallVisitorUtils {
if (wallContext != null) {
dbType = wallContext.getDbType();
}
return SQLEvalVisitorUtils.eval(dbType, x, Collections.emptyList(), false);
}
public static class WallConditionContext {
private boolean partAllowTrue;
private boolean partAlwayrue;
private boolean constArithmetic = false;
private boolean xor = false;
private boolean bitwise = false;
public boolean isPartAllowTrue() {
return partAllowTrue;
public boolean hasPartAlwayTrue() {
return partAlwayrue;
}
public void setPartAlwayTrue(boolean partAllowTrue) {
this.partAllowTrue = partAllowTrue;
this.partAlwayrue = partAllowTrue;
}
public boolean isConstArithmetic() {
public boolean hasConstArithmetic() {
return constArithmetic;
}
@@ -489,6 +491,21 @@ public class WallVisitorUtils {
this.constArithmetic = constArithmetic;
}
public boolean hasXor() {
return xor;
}
public void setXor(boolean xor) {
this.xor = xor;
}
public boolean hasBitwise() {
return bitwise;
}
public void setBitwise(boolean bitwise) {
this.bitwise = bitwise;
}
}
private static ThreadLocal<WallConditionContext> wallConditionContextLocal = new ThreadLocal<WallConditionContext>();
@@ -504,11 +521,19 @@ public class WallVisitorUtils {
final Object value = getValue(x);
final WallConditionContext current = wallConditionContextLocal.get();
if (current.isPartAllowTrue() && alwayTrueCheck) {
if (current.hasPartAlwayTrue() && alwayTrueCheck) {
addViolation(visitor, x);
}
if (current.isConstArithmetic() && !visitor.getConfig().isConstArithmeticAllow()) {
if (current.hasConstArithmetic() && !visitor.getConfig().isConstArithmeticAllow()) {
addViolation(visitor, x);
}
if (current.hasXor() && !visitor.getConfig().isConditionOpXorAllow()) {
addViolation(visitor, x);
}
if (current.hasBitwise() && !visitor.getConfig().isConditionOpBitwseAllow()) {
addViolation(visitor, x);
}