📄 constructorcallsoverridablemethodrule.java
字号:
varNames.add(name); } } } } } } else { //if no this or super found, everything is method name or variable //System.out.println("no this found:"); FIRSTNODE:{ //variable names are in the prefix + the first method call [a.b.c.x()] ASTPrimaryPrefix child = (ASTPrimaryPrefix) node.jjtGetChild(0); String toParse = getNameFromPrefix(child); // System.out.println("parsing for var names in : " + toParse); java.util.StringTokenizer st = new java.util.StringTokenizer(toParse, "."); while (st.hasMoreTokens()) { String value = st.nextToken(); if (!st.hasMoreTokens()) { if (i == 2) {//if this expression is 2 nodes long, then the last part of prefix is method name methodName = value; } else { varNames.add(value); } } else { //variable name varNames.add(value); } } } OTHERNODES:{ //other methods called in this statement are grabbed here for (int x = 1; x < i - 1; x++) { ASTPrimarySuffix child = (ASTPrimarySuffix) node.jjtGetChild(x); if (child.isArguments() == false) { String name = getNameFromSuffix(child); if (x == i - 2) { methodName = name; } else { varNames.add(name); } } } } } meth = new MethodInvocation(node, packagesAndClasses, varNames, methodName, numOfArguments, superFirst); } } return meth; } public void show() { System.out.println("<MethodInvocation>"); List pkg = getQualifierNames(); System.out.println(" <Qualifiers>"); for (Iterator it = pkg.iterator(); it.hasNext();) { String name = (String) it.next(); System.out.println(" " + name); } System.out.println(" </Qualifiers>"); System.out.println(" <Super>" + isSuper() + "</Super>"); List vars = getReferenceNames(); System.out.println(" <References>"); for (Iterator it = vars.iterator(); it.hasNext();) { String name = (String) it.next(); System.out.println(" " + name); } System.out.println(" </References>"); System.out.println(" <Name>" + getName() + "</Name>"); System.out.println("</MethodInvocation>"); } } private final class ConstructorInvocation { private ASTExplicitConstructorInvocation m_Eci; private String name; private int count = 0; public ConstructorInvocation(ASTExplicitConstructorInvocation eci) { m_Eci = eci; List l = new ArrayList(); eci.findChildrenOfType(ASTArguments.class, l); if (l.size() > 0) { ASTArguments aa = (ASTArguments) l.get(0); count = aa.getArgumentCount(); } name = eci.getImage(); } public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() { return m_Eci; } public int getArgumentCount() { return count; } public String getName() { return name; } } private final class MethodHolder { private ASTMethodDeclarator m_Amd; private boolean m_Dangerous = false; public MethodHolder(ASTMethodDeclarator amd) { m_Amd = amd; } public ASTMethodDeclarator getASTMethodDeclarator() { return m_Amd; } public boolean isDangerous() { return m_Dangerous; } public void setDangerous(boolean dangerous) { m_Dangerous = dangerous; } } private final class ConstructorHolder { private ASTConstructorDeclaration m_Cd; private boolean m_Dangerous = false; private ConstructorInvocation m_Ci; private boolean m_CiInitialized = false; public ConstructorHolder(ASTConstructorDeclaration cd) { m_Cd = cd; } public ASTConstructorDeclaration getASTConstructorDeclaration() { return m_Cd; } public ConstructorInvocation getCalledConstructor() { if (m_CiInitialized == false) { initCI(); } return m_Ci; } public ASTExplicitConstructorInvocation getASTExplicitConstructorInvocation() { ASTExplicitConstructorInvocation eci = null; if (m_CiInitialized == false) { initCI(); } if (m_Ci != null) { eci = m_Ci.getASTExplicitConstructorInvocation(); } return eci; } private void initCI() { List expressions = new ArrayList(); m_Cd.findChildrenOfType(ASTExplicitConstructorInvocation.class, expressions); //only 1... if (expressions.size() > 0) { ASTExplicitConstructorInvocation eci = (ASTExplicitConstructorInvocation) expressions.get(0); m_Ci = new ConstructorInvocation(eci); //System.out.println("Const call " + eci.getImage()); //super or this??? } m_CiInitialized = true; } public boolean isDangerous() { return m_Dangerous; } public void setDangerous(boolean dangerous) { m_Dangerous = dangerous; } } /** * 1 package per class. holds info for evaluating a single class. */ private static class EvalPackage { public EvalPackage() { } public EvalPackage(String className) { m_ClassName = className; calledMethods = new ArrayList();//meths called from constructor allMethodsOfClass = new HashMap(); calledConstructors = new ArrayList();//all constructors called from constructor allPrivateConstructorsOfClass = new HashMap(); } public String m_ClassName; public List calledMethods; public Map allMethodsOfClass; public List calledConstructors; public Map allPrivateConstructorsOfClass; } private static final class NullEvalPackage extends EvalPackage { public NullEvalPackage() { m_ClassName = ""; calledMethods = Collections.EMPTY_LIST; allMethodsOfClass = Collections.EMPTY_MAP; calledConstructors = Collections.EMPTY_LIST; allPrivateConstructorsOfClass = Collections.EMPTY_MAP; } } private static final NullEvalPackage nullEvalPackage = new NullEvalPackage(); /** * 1 package per class. */ private final List evalPackages = new ArrayList();//could use java.util.Stack private EvalPackage getCurrentEvalPackage() { return (EvalPackage) evalPackages.get(evalPackages.size() - 1); } /** * Adds and evaluation package and makes it current */ private void putEvalPackage(EvalPackage ep) { evalPackages.add(ep); } private void removeCurrentEvalPackage() { evalPackages.remove(evalPackages.size() - 1); } private void clearEvalPackages() { evalPackages.clear(); } /** * This check must be evaluated independelty for each class. Inner classses * get their own EvalPackage in order to perform independent evaluation. */ private Object visitClassDec(AccessNode node, Object data) { String className = ((ASTUnmodifiedClassDeclaration) node.jjtGetChild(0)).getImage(); // System.out.println("Class is " + className); //evaluate each level independently if (!node.isFinal() && !node.isStatic()) { putEvalPackage(new EvalPackage(className)); } else { putEvalPackage(nullEvalPackage); } //store any errors caught from other passes. if (node instanceof ASTClassDeclaration) { super.visit((ASTClassDeclaration) node, data); } else { super.visit((ASTNestedClassDeclaration) node, data); } //skip this class if it has no evaluation package if (!(getCurrentEvalPackage() instanceof NullEvalPackage)) { //evaluate danger of all methods in class while (evaluateDangerOfMethods(getCurrentEvalPackage().allMethodsOfClass) == true) ; //evaluate danger of constructors evaluateDangerOfConstructors1(getCurrentEvalPackage().allPrivateConstructorsOfClass, getCurrentEvalPackage().allMethodsOfClass.keySet()); while (evaluateDangerOfConstructors2(getCurrentEvalPackage().allPrivateConstructorsOfClass) == true) ; //get each method called on this object from a non-private constructor, if its dangerous flag it for (Iterator it = getCurrentEvalPackage().calledMethods.iterator(); it.hasNext();) { MethodInvocation meth = (MethodInvocation) it.next(); //check against each dangerous method in class for (Iterator it2 = getCurrentEvalPackage().allMethodsOfClass.keySet().iterator(); it2.hasNext();) { MethodHolder h = (MethodHolder) it2.next(); if (h.isDangerous()) { String methName = h.getASTMethodDeclarator().getImage(); int count = h.getASTMethodDeclarator().getParameterCount(); if (meth.getName().equals(methName) && (meth.getArgumentCount() == count)) { //bad call RuleContext ctx = (RuleContext) data; ctx.getReport().addRuleViolation(createRuleViolation(ctx, meth.getASTPrimaryExpression().getBeginLine())); } } } } //get each unsafe private constructor, and check if its called from any non private constructors for (Iterator privConstIter = getCurrentEvalPackage().allPrivateConstructorsOfClass.keySet().iterator(); privConstIter.hasNext();) { ConstructorHolder ch = (ConstructorHolder) privConstIter.next(); if (ch.isDangerous()) { //if its dangerous check if its called from any non-private constructors //System.out.println("visitClassDec Evaluating dangerous constructor with " + ch.getASTConstructorDeclaration().getParameterCount() + " params"); int paramCount = ch.getASTConstructorDeclaration().getParameterCount(); for (Iterator calledConstIter = getCurrentEvalPackage().calledConstructors.iterator(); calledConstIter.hasNext();) { ConstructorInvocation ci = (ConstructorInvocation) calledConstIter.next(); if (ci.getArgumentCount() == paramCount) { //match name super / this !? RuleContext ctx = (RuleContext) data; ctx.getReport().addRuleViolation(createRuleViolation(ctx, ci.getASTExplicitConstructorInvocation().getBeginLine())); } } } } } //finished evaluating this class, move up a level removeCurrentEvalPackage(); return data; } /** * Check the methods called on this class by each of the methods on this * class. If a method calls an unsafe method, mark the calling method as * unsafe. This changes the list of unsafe methods which necessitates * another pass. Keep passing until you make a clean pass in which no * methods are changed to unsafe. * For speed it is possible to limit the number of passes. * * Impossible to tell type of arguments to method, so forget method matching * on types. just use name and num of arguments. will be some false hits, * but oh well.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -