/** Check that the local variable <code>l</code> is used correctly. */ protected void checkLocal(FlowGraph graph, Local l, DataFlowItem dfIn, DataFlowItem dfOut) throws SemanticException { if (!currCBI.localDeclarations.contains(l.localInstance())) { // it's a local variable that has not been declared within // this scope. The only way this can arise is from an // inner class that is not a member of a class (typically // a local class, or an anonymous class declared in a method, // constructor or initializer). // We need to check that it is a final local, and also // keep track of it, to ensure that it has been definitely // assigned at this point. currCBI.outerLocalsUsed.add(l.localInstance()); } else { MinMaxInitCount initCount = (MinMaxInitCount) dfIn.initStatus.get(l.localInstance()); if (initCount != null && InitCount.ZERO.equals(initCount.getMin())) { // the local variable may not have been initialized. // However, we only want to complain if the local is reachable if (l.reachable()) { throw new SemanticException( "Local variable \"" + l.name() + "\" may not have been initialized", l.position()); } } } }
@Override public Node labelCheckLHS(LabelChecker lc) throws SemanticException { final Assign assign = (Assign) node(); Local lve = (Local) assign.left(); JifTypeSystem ts = lc.jifTypeSystem(); JifContext A = lc.jifContext(); A = (JifContext) lve.del().enterScope(A); List throwTypes = new ArrayList(assign.del().throwTypes(ts)); final LocalInstance li = lve.localInstance(); Label L = ts.labelOfLocal(li, A.pc()); Expr rhs = (Expr) lc.context(A).labelCheck(assign.right()); PathMap Xr = rhsPathMap(lc.context(A), rhs, throwTypes); PathMap X; if (assign.operator() != Assign.ASSIGN) { PathMap Xv = ts.pathMap(); Xv = Xv.N(A.pc()); Xv = Xv.NV(lc.upperBound(L, A.pc())); if (assign.throwsArithmeticException()) { Type arithExc = ts.ArithmeticException(); checkAndRemoveThrowType(throwTypes, arithExc); X = Xv.join(Xr).exc(Xr.NV(), arithExc); } else { X = Xv.join(Xr); } } else { X = Xr; } lc.constrain( new NamedLabel( "rhs.nv", "label of successful evaluation of right hand of assignment", X.NV()), LabelConstraint.LEQ, new NamedLabel("label of var " + li.name(), L), A.labelEnv(), lve.position(), new LabelConstraintMessage() { @Override public String msg() { return "Label of right hand side not less " + "restrictive than the label for local variable " + li.name(); } @Override public String detailMsg() { return "More information is revealed by the successful " + "evaluation of the right hand side of the " + "assignment than is allowed to flow to " + "the local variable " + li.name() + "."; } @Override public String technicalMsg() { return "Invalid assignment: path NV of rhs is " + "not less restrictive than the declared label " + "of the local variable <" + li.name() + ">."; } }); if (JLiftOptions.getInstance().safeMutateConstraintSet) { // also constrain PC label lc.constrain( new NamedLabel("pc", "program counter label for assignment", A.pc()), LabelConstraint.LEQ, new NamedLabel("label of var " + li.name(), L), A.labelEnv(), lve.position(), new LabelConstraintMessage() { @Override public String msg() { return "Program counter not less " + "restrictive than the label for local variable " + li.name(); } }); } Expr lhs = (Expr) updatePathMap(lve, X); checkThrowTypes(throwTypes); return updatePathMap(assign.right(rhs).left(lhs), X); }