From b3bbdf9eb5ac36176d303c6f1efa544f7cf8f5a9 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 26 Aug 2013 20:53:06 +0800 Subject: [PATCH] improve sql wall --- .../sql/visitor/SQLEvalVisitorUtils.java | 57 ++++++++++++++++--- .../druid/sql/visitor/functions/Left.java | 4 ++ .../druid/sql/visitor/functions/Unhex.java | 5 ++ .../druid/wall/spi/WallVisitorUtils.java | 11 ++-- .../druid/wall/violation/ErrorCode.java | 6 +- 5 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 37489d6a5f..8958f34e3d 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -52,6 +52,7 @@ 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.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.visitor.DB2EvalVisitor; @@ -605,8 +606,32 @@ public class SQLEvalVisitorUtils { return false; } + public static SQLExpr unwrap(SQLExpr expr) { + if (expr == null) { + return null; + } + + if (expr instanceof SQLQueryExpr) { + SQLSelect select = ((SQLQueryExpr) expr).getSubQuery(); + if (select == null) { + return null; + } + if (select.getQuery() instanceof SQLSelectQueryBlock) { + SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery(); + if (queryBlock.getFrom() == null) { + if (queryBlock.getSelectList().size() == 1) { + return queryBlock.getSelectList().get(0).getExpr(); + } + } + } + } + + return expr; + } + public static boolean visit(SQLEvalVisitor visitor, SQLBetweenExpr x) { - x.getTestExpr().accept(visitor); + SQLExpr testExpr = unwrap(x.getTestExpr()); + testExpr.accept(visitor); if (!x.getTestExpr().getAttributes().containsKey(EVAL_VALUE)) { return false; @@ -912,8 +937,12 @@ public class SQLEvalVisitorUtils { x.putAttribute(EVAL_VALUE, value); break; case Divide: - value = div(leftValue, rightValue); - x.putAttribute(EVAL_VALUE, value); + if (rightValue instanceof Number && ((Number) rightValue).intValue() == 0) { + x.putAttribute(EVAL_VALUE, EVAL_ERROR); + } else { + value = div(leftValue, rightValue); + x.putAttribute(EVAL_VALUE, value); + } break; case RightShift: value = rightShift(leftValue, rightValue); @@ -1161,7 +1190,11 @@ public class SQLEvalVisitorUtils { } } - return ((Number) val).intValue(); + if (val instanceof Number) { + return ((Number) val).intValue(); + } + + throw new DruidRuntimeException("cast error"); } @SuppressWarnings("rawtypes") @@ -1334,7 +1367,9 @@ public class SQLEvalVisitorUtils { } if (a instanceof BigDecimal || b instanceof BigDecimal) { - return castToDecimal(a).divide(castToDecimal(b)); + BigDecimal decimalA = castToDecimal(a); + BigDecimal decimalB = castToDecimal(b); + return decimalA.divide(decimalB, BigDecimal.ROUND_HALF_UP); } if (a instanceof Double || b instanceof Double) { @@ -1364,7 +1399,9 @@ public class SQLEvalVisitorUtils { } if (a instanceof Integer || b instanceof Integer) { - return castToInteger(a) / castToInteger(b); + Integer intA = castToInteger(a); + Integer intB = castToInteger(b); + return intA / intB; } if (a instanceof Short || b instanceof Short) { @@ -1379,11 +1416,11 @@ public class SQLEvalVisitorUtils { } public static boolean gt(Object a, Object b) { - if (a == null) { + if (a == null || a == EVAL_VALUE_NULL) { return false; } - if (b == null) { + if (b == null || a == EVAL_VALUE_NULL) { return true; } @@ -1471,7 +1508,9 @@ public class SQLEvalVisitorUtils { } if (a instanceof Integer || b instanceof Integer) { - return castToInteger(a) < castToInteger(b); + Integer intA = castToInteger(a); + Integer intB = castToInteger(b); + return intA < intB; } if (a instanceof Short || b instanceof Short) { diff --git a/src/main/java/com/alibaba/druid/sql/visitor/functions/Left.java b/src/main/java/com/alibaba/druid/sql/visitor/functions/Left.java index 5f117ddcf2..857a6a01f1 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/functions/Left.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/functions/Left.java @@ -44,6 +44,10 @@ public class Left implements Function { String strValue = param0Value.toString(); int intValue = SQLEvalVisitorUtils.castToInteger(param1Value); + + if (intValue > strValue.length()) { + return SQLEvalVisitor.EVAL_ERROR; + } String result = strValue.substring(0, intValue); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/functions/Unhex.java b/src/main/java/com/alibaba/druid/sql/visitor/functions/Unhex.java index 1b634108de..c29198c1dd 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/functions/Unhex.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/functions/Unhex.java @@ -20,6 +20,7 @@ import static com.alibaba.druid.sql.visitor.SQLEvalVisitor.EVAL_VALUE; import java.io.UnsupportedEncodingException; +import com.alibaba.druid.DruidRuntimeException; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.visitor.SQLEvalVisitor; @@ -61,6 +62,10 @@ public class Unhex implements Function { if (param0Value instanceof String) { byte[] bytes = HexBin.decode((String) param0Value); + if (bytes == null) { + return SQLEvalVisitor.EVAL_VALUE_NULL; + } + String result; try { result = new String(bytes, "UTF-8"); 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 26aba10a06..320ff1720f 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -215,7 +215,7 @@ public class WallVisitorUtils { SQLExpr where = x.getWhere(); if (where != null) { if (queryBlockFromIsNull(visitor, x, false)) { - addViolation(visitor, ErrorCode.EmptyQueryHasCondition, "empty select has condition", x); + addViolation(visitor, ErrorCode.EMPTY_QUERY_HAS_CONDITION, "empty select has condition", x); } where.setParent(x); @@ -650,7 +650,7 @@ public class WallVisitorUtils { Object rightResult = getValue(visitor, right); if (x.getOperator() == SQLBinaryOperator.Like && leftResult instanceof String && leftResult.equals(rightResult)) { - addViolation(visitor, ErrorCode.SameConstLike, "same const like", x); + addViolation(visitor, ErrorCode.SAME_CONST_LIKE, "same const like", x); } if (x.getOperator() == SQLBinaryOperator.Like || x.getOperator() == SQLBinaryOperator.NotLike) { @@ -670,14 +670,14 @@ public class WallVisitorUtils { && leftBinaryOpExpr.getOperator() != SQLBinaryOperator.BooleanOr // && leftResult != null // && visitor != null) { - addViolation(visitor, ErrorCode.DoubleConstCondition, "double const condition", x); + addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, "double const condition", x); } if (leftBinaryOpExpr.getOperator() == SQLBinaryOperator.BooleanAnd // || leftBinaryOpExpr.getOperator() == SQLBinaryOperator.BooleanOr) { Object leftRightVal = getValue(leftBinaryOpExpr.getRight()); if (leftRightVal != null) { - addViolation(visitor, ErrorCode.DoubleConstCondition, "double const condition", x); + addViolation(visitor, ErrorCode.DOUBLE_CONST_CONDITION, "double const condition", x); } } } @@ -1029,7 +1029,8 @@ public class WallVisitorUtils { if (caseExpr.getItems().size() > 0) { SQLCaseExpr.Item item = caseExpr.getItems().get(0); Object conditionVal = getValue(visitor, item.getConditionExpr()); - if (conditionVal instanceof Boolean) { + Object itemVal = getValue(visitor, item.getValueExpr()); + if (conditionVal instanceof Boolean && itemVal != null) { addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, "const case condition", caseExpr); } } diff --git a/src/main/java/com/alibaba/druid/wall/violation/ErrorCode.java b/src/main/java/com/alibaba/druid/wall/violation/ErrorCode.java index 62a9b47ca7..7cb03e9224 100644 --- a/src/main/java/com/alibaba/druid/wall/violation/ErrorCode.java +++ b/src/main/java/com/alibaba/druid/wall/violation/ErrorCode.java @@ -60,9 +60,9 @@ public interface ErrorCode { public final static int BITWISE = 2103; public final static int NONE_CONDITION = 2104; public final static int LIKE_NUMBER = 2105; - public final static int EmptyQueryHasCondition = 2106; - public final static int DoubleConstCondition = 2107; - public final static int SameConstLike = 2108; + public final static int EMPTY_QUERY_HAS_CONDITION = 2106; + public final static int DOUBLE_CONST_CONDITION = 2107; + public final static int SAME_CONST_LIKE = 2108; public final static int CONST_CASE_CONDITION = 2109; public final static int NOT_PARAMETERIZED = 2200;