int pc = getPC(); if (tryBlocks.get(pc)) { ScopeBlock sb = new ScopeBlock(pc, findCatchHandlerFor(pc)); sb.setTry(); rootScopeBlock.addChild(sb); sawStore(seen, pc); } else if (OpcodeUtils.isLoad(seen)) { sawLoad(seen, pc); } else if ((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) { uo = sawInstanceCall(pc); } else if ((seen == INVOKESTATIC) || (seen == INVOKESPECIAL)) { uo = sawStaticCall(); } else if (((seen >= IFEQ) && (seen <= GOTO)) || (seen == IFNULL) || (seen == IFNONNULL) || (seen == GOTO_W)) { sawBranch(seen, pc); } else if (seen == GETFIELD) { uo = sawGetField(); } else if (seen == PUTFIELD) { sawPutField(pc); } else if (seen == IINC) { sawIINC(pc); } else if ((seen == TABLESWITCH) || (seen == LOOKUPSWITCH)) { sawSwitch(pc); } else if (seen == MONITORENTER) { sawMonitorEnter(pc); } else if (seen == MONITOREXIT) { sawMonitorExit(pc);
/** * processes a instance method call to see if that call is modifies state or is otherwise'risky', if so mark the variable(s) associated with the caller as * not reportable * * @param pc * the current program counter * * @return a user object to place on the return value's OpcodeStack item */ @Nullable private UserObject sawInstanceCall(int pc) { String signature = getSigConstantOperand(); String name = getNameConstantOperand(); // this is kind of a wart. there should be a more seamless way to check this if ("wasNull".equals(getNameConstantOperand()) && SignatureBuilder.SIG_VOID_TO_BOOLEAN.equals(signature)) { dontReport = true; } if (signature.endsWith(Values.SIG_VOID)) { return null; } MethodInfo mi = Statistics.getStatistics().getMethodStatistics(getClassConstantOperand(), name, signature); UserObject uo = new UserObject(getCallingObject(), mi.getModifiesState() || isRiskyMethodCall()); if (uo.caller != null) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.removeByAssoc(uo.caller); } } return uo; }
/** * processes a monitor exit to set the end of the already created scope block * * @param pc * the current program counter */ private void sawMonitorExit(int pc) { if (!monitorSyncPCs.isEmpty()) { ScopeBlock sb = findSynchronizedScopeBlock(rootScopeBlock, monitorSyncPCs.get(0).intValue()); if (sb != null) { sb.setFinish(pc); } monitorSyncPCs.remove(monitorSyncPCs.size() - 1); } }
public boolean isRiskyMethodCall() { String clsName = getClassConstantOperand(); if (dangerousAssignmentClassSources.contains(clsName)) { return true; } FQMethod key = new FQMethod(clsName, getNameConstantOperand(), getSigConstantOperand()); if (dangerousAssignmentMethodSources.contains(key)) { return true; } String sig = key.toFQMethodSignature(); for (Pattern p : dangerousAssignmentMethodPatterns) { Matcher m = p.matcher(sig); if (m.matches()) { return true; } } return false; }
int target = getBranchTarget(); if (target > pc) { if ((seen == GOTO) || (seen == GOTO_W)) { int nextPC = getNextPC(); if (!switchTargets.get(nextPC)) { ScopeBlock sb = findScopeBlockWithTarget(rootScopeBlock, pc, nextPC); if (sb == null) { sb = new ScopeBlock(pc, target); ScopeBlock sb = findScopeBlockWithTarget(rootScopeBlock, pc, target); if ((sb != null) && !sb.isLoop() && !sb.isCase() && !sb.hasChildren()) { if (sb.isGoto()) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { ScopeBlock parentSB = sb.getParent(); ScopeBlock previous = findPreviousSiblingScopeBlock(sb); if ((previous != null) && (previous.getStart() >= target)) { sb = previous;
ScopeBlock catchSB = findScopeBlock(rootScopeBlock, pc + 1); if ((catchSB != null) && (catchSB.getStart() < pc)) { ScopeBlock sb = new ScopeBlock(pc, catchSB.getFinish()); catchSB.setFinish(getPC() - 1); rootScopeBlock.addChild(sb); } else if (sawNull) { ignoreRegs.set(reg); } else if (isRiskyStoreClass(reg)) { ignoreRegs.set(reg); ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { UserObject assoc = null; ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.markFieldAssociatedWrites(reg);
/** * creates a new scope block for each case statement * * @param pc * the current program counter */ private void sawSwitch(int pc) { int[] offsets = getSwitchOffsets(); List<Integer> targets = new ArrayList<>(offsets.length); for (int offset : offsets) { targets.add(Integer.valueOf(offset + pc)); } Integer defOffset = Integer.valueOf(getDefaultSwitchOffset() + pc); if (!targets.contains(defOffset)) { targets.add(defOffset); } Collections.sort(targets); Integer lastTarget = targets.get(0); for (int i = 1; i < targets.size(); i++) { Integer nextTarget = targets.get(i); ScopeBlock sb = new ScopeBlock(lastTarget.intValue(), nextTarget.intValue()); sb.setCase(); rootScopeBlock.addChild(sb); lastTarget = nextTarget; } for (Integer target : targets) { switchTargets.set(target.intValue()); } }
int reg = getRegisterOperand(); if (!ignoreRegs.get(reg)) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addLoad(reg, pc); ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addStore(reg, pc, null);
/** * processes a register store by updating the appropriate scope block to mark this register as being read in the block * * @param seen * the currently parsed opcode * @param pc * the current program counter */ private void sawLoad(int seen, int pc) { int reg = RegisterUtils.getLoadReg(this, seen); if (!ignoreRegs.get(reg)) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addLoad(reg, pc); } else { ignoreRegs.set(reg); } } }
/** * in some cases the java compiler synthesizes variable for its own purposes. Hopefully when it does this these, can not be found in the localvariable * table. If we find this to be the case, don't report them * * @param reg * the register to check * * @return if reg variable appears in the local variable table */ private boolean appearsToBeUserRegister(int reg) { LocalVariableTable lvt = getMethod().getLocalVariableTable(); if (lvt == null) { return false; } LocalVariable lv = lvt.getLocalVariable(reg); return lv != null; }
/** * returns an existing scope block that has the same target as the one looked for * * @param sb * the scope block to start with * @param start * the current pc * @param target * the target to look for * * @return the scope block found or null */ private ScopeBlock findScopeBlockWithTarget(ScopeBlock sb, int start, int target) { ScopeBlock parentBlock = null; if ((sb.startLocation < start) && (sb.finishLocation >= start) && ((sb.finishLocation <= target) || (sb.isGoto() && !sb.isLoop()))) { parentBlock = sb; } if (sb.children != null) { for (ScopeBlock child : sb.children) { ScopeBlock targetBlock = findScopeBlockWithTarget(child, start, target); if (targetBlock != null) { return targetBlock; } } } return parentBlock; }
int target = getBranchTarget(); if (target > pc) { if ((seen == Const.GOTO) || (seen == Const.GOTO_W)) { int nextPC = getNextPC(); if (!switchTargets.get(nextPC)) { ScopeBlock sb = findScopeBlockWithTarget(rootScopeBlock, pc, nextPC); if (sb == null) { sb = new ScopeBlock(pc, target); ScopeBlock sb = findScopeBlockWithTarget(rootScopeBlock, pc, target); if ((sb != null) && !sb.isLoop() && !sb.isCase() && !sb.hasChildren()) { if (sb.isGoto()) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { ScopeBlock parentSB = sb.getParent(); ScopeBlock previous = findPreviousSiblingScopeBlock(sb); if ((previous != null) && (previous.getStart() >= target)) { sb = previous;
public boolean isRiskyMethodCall() { String clsName = getClassConstantOperand(); if (dangerousAssignmentClassSources.contains(clsName)) { return true; } FQMethod key = new FQMethod(clsName, getNameConstantOperand(), getSigConstantOperand()); if (dangerousAssignmentMethodSources.contains(key)) { return true; } String sig = key.toFQMethodSignature(); for (Pattern p : dangerousAssignmentMethodPatterns) { Matcher m = p.matcher(sig); if (m.matches()) { return true; } } return false; }
ScopeBlock catchSB = findScopeBlock(rootScopeBlock, pc + 1); if ((catchSB != null) && (catchSB.getStart() < pc)) { ScopeBlock sb = new ScopeBlock(pc, catchSB.getFinish()); catchSB.setFinish(getPC() - 1); rootScopeBlock.addChild(sb); } else if (sawNull) { ignoreRegs.set(reg); } else if (isRiskyStoreClass(reg)) { ignoreRegs.set(reg); ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { UserObject assoc = null; ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.markFieldAssociatedWrites(reg);
/** * creates a new scope block for each case statement * * @param pc * the current program counter */ private void sawSwitch(int pc) { int[] offsets = getSwitchOffsets(); List<Integer> targets = new ArrayList<>(offsets.length); for (int offset : offsets) { targets.add(Integer.valueOf(offset + pc)); } Integer defOffset = Integer.valueOf(getDefaultSwitchOffset() + pc); if (!targets.contains(defOffset)) { targets.add(defOffset); } Collections.sort(targets); Integer lastTarget = targets.get(0); for (int i = 1; i < targets.size(); i++) { Integer nextTarget = targets.get(i); ScopeBlock sb = new ScopeBlock(lastTarget.intValue(), nextTarget.intValue()); sb.setCase(); rootScopeBlock.addChild(sb); lastTarget = nextTarget; } for (Integer target : targets) { switchTargets.set(target.intValue()); } }
int reg = getRegisterOperand(); if (!ignoreRegs.get(reg)) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addLoad(reg, pc); ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addStore(reg, pc, null);
/** * processes a register store by updating the appropriate scope block to mark this register as being read in the block * * @param seen * the currently parsed opcode * @param pc * the current program counter */ private void sawLoad(int seen, int pc) { int reg = RegisterUtils.getLoadReg(this, seen); if (!ignoreRegs.get(reg)) { ScopeBlock sb = findScopeBlock(rootScopeBlock, pc); if (sb != null) { sb.addLoad(reg, pc); } else { ignoreRegs.set(reg); } } }
/** * in some cases the java compiler synthesizes variable for its own purposes. Hopefully when it does this these, can not be found in the localvariable * table. If we find this to be the case, don't report them * * @param reg * the register to check * * @return if reg variable appears in the local variable table */ private boolean appearsToBeUserRegister(int reg) { LocalVariableTable lvt = getMethod().getLocalVariableTable(); if (lvt == null) { return false; } LocalVariable lv = lvt.getLocalVariable(reg); return lv != null; }