2323
2424/*
2525 * @test
26- * @bug 8341277
26+ * @bug 8341277 8361102
2727 * @summary Testing ClassFile instruction argument validation.
2828 * @run junit InstructionValidationTest
2929 */
3232import java .lang .classfile .constantpool .ClassEntry ;
3333import java .lang .classfile .constantpool .ConstantPoolBuilder ;
3434import java .lang .classfile .instruction .*;
35- import java .lang .constant .ClassDesc ;
36- import java .lang .reflect .Parameter ;
35+ import java .util .Collections ;
3736import java .util .List ;
3837import java .util .function .Consumer ;
3938import java .util .function .ObjIntConsumer ;
4039import java .util .stream .Stream ;
4140
41+ import helpers .TestUtil ;
4242import org .junit .jupiter .api .Test ;
4343import org .junit .jupiter .api .function .Executable ;
4444
45- import static java .lang .classfile .ClassFile .ACC_STATIC ;
4645import static java .lang .constant .ConstantDescs .*;
46+ import static helpers .TestConstants .*;
4747import static org .junit .jupiter .api .Assertions .*;
4848import static java .lang .classfile .Opcode .*;
4949import static org .junit .jupiter .api .Assertions .assertThrows ;
5050
5151class InstructionValidationTest {
5252
53+ @ Test
54+ void testOpcodeInCodeBuilder () {
55+ TestUtil .runCodeHandler (cob -> {
56+ var mref = cob .constantPool ().methodRefEntry (CD_System , "exit" , MTD_INT_VOID );
57+ var fref = cob .constantPool ().fieldRefEntry (CD_System , "out" , CD_PrintStream );
58+ var label = cob .newLabel ();
59+
60+ // Sanity
61+ cob .iconst_0 ();
62+ assertDoesNotThrow (() -> cob .invoke (INVOKESTATIC , mref ));
63+ assertDoesNotThrow (() -> cob .fieldAccess (GETSTATIC , fref ));
64+ cob .pop ();
65+ assertDoesNotThrow (() -> cob .branch (GOTO , label ));
66+
67+ // Opcode NPE
68+ assertThrows (NullPointerException .class , () -> cob .invoke (null , mref ));
69+ assertThrows (NullPointerException .class , () -> cob .fieldAccess (null , fref ));
70+ assertThrows (NullPointerException .class , () -> cob .branch (null , label ));
71+
72+ // Opcode IAE
73+ assertThrows (IllegalArgumentException .class , () -> cob .invoke (IFNE , mref ));
74+ assertThrows (IllegalArgumentException .class , () -> cob .fieldAccess (JSR , fref ));
75+ assertThrows (IllegalArgumentException .class , () -> cob .branch (CHECKCAST , label ));
76+
77+ // Wrap up
78+ cob .labelBinding (label );
79+ cob .return_ ();
80+ });
81+ }
82+
83+ @ Test
84+ void testLongJump () {
85+ TestUtil .runCodeHandler (cob -> {
86+ assertThrows (NullPointerException .class , () -> cob .goto_w (null ));
87+ // Ensures nothing redundant is written in case of failure
88+ cob .return_ ();
89+ });
90+ }
91+
92+ @ Test
93+ void testSwitch () {
94+ TestUtil .runCodeHandler (cob -> {
95+ assertThrows (NullPointerException .class , () -> cob .tableswitch (-1 , 1 , cob .startLabel (), null ));
96+ assertThrows (NullPointerException .class , () -> cob .lookupswitch (cob .startLabel (), null ));
97+ assertThrows (NullPointerException .class , () -> cob .tableswitch (-1 , 1 , cob .startLabel (), Collections .singletonList (null )));
98+ assertThrows (NullPointerException .class , () -> cob .lookupswitch (cob .startLabel (), Collections .singletonList (null )));
99+ assertThrows (NullPointerException .class , () -> cob .tableswitch (-1 , 1 , null , List .of ()));
100+ assertThrows (NullPointerException .class , () -> cob .lookupswitch (null , List .of ()));
101+ // Ensures nothing redundant is written in case of failure
102+ cob .return_ ();
103+ });
104+ }
105+
53106 @ Test
54107 void testArgumentConstant () {
55108 assertDoesNotThrow (() -> ConstantInstruction .ofArgument (SIPUSH , 0 ));
@@ -63,6 +116,14 @@ void testArgumentConstant() {
63116 assertThrows (IllegalArgumentException .class , () -> ConstantInstruction .ofArgument (SIPUSH , (int ) Short .MAX_VALUE + 1 ));
64117 assertThrows (IllegalArgumentException .class , () -> ConstantInstruction .ofArgument (BIPUSH , (int ) Byte .MIN_VALUE - 1 ));
65118 assertThrows (IllegalArgumentException .class , () -> ConstantInstruction .ofArgument (BIPUSH , (int ) Byte .MAX_VALUE + 1 ));
119+
120+ TestUtil .runCodeHandler (cob -> {
121+ assertThrows (IllegalArgumentException .class , () -> cob .sipush ((int ) Short .MIN_VALUE - 1 ));
122+ assertThrows (IllegalArgumentException .class , () -> cob .sipush ((int ) Short .MAX_VALUE + 1 ));
123+ assertThrows (IllegalArgumentException .class , () -> cob .bipush ((int ) Byte .MIN_VALUE - 1 ));
124+ assertThrows (IllegalArgumentException .class , () -> cob .bipush ((int ) Byte .MAX_VALUE + 1 ));
125+ cob .return_ ();
126+ });
66127 }
67128
68129 /**
@@ -163,26 +224,15 @@ record Result(boolean shouldFail, int slot) {
163224 // CodeBuilder can fail with IAE due to other reasons, so we cannot check
164225 // "success" but can ensure things fail fast
165226 static void ensureFailFast (int value , Consumer <CodeBuilder > action ) {
166- // Can fail with AssertionError instead of IAE
167227 Consumer <CodeBuilder > checkedAction = cob -> {
168- action .accept (cob );
169- fail ( "Bad slot access did not fail fast: " + value );
228+ assertThrows ( IllegalArgumentException . class , () -> action .accept (cob ) );
229+ cob . return_ ( );
170230 };
171- var cf = ClassFile .of ();
172- CodeTransform noopCodeTransform = CodeBuilder ::with ;
173- // Direct builders
174- assertThrows (IllegalArgumentException .class , () -> cf .build (ClassDesc .of ("Test" ), clb -> clb
175- .withMethodBody ("test" , MTD_void , ACC_STATIC , checkedAction )));
176- // Chained builders
177- assertThrows (IllegalArgumentException .class , () -> cf .build (ClassDesc .of ("Test" ), clb -> clb
178- .withMethodBody ("test" , MTD_void , ACC_STATIC , cob -> cob
179- .transforming (CodeTransform .ACCEPT_ALL , checkedAction ))));
180- var classTemplate = cf .build (ClassDesc .of ("Test" ), clb -> clb
181- .withMethodBody ("test" , MTD_void , ACC_STATIC , CodeBuilder ::return_ ));
182- // Indirect builders
183- assertThrows (IllegalArgumentException .class , () -> cf .transformClass (cf .parse (classTemplate ),
184- ClassTransform .transformingMethodBodies (CodeTransform .endHandler (checkedAction )
185- .andThen (noopCodeTransform ))));
231+ try {
232+ TestUtil .runCodeHandler (checkedAction );
233+ } catch (Throwable _) {
234+ System .out .printf ("Erroneous value %d%n" , value );
235+ }
186236 }
187237
188238 static void check (boolean fails , Executable exec ) {
@@ -200,7 +250,10 @@ void testIincConstant() {
200250 IncrementInstruction .of (0 , Short .MIN_VALUE );
201251 for (int i : new int [] {Short .MIN_VALUE - 1 , Short .MAX_VALUE + 1 }) {
202252 assertThrows (IllegalArgumentException .class , () -> IncrementInstruction .of (0 , i ));
203- ensureFailFast (i , cob -> cob .iinc (0 , i ));
253+ TestUtil .runCodeHandler (cob -> {
254+ assertThrows (IllegalArgumentException .class , () -> cob .iinc (0 , i ));
255+ cob .return_ ();
256+ });
204257 }
205258 }
206259
@@ -215,5 +268,14 @@ void testNewMultiArrayDimension() {
215268 assertThrows (IllegalArgumentException .class , () -> NewMultiArrayInstruction .of (ce , -1 ));
216269 assertThrows (IllegalArgumentException .class , () -> NewMultiArrayInstruction .of (ce , Integer .MIN_VALUE ));
217270 assertThrows (IllegalArgumentException .class , () -> NewMultiArrayInstruction .of (ce , Integer .MAX_VALUE ));
271+
272+ TestUtil .runCodeHandler (cob -> {
273+ assertThrows (IllegalArgumentException .class , () -> cob .multianewarray (ce , 0 ));
274+ assertThrows (IllegalArgumentException .class , () -> cob .multianewarray (ce , 0x100 ));
275+ assertThrows (IllegalArgumentException .class , () -> cob .multianewarray (ce , -1 ));
276+ assertThrows (IllegalArgumentException .class , () -> cob .multianewarray (ce , Integer .MIN_VALUE ));
277+ assertThrows (IllegalArgumentException .class , () -> cob .multianewarray (ce , Integer .MAX_VALUE ));
278+ cob .return_ ();
279+ });
218280 }
219281}
0 commit comments