/** * Checks a given class. * * @param cr * a <code>ClassReader</code> that contains bytecode for the * analysis. * @param loader * a <code>ClassLoader</code> which will be used to load * referenced classes. This is useful if you are verifiying * multiple interdependent classes. * @param dump * true if bytecode should be printed out not only when errors * are found. * @param pw * write where results going to be printed */ public static void verify(final ClassReader cr, final ClassLoader loader, final boolean dump, final PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); Type syperType = cn.superName == null ? null : Type .getObjectType(cn.superName); List<MethodNode> methods = cn.methods; List<Type> interfaces = new ArrayList<Type>(); for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) { interfaces.add(Type.getObjectType(i.next())); } for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); SimpleVerifier verifier = new SimpleVerifier( Type.getObjectType(cn.name), syperType, interfaces, (cn.access & Opcodes.ACC_INTERFACE) != 0); Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier); if (loader != null) { verifier.setClassLoader(loader); } try { a.analyze(cn.name, method); if (!dump) { continue; } } catch (Exception e) { e.printStackTrace(pw); } printAnalyzerResult(method, a, pw); } pw.flush(); }
/** * Checks a given class. * * @param cr * a <code>ClassReader</code> that contains bytecode for the * analysis. * @param loader * a <code>ClassLoader</code> which will be used to load * referenced classes. This is useful if you are verifiying * multiple interdependent classes. * @param dump * true if bytecode should be printed out not only when errors * are found. * @param pw * write where results going to be printed */ public static void verify(final ClassReader cr, final ClassLoader loader, final boolean dump, final PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); Type syperType = cn.superName == null ? null : Type .getObjectType(cn.superName); List<MethodNode> methods = cn.methods; List<Type> interfaces = new ArrayList<Type>(); for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) { interfaces.add(Type.getObjectType(i.next().toString())); } for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); SimpleVerifier verifier = new SimpleVerifier( Type.getObjectType(cn.name), syperType, interfaces, (cn.access & Opcodes.ACC_INTERFACE) != 0); Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier); if (loader != null) { verifier.setClassLoader(loader); } try { a.analyze(cn.name, method); if (!dump) { continue; } } catch (Exception e) { e.printStackTrace(pw); } printAnalyzerResult(method, a, pw); } pw.flush(); }
public static void verifyMethodIntegrity(String ownerInternalName, MethodNode method) { try { new Analyzer(new SimpleVerifier()).analyze(ownerInternalName, method); } catch (AnalyzerException e) { throw new RuntimeException( "Integrity error in method '" + method.name + "' of type '" + ownerInternalName + "': ", e); } }
public static void verifyMethodIntegrity(final String ownerInternalName, final MethodNode method) { try { new Analyzer(new SimpleVerifier()).analyze(ownerInternalName, method); } catch (AnalyzerException e) { throw new RuntimeException( "Integrity error in method '" + method.name + "' of type '" + ownerInternalName + "': ", e); } }
/** * Checks a given class * * @param cr a <code>ClassReader</code> that contains bytecode for the analysis. * @param dump true if bytecode should be printed out not only when errors are found. * @param pw write where results going to be printed */ public static void verify(ClassReader cr, boolean dump, PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn), true); List methods = cn.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = (MethodNode) methods.get(i); if (method.instructions.size() > 0) { Analyzer a = new Analyzer(new SimpleVerifier(Type.getType("L" + cn.name + ";"), Type.getType("L" + cn.superName + ";"), (cn.access & Opcodes.ACC_INTERFACE) != 0)); try { a.analyze(cn.name, method); if (!dump) { continue; } } catch (Exception e) { e.printStackTrace(); } Frame[] frames = a.getFrames(); TraceMethodVisitor mv = new TraceMethodVisitor(); pw.println(method.name + method.desc); for (int j = 0; j < method.instructions.size(); ++j) { ((AbstractInsnNode) method.instructions.get(j)).accept(mv); StringBuffer s = new StringBuffer(); Frame f = frames[j]; if (f == null) { s.append('?'); } else { for (int k = 0; k < f.getLocals(); ++k) { s.append(getShortName(f.getLocal(k).toString())) .append(' '); } s.append(" : "); for (int k = 0; k < f.getStackSize(); ++k) { s.append(getShortName(f.getStack(k).toString())) .append(' '); } } while (s.length() < method.maxStack + method.maxLocals + 1) { s.append(' '); } pw.print(Integer.toString(j + 100000).substring(1)); pw.print(" " + s + " : " + mv.buf); // mv.text.get(j)); } for (int j = 0; j < method.tryCatchBlocks.size(); ++j) { ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv); pw.print(" " + mv.buf); } pw.println(); } } }
private boolean readClass(String clazz) throws IOException { ClassReader cr = new ClassReader(new FileInputStream(clazz)); ClassNode ca = new ClassNode() { public void visitEnd() { //accept(cv); } }; cr.accept(new CheckClassAdapter(ca), ClassWriter.COMPUTE_MAXS); boolean failed = false; List methods = ca.methods; for (int i = 0; i < methods.size(); ++i) { MethodNode method = (MethodNode) methods.get(i); if (method.instructions.size() > 0) { Analyzer a = new Analyzer(new SimpleVerifier()); try { a.analyze(ca.name, method); continue; } catch (Exception e) { e.printStackTrace(); } if (!failed) { failed = true; log("verifying of class " + clazz + " failed"); } if (verbose) log(method.name + method.desc); TraceMethodVisitor mv = new TraceMethodVisitor(null); /*= new TraceMethodVisitor(null) { public void visitMaxs(int maxStack, int maxLocals) { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < text.size(); ++i) { String s = frames[i] == null ? "null" : frames[i].toString(); while (s.length() < maxStack + maxLocals + 1) { s += " "; } buffer.append(Integer.toString(i + 100000).substring(1)); buffer.append(" "); buffer.append(s); buffer.append(" : "); buffer.append(text.get(i)); } if (verbose) log(buffer.toString()); } };*/ for (int j = 0; j < method.instructions.size(); ++j) { Object insn = method.instructions.get(j); if (insn instanceof AbstractInsnNode) { ((AbstractInsnNode) insn).accept(mv); } else { mv.visitLabel((Label) insn); } } mv.visitMaxs(method.maxStack, method.maxLocals); } } return !failed; }
public void visitEnd() { if (instructions.size() == 0 || labels.size() == 0) { accept(mv); return; } /* * { TraceMethodVisitor mv = new TraceMethodVisitor(); * System.err.println(name + desc); for (int j = 0; j < * instructions.size(); ++j) { ((AbstractInsnNode) * instructions.get(j)).accept(mv); System.err.print(" " + * mv.text.get(j)); // mv.text.get(j)); } System.err.println(); } */ this.stackRecorderVar = maxLocals; try { moveNew(); // analyzer = new Analyzer(new BasicVerifier()); analyzer = new Analyzer(new SimpleVerifier() { protected Class<?> getClass(Type t) { try { return Class.forName(t.getClassName()); } catch (ClassNotFoundException e) { try { return ContinuationClassLoader.getInstance() .loadClass(t.getClassName()); } catch (ClassNotFoundException ee) { throw new RuntimeException(ee.toString()); } // throw new RuntimeException(e.toString()); } } }) { protected Frame newFrame(final int nLocals, final int nStack) { return new MonitoringFrame(nLocals, nStack); } protected Frame newFrame(final Frame src) { return new MonitoringFrame(src); } public Frame[] analyze(final String owner, final MethodNode m) throws AnalyzerException { // System.out.println("Analyze: "+owner+"|"+m.name+"|"+m.signature+"|"+m.tryCatchBlocks); final Frame[] frames = super.analyze(owner, m); for (int i = 0; i < m.instructions.size(); i++) { int opcode = m.instructions.get(i).getOpcode(); if (opcode == MONITORENTER || opcode == MONITOREXIT) { // System.out.println(i); } } return frames; } }; analyzer.analyze(className, this); accept(new ContinuationMethodAdapter(this)); /* * { TraceMethodVisitor mv = new TraceMethodVisitor(); * System.err.println("================="); * * System.err.println(name + desc); for (int j = 0; j < * instructions.size(); ++j) { ((AbstractInsnNode) * instructions.get(j)).accept(mv); System.err.print(" " + * mv.text.get(j)); // mv.text.get(j)); } System.err.println(); } */ } catch (AnalyzerException ex) { // TODO log the error or fail? ex.printStackTrace(); accept(mv); } }
/** * Checks a given class. * * @param cr a <code>ClassReader</code> that contains bytecode for the * analysis. * @param loader a <code>ClassLoader</code> which will be used to load * referenced classes. This is useful if you are verifiying multiple * interdependent classes. * @param dump true if bytecode should be printed out not only when errors * are found. * @param pw write where results going to be printed */ public static void verify( final ClassReader cr, final ClassLoader loader, final boolean dump, final PrintWriter pw) { ClassNode cn = new ClassNode(); cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG); Type syperType = cn.superName == null ? null : Type.getObjectType(cn.superName); List<MethodNode> methods = cn.methods; List<Type> interfaces = new ArrayList<Type>(); for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) { interfaces.add(Type.getObjectType(i.next().toString())); } for (int i = 0; i < methods.size(); ++i) { MethodNode method = methods.get(i); SimpleVerifier verifier = new SimpleVerifier(Type.getObjectType(cn.name), syperType, interfaces, (cn.access & Opcodes.ACC_INTERFACE) != 0); Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier); if (loader != null) { verifier.setClassLoader(loader); } try { a.analyze(cn.name, method); if (!dump) { continue; } } catch (Exception e) { e.printStackTrace(pw); } printAnalyzerResult(method, a, pw); } pw.flush(); }