@@ -15,11 +15,11 @@ pub enum Opcode {
1515 Aaload ,
1616 Aastore ,
1717 AconstNull ,
18- Aload ( u8 ) ,
18+ Aload ( u16 ) ,
1919 Anewarray ( ConstantPoolReference ) ,
2020 Areturn ,
2121 Arraylength ,
22- Astore ( u8 ) ,
22+ Astore ( u16 ) ,
2323 Athrow ,
2424 Baload ,
2525 Bastore ,
@@ -37,12 +37,12 @@ pub enum Opcode {
3737 Dcmpl ,
3838 Dconst ( u8 ) ,
3939 Ddiv ,
40- Dload ( u8 ) ,
40+ Dload ( u16 ) ,
4141 Dmul ,
4242 Dneg ,
4343 Drem ,
4444 Dreturn ,
45- Dstore ( u8 ) ,
45+ Dstore ( u16 ) ,
4646 Dsub ,
4747 Dup ,
4848 DupX1 ,
@@ -60,12 +60,12 @@ pub enum Opcode {
6060 Fcmpl ,
6161 Fconst ( u8 ) ,
6262 Fdiv ,
63- Fload ( u8 ) ,
63+ Fload ( u16 ) ,
6464 Fmul ,
6565 Fneg ,
6666 Frem ,
6767 Freturn ,
68- Fstore ( u8 ) ,
68+ Fstore ( u16 ) ,
6969 Fsub ,
7070 Getfield ( ConstantPoolReference ) ,
7171 Getstatic ( ConstantPoolReference ) ,
@@ -99,8 +99,8 @@ pub enum Opcode {
9999 Ifle ( i16 ) ,
100100 Ifnonnull ( i16 ) ,
101101 Ifnull ( i16 ) ,
102- Iinc ( u8 , i8 ) ,
103- Iload ( u8 ) ,
102+ Iinc ( u16 , i16 ) ,
103+ Iload ( u16 ) ,
104104 Imul ,
105105 Ineg ,
106106 Instanceof ( ConstantPoolReference ) ,
@@ -114,7 +114,7 @@ pub enum Opcode {
114114 Ireturn ,
115115 Ishl ,
116116 Ishr ,
117- Istore ( u8 ) ,
117+ Istore ( u16 ) ,
118118 Isub ,
119119 Iushr ,
120120 Ixor ,
@@ -133,7 +133,7 @@ pub enum Opcode {
133133 LdcW ( ConstantPoolReference ) ,
134134 Ldc2W ( ConstantPoolReference ) ,
135135 Ldiv ,
136- Lload ( u8 ) ,
136+ Lload ( u16 ) ,
137137 Lmul ,
138138 Lneg ,
139139 Lookupswitch ( i32 , Vec < ( i32 , i32 ) > ) ,
@@ -142,7 +142,7 @@ pub enum Opcode {
142142 Lreturn ,
143143 Lshl ,
144144 Lshr ,
145- Lstore ( u8 ) ,
145+ Lstore ( u16 ) ,
146146 Lsub ,
147147 Lushr ,
148148 Lxor ,
@@ -156,14 +156,13 @@ pub enum Opcode {
156156 Pop2 ,
157157 Putfield ( ConstantPoolReference ) ,
158158 Putstatic ( ConstantPoolReference ) ,
159- Ret ( u8 ) ,
159+ Ret ( u16 ) ,
160160 Return ,
161161 Saload ,
162162 Sastore ,
163163 Sipush ( i16 ) ,
164164 Swap ,
165165 Tableswitch ( i32 , Vec < ( i32 , i32 ) > ) ,
166- Wide ,
167166}
168167
169168impl Opcode {
@@ -176,7 +175,7 @@ impl Opcode {
176175 0x32 => success ( Opcode :: Aaload ) . parse ( data) ,
177176 0x53 => success ( Opcode :: Aastore ) . parse ( data) ,
178177 0x01 => success ( Opcode :: AconstNull ) . parse ( data) ,
179- 0x19 => map ( u8, Opcode :: Aload ) . parse ( data) ,
178+ 0x19 => map ( u8, |x| Opcode :: Aload ( x as u16 ) ) . parse ( data) ,
180179 0x2a => success ( Opcode :: Aload ( 0 ) ) . parse ( data) ,
181180 0x2b => success ( Opcode :: Aload ( 1 ) ) . parse ( data) ,
182181 0x2c => success ( Opcode :: Aload ( 2 ) ) . parse ( data) ,
@@ -187,7 +186,7 @@ impl Opcode {
187186 . parse ( data) ,
188187 0xb0 => success ( Opcode :: Areturn ) . parse ( data) ,
189188 0xbe => success ( Opcode :: Arraylength ) . parse ( data) ,
190- 0x3a => map ( u8, Opcode :: Astore ) . parse ( data) ,
189+ 0x3a => map ( u8, |x| Opcode :: Astore ( x as u16 ) ) . parse ( data) ,
191190 0x4b => success ( Opcode :: Astore ( 0 ) ) . parse ( data) ,
192191 0x4c => success ( Opcode :: Astore ( 1 ) ) . parse ( data) ,
193192 0x4d => success ( Opcode :: Astore ( 2 ) ) . parse ( data) ,
@@ -213,7 +212,7 @@ impl Opcode {
213212 0x0e => success ( Opcode :: Dconst ( 0 ) ) . parse ( data) ,
214213 0x0f => success ( Opcode :: Dconst ( 1 ) ) . parse ( data) ,
215214 0x6f => success ( Opcode :: Ddiv ) . parse ( data) ,
216- 0x18 => map ( u8, Opcode :: Dload ) . parse ( data) ,
215+ 0x18 => map ( u8, |x| Opcode :: Dload ( x as u16 ) ) . parse ( data) ,
217216 0x26 => success ( Opcode :: Dload ( 0 ) ) . parse ( data) ,
218217 0x27 => success ( Opcode :: Dload ( 1 ) ) . parse ( data) ,
219218 0x28 => success ( Opcode :: Dload ( 2 ) ) . parse ( data) ,
@@ -222,7 +221,7 @@ impl Opcode {
222221 0x77 => success ( Opcode :: Dneg ) . parse ( data) ,
223222 0x73 => success ( Opcode :: Drem ) . parse ( data) ,
224223 0xaf => success ( Opcode :: Dreturn ) . parse ( data) ,
225- 0x39 => map ( u8, Opcode :: Dstore ) . parse ( data) ,
224+ 0x39 => map ( u8, |x| Opcode :: Dstore ( x as u16 ) ) . parse ( data) ,
226225 0x47 => success ( Opcode :: Dstore ( 0 ) ) . parse ( data) ,
227226 0x48 => success ( Opcode :: Dstore ( 1 ) ) . parse ( data) ,
228227 0x49 => success ( Opcode :: Dstore ( 2 ) ) . parse ( data) ,
@@ -246,7 +245,7 @@ impl Opcode {
246245 0x0c => success ( Opcode :: Fconst ( 1 ) ) . parse ( data) ,
247246 0x0d => success ( Opcode :: Fconst ( 2 ) ) . parse ( data) ,
248247 0x6e => success ( Opcode :: Fdiv ) . parse ( data) ,
249- 0x17 => map ( u8, Opcode :: Fload ) . parse ( data) ,
248+ 0x17 => map ( u8, |x| Opcode :: Fload ( x as u16 ) ) . parse ( data) ,
250249 0x22 => success ( Opcode :: Fload ( 0 ) ) . parse ( data) ,
251250 0x23 => success ( Opcode :: Fload ( 1 ) ) . parse ( data) ,
252251 0x24 => success ( Opcode :: Fload ( 2 ) ) . parse ( data) ,
@@ -255,7 +254,7 @@ impl Opcode {
255254 0x76 => success ( Opcode :: Fneg ) . parse ( data) ,
256255 0x72 => success ( Opcode :: Frem ) . parse ( data) ,
257256 0xae => success ( Opcode :: Freturn ) . parse ( data) ,
258- 0x38 => map ( u8, Opcode :: Fstore ) . parse ( data) ,
257+ 0x38 => map ( u8, |x| Opcode :: Fstore ( x as u16 ) ) . parse ( data) ,
259258 0x43 => success ( Opcode :: Fstore ( 0 ) ) . parse ( data) ,
260259 0x44 => success ( Opcode :: Fstore ( 1 ) ) . parse ( data) ,
261260 0x45 => success ( Opcode :: Fstore ( 2 ) ) . parse ( data) ,
@@ -305,8 +304,8 @@ impl Opcode {
305304 0x9e => map ( be_i16, Opcode :: Ifle ) . parse ( data) ,
306305 0xc7 => map ( be_i16, Opcode :: Ifnonnull ) . parse ( data) ,
307306 0xc6 => map ( be_i16, Opcode :: Ifnull ) . parse ( data) ,
308- 0x84 => map ( ( u8, i8) , |( index, constant) | Opcode :: Iinc ( index, constant) ) . parse ( data) ,
309- 0x15 => map ( u8, Opcode :: Iload ) . parse ( data) ,
307+ 0x84 => map ( ( u8, i8) , |( index, constant) | Opcode :: Iinc ( index as u16 , constant as i16 ) ) . parse ( data) ,
308+ 0x15 => map ( u8, |x| Opcode :: Iload ( x as u16 ) ) . parse ( data) ,
310309 0x1a => success ( Opcode :: Iload ( 0 ) ) . parse ( data) ,
311310 0x1b => success ( Opcode :: Iload ( 1 ) ) . parse ( data) ,
312311 0x1c => success ( Opcode :: Iload ( 2 ) ) . parse ( data) ,
@@ -342,7 +341,7 @@ impl Opcode {
342341 0xac => success ( Opcode :: Ireturn ) . parse ( data) ,
343342 0x78 => success ( Opcode :: Ishl ) . parse ( data) ,
344343 0x7a => success ( Opcode :: Ishr ) . parse ( data) ,
345- 0x36 => map ( u8, Opcode :: Istore ) . parse ( data) ,
344+ 0x36 => map ( u8, |x| Opcode :: Istore ( x as u16 ) ) . parse ( data) ,
346345 0x3b => success ( Opcode :: Istore ( 0 ) ) . parse ( data) ,
347346 0x3c => success ( Opcode :: Istore ( 1 ) ) . parse ( data) ,
348347 0x3d => success ( Opcode :: Istore ( 2 ) ) . parse ( data) ,
@@ -369,7 +368,7 @@ impl Opcode {
369368 } )
370369 . parse ( data) ,
371370 0x6d => success ( Opcode :: Ldiv ) . parse ( data) ,
372- 0x16 => map ( u8, Opcode :: Lload ) . parse ( data) ,
371+ 0x16 => map ( u8, |x| Opcode :: Lload ( x as u16 ) ) . parse ( data) ,
373372 0x1e => success ( Opcode :: Lload ( 0 ) ) . parse ( data) ,
374373 0x1f => success ( Opcode :: Lload ( 1 ) ) . parse ( data) ,
375374 0x20 => success ( Opcode :: Lload ( 2 ) ) . parse ( data) ,
@@ -385,7 +384,7 @@ impl Opcode {
385384 0xad => success ( Opcode :: Lreturn ) . parse ( data) ,
386385 0x79 => success ( Opcode :: Lshl ) . parse ( data) ,
387386 0x7b => success ( Opcode :: Lshr ) . parse ( data) ,
388- 0x37 => map ( u8, Opcode :: Lstore ) . parse ( data) ,
387+ 0x37 => map ( u8, |x| Opcode :: Lstore ( x as u16 ) ) . parse ( data) ,
389388 0x3f => success ( Opcode :: Lstore ( 0 ) ) . parse ( data) ,
390389 0x40 => success ( Opcode :: Lstore ( 1 ) ) . parse ( data) ,
391390 0x41 => success ( Opcode :: Lstore ( 2 ) ) . parse ( data) ,
@@ -412,7 +411,7 @@ impl Opcode {
412411 Opcode :: Putstatic ( ConstantPoolReference :: from_constant_pool ( constant_pool, x as _ ) )
413412 } )
414413 . parse ( data) ,
415- 0xa9 => map ( u8, Opcode :: Ret ) . parse ( data) ,
414+ 0xa9 => map ( u8, |x| Opcode :: Ret ( x as u16 ) ) . parse ( data) ,
416415 0xb1 => success ( Opcode :: Return ) . parse ( data) ,
417416 0x35 => success ( Opcode :: Saload ) . parse ( data) ,
418417 0x56 => success ( Opcode :: Sastore ) . parse ( data) ,
@@ -427,10 +426,31 @@ impl Opcode {
427426 }
428427 } )
429428 . parse ( data) ,
430- 0xc4 => success ( Opcode :: Wide ) . parse ( data) ,
429+ 0xc4 => Self :: parse_wide ( data) ,
431430 _ => panic ! ( "Unknown opcode: {:02x}" , opcode) ,
432431 }
433432 }
433+
434+ // wide (0xc4): widens the local variable index of the following instruction to 16 bits
435+ fn parse_wide ( data : & [ u8 ] ) -> IResult < & [ u8 ] , Self > {
436+ let ( data, opcode) = u8 ( data) ?;
437+
438+ match opcode {
439+ 0x84 => map ( ( be_u16, be_i16) , |( index, constant) | Opcode :: Iinc ( index, constant) ) . parse ( data) ,
440+ 0x15 => map ( be_u16, Opcode :: Iload ) . parse ( data) ,
441+ 0x16 => map ( be_u16, Opcode :: Lload ) . parse ( data) ,
442+ 0x17 => map ( be_u16, Opcode :: Fload ) . parse ( data) ,
443+ 0x18 => map ( be_u16, Opcode :: Dload ) . parse ( data) ,
444+ 0x19 => map ( be_u16, Opcode :: Aload ) . parse ( data) ,
445+ 0x36 => map ( be_u16, Opcode :: Istore ) . parse ( data) ,
446+ 0x37 => map ( be_u16, Opcode :: Lstore ) . parse ( data) ,
447+ 0x38 => map ( be_u16, Opcode :: Fstore ) . parse ( data) ,
448+ 0x39 => map ( be_u16, Opcode :: Dstore ) . parse ( data) ,
449+ 0x3a => map ( be_u16, Opcode :: Astore ) . parse ( data) ,
450+ 0xa9 => map ( be_u16, Opcode :: Ret ) . parse ( data) ,
451+ _ => panic ! ( "Invalid wide opcode: {:02x}" , opcode) ,
452+ }
453+ }
434454}
435455
436456#[ cfg( test) ]
@@ -487,4 +507,22 @@ mod test {
487507 assert ! ( remaining. is_empty( ) ) ;
488508 assert ! ( matches!( opcode, Opcode :: Invokedynamic ( _) ) ) ;
489509 }
510+
511+ #[ test]
512+ fn test_wide_iload_reads_u16_index ( ) {
513+ // wide iload 0x0100, then nop — the trailing nop must not be misparsed
514+ let ( remaining, opcode) = Opcode :: parse ( & [ 0xc4 , 0x15 , 0x01 , 0x00 , 0x00 ] , 0 , & constant_pool ( ) ) . unwrap ( ) ;
515+
516+ assert ! ( matches!( opcode, Opcode :: Iload ( 0x0100 ) ) ) ;
517+ assert_eq ! ( remaining, & [ 0x00 ] ) ;
518+ }
519+
520+ #[ test]
521+ fn test_wide_iinc_reads_u16_index_and_i16_const ( ) {
522+ // wide iinc 0x012c, 1000
523+ let ( remaining, opcode) = Opcode :: parse ( & [ 0xc4 , 0x84 , 0x01 , 0x2c , 0x03 , 0xe8 ] , 0 , & constant_pool ( ) ) . unwrap ( ) ;
524+
525+ assert ! ( matches!( opcode, Opcode :: Iinc ( 0x012c , 1000 ) ) ) ;
526+ assert ! ( remaining. is_empty( ) ) ;
527+ }
490528}
0 commit comments