Commit 3b89bfdc authored by ebruneton's avatar ebruneton

"fixed" bug #315135

parent 7241093f
......@@ -61,34 +61,34 @@ import org.objectweb.asm.tree.analysis.Frame;
* <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
* "i", "D", null)</tt>
* will <i>not</i> be detected by this class adapter.
*
*
* <p><code>CheckClassAdapter</code> can be also used to verify bytecode
* transformations in order to make sure transformed bytecode is sane. For
* example:
*
*
* <pre>
* InputStream is = ...; // get bytes for the source class
* ClassReader cr = new ClassReader(is);
* ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
* ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
* cr.accept(cv, 0);
*
*
* StringWriter sw = new StringWriter();
* PrintWriter pw = new PrintWriter(sw);
* CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
* assertTrue(sw.toString(), sw.toString().length()==0);
* </pre>
*
*
* Above code runs transformed bytecode trough the
* <code>CheckClassAdapter</code>. It won't be exactly the same verification
* as JVM does, but it run data flow analysis for the code of each method and
* checks that expectations are met for each method instruction.
*
*
* <p>If method bytecode has errors, assertion text will show the erroneous
* instruction number and dump of the failed method with information about
* locals and stack slot for each instruction. For example (format is -
* insnNumber locals : stack):
*
*
* <pre>
* org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
* at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
......@@ -101,23 +101,23 @@ import org.objectweb.asm.tree.analysis.Frame;
* ISTORE 2
* 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
* ...
*
* 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
*
* 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
* ILOAD 1
* 00072 <b>?</b>
* 00072 <b>?</b>
* INVOKESPECIAL java/lang/Integer.<init> (I)V
* ...
* </pre>
*
*
* In the above output you can see that variable 1 loaded by
* <code>ILOAD 1</code> instruction at position <code>00071</code> is not
* initialized. You can also see that at the beginning of the method (code
* inserted by the transformation) variable 2 is initialized.
*
*
* <p>Note that when used like that, <code>CheckClassAdapter.verify()</code>
* can trigger additional class loading, because it is using
* <code>SimpleVerifier</code>.
*
*
* @author Eric Bruneton
*/
public class CheckClassAdapter extends ClassAdapter {
......@@ -141,7 +141,7 @@ public class CheckClassAdapter extends ClassAdapter {
* <tt>true</tt> if the visitEnd method has been called.
*/
private boolean end;
/**
* The already visited labels. This map associate Integer values to Label
* keys.
......@@ -152,13 +152,13 @@ public class CheckClassAdapter extends ClassAdapter {
* <tt>true</tt> if the method code must be checked with a BasicVerifier.
*/
private boolean checkDataFlow;
/**
* Checks a given class. <p> Usage: CheckClassAdapter &lt;fully qualified
* class name or class file name&gt;
*
*
* @param args the command line arguments.
*
*
* @throws Exception if the class cannot be found, or if an IO exception
* occurs.
*/
......@@ -181,7 +181,7 @@ public class CheckClassAdapter extends ClassAdapter {
/**
* 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
......@@ -232,10 +232,10 @@ public class CheckClassAdapter extends ClassAdapter {
}
pw.flush();
}
/**
* 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
......@@ -249,7 +249,7 @@ public class CheckClassAdapter extends ClassAdapter {
{
verify(cr, null, dump, pw);
}
static void printAnalyzerResult(
MethodNode method,
Analyzer a,
......@@ -301,7 +301,7 @@ public class CheckClassAdapter extends ClassAdapter {
/**
* Constructs a new {@link CheckClassAdapter}.
*
*
* @param cv the class visitor to which this adapter must delegate calls.
*/
public CheckClassAdapter(final ClassVisitor cv) {
......@@ -310,11 +310,12 @@ public class CheckClassAdapter extends ClassAdapter {
/**
* Constructs a new {@link CheckClassAdapter}.
*
*
* @param cv the class visitor to which this adapter must delegate calls.
* @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or
* <tt>false</tt> to not perform any data flow check (see
* {@link CheckMethodAdapter}).
* {@link CheckMethodAdapter}). This option requires valid maxLocals
* and maxStack values.
*/
public CheckClassAdapter(final ClassVisitor cv, boolean checkDataFlow) {
super(cv);
......@@ -533,7 +534,7 @@ public class CheckClassAdapter extends ClassAdapter {
* Checks that the given access flags do not contain invalid flags. This
* method also checks that mutually incompatible flags are not set
* simultaneously.
*
*
* @param access the access flags to be checked
* @param possibleAccess the valid access flags.
*/
......
......@@ -367,6 +367,11 @@ public class CheckMethodAdapter extends MethodAdapter {
try {
a.analyze("dummy", this);
} catch (Exception e) {
if (e instanceof IndexOutOfBoundsException
&& maxLocals == 0 && maxStack == 0)
{
throw new RuntimeException("Data flow checking option requires valid, non zero maxLocals and maxStack values.");
}
e.printStackTrace();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment