| Newsgroups |
gmane.comp.java.objectweb.asm |
| Message-ID |
<[email protected]> |
This is a multi-part message in MIME format...
------------=_1682012203-21111-31
Content-Type: text/plain; charset=UTF-8;
format=flowed
Content-Transfer-Encoding: 8bit
Hi,
Thanks for your report. This is a bug in ASM, which will be fixed by
https://gitlab.ow2.org/asm/asm/-/merge_requests/374.
Eric
Le 18/04/2023 18:13, "Pascal Kesseli" a écrit :
> Hi everyone,
>
> I tried to enable `CheckClassAdapter` with `checkDataFlow` set to
> `true` to
> make sure that my instrumentation is valid. However, I encountered an
> issue
> that even original classes from third party libraries are considered
> invalid.
> As an example the method `getCanonicalName` in the class
> `AssertionUtils` in
> JUnit 5.9.2:
>
> ```pom.xml
> <dependency>
> <groupId>org.ow2.asm</groupId>
> <artifactId>asm-util</artifactId>
> <version>9.5</version>
> </dependency>
> <dependency>
> <groupId>org.junit.jupiter</groupId>
> <artifactId>junit-jupiter-engine</artifactId>
> <version>5.9.2</version>
> <scope>test</scope>
> </dependency>
> ```
>
> ```java
> @Test
> void assertionUtils() throws Exception {
> String classRes = "/org/junit/jupiter/api/AssertionUtils.class";
> byte[] classfileBuffer;
> try (InputStream is = MyTest.class.getResourceAsStream(classRes)) {
> classfileBuffer = IOUtils.toByteArray(is);
> }
>
> ClassReader reader = new ClassReader(classfileBuffer);
> TraceClassVisitor trace = new TraceClassVisitor(null, new Textifier(),
> new PrintWriter(System.err));
> reader.accept(trace, 0);
>
> reader = new ClassReader(classfileBuffer);
> ClassWriter writer = new ClassWriter(reader, 0);
> CheckClassAdapter checker = new CheckClassAdapter(writer, true);
> try {
> reader.accept(checker, 0);
> } catch (IllegalArgumentException e) {
> e.printStackTrace();
> }
>
> Class.forName("org.junit.jupiter.api.AssertionUtils");
> }
> ```
>
> This unit test passes the byte content for `AssertionUtils` without
> instrumentation or modification into a `ClassReader`, outputs the byte
> code
> using `TraceClassVisitor` and then independently runs it through
> `CheckClassAdapter`. The output of this test is as follows:
>
> ```
> // `TraceClassVisitor` output
> // class version 52.0 (52)
> // access flags 0x20
> class org/junit/jupiter/api/AssertionUtils {
> // ...
> // access flags 0x8
> // signature (Ljava/lang/Class<*>;)Ljava/lang/String;
> // declaration: java.lang.String getCanonicalName(java.lang.Class<?>)
> static getCanonicalName(Ljava/lang/Class;)Ljava/lang/String;
> TRYCATCHBLOCK L0 L1 L2 java/lang/Throwable
> L0
> LINENUMBER 59 L0
> ALOAD 0
> INVOKEVIRTUAL java/lang/Class.getCanonicalName ()Ljava/lang/String;
> ASTORE 1
> L3
> LINENUMBER 60 L3
> ALOAD 1
> IFNULL L4
> ALOAD 1
> GOTO L1
> L4
> FRAME APPEND [java/lang/String]
> ALOAD 0
> INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
> L1
> FRAME SAME1 java/lang/String
> ARETURN
> L2
> LINENUMBER 62 L2
> FRAME FULL [java/lang/Class] [java/lang/Throwable]
> ASTORE 1
> L5
> LINENUMBER 63 L5
> ALOAD 1
> INVOKESTATIC org/junit/platform/commons/util/
> UnrecoverableExceptions.rethrowIfUnrecoverable (Ljava/lang/Throwable;)V
> L6
> LINENUMBER 64 L6
> ALOAD 0
> INVOKEVIRTUAL java/lang/Class.getName ()Ljava/lang/String;
> ARETURN
> L7
> LOCALVARIABLE canonicalName Ljava/lang/String; L3 L2 1
> LOCALVARIABLE t Ljava/lang/Throwable; L5 L7 1
> LOCALVARIABLE clazz Ljava/lang/Class; L0 L7 0
> // signature Ljava/lang/Class<*>;
> // declaration: clazz extends java.lang.Class<?>
> MAXSTACK = 1
> MAXLOCALS = 2
> // ...
> }
> // `e.printStackTrace();` for `IllegalArgumentException`
> java.lang.IllegalArgumentException: Error at instruction 12: Cannot
> append
> more locals than maxLocals
> getCanonicalName(Ljava/lang/Class;)Ljava/lang/
> String;
> 00000 R . : : L0
> 00001 ? : LINENUMBER 59 L0
> 00002 ? : ALOAD 0
> 00003 ? : INVOKEVIRTUAL java/lang/Class.getCanonicalName
> ()Ljava/lang/
> String;
> 00004 ? : ASTORE 1
> 00005 ? : L1
> 00006 ? : LINENUMBER 60 L1
> 00007 ? : ALOAD 1
> 00008 ? : IFNULL L2
> 00009 ? : ALOAD 1
> 00010 ? : GOTO L3
> 00011 ? : L2
> 00012 ? : FRAME APPEND [java/lang/String]
> 00013 ? : ALOAD 0
> 00014 ? : INVOKEVIRTUAL java/lang/Class.getName
> ()Ljava/lang/String;
> 00015 ? : L3
> 00016 ? : FRAME SAME1 java/lang/String
> 00017 ? : ARETURN
> 00018 ? : L4
> 00019 ? : LINENUMBER 62 L4
> 00020 ? : FRAME FULL [java/lang/Class] [java/lang/Throwable]
> 00021 ? : ASTORE 1
> 00022 ? : L5
> 00023 ? : LINENUMBER 63 L5
> 00024 ? : ALOAD 1
> 00025 ? : INVOKESTATIC org/junit/platform/commons/util/
> UnrecoverableExceptions.rethrowIfUnrecoverable (Ljava/lang/Throwable;)V
> 00026 ? : L6
> 00027 ? : LINENUMBER 64 L6
> 00028 ? : ALOAD 0
> 00029 ? : INVOKEVIRTUAL java/lang/Class.getName
> ()Ljava/lang/String;
> 00030 ? : ARETURN
> 00031 ? : L7
> TRYCATCHBLOCK L0 L3 L4 java/lang/Throwable
>
> at org.objectweb.asm.util.CheckMethodAdapter
> $1.throwError(CheckMethodAdapter.java:489)
> at org.objectweb.asm.util.CheckMethodAdapter
> $1.visitEnd(CheckMethodAdapter.java:475)
> at org.objectweb.asm.MethodVisitor.visitEnd(MethodVisitor.java:796)
> at
> org.objectweb.asm.util.CheckMethodAdapter.visitEnd(CheckMethodAdapter.java:1044)
> at org.objectweb.asm.ClassReader.readMethod(ClassReader.java:1518)
> at org.objectweb.asm.ClassReader.accept(ClassReader.java:744)
> at org.objectweb.asm.ClassReader.accept(ClassReader.java:424)
> at
> net.lacework.caa.java.instrument.TracepointClassFileTransformerTest.assertionUtils(TracepointClassFileTransformerTest.java:98)
> at java.base/
> jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
> at java.base/java.lang.reflect.Method.invoke(Method.java:578)
> at
> org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
> at
> org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
> at org.junit.jupiter.engine.execution.InvocationInterceptorChain
> $ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
> at
> org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
> at
> org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
> at
> org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
> at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker
> $ReflectiveInterceptorCall.lambda$ofVoidMethod
> $0(InterceptingExecutableInvoker.java:103)
> at
> org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke
> $0(InterceptingExecutableInvoker.java:93)
> at org.junit.jupiter.engine.execution.InvocationInterceptorChain
> $InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
> at
> org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
> at
> org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
> at
> org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
> at
> org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
> at
> org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
> at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda
> $invokeTestMethod$7(TestMethodTestDescriptor.java:217)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at
> org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
> at
> org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
> at
> org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$6(NodeTestTask.java:151)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$8(NodeTestTask.java:141)
> at
> org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$9(NodeTestTask.java:139)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
> at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
> at
> org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$6(NodeTestTask.java:155)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$8(NodeTestTask.java:141)
> at
> org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$9(NodeTestTask.java:139)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
> at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
> at
> org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$6(NodeTestTask.java:155)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$8(NodeTestTask.java:141)
> at
> org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
> at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda
> $executeRecursively$9(NodeTestTask.java:139)
> at
> org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
> at
> org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
> at
> org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
> at
> org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
> at
> org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
> at
> org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
> at
> org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
> at
> org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
> at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda
> $execute$0(EngineExecutionOrchestrator.java:55)
> at
> org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
> at
> org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
> at
> org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
> at
> org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:95)
> at org.junit.platform.launcher.core.DefaultLauncherSession
> $DelegatingLauncher.execute(DefaultLauncherSession.java:91)
> at
> org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:60)
> at
> org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
> at
> org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
> at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
> Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Error at
> instruction 12: Cannot append more locals than maxLocals
> at
> org.objectweb.asm.util.CheckFrameAnalyzer.expandFrames(CheckFrameAnalyzer.java:240)
> at
> org.objectweb.asm.util.CheckFrameAnalyzer.init(CheckFrameAnalyzer.java:124)
> at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:142)
> at org.objectweb.asm.util.CheckMethodAdapter
> $1.visitEnd(CheckMethodAdapter.java:470)
> ... 74 more
> Caused by: org.objectweb.asm.tree.analysis.AnalyzerException: Cannot
> append
> more locals than maxLocals
> at
> org.objectweb.asm.util.CheckFrameAnalyzer.expandFrame(CheckFrameAnalyzer.java:277)
> at
> org.objectweb.asm.util.CheckFrameAnalyzer.expandFrames(CheckFrameAnalyzer.java:237)
> ... 77 more
> ```
>
> The class loads without issues in
> `Class.forName("org.junit.jupiter.api.AssertionUtils");`, complaining
> that the
> `FRAME APPEND` on offset `12` exceeds the maximum of 2 local variables.
> Given
> that the preceding implicit init frame based on the single argument and
> the
> fact that it is a `static` method should have 1 local variable, my
> understanding is that this is not actually the case and that the
> bytecode is
> valid. I see similar errors like this for multiple classes in JUnit and
> other
> JARs.
>
> Conversely, this check works as well:
> ```
> reader = new ClassReader(classfileBuffer);
> CheckClassAdapter.verify(reader,
> TracepointClassFileTransformerTest.class.getClassLoader(), false, new
> PrintWriter(System.err));
> ```
>
> Thus my question: Am I misusing the `CheckClassAdapter` or the
> `Analyzer` API
> somehow? Or is this a bug in the analysis?
>
> Thanks,
>
>
> --
> You receive this message as a subscriber of the [email protected] mailing
> list.
> To unsubscribe: mailto:[email protected]
> For general help: mailto:[email protected]?subject=help
> OW2 mailing lists service home page: http://www.ow2.org/wws
------------=_1682012203-21111-31
Content-Type: text/plain; charset="UTF-8"
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
--
You receive this message as a subscriber of the [email protected] mailing list.
To unsubscribe: mailto:[email protected]
For general help: mailto:[email protected]?subject=help
OW2 mailing lists service home page: http://www.ow2.org/wws
------------=_1682012203-21111-31--