private boolean isPreparedStatementDatabaseSink(Instruction ins, ConstantPoolGen cpg) { if (!(ins instanceof INVOKEINTERFACE)) { return false; } INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins; String methodName = invoke.getMethodName(cpg); String methodSignature = invoke.getSignature(cpg); String interfaceName = invoke.getClassName(cpg); if (methodName.equals("prepareStatement") && interfaceName.equals("java.sql.Connection") && methodSignature.startsWith("(Ljava/lang/String;")) { return true; } return false; }
private boolean isExecuteDatabaseSink(InvokeInstruction ins, ConstantPoolGen cpg) { if (!(ins instanceof INVOKEINTERFACE)) { return false; } INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins; String methodName = invoke.getMethodName(cpg); String methodSignature = invoke.getSignature(cpg); String interfaceName = invoke.getClassName(cpg); if (methodName.startsWith("execute") && interfaceName.equals("java.sql.Statement") && methodSignature.startsWith("(Ljava/lang/String;")) { return true; } return false; }
public boolean isAssertionHandle(InstructionHandle handle, ConstantPoolGen cpg) { Instruction ins = handle.getInstruction(); if (isAssertionInstruction(ins, cpg)) return true; if (ins instanceof SIPUSH) { int v = ((SIPUSH) ins).getValue().intValue(); if (v == 500) { Instruction next = handle.getNext().getInstruction(); if (next instanceof INVOKEINTERFACE) { INVOKEINTERFACE iInterface = (INVOKEINTERFACE) next; String className = iInterface.getClassName(cpg); String fieldName = iInterface.getMethodName(cpg); if (className.equals("javax.servlet.http.HttpServletResponse") && fieldName.equals("setStatus")) return true; } } } return false; }
private void analyzeMethod(Method m, ClassContext classContext) throws CFGBuilderException, DataflowAnalysisException { ConstantPoolGen cpg = classContext.getConstantPoolGen(); CFG cfg = classContext.getCFG(m); for (Iterator<Location> i = cfg.locationIterator(); i.hasNext(); ) { Location location = i.next(); Instruction inst = location.getHandle().getInstruction(); if (inst instanceof INVOKEINTERFACE) { INVOKEINTERFACE invoke = (INVOKEINTERFACE) inst; String methodName = invoke.getMethodName(cpg); String className = invoke.getClassName(cpg); if (className.equals("javax.servlet.http.HttpServletResponse") && (methodName.equals("addHeader") || methodName.equals("setHeader"))) { LDC ldc = ByteCode.getPrevInstruction(location.getHandle().getPrev(), LDC.class); if (ldc != null) { String headerValue = ByteCode.getConstantLDC(location.getHandle().getPrev(), cpg, String.class); if ("Access-Control-Allow-Origin".equalsIgnoreCase((String)ldc.getValue(cpg)) && (headerValue.contains("*") || "null".equalsIgnoreCase(headerValue))) { JavaClass clz = classContext.getJavaClass(); bugReporter.reportBug(new BugInstance(this, PERMISSIVE_CORS, Priorities.HIGH_PRIORITY) .addClass(clz) .addMethod(clz, m) .addSourceLine(classContext, m, location)); } } } } } }
public boolean isStreamClose(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg, ResourceValueFrame frame, RepositoryLookupFailureCallback lookupFailureCallback) { if (!mightCloseStream(basicBlock, handle, cpg)) return false; Instruction ins = handle.getInstruction(); if ((ins instanceof INVOKEVIRTUAL) || (ins instanceof INVOKEINTERFACE)) { // Does this instruction close the stream? InvokeInstruction inv = (InvokeInstruction) ins; if (!frame.isValid() || !getInstanceValue(frame, inv, cpg).isInstance()) return false; // It's a close if the invoked class is any subtype of the stream // base class. // (Basically, we may not see the exact original stream class, // even though it's the same instance.) try { String classClosed = inv.getClassName(cpg); return Hierarchy.isSubtype(classClosed, streamBase) || Hierarchy.isSubtype(streamBase, classClosed) ; } catch (ClassNotFoundException e) { lookupFailureCallback.reportMissingClass(e); return false; } } return false; }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { if (returnsString(obj)) handleInstanceMethod(obj); else super.visitINVOKEINTERFACE(obj); }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { // Don't know what this method invocation is doing. // Kill all loads. if (obj.getMethodName(cpg).equals("lock")) getFrame().killAllLoads(); else killLoadsOfObjectsPassed(obj); handleNormalInstruction(obj); }
/** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINVOKEINTERFACE(INVOKEINTERFACE o){ try { // INVOKEINTERFACE is a LoadClass; the Class where the referenced method is declared in, // is therefore resolved/verified. // INVOKEINTERFACE is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. String classname = o.getClassName(cpg); JavaClass jc = Repository.lookupClass(classname); Method[] ms = jc.getMethods(); Method m = null; for (int i=0; i<ms.length; i++){ if ( (ms[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ m = ms[i]; break; } } if (m == null){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature '"+o.getSignature(cpg)+"' not found in class '"+jc.getClassName()+"'. The native verifier does allow the method to be declared in some superinterface, which the Java Virtual Machine Specification, Second Edition does not."); } if (jc.isClass()){ constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is a class, but not an interface as expected."); } } catch (ClassNotFoundException e) { // FIXME: maybe not the best way to handle this throw new AssertionViolatedException("Missing class: " + e.toString()); } }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { visitInvoke(obj); }
public static boolean mightCloseStream(BasicBlock basicBlock, InstructionHandle handle, ConstantPoolGen cpg) { Instruction ins = handle.getInstruction(); if ((ins instanceof INVOKEVIRTUAL) || (ins instanceof INVOKEINTERFACE)) { // Does this instruction close the stream? InvokeInstruction inv = (InvokeInstruction) ins; // It's a close if the invoked class is any subtype of the stream // base class. // (Basically, we may not see the exact original stream class, // even though it's the same instance.) return inv.getName(cpg).equals("close") && inv.getSignature(cpg).equals("()V"); } return false; }
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { MethodGen methodGen = classContext.getMethodGen(method); if (methodGen == null) return; BitSet bytecodeSet = classContext.getBytecodeSet(method); if (bytecodeSet == null) return; // We don't adequately model instanceof interfaces yet if (bytecodeSet.get(Constants.INSTANCEOF) || bytecodeSet.get(Constants.CHECKCAST)) return; CFG cfg = classContext.getCFG(method); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); ConstantPoolGen cpg = classContext.getConstantPoolGen(); String sourceFile = classContext.getJavaClass().getSourceFileName(); if (DEBUG) { String methodName = methodGen.getClassName() + "." + methodGen.getName(); System.out.println("Checking " + methodName); } for (Iterator<Location> i = cfg.locationIterator(); i.hasNext();) { Location location = i.next(); InstructionHandle handle = location.getHandle(); Instruction ins = handle.getInstruction(); if (!(ins instanceof INVOKEINTERFACE)) continue; INVOKEINTERFACE invoke = (INVOKEINTERFACE) ins; String mName = invoke.getMethodName(cpg); if (!mName.equals("setAttribute")) continue; String cName = invoke.getClassName(cpg); if (!cName.equals("javax.servlet.http.HttpSession")) continue; TypeFrame frame = typeDataflow.getFactAtLocation(location); if (!frame.isValid()) { // This basic block is probably dead continue; } Type operandType = frame.getTopValue(); if (operandType.equals(TopType.instance())) { // unreachable continue; } if (!(operandType instanceof ReferenceType)) { // Shouldn't happen - illegal bytecode continue; } ReferenceType refType = (ReferenceType) operandType; if (refType.equals(NullType.instance())) { continue; } try { double isSerializable = DeepSubtypeAnalysis.isDeepSerializable(refType); if (isSerializable < 0.9) { SourceLineAnnotation sourceLineAnnotation = SourceLineAnnotation.fromVisitedInstruction(classContext, methodGen, sourceFile, handle); ReferenceType problem = DeepSubtypeAnalysis.getLeastSerializableTypeComponent(refType); bugAccumulator.accumulateBug(new BugInstance(this, "J2EE_STORE_OF_NON_SERIALIZABLE_OBJECT_INTO_SESSION", isSerializable < 0.15 ? HIGH_PRIORITY : isSerializable > 0.5 ? LOW_PRIORITY : NORMAL_PRIORITY) .addClassAndMethod(methodGen, sourceFile).addType(problem).describe(TypeAnnotation.FOUND_ROLE), sourceLineAnnotation); } } catch (ClassNotFoundException e) { // ignore } } }
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { if (method.isSynthetic() || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) return; CFG cfg = classContext.getCFG(method); ConstantPoolGen cpg = classContext.getConstantPoolGen(); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext();) { BasicBlock basicBlock = i.next(); // Check if it's a method invocation. if (!basicBlock.isExceptionThrower()) continue; InstructionHandle thrower = basicBlock.getExceptionThrower(); Instruction ins = thrower.getInstruction(); if (!(ins instanceof InvokeInstruction)) continue; InvokeInstruction inv = (InvokeInstruction) ins; boolean foundThrower = false; boolean foundNonThrower = false; if (inv instanceof INVOKEINTERFACE) continue; String className = inv.getClassName(cpg); Location loc = new Location(thrower, basicBlock); TypeFrame typeFrame = typeDataflow.getFactAtLocation(loc); XMethod primaryXMethod = XFactory.createXMethod(inv, cpg); // if (primaryXMethod.isAbstract()) continue; Set<XMethod> targetSet = null; try { if (className.startsWith("[")) continue; String methodSig = inv.getSignature(cpg); if (!methodSig.endsWith("V")) continue; targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg); for (XMethod xMethod : targetSet) { if (DEBUG) System.out.println("\tFound " + xMethod); boolean isUnconditionalThrower = xMethod.isUnconditionalThrower() && !xMethod.isUnsupported() && !xMethod.isSynthetic(); if (isUnconditionalThrower) { foundThrower = true; if (DEBUG) System.out.println("Found thrower"); } else { foundNonThrower = true; if (DEBUG) System.out.println("Found non thrower"); } } } catch (ClassNotFoundException e) { analysisContext.getLookupFailureCallback().reportMissingClass(e); } boolean newResult = foundThrower && !foundNonThrower; if (newResult) bugReporter.reportBug(new BugInstance(this, "TESTING", Priorities.NORMAL_PRIORITY) .addClassAndMethod(classContext.getJavaClass(), method) .addString("Call to method that always throws Exception").addMethod(primaryXMethod) .describe(MethodAnnotation.METHOD_CALLED).addSourceLine(classContext, method, loc)); } }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE inv) { handleInvoke(inv); }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE obj) { handleInvoke(obj); }
private void analyzeMethod(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { if (BCELUtil.isSynthetic(method) || (method.getAccessFlags() & Constants.ACC_BRIDGE) == Constants.ACC_BRIDGE) return; CFG cfg = classContext.getCFG(method); ConstantPoolGen cpg = classContext.getConstantPoolGen(); TypeDataflow typeDataflow = classContext.getTypeDataflow(method); for (Iterator<BasicBlock> i = cfg.blockIterator(); i.hasNext();) { BasicBlock basicBlock = i.next(); // Check if it's a method invocation. if (!basicBlock.isExceptionThrower()) continue; InstructionHandle thrower = basicBlock.getExceptionThrower(); Instruction ins = thrower.getInstruction(); if (!(ins instanceof InvokeInstruction)) continue; InvokeInstruction inv = (InvokeInstruction) ins; boolean foundThrower = false; boolean foundNonThrower = false; if (inv instanceof INVOKEINTERFACE) continue; String className = inv.getClassName(cpg); Location loc = new Location(thrower, basicBlock); TypeFrame typeFrame = typeDataflow.getFactAtLocation(loc); XMethod primaryXMethod = XFactory.createXMethod(inv, cpg); // if (primaryXMethod.isAbstract()) continue; Set<XMethod> targetSet = null; try { if (className.startsWith("[")) continue; String methodSig = inv.getSignature(cpg); if (!methodSig.endsWith("V")) continue; targetSet = Hierarchy2.resolveMethodCallTargets(inv, typeFrame, cpg); for (XMethod xMethod : targetSet) { if (DEBUG) System.out.println("\tFound " + xMethod); boolean isUnconditionalThrower = xMethod.isUnconditionalThrower() && !xMethod.isUnsupported() && !xMethod.isSynthetic(); if (isUnconditionalThrower) { foundThrower = true; if (DEBUG) System.out.println("Found thrower"); } else { foundNonThrower = true; if (DEBUG) System.out.println("Found non thrower"); } } } catch (ClassNotFoundException e) { analysisContext.getLookupFailureCallback().reportMissingClass(e); } boolean newResult = foundThrower && !foundNonThrower; if (newResult) bugReporter.reportBug(new BugInstance(this, "TESTING", Priorities.NORMAL_PRIORITY) .addClassAndMethod(classContext.getJavaClass(), method) .addString("Call to method that always throws Exception").addMethod(primaryXMethod) .describe(MethodAnnotation.METHOD_CALLED).addSourceLine(classContext, method, loc)); } }
@Override public void visitINVOKEINTERFACE(INVOKEINTERFACE invoke) { addMethodCall(method, invoke, constantPoolGen); }