Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
asm
asm
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 5
    • Issues 5
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Merge Requests 3
    • Merge Requests 3
  • CI / CD
    • CI / CD
    • Pipelines
    • Jobs
    • Schedules
  • Operations
    • Operations
    • Incidents
    • Environments
  • Packages & Registries
    • Packages & Registries
    • Container Registry
  • Analytics
    • Analytics
    • CI / CD
    • Repository
    • Value Stream
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Collapse sidebar
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
  • asm
  • asmasm
  • Issues
  • #317823

Closed
Open
Opened Apr 19, 2018 by laurit@laurit

Computing maximum stack size does not work correctly with JSR/RET instructions present

Commenting in the ACONST_NULL and POP instructions should mean that the maximum stack size is at least two, but one is computed.

With mv.visitMaxs(5, 0);, the verify error is thrown with ASM 6.1, but not with ASM 6.0. This is most likely caused by the computation of maximum stack size no longer taking the passed parameter into account with COMPUTE_MAXS present.

With mv.visitMaxs(0, 0), the class verification fails with both versions.

This is distilled down version of com/sun/corba/ee/impl/protocol/CorbaClientDelegateImpl from GlassFish 2.

import static org.objectweb.asm.Opcodes.*;


import java.util.Arrays;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;

public class TestCase {

  public static void main(String[] args){
    byte[] bytes = dumpBytes();
    Class test = new ClassLoader() {
      public Class<?> defineClass(String name, byte[] bytes) {
        return defineClass(name, bytes, 0, bytes.length, null);
      }
    }.defineClass("test.Test", bytes);
    System.out.println(Arrays.toString(test.getDeclaredMethods()));
  }

  public static byte[] dumpBytes() {

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    MethodVisitor mv;

    cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, "test/Test", null, "java/lang/Object", null);

    {
      mv = cw.visitMethod(ACC_PUBLIC, "test", "()Ljava/lang/Object;", null, null);
      mv.visitCode();
      Label l0 = new Label();
      Label l1 = new Label();
      Label l2 = new Label();
      mv.visitTryCatchBlock(l0, l1, l2, null);
      Label l3 = new Label();
      mv.visitTryCatchBlock(l2, l3, l2, null);
      Label l4 = new Label();
      Label l5 = new Label();
      mv.visitTryCatchBlock(l0, l4, l5, "java/lang/RuntimeException");
      Label l6 = new Label();
      Label l7 = new Label();
      mv.visitTryCatchBlock(l0, l6, l7, null);
      Label l8 = new Label();
      mv.visitTryCatchBlock(l7, l8, l7, null);
      mv.visitLabel(l0);
      Label l9 = new Label();
      mv.visitJumpInsn(JSR, l9);
      mv.visitLabel(l1);
      Label l10 = new Label();
      mv.visitJumpInsn(GOTO, l10);
      mv.visitLabel(l2);
      mv.visitInsn(POP);
      mv.visitJumpInsn(JSR, l9);
      mv.visitLabel(l3);
      mv.visitInsn(ACONST_NULL);
      mv.visitInsn(ATHROW);
      mv.visitLabel(l9);
      mv.visitVarInsn(ASTORE, 10);
      mv.visitVarInsn(RET, 10);
      mv.visitLabel(l10);
      mv.visitInsn(ACONST_NULL);
      // Comment in the following block to reproduce the issue
      {
//        mv.visitInsn(ACONST_NULL);
//        mv.visitInsn(ACONST_NULL);
//        mv.visitInsn(POP);
//        mv.visitInsn(POP);
      }
      mv.visitInsn(POP);
      mv.visitLabel(l4);
      Label l13 = new Label();
      mv.visitJumpInsn(GOTO, l13);
      mv.visitLabel(l5);
      mv.visitInsn(POP);
      mv.visitJumpInsn(GOTO, l13);
      mv.visitInsn(ACONST_NULL);
      mv.visitInsn(ATHROW);
      mv.visitLabel(l13);
      mv.visitInsn(ICONST_0);
      mv.visitJumpInsn(IFNE, l0);
      Label l14 = new Label();
      mv.visitJumpInsn(JSR, l14);
      mv.visitLabel(l6);
      mv.visitInsn(ACONST_NULL);
      mv.visitInsn(ARETURN);
      mv.visitLabel(l7);
      mv.visitInsn(POP);
      mv.visitJumpInsn(JSR, l14);
      mv.visitLabel(l8);
      mv.visitInsn(ACONST_NULL);
      mv.visitInsn(ATHROW);
      mv.visitLabel(l14);
      mv.visitVarInsn(ASTORE, 12);
      mv.visitVarInsn(RET, 12);
      mv.visitMaxs(5, 0);
//      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }

}
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: asm/asm#317823