Java Code Examples for soot.jimple.AssignStmt#getLeftOp()
The following examples show how to use
soot.jimple.AssignStmt#getLeftOp() .
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: AbstractBoomerangTest.java From SPDS with Eclipse Public License 2.0 | 6 votes |
public Optional<? extends Query> test(Stmt stmt) { if (stmt instanceof AssignStmt) { AssignStmt as = (AssignStmt) stmt; if (as.getLeftOp().toString().equals("allocation")) { Statement statement = new Statement(stmt, staticIcfg.getMethodOf(stmt)); if (as.getLeftOp() instanceof Local && as.getRightOp() instanceof IntConstant) { Local local = (Local) as.getLeftOp(); ForwardQuery forwardQuery = new ForwardQuery(statement, new AllocVal(local, staticIcfg.getMethodOf(stmt), as.getRightOp(), new Statement(as, staticIcfg.getMethodOf(stmt)))); return Optional.<Query> of(forwardQuery); } if (as.containsInvokeExpr()) { AtomicReference<Query> returnValue = new AtomicReference<>(); staticIcfg.addCalleeListener( new IntegerAllocationSiteCalleeListener(returnValue, as, statement, stmt)); if (returnValue.get() != null) { return Optional.of(returnValue.get()); } } } } return Optional.empty(); }
Example 2
Source File: ForwardBoomerangSolver.java From SPDS with Eclipse Public License 2.0 | 6 votes |
@Override protected boolean killFlow(SootMethod m, Stmt curr, Val value) { if (!m.getActiveBody().getLocals().contains(value.value()) && !value.isStatic()) return true; if (curr instanceof AssignStmt) { AssignStmt as = (AssignStmt) curr; // Kill x at any statement x = * during propagation. if (as.getLeftOp().equals(value.value())) { // But not for a statement x = x.f if (as.getRightOp() instanceof InstanceFieldRef) { InstanceFieldRef iie = (InstanceFieldRef) as.getRightOp(); if (iie.getBase().equals(value.value())) { return false; } } return true; } if (as.getLeftOp() instanceof StaticFieldRef) { StaticFieldRef sfr = (StaticFieldRef) as.getLeftOp(); if (value.isStatic() && value.equals(new StaticFieldVal(as.getLeftOp(), sfr.getField(), m))) { return true; } } } return false; }
Example 3
Source File: AbstractBoomerangTest.java From SPDS with Eclipse Public License 2.0 | 6 votes |
public Optional<? extends Query> test(Stmt unit) { if (unit instanceof AssignStmt) { AssignStmt as = (AssignStmt) unit; if (as.getLeftOp() instanceof Local && as.getRightOp() instanceof NewExpr) { NewExpr expr = ((NewExpr) as.getRightOp()); if (allocatesObjectOfInterest(expr)) { Local local = (Local) as.getLeftOp(); Statement statement = new Statement(unit, staticIcfg.getMethodOf(unit)); ForwardQuery forwardQuery = new ForwardQuery(statement, new AllocVal(local, staticIcfg.getMethodOf(unit), as.getRightOp(), statement)); return Optional.<Query> of(forwardQuery); } } } return Optional.empty(); }
Example 4
Source File: WeightedBoomerang.java From SPDS with Eclipse Public License 2.0 | 5 votes |
protected FieldReadPOI createArrayFieldLoad(Statement s) { Stmt stmt = s.getUnit().get(); AssignStmt as = (AssignStmt) stmt; ArrayRef ifr = (ArrayRef) as.getRightOp(); Val base = new Val(ifr.getBase(), icfg().getMethodOf(as)); Val stored = new Val(as.getLeftOp(), icfg().getMethodOf(as)); return fieldReads.getOrCreate(new FieldReadPOI(s, base, Field.array(), stored)); }
Example 5
Source File: WeightedBoomerang.java From SPDS with Eclipse Public License 2.0 | 5 votes |
protected FieldWritePOI createFieldStore(Statement s) { Stmt stmt = s.getUnit().get(); AssignStmt as = (AssignStmt) stmt; InstanceFieldRef ifr = (InstanceFieldRef) as.getLeftOp(); Val base = new Val(ifr.getBase(), icfg().getMethodOf(as)); Val stored = new Val(as.getRightOp(), icfg().getMethodOf(as)); Field field = new Field(ifr.getField()); return fieldWrites.getOrCreate(new FieldWritePOI(s, base, field, stored)); }
Example 6
Source File: AbstractBoomerangSolver.java From SPDS with Eclipse Public License 2.0 | 5 votes |
protected boolean isFieldWriteWithBase(Stmt curr, Val base) { if (curr instanceof AssignStmt) { AssignStmt as = (AssignStmt) curr; if (as.getLeftOp() instanceof InstanceFieldRef) { InstanceFieldRef ifr = (InstanceFieldRef) as.getLeftOp(); return ifr.getBase().equals(base.value()); } } return false; }
Example 7
Source File: AbstractBoomerangSolver.java From SPDS with Eclipse Public License 2.0 | 5 votes |
protected Field getWrittenField(Stmt curr) { AssignStmt as = (AssignStmt) curr; if (as.getLeftOp() instanceof StaticFieldRef) { StaticFieldRef staticFieldRef = (StaticFieldRef) as.getLeftOp(); return new Field(staticFieldRef.getField()); } InstanceFieldRef ifr = (InstanceFieldRef) as.getLeftOp(); return new Field(ifr.getField()); }
Example 8
Source File: AbstractBoomerangSolver.java From SPDS with Eclipse Public License 2.0 | 5 votes |
private boolean containsStaticFieldAccess(Stmt succ) { if (succ instanceof AssignStmt) { AssignStmt assignStmt = (AssignStmt) succ; return assignStmt.getLeftOp() instanceof StaticFieldRef || assignStmt.getRightOp() instanceof StaticFieldRef; } return false; }
Example 9
Source File: UnitThrowAnalysis.java From JAADAS with GNU General Public License v3.0 | 5 votes |
@Override public void caseAssignStmt(AssignStmt s) { Value lhs = s.getLeftOp(); if (lhs instanceof ArrayRef && (lhs.getType() instanceof UnknownType || lhs.getType() instanceof RefType)) { // This corresponds to an aastore byte code. result = result.add(mgr.ARRAY_STORE_EXCEPTION); } result = result.add(mightThrow(s.getLeftOp())); result = result.add(mightThrow(s.getRightOp())); }
Example 10
Source File: JimpleReduceStaticFieldsTransformer.java From soot-infoflow-android-iccta with GNU Lesser General Public License v2.1 | 5 votes |
private void replaceSootField(SootClass sc, Body b, AssignStmt aStmt, SootField sf) { SootClass sfClass = sf.getDeclaringClass(); LocalGenerator lg = new LocalGenerator(b); Local sfLocal = lg.generateLocal(sc.getType()); Unit sfLocalAssignU = Jimple.v().newAssignStmt( sfLocal, Jimple.v().newStaticFieldRef(sc.getField("instance", sc.getType()).makeRef())); Local sfLocal2 = lg.generateLocal(sfClass.getType()); Unit sfLocalAssignU2 = Jimple.v().newAssignStmt( sfLocal2, Jimple.v().newInstanceFieldRef(sfLocal, sc.getField(sfClass.getName(), sfClass.getType()).makeRef())); Unit assignU = null; if (aStmt.getLeftOp() instanceof FieldRef) { assignU = Jimple.v().newAssignStmt(Jimple.v().newInstanceFieldRef(sfLocal2, sf.makeRef()), aStmt.getRightOp()); } else { assignU = Jimple.v().newAssignStmt(aStmt.getLeftOp(), Jimple.v().newInstanceFieldRef(sfLocal2, sf.makeRef())); } b.getUnits().insertBefore(sfLocalAssignU, aStmt); b.getUnits().insertBefore(sfLocalAssignU2, aStmt); b.getUnits().insertBefore(assignU, aStmt); b.getUnits().remove(aStmt); System.out.println(b); }
Example 11
Source File: DexNullTransformer.java From JAADAS with GNU General Public License v3.0 | 5 votes |
/** * Collect all the locals which are assigned a IntConstant(0) or are used * within a zero comparison. * * @param body * the body to analyze */ private Set<Local> getNullCandidates(Body body) { Set<Local> candidates = null; for (Unit u : body.getUnits()) { if (u instanceof AssignStmt) { AssignStmt a = (AssignStmt) u; if (!(a.getLeftOp() instanceof Local)) continue; Local l = (Local) a.getLeftOp(); Value r = a.getRightOp(); if ((r instanceof IntConstant && ((IntConstant) r).value == 0) || (r instanceof LongConstant && ((LongConstant) r).value == 0)) { if (candidates == null) candidates = new HashSet<Local>(); candidates.add(l); Debug.printDbg("[add null candidate: ", u); } } else if (u instanceof IfStmt) { ConditionExpr expr = (ConditionExpr) ((IfStmt) u) .getCondition(); if (isZeroComparison(expr) && expr.getOp1() instanceof Local) { if (candidates == null) candidates = new HashSet<Local>(); candidates.add((Local) expr.getOp1()); Debug.printDbg("[add null candidate if: ", u); } } } return candidates == null ? Collections.<Local>emptySet() : candidates; }
Example 12
Source File: NormalEdgeFunctionFactory.java From DroidRA with GNU Lesser General Public License v2.1 | 5 votes |
/** * Returns a normal edge function. * * @param curr The current statement. * @param currNode The current variable. * @param succNode The variable the current variable is propagated to after the statement. * @param zeroValue The zero value, which represents the absence of a data flow fact. * @param pointsToAnalysis The pointer analysis. * @return A normal edge function. */ public EdgeFunction<BasePropagationValue> getNormalEdgeFunction(Unit curr, Value currNode, Value succNode, Value zeroValue, PointsToAnalysis pointsToAnalysis) { if (curr instanceof AssignStmt) { if (logger.isDebugEnabled()) { logger.debug("Normal edge: " + curr); logger.debug(currNode + " " + succNode); } AssignStmt assignStmt = (AssignStmt) curr; final Value left = assignStmt.getLeftOp(); final String type = left.getType().toString(); final Value right = assignStmt.getRightOp(); if (Model.v().isModeledType(type)) { if (currNode.equivTo(zeroValue) && succNode.equivTo(left)) { if (right instanceof StaticFieldRef) { StaticFieldRef staticFieldRef = (StaticFieldRef) right; Argument[] arguments = Model.v().getArgumentsForStaticField(staticFieldRef.getField().getSignature()); EdgeFunction<BasePropagationValue> result = PropagationTransformerFactory.makeTransformer(null, arguments, false); if (arguments != null) { if (logger.isDebugEnabled()) { logger.debug("Returning " + result); } return PropagationTransformerFactory.makeTransformer(null, arguments, false); } } else if (right instanceof NullConstant) { return PropagationTransformerFactory.makeTransformer(null, null, false); } } } } return EdgeIdentity.v(); }
Example 13
Source File: ImplicitFlowAliasStrategy.java From JAADAS with GNU General Public License v3.0 | 5 votes |
/** * Computes the global non-flow-sensitive alias information for the given * method * @param method The method for which to compute the alias information */ private Map<AccessPath, Set<AccessPath>> computeGlobalAliases(SootMethod method) { Map<AccessPath, Set<AccessPath>> res = new HashMap<AccessPath, Set<AccessPath>>(); // Find the aliases for (Unit u : method.getActiveBody().getUnits()) { if (!(u instanceof AssignStmt)) continue; final AssignStmt assign = (AssignStmt) u; // Aliases can only be generated on the heap if (!(assign.getLeftOp() instanceof FieldRef && (assign.getRightOp() instanceof FieldRef || assign.getRightOp() instanceof Local))) if (!(assign.getRightOp() instanceof FieldRef && (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof Local))) continue; final AccessPath apLeft = new AccessPath(assign.getLeftOp(), true); final AccessPath apRight = new AccessPath(assign.getRightOp(), true); Set<AccessPath> mapLeft = res.get(apLeft); if (mapLeft == null) { mapLeft = new HashSet<AccessPath>(); res.put(apLeft, mapLeft); } mapLeft.add(apRight); Set<AccessPath> mapRight = res.get(apRight); if (mapRight == null) { mapRight = new HashSet<AccessPath>(); res.put(apRight, mapRight); } mapLeft.add(apLeft); } return res; }
Example 14
Source File: WeightedBoomerang.java From SPDS with Eclipse Public License 2.0 | 5 votes |
protected FieldWritePOI createArrayFieldStore(Statement s) { Stmt stmt = s.getUnit().get(); AssignStmt as = (AssignStmt) stmt; ArrayRef ifr = (ArrayRef) as.getLeftOp(); Val base = new Val(ifr.getBase(), icfg().getMethodOf(as)); Val stored = new Val(as.getRightOp(), icfg().getMethodOf(as)); return fieldWrites.getOrCreate(new FieldWritePOI(s, base, Field.array(), stored)); }
Example 15
Source File: DexReturnValuePropagator.java From JAADAS with GNU General Public License v3.0 | 4 votes |
@Override protected void internalTransform(Body body, String phaseName, Map<String, String> options) { ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body, DalvikThrowAnalysis.v(), true); LocalDefs localDefs = LocalDefs.Factory.newLocalDefs(graph); LocalUses localUses = null; LocalCreation localCreation = null; // If a return statement's operand has only one definition and this is // a copy statement, we take the original operand for (Unit u : body.getUnits()) if (u instanceof ReturnStmt) { ReturnStmt retStmt = (ReturnStmt) u; if (retStmt.getOp() instanceof Local) { List<Unit> defs = localDefs.getDefsOfAt((Local) retStmt.getOp(), retStmt); if (defs.size() == 1 && defs.get(0) instanceof AssignStmt) { AssignStmt assign = (AssignStmt) defs.get(0); final Value rightOp = assign.getRightOp(); final Value leftOp = assign.getLeftOp(); // Copy over the left side if it is a local if (rightOp instanceof Local) { // We must make sure that the definition we propagate to // the return statement is not overwritten in between // a = 1; b = a; a = 3; return b; may not be translated // to return a; if (!isRedefined((Local) rightOp, u, assign, graph)) retStmt.setOp(rightOp); } else if (rightOp instanceof Constant) { retStmt.setOp(rightOp); } // If this is a field access which has no other uses, // we rename the local to help splitting else if (rightOp instanceof FieldRef) { if (localUses == null) localUses = LocalUses.Factory.newLocalUses(body, localDefs); if (localUses.getUsesOf(assign).size() == 1) { if (localCreation == null) localCreation = new LocalCreation(body.getLocals(), "ret"); Local newLocal = localCreation.newLocal(leftOp.getType()); assign.setLeftOp(newLocal); retStmt.setOp(newLocal); } } } } } }
Example 16
Source File: StmtVisitor.java From JAADAS with GNU General Public License v3.0 | 4 votes |
@Override public void caseAssignStmt(AssignStmt stmt) { constantV.setOrigStmt(stmt); exprV.setOrigStmt(stmt); Value lhs = stmt.getLeftOp(); if (lhs instanceof ConcreteRef) { // special cases that lead to *put* opcodes Value source = stmt.getRightOp(); addInsn(buildPutInsn((ConcreteRef) lhs, source), stmt); return; } // other cases, where lhs is a local if (!(lhs instanceof Local)) { throw new Error("left-hand side of AssignStmt is not a Local: " + lhs.getClass()); } Register lhsReg = regAlloc.asLocal(lhs); Value rhs = stmt.getRightOp(); if (rhs instanceof Local) { // move rhs local to lhs local, if different String lhsName = ((Local)lhs).getName(); String rhsName = ((Local)rhs).getName(); if (lhsName.equals(rhsName)) { return; } Register sourceReg = regAlloc.asLocal(rhs); addInsn(buildMoveInsn(lhsReg, sourceReg), stmt); } else if (rhs instanceof Constant) { // move rhs constant into the lhs local constantV.setDestination(lhsReg); rhs.apply(constantV); } else if (rhs instanceof ConcreteRef) { addInsn(buildGetInsn((ConcreteRef) rhs, lhsReg), stmt); } else { // evaluate rhs expression, saving the result in the lhs local exprV.setDestinationReg(lhsReg); rhs.apply(exprV); if (rhs instanceof InvokeExpr) { // do the actual "assignment" for an invocation: move its result to the lhs reg (it was not used yet) Insn moveResultInsn = buildMoveResultInsn(lhsReg); int invokeInsnIndex = insns.indexOf(getLastInvokeInsn()); addInsn(invokeInsnIndex + 1, moveResultInsn); } } this.insnRegisterMap.put(insns.get(insns.size() - 1), LocalRegisterAssignmentInformation.v(lhsReg, (Local)lhs)); }
Example 17
Source File: InterproceduralConstantValuePropagator.java From JAADAS with GNU General Public License v3.0 | 4 votes |
/** * Checks whether the given method or one of its transitive callees has * side-effects or calls a sink method * @param method The method to check * @param runList A set to receive all methods that have already been * processed * @param cache The cache in which to store the results * @return True if the given method or one of its transitive callees has * side-effects or calls a sink method, otherwise false. */ private boolean hasSideEffectsOrReadsThis(SootMethod method, Set<SootMethod> runList) { // Without a body, we cannot say much if (!method.hasActiveBody()) return false; // Do we already have an entry? Boolean hasSideEffects = methodSideEffects.get(method); if (hasSideEffects != null) return hasSideEffects; // Do not process the same method twice if (!runList.add(method)) return false; // If this is an Android stub method that just throws a stub exception, // this will never happen in practice and can be removed if (methodIsAndroidStub(method)) { methodSideEffects.put(method, false); return false; } // Scan for references to this variable Local thisLocal = method.isStatic() ? null : method.getActiveBody().getThisLocal(); for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof ArrayRef) { methodSideEffects.put(method, true); return true; } } Stmt s = (Stmt) u; // If this statement uses the "this" local, we have to // conservatively assume that is can read data if (thisLocal != null) for (ValueBox vb : s.getUseBoxes()) if (vb.getValue() == thisLocal) return true; if (s.containsInvokeExpr()) { // Check the callees for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(u); edgeIt.hasNext(); ) { Edge e = edgeIt.next(); if (hasSideEffectsOrReadsThis(e.getTgt().method(), runList)) return true; } } } // Variable is not read methodSideEffects.put(method, false); return false; }
Example 18
Source File: InterproceduralConstantValuePropagator.java From JAADAS with GNU General Public License v3.0 | 4 votes |
/** * Checks whether the given method or one of its transitive callees has * side-effects or calls a sink method * @param method The method to check * @param runList A set to receive all methods that have already been * processed * @param cache The cache in which to store the results * @return True if the given method or one of its transitive callees has * side-effects or calls a sink method, otherwise false. */ private boolean hasSideEffectsOrCallsSink(SootMethod method, Set<SootMethod> runList) { // Without a body, we cannot say much if (!method.hasActiveBody()) return false; // Do we already have an entry? Boolean hasSideEffects = methodSideEffects.get(method); if (hasSideEffects != null) return hasSideEffects; Boolean hasSink = methodSinks.get(method); if (hasSink != null) return hasSink; // Do not process the same method twice if (!runList.add(method)) return false; // If this is an Android stub method that just throws a stub exception, // this will never happen in practice and can be removed if (methodIsAndroidStub(method)) { methodSideEffects.put(method, false); return false; } // Scan for references to this variable for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() instanceof FieldRef || assign.getLeftOp() instanceof ArrayRef) { methodSideEffects.put(method, true); return true; } } Stmt s = (Stmt) u; // If this method calls another method for which we have a taint // wrapper, we need to conservatively assume that the taint wrapper // can do anything if (taintWrapper != null && taintWrapper.supportsCallee(s)) { methodSideEffects.put(method, true); return true; } if (s.containsInvokeExpr()) { // If this method calls a sink, we need to keep it if (sourceSinkManager != null && sourceSinkManager.isSink((Stmt) u, icfg, null)) { methodSinks.put(method, true); return true; } // Check the callees for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(u); edgeIt.hasNext(); ) { Edge e = edgeIt.next(); if (hasSideEffectsOrCallsSink(e.getTgt().method(), runList)) return true; } } } // Variable is not read methodSideEffects.put(method, false); return false; }
Example 19
Source File: InfoflowCFG.java From JAADAS with GNU General Public License v3.0 | 4 votes |
public boolean isStaticFieldWrite(SootMethod method, SootField variable, Set<SootMethod> runList) { // Without a body, we cannot say much if (!method.hasActiveBody()) return false; // Do not process the same method twice if (!runList.add(method)) return false; // Do we already have an entry? Map<SootField, StaticFieldUse> entry = staticFieldUses.get(method); if (entry != null) { StaticFieldUse b = entry.get(variable); if (b != null && b != StaticFieldUse.Unknown) { return b == StaticFieldUse.Write; } } // Scan for references to this variable for (Unit u : method.getActiveBody().getUnits()) { if (u instanceof AssignStmt) { AssignStmt assign = (AssignStmt) u; if (assign.getLeftOp() instanceof StaticFieldRef) { SootField sf = ((StaticFieldRef) assign.getLeftOp()).getField(); registerStaticVariableUse(method, sf, StaticFieldUse.Write); return true; } } if (((Stmt) u).containsInvokeExpr()) for (Iterator<Edge> edgeIt = Scene.v().getCallGraph().edgesOutOf(u); edgeIt.hasNext(); ) { Edge e = edgeIt.next(); if (isStaticFieldWrite(e.getTgt().method(), variable, runList)); return true; } } // Variable is not read registerStaticVariableUse(method, variable, StaticFieldUse.Unwrite); return false; }
Example 20
Source File: AndroidSourceSinkManager.java From JAADAS with GNU General Public License v3.0 | 4 votes |
/** * Finds the last assignment to the given local representing a resource ID * by searching upwards from the given statement * * @param stmt * The statement from which to look backwards * @param local * The variable for which to look for assignments * @return The last value assigned to the given variable */ private Integer findLastResIDAssignment(Stmt stmt, Local local, BiDiInterproceduralCFG<Unit, SootMethod> cfg, Set<Stmt> doneSet) { if (!doneSet.add(stmt)) return null; // If this is an assign statement, we need to check whether it changes // the variable we're looking for if (stmt instanceof AssignStmt) { AssignStmt assign = (AssignStmt) stmt; if (assign.getLeftOp() == local) { // ok, now find the new value from the right side if (assign.getRightOp() instanceof IntConstant) return ((IntConstant) assign.getRightOp()).value; else if (assign.getRightOp() instanceof FieldRef) { SootField field = ((FieldRef) assign.getRightOp()).getField(); for (Tag tag : field.getTags()) if (tag instanceof IntegerConstantValueTag) return ((IntegerConstantValueTag) tag).getIntValue(); else System.err.println("Constant " + field + " was of unexpected type"); } else if (assign.getRightOp() instanceof InvokeExpr) { InvokeExpr inv = (InvokeExpr) assign.getRightOp(); if (inv.getMethod().getName().equals("getIdentifier") && inv.getMethod().getDeclaringClass().getName().equals("android.content.res.Resources") && this.resourcePackages != null) { // The right side of the assignment is a call into the // well-known // Android API method for resource handling if (inv.getArgCount() != 3) { System.err.println("Invalid parameter count for call to getIdentifier"); return null; } // Find the parameter values String resName = ""; String resID = ""; String packageName = ""; // In the trivial case, these values are constants if (inv.getArg(0) instanceof StringConstant) resName = ((StringConstant) inv.getArg(0)).value; if (inv.getArg(1) instanceof StringConstant) resID = ((StringConstant) inv.getArg(1)).value; if (inv.getArg(2) instanceof StringConstant) packageName = ((StringConstant) inv.getArg(2)).value; else if (inv.getArg(2) instanceof Local) packageName = findLastStringAssignment(stmt, (Local) inv.getArg(2), cfg); else { System.err.println("Unknown parameter type in call to getIdentifier"); return null; } // Find the resource ARSCFileParser.AbstractResource res = findResource(resName, resID, packageName); if (res != null) return res.getResourceID(); } } } } // Continue the search upwards for (Unit pred : cfg.getPredsOf(stmt)) { if (!(pred instanceof Stmt)) continue; Integer lastAssignment = findLastResIDAssignment((Stmt) pred, local, cfg, doneSet); if (lastAssignment != null) return lastAssignment; } return null; }