要自动执行C#代码的安全性审核,我想从具有[HttpPost]
属性但没有[ValidateAntiForgeryToken]
属性的控制器中检索所有方法。我正在使用ANTLR来获取C#代码的ParseTree。当我有这个时,获得具有HttpPost子节点而不是ValidateAntiForgeryToken子节点的节点的最佳方法是什么?
我尝试过XPath,但似乎ANTLR只支持XPath的一个子集。我正在考虑将解析树转换为XML并在其上使用真正的XPath。有更简单的方法吗?
我使用以下代码来解析C#文件:
import java.io.*;
import java.util.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.tree.xpath.*;
public class MyParser {
public static void main(String[] args) throws IOException {
CharStream input = CharStreams.fromFileName(args[0]);
Lexer lexer = new CSharpLexer(input);
TokenStream stream = new CommonTokenStream(lexer);
CSharpParser parser = new CSharpParser(stream);
ParseTree tree = parser.compilation_unit();
String xpath = "//class_member_declaration";
Collection<ParseTree> matches = XPath.findAll(tree, xpath, parser);
System.out.println(matches);
}
}
树看起来像这样:
答案 0 :(得分:1)
除了XPath的一个子集外,Antlr4不支持ParseTree上的花式匹配。但是,这也可能是解决这个问题的错误方法。
对于大多数用例,您应该遍历解析树并收集所需的信息。这可以使用听众或访客来完成。例如,以下代码收集方法和属性,并打印具有某些属性的方法:
import java.util.*;
public class MyListener extends CSharpParserBaseListener {
String currentClass = null;
String currentMethod = null;
List<String> attributes;
boolean inClassMember = false;
@Override public void enterClass_definition(CSharpParser.Class_definitionContext ctx) {
this.currentClass = ctx.identifier().getText();
}
// Class member declaration. This thing holds both the attributes and the method declaration.
@Override public void enterClass_member_declaration(CSharpParser.Class_member_declarationContext ctx) {
this.attributes = new ArrayList<String>();
this.inClassMember = true;
}
@Override public void enterAttribute(CSharpParser.AttributeContext ctx) {
if (this.inClassMember) {
String attrName = ctx.namespace_or_type_name().identifier().get(0).getText();
this.attributes.add(attrName);
}
}
@Override public void enterMethod_declaration(CSharpParser.Method_declarationContext ctx) {
this.currentMethod = ctx.method_member_name().identifier().get(0).getText();
}
// In the exit we have collected our method name and attributes.
@Override public void exitClass_member_declaration(CSharpParser.Class_member_declarationContext ctx) {
if (this.attributes.contains("HttpPost") && !this.attributes.contains("ValidateAntiForgeryToken")) {
System.out.println(this.currentClass + "." + this.currentMethod);
}
this.attributes = null;
this.currentMethod = null;
this.inClassMember = false;
}
}
为了使这种功能更加通用,更好的方法是将解析树转换为另一棵树(即抽象语法树),并在树中搜索您想要的信息。
答案 1 :(得分:0)
我正在考虑将解析树转换为XML并在其上使用真正的XPath。有更简单的方法吗?
无需将树转换为实际的XML即可使用XPath查询。 Apache Commons libary JXPath支持Java对象的内存树中的XPath查询。