[jboss-user] [Javassist user questions] - Pop from empty stack after MethodCall.replace

dschulten do-not-reply at jboss.com
Fri Aug 21 02:27:11 EDT 2009


Hi,

I need to replace the following call in legacy bytecode:

dataInputStream.read(buf, 0, len);

by

dataInputStream.readFully(buf, 0, len);

The original read() has the obvious flaw that it does not check for the return value of dataInputStream.read, which leads to problems if the implementation chooses to fill the buffer only partially. I want to solve this bug using Javassist.

I do the following:

        ExprEditor exprEditor = new ExprEditor() {

            @Override
            public void edit(MethodCall methodCall) 
                    throws CannotCompileException {
                String methodName = methodCall.getMethodName();
                if (methodName.equals("read")) {
                    methodCall.replace("$_ = $0.readFully($$);");
                    didChangesToClassfile = true;
                }
            }
        };

But the created class is broken, it is rejected by the classloader and jode says "Pop from empty stack".

Obviously I want to replace a method call with a return value which is being ignored by a void method call. I guess this is what causes the problem, but maybe I am wrong.

The offending bytecode is below, look around readFully in line 114:

public void (String arg1)
Code(max_stack = 4, max_locals = 9, code_length = 139)
0:    aload_0
1:    invokespecial	java.lang.Object. ()V (23)
4:    new		<java.io.DataInputStream> (2)
7:    dup
8:    aload_0
9:    invokevirtual	java.lang.Object.getClass ()Ljava/lang/Class; (24)
12:   aload_1
13:   invokevirtual	java.lang.Class.getResourceAsStream (Ljava/lang/String;)Ljava/io/InputStream; (22)
16:   invokespecial	java.io.DataInputStream. (Ljava/io/InputStream;)V (16)
19:   dup
20:   astore_1
21:   invokevirtual	java.io.DataInputStream.readUnsignedByte ()I (21)
24:   i2c
25:   bipush		70
27:   if_icmpeq		#31
30:   return
31:   aload_1
32:   invokevirtual	java.io.DataInputStream.readUnsignedByte ()I (21)
35:   i2c
36:   bipush		49
38:   if_icmpeq		#42
41:   return
42:   aload_0
43:   aload_1
44:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
47:   putfield		ak.h I (15)
50:   aload_0
51:   aload_1
52:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
55:   putfield		ak.d I (11)
58:   aload_0
59:   aload_1
60:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
63:   putfield		ak.e I (12)
66:   aload_0
67:   aload_1
68:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
71:   putfield		ak.f I (13)
74:   aload_0
75:   aload_1
76:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
79:   putfield		ak.g I (14)
82:   aload_1
83:   invokevirtual	java.io.DataInputStream.readShort ()S (20)
86:   dup
87:   istore_2
88:   newarray		
90:   astore_3
91:   aload_1
92:   aload_3
93:   iconst_0
94:   iload_2
95:   istore		%7
97:   istore		%6
99:   astore		%5
101:  astore		%4
103:  iconst_0
104:  istore		%8
106:  aload		%4
108:  aload		%5
110:  iload		%6
112:  iload		%7
114:  invokevirtual	java.io.DataInputStream.readFully ([BII)V (116)
117:  istore		%8
119:  iload		%8
121:  pop
122:  aload_0
123:  aload_3
124:  iconst_0
125:  iload_2
126:  invokestatic	javax.microedition.lcdui.Image.createImage ([BII)Ljavax/microedition/lcdui/Image; (34)
129:  putfield		ak.G Ljavax/microedition/lcdui/Image; (10)
132:  aload_1
133:  invokevirtual	java.io.DataInputStream.close ()V (17)
136:  return
137:  pop
138:  return

The original bytecode looks like this:

public void (String arg1)
Code(max_stack = 4, max_locals = 4, code_length = 116)
0:    aload_0
1:    invokespecial	java.lang.Object. ()V (23)
4:    new		<java.io.DataInputStream> (2)
7:    dup
8:    aload_0
9:    invokevirtual	java.lang.Object.getClass ()Ljava/lang/Class; (24)
12:   aload_1
13:   invokevirtual	java.lang.Class.getResourceAsStream (Ljava/lang/String;)Ljava/io/InputStream; (22)
16:   invokespecial	java.io.DataInputStream. (Ljava/io/InputStream;)V (16)
19:   dup
20:   astore_1
21:   invokevirtual	java.io.DataInputStream.readUnsignedByte ()I (21)
24:   i2c
25:   bipush		70
27:   if_icmpeq		#31
30:   return
31:   aload_1
32:   invokevirtual	java.io.DataInputStream.readUnsignedByte ()I (21)
35:   i2c
36:   bipush		49
38:   if_icmpeq		#42
41:   return
42:   aload_0
43:   aload_1
44:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
47:   putfield		ak.h I (15)
50:   aload_0
51:   aload_1
52:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
55:   putfield		ak.d I (11)
58:   aload_0
59:   aload_1
60:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
63:   putfield		ak.e I (12)
66:   aload_0
67:   aload_1
68:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
71:   putfield		ak.f I (13)
74:   aload_0
75:   aload_1
76:   invokevirtual	java.io.DataInputStream.readByte ()B (19)
79:   putfield		ak.g I (14)
82:   aload_1
83:   invokevirtual	java.io.DataInputStream.readShort ()S (20)
86:   dup
87:   istore_2
88:   newarray		
90:   astore_3
91:   aload_1
92:   aload_3
93:   iconst_0
94:   iload_2
95:   invokevirtual	java.io.DataInputStream.read ([BII)I (18)
98:   pop
99:   aload_0
100:  aload_3
101:  iconst_0
102:  iload_2
103:  invokestatic	javax.microedition.lcdui.Image.createImage ([BII)Ljavax/microedition/lcdui/Image; (34)
106:  putfield		ak.G Ljavax/microedition/lcdui/Image; (10)
109:  aload_1
110:  invokevirtual	java.io.DataInputStream.close ()V (17)
113:  return
114:  pop
115:  return

View the original post : http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4250792#4250792

Reply to the post : http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=4250792



More information about the jboss-user mailing list