diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index ad4655ff15..c13610eb13 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -65,6 +65,7 @@ import com.alibaba.druid.wall.WallContext; import com.alibaba.druid.wall.WallProvider; import com.alibaba.druid.wall.WallSqlTableStat; import com.alibaba.druid.wall.WallVisitor; +import com.alibaba.druid.wall.spi.WallVisitorUtils.WallTopStatementContext; import com.alibaba.druid.wall.violation.ErrorCode; import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation; @@ -310,6 +311,13 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi } if (varName.startsWith("@@") && !checkVar(x.getParent(), x.getName())) { + + final WallTopStatementContext topStatementContext = WallVisitorUtils.getWallTopStatementContext(); + if (topStatementContext != null + && (topStatementContext.fromSysSchema() || topStatementContext.fromSysTable())) { + return false; + } + boolean isTop = WallVisitorUtils.isTopNoneFromSelect(this, x); if (!isTop) { boolean allow = true; @@ -346,7 +354,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi @Override public boolean visit(MySqlOutFileExpr x) { - if (!config.isSelectIntoOutfileAllow()) { + if (!config.isSelectIntoOutfileAllow() && !WallVisitorUtils.isTopSelectOutFile(x)) { violations.add(new IllegalSQLObjectViolation(ErrorCode.INTO_OUTFILE, "into out file not allow", toSQL(x))); } diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java index ed3d573ddb..9b2c93bdb7 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java @@ -53,6 +53,7 @@ import com.alibaba.druid.wall.Violation; import com.alibaba.druid.wall.WallConfig; import com.alibaba.druid.wall.WallProvider; import com.alibaba.druid.wall.WallVisitor; +import com.alibaba.druid.wall.spi.WallVisitorUtils.WallTopStatementContext; import com.alibaba.druid.wall.violation.ErrorCode; import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation; @@ -254,6 +255,12 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements if (config.isVariantCheck() && varName.startsWith("@@")) { + final WallTopStatementContext topStatementContext = WallVisitorUtils.getWallTopStatementContext(); + if (topStatementContext != null + && (topStatementContext.fromSysSchema() || topStatementContext.fromSysTable())) { + return false; + } + boolean allow = true; if (WallVisitorUtils.isWhereOrHaving(x) && isDeny(varName)) { allow = false; 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 370da33580..2b47abb0c1 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -88,6 +88,7 @@ import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.ast.statement.SQLUseStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; @@ -204,7 +205,7 @@ public class WallVisitorUtils { SQLExpr expr = x.getExpr(); if (expr instanceof SQLVariantRefExpr) { - if (!isTopSelectStatement(expr) && "@".equals(((SQLVariantRefExpr) expr).getName())) { + if (!isTopSelectItem(expr) && "@".equals(((SQLVariantRefExpr) expr).getName())) { addViolation(visitor, ErrorCode.EVIL_NAME, "@ not allow", x); } } @@ -1492,6 +1493,7 @@ public class WallVisitorUtils { } boolean isWhereQueryExpr = false; + boolean isSelectItem = false; do { x = parent; parent = parent.getParent(); @@ -1503,7 +1505,9 @@ public class WallVisitorUtils { } else if (parent instanceof SQLQueryExpr || parent instanceof SQLInSubQueryExpr || parent instanceof SQLExistsExpr) { isWhereQueryExpr = isWhereOrHaving(parent); - } else if (isWhereQueryExpr && parent instanceof SQLSelectQueryBlock) { + } else if (parent instanceof SQLSelectItem) { + isSelectItem = true; + } else if ((isWhereQueryExpr || isSelectItem) && parent instanceof SQLSelectQueryBlock) { if (hasTableSource((SQLSelectQueryBlock) parent)) { return false; } @@ -1574,8 +1578,7 @@ public class WallVisitorUtils { return false; } - private static boolean isTopSelectStatement(SQLObject x) { - + private static boolean isTopSelectItem(SQLObject x) { for (;;) { if ((x.getParent() instanceof SQLExpr) || (x.getParent() instanceof Item)) { x = x.getParent(); @@ -1587,12 +1590,18 @@ public class WallVisitorUtils { if (!(x.getParent() instanceof SQLSelectItem)) { return false; } + SQLSelectItem item = (SQLSelectItem) x.getParent(); - if (!(item.getParent() instanceof SQLSelectQueryBlock)) { + return isTopSelectStatement(item.getParent()); + } + + private static boolean isTopSelectStatement(SQLObject x) { + + if (!(x instanceof SQLSelectQueryBlock)) { return false; } - SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) item.getParent(); + SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x; if (!(queryBlock.getParent() instanceof SQLSelect)) { return false; } @@ -1606,6 +1615,14 @@ public class WallVisitorUtils { return stmt.getParent() == null; } + public static boolean isTopSelectOutFile(MySqlOutFileExpr x) { + if (!(x.getParent() instanceof SQLExprTableSource)) { + return false; + } + SQLExprTableSource tableSource = (SQLExprTableSource) x.getParent(); + return isTopSelectStatement(tableSource.getParent()); + } + public static boolean check(WallVisitor visitor, SQLExprTableSource x) { final WallTopStatementContext topStatementContext = wallTopStatementContextLocal.get();