8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 8066103
27 * @summary C2's range check smearing allows out of bound array accesses
28 * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing
29 *
30 */
31
32 public class TestRangeCheckSmearing {
33
34 // first range check is i + max of all constants
35 static int m1(int[] array, int i, boolean allaccesses) {
36 int res = 0;
37 res += array[i+9];
38 if (allaccesses) {
39 res += array[i+8];
40 res += array[i+7];
41 res += array[i+6];
42 res += array[i+5];
43 res += array[i+4];
44 res += array[i+3];
45 res += array[i+2];
46 res += array[i+1];
47 }
48 return res;
49 }
50
51 // first range check is i + min of all constants
52 static int m2(int[] array, int i, boolean allaccesses) {
53 int res = 0;
54 res += array[i+1];
55 if (allaccesses) {
56 res += array[i+2];
57 res += array[i+3];
58 res += array[i+4];
59 res += array[i+5];
60 res += array[i+6];
61 res += array[i+7];
62 res += array[i+8];
63 res += array[i+9];
64 }
65 return res;
66 }
67
68 // first range check is not i + min/max of all constants
69 static int m3(int[] array, int i, boolean allaccesses) {
70 int res = 0;
71 res += array[i+3];
72 if (allaccesses) {
73 res += array[i+2];
74 res += array[i+1];
75 res += array[i+4];
76 res += array[i+5];
77 res += array[i+6];
78 res += array[i+7];
79 res += array[i+8];
80 res += array[i+9];
81 }
82 return res;
83 }
84
85 static int m4(int[] array, int i, boolean allaccesses) {
86 int res = 0;
87 res += array[i+3];
88 if (allaccesses) {
89 res += array[i+4];
90 res += array[i+1];
91 res += array[i+2];
92 res += array[i+5];
93 res += array[i+6];
94 res += array[i+7];
95 res += array[i+8];
96 res += array[i+9];
97 }
98 return res;
99 }
100
101 static int m5(int[] array, int i, boolean allaccesses) {
102 int res = 0;
103 res += array[i+3];
104 res += array[i+2];
105 if (allaccesses) {
106 res += array[i+1];
107 res += array[i+4];
108 res += array[i+5];
109 res += array[i+6];
110 res += array[i+7];
111 res += array[i+8];
112 res += array[i+9];
113 }
114 return res;
115 }
116
117 static int m6(int[] array, int i, boolean allaccesses) {
118 int res = 0;
119 res += array[i+3];
120 res += array[i+4];
121 if (allaccesses) {
122 res += array[i+2];
123 res += array[i+1];
124 res += array[i+5];
125 res += array[i+6];
126 res += array[i+7];
127 res += array[i+8];
128 res += array[i+9];
129 }
130 return res;
131 }
132
133 static int m7(int[] array, int i, boolean allaccesses) {
134 int res = 0;
135 res += array[i+3];
136 res += array[i+2];
137 res += array[i+4];
138 if (allaccesses) {
139 res += array[i+1];
140 res += array[i+5];
141 res += array[i+6];
142 res += array[i+7];
143 res += array[i+8];
144 res += array[i+9];
145 }
146 return res;
147 }
148
149 static int m8(int[] array, int i, boolean allaccesses) {
150 int res = 0;
151 res += array[i+3];
152 res += array[i+4];
153 res += array[i+2];
154 if (allaccesses) {
155 res += array[i+1];
156 res += array[i+5];
157 res += array[i+6];
158 res += array[i+7];
159 res += array[i+8];
160 res += array[i+9];
161 }
162 return res;
163 }
164
165 static int m9(int[] array, int i) {
166 int res = 0;
167 res += array[i+3];
168 res += array[i+3];
169 return res;
170 }
171
172 static int m10(int[] array, int i, boolean allaccesses) {
173 int res = 0;
174 res += array[i+3];
175 if (allaccesses) {
176 res += array[i-2];
177 res += array[i-1];
178 res += array[i-4];
179 res += array[i-5];
180 res += array[i-6];
181 }
182 return res;
183 }
184
185 static int m11(int[] array, int i, boolean allaccesses) {
186 int res = 0;
187 res += array[i+3];
188 if (allaccesses) {
189 res += array[i-2];
190 res += array[i-1];
191 res += array[i-3];
192 res += array[i+4];
193 res += array[i+5];
194 res += array[i+6];
195 }
196 return res;
197 }
198
199 static int m12(int[] array, int i, boolean allaccesses) {
200 int res = 0;
201 res += array[i+3];
202 res += array[i-2];
203 if (allaccesses) {
204 res += array[i+5];
205 res += array[i+6];
206 }
207 return res;
208 }
209
210 static int m13(int[] array, int i, boolean allaccesses) {
211 int res = 0;
212 res += array[i+3];
213 res += array[i+6];
214 if (allaccesses) {
215 res += array[i-2];
216 res += array[i-3];
217 }
218 return res;
219 }
220
221 static public void main(String[] args) {
222 boolean success = true;
223 boolean exception = false;
224 int[] array = new int[10];
225
226 for (int i = 0; i < 20000; i++) {
227 m1(array, 0, (i % 2) == 0);
228 }
229
230 exception = false;
231 try {
232 m1(array, 8, false);
233 } catch(ArrayIndexOutOfBoundsException aioob) {
234 exception = true;
235 System.out.println("ArrayIndexOutOfBoundsException thrown in m1");
236 }
237 if (!exception) {
238 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m1");
239 success = false;
240 }
241
242 for (int i = 0; i < 20000; i++) {
243 m2(array, 0, (i % 2) == 0);
244 }
245
246 exception = false;
247 try {
248 m2(array, -9, false);
249 } catch(ArrayIndexOutOfBoundsException aioob) {
250 exception = true;
251 System.out.println("ArrayIndexOutOfBoundsException thrown in m2");
252 }
253 if (!exception) {
254 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m2");
255 success = false;
256 }
257
258 for (int i = 0; i < 20000; i++) {
259 m3(array, 0, (i % 2) == 0);
260 }
261
262 exception = false;
263 try {
264 m3(array, 8, false);
265 } catch(ArrayIndexOutOfBoundsException aioob) {
266 exception = true;
267 System.out.println("ArrayIndexOutOfBoundsException thrown in m3");
268 }
269 if (!exception) {
270 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m3");
271 success = false;
272 }
273
274 for (int i = 0; i < 20000; i++) {
275 m4(array, 0, (i % 2) == 0);
276 }
277
278 exception = false;
279 try {
280 m4(array, -9, false);
281 } catch(ArrayIndexOutOfBoundsException aioob) {
282 exception = true;
283 System.out.println("ArrayIndexOutOfBoundsException thrown in m4");
284 }
285 if (!exception) {
286 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m4");
287 success = false;
288 }
289
290 for (int i = 0; i < 20000; i++) {
291 m5(array, 0, (i % 2) == 0);
292 }
293
294 exception = false;
295 try {
296 m5(array, -3, false);
297 } catch(ArrayIndexOutOfBoundsException aioob) {
298 exception = true;
299 System.out.println("ArrayIndexOutOfBoundsException thrown in m5");
300 }
301 if (!exception) {
302 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m5");
303 success = false;
304 }
305
306 for (int i = 0; i < 20000; i++) {
307 m6(array, 0, (i % 2) == 0);
308 }
309
310 exception = false;
311 try {
312 m6(array, 6, false);
313 } catch(ArrayIndexOutOfBoundsException aioob) {
314 exception = true;
315 System.out.println("ArrayIndexOutOfBoundsException thrown in m6");
316 }
317 if (!exception) {
318 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m6");
319 success = false;
320 }
321
322 for (int i = 0; i < 20000; i++) {
323 m7(array, 0, (i % 2) == 0);
324 }
325
326 exception = false;
327 try {
328 m7(array, 6, false);
329 } catch(ArrayIndexOutOfBoundsException aioob) {
330 exception = true;
331 System.out.println("ArrayIndexOutOfBoundsException thrown in m7");
332 }
333 if (!exception) {
334 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m7");
335 success = false;
336 }
337
338 for (int i = 0; i < 20000; i++) {
339 m8(array, 0, (i % 2) == 0);
340 }
341
342 exception = false;
343 try {
344 m8(array, -3, false);
345 } catch(ArrayIndexOutOfBoundsException aioob) {
346 exception = true;
347 System.out.println("ArrayIndexOutOfBoundsException thrown in m8");
348 }
349 if (!exception) {
350 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m8");
351 success = false;
352 }
353
354 for (int i = 0; i < 20000; i++) {
355 m9(array, 0);
356 }
357
358
359 for (int i = 0; i < 20000; i++) {
360 m10(array, 6, (i % 2) == 0);
361 }
362
363 exception = false;
364 try {
365 m10(array, 15, false);
366 } catch(ArrayIndexOutOfBoundsException aioob) {
367 exception = true;
368 System.out.println("ArrayIndexOutOfBoundsException thrown in m10");
369 }
370 if (!exception) {
371 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m10");
372 success = false;
373 }
374
375 for (int i = 0; i < 20000; i++) {
376 m11(array, 3, (i % 2) == 0);
377 }
378
379 exception = false;
380 try {
381 m11(array, 12, false);
382 } catch(ArrayIndexOutOfBoundsException aioob) {
383 exception = true;
384 System.out.println("ArrayIndexOutOfBoundsException thrown in m11");
385 }
386 if (!exception) {
387 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m11");
388 success = false;
389 }
390
391 for (int i = 0; i < 20000; i++) {
392 m12(array, 3, (i % 2) == 0);
393 }
394
395 exception = false;
396 try {
397 m12(array, -3, false);
398 } catch(ArrayIndexOutOfBoundsException aioob) {
399 exception = true;
400 System.out.println("ArrayIndexOutOfBoundsException thrown in m12");
401 }
402 if (!exception) {
403 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m12");
404 success = false;
405 }
406
407 for (int i = 0; i < 20000; i++) {
408 m13(array, 3, (i % 2) == 0);
409 }
410
411 exception = false;
412 try {
413 m13(array, 6, false);
414 } catch(ArrayIndexOutOfBoundsException aioob) {
415 exception = true;
416 System.out.println("ArrayIndexOutOfBoundsException thrown in m13");
417 }
418 if (!exception) {
419 System.out.println("ArrayIndexOutOfBoundsException was not thrown in m13");
420 success = false;
421 }
422
423 if (!success) {
424 throw new RuntimeException("Some tests failed");
425 }
426 }
427 }
|
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 /*
25 * @test
26 * @bug 8066103
27 * @summary C2's range check smearing allows out of bound array accesses
28 * @library /testlibrary /testlibrary/whitebox /compiler/whitebox /testlibrary/com/oracle/java/testlibrary
29 * @build TestRangeCheckSmearing
30 * @run main ClassFileInstaller sun.hotspot.WhiteBox
31 * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
32 * @run main/othervm -ea -Xmixed -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
33 * -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestRangeCheckSmearing
34 *
35 */
36
37 import java.lang.annotation.*;
38 import java.lang.reflect.*;
39 import java.util.*;
40 import sun.hotspot.WhiteBox;
41 import sun.hotspot.code.NMethod;
42 import com.oracle.java.testlibrary.Platform;
43
44 public class TestRangeCheckSmearing {
45 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
46
47 @Retention(RetentionPolicy.RUNTIME)
48 @interface Args { int[] value(); }
49
50 // first range check is i + max of all constants
51 @Args({0, 8})
52 static int m1(int[] array, int i, boolean allaccesses) {
53 int res = 0;
54 res += array[i+9];
55 if (allaccesses) {
56 res += array[i+8];
57 res += array[i+7];
58 res += array[i+6];
59 res += array[i+5];
60 res += array[i+4];
61 res += array[i+3];
62 res += array[i+2];
63 res += array[i+1];
64 }
65 return res;
66 }
67
68 // first range check is i + min of all constants
69 @Args({0, -9})
70 static int m2(int[] array, int i, boolean allaccesses) {
71 int res = 0;
72 res += array[i+1];
73 if (allaccesses) {
74 res += array[i+2];
75 res += array[i+3];
76 res += array[i+4];
77 res += array[i+5];
78 res += array[i+6];
79 res += array[i+7];
80 res += array[i+8];
81 res += array[i+9];
82 }
83 return res;
84 }
85
86 // first range check is not i + min/max of all constants
87 @Args({0, 8})
88 static int m3(int[] array, int i, boolean allaccesses) {
89 int res = 0;
90 res += array[i+3];
91 if (allaccesses) {
92 res += array[i+2];
93 res += array[i+1];
94 res += array[i+4];
95 res += array[i+5];
96 res += array[i+6];
97 res += array[i+7];
98 res += array[i+8];
99 res += array[i+9];
100 }
101 return res;
102 }
103
104 @Args({0, -9})
105 static int m4(int[] array, int i, boolean allaccesses) {
106 int res = 0;
107 res += array[i+3];
108 if (allaccesses) {
109 res += array[i+4];
110 res += array[i+1];
111 res += array[i+2];
112 res += array[i+5];
113 res += array[i+6];
114 res += array[i+7];
115 res += array[i+8];
116 res += array[i+9];
117 }
118 return res;
119 }
120
121 @Args({0, -3})
122 static int m5(int[] array, int i, boolean allaccesses) {
123 int res = 0;
124 res += array[i+3];
125 res += array[i+2];
126 if (allaccesses) {
127 res += array[i+1];
128 res += array[i+4];
129 res += array[i+5];
130 res += array[i+6];
131 res += array[i+7];
132 res += array[i+8];
133 res += array[i+9];
134 }
135 return res;
136 }
137
138 @Args({0, 6})
139 static int m6(int[] array, int i, boolean allaccesses) {
140 int res = 0;
141 res += array[i+3];
142 res += array[i+4];
143 if (allaccesses) {
144 res += array[i+2];
145 res += array[i+1];
146 res += array[i+5];
147 res += array[i+6];
148 res += array[i+7];
149 res += array[i+8];
150 res += array[i+9];
151 }
152 return res;
153 }
154
155 @Args({0, 6})
156 static int m7(int[] array, int i, boolean allaccesses) {
157 int res = 0;
158 res += array[i+3];
159 res += array[i+2];
160 res += array[i+4];
161 if (allaccesses) {
162 res += array[i+1];
163 res += array[i+5];
164 res += array[i+6];
165 res += array[i+7];
166 res += array[i+8];
167 res += array[i+9];
168 }
169 return res;
170 }
171
172 @Args({0, -3})
173 static int m8(int[] array, int i, boolean allaccesses) {
174 int res = 0;
175 res += array[i+3];
176 res += array[i+4];
177 res += array[i+2];
178 if (allaccesses) {
179 res += array[i+1];
180 res += array[i+5];
181 res += array[i+6];
182 res += array[i+7];
183 res += array[i+8];
184 res += array[i+9];
185 }
186 return res;
187 }
188
189 @Args({0})
190 static int m9(int[] array, int i, boolean ignore) {
191 int res = 0;
192 res += array[i+3];
193 res += array[i+3];
194 return res;
195 }
196
197 @Args({6, 15})
198 static int m10(int[] array, int i, boolean allaccesses) {
199 int res = 0;
200 res += array[i+3];
201 if (allaccesses) {
202 res += array[i-2];
203 res += array[i-1];
204 res += array[i-4];
205 res += array[i-5];
206 res += array[i-6];
207 }
208 return res;
209 }
210
211 @Args({3, 12})
212 static int m11(int[] array, int i, boolean allaccesses) {
213 int res = 0;
214 res += array[i+3];
215 if (allaccesses) {
216 res += array[i-2];
217 res += array[i-1];
218 res += array[i-3];
219 res += array[i+4];
220 res += array[i+5];
221 res += array[i+6];
222 }
223 return res;
224 }
225
226 @Args({3, -3})
227 static int m12(int[] array, int i, boolean allaccesses) {
228 int res = 0;
229 res += array[i+3];
230 res += array[i-2];
231 if (allaccesses) {
232 res += array[i+5];
233 res += array[i+6];
234 }
235 return res;
236 }
237
238 @Args({3, 6})
239 static int m13(int[] array, int i, boolean allaccesses) {
240 int res = 0;
241 res += array[i+3];
242 res += array[i+6];
243 if (allaccesses) {
244 res += array[i-2];
245 res += array[i-3];
246 }
247 return res;
248 }
249
250 static public void main(String[] args) {
251 if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
252 throw new AssertionError("Background compilation enabled");
253 }
254 new TestRangeCheckSmearing().doTests();
255 }
256 boolean success = true;
257 boolean exception = false;
258 final int[] array = new int[10];
259 final HashMap<String,Method> tests = new HashMap<>();
260 {
261 final Class<?> TEST_PARAM_TYPES[] = { int[].class, int.class, boolean.class };
262 for (Method m : this.getClass().getDeclaredMethods()) {
263 if (m.getName().matches("m[0-9]+")) {
264 assert(Modifier.isStatic(m.getModifiers())) : m;
265 assert(m.getReturnType() == int.class) : m;
266 assert(Arrays.equals(m.getParameterTypes(), TEST_PARAM_TYPES)) : m;
267 tests.put(m.getName(), m);
268 }
269 }
270 }
271
272 void invokeTest(Method m, int[] array, int index, boolean z) {
273 try {
274 m.invoke(null, array, index, z);
275 } catch (ReflectiveOperationException roe) {
276 Throwable ex = roe.getCause();
277 if (ex instanceof ArrayIndexOutOfBoundsException)
278 throw (ArrayIndexOutOfBoundsException) ex;
279 throw new AssertionError(roe);
280 }
281 }
282
283 void doTest(String name) {
284 Method m = tests.get(name);
285 tests.remove(name);
286 int[] args = m.getAnnotation(Args.class).value();
287 int index0 = args[0], index1;
288 boolean exceptionRequired = true;
289 if (args.length == 2) {
290 index1 = args[1];
291 } else {
292 // no negative test for this one
293 assert(args.length == 1);
294 assert(name.equals("m9"));
295 exceptionRequired = false;
296 index1 = index0;
297 }
298 // Get the method compiled.
299 if (!WHITE_BOX.isMethodCompiled(m)) {
300 // If not, try to compile it with C2
301 if(!WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION)) {
302 // C2 compiler not available, try to compile with C1
303 WHITE_BOX.enqueueMethodForCompilation(m, CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE);
304 }
305 }
306 if (!WHITE_BOX.isMethodCompiled(m)) {
307 throw new RuntimeException(m + " not compiled");
308 }
309
310 // valid access
311 invokeTest(m, array, index0, true);
312
313 if (!WHITE_BOX.isMethodCompiled(m)) {
314 throw new RuntimeException(m + " deoptimized on valid array access");
315 }
316
317 exception = false;
318 try {
319 invokeTest(m, array, index1, false);
320 } catch(ArrayIndexOutOfBoundsException aioob) {
321 exception = true;
322 System.out.println("ArrayIndexOutOfBoundsException thrown in "+name);
323 }
324 if (!exception) {
325 System.out.println("ArrayIndexOutOfBoundsException was not thrown in "+name);
326 }
327
328 if (Platform.isServer()) {
329 if (exceptionRequired == WHITE_BOX.isMethodCompiled(m)) {
330 System.out.println((exceptionRequired?"Didn't deoptimized":"deoptimized") + " in "+name);
331 success = false;
332 }
333 }
334
335 if (exception != exceptionRequired) {
336 success = false;
337 }
338
339 if (!success) {
340 System.out.println("TEST FAILED: "+name);
341 }
342
343 }
344 void doTests() {
345 doTest("m1");
346 doTest("m2");
347 doTest("m3");
348 doTest("m4");
349 doTest("m5");
350 doTest("m6");
351 doTest("m7");
352 doTest("m8");
353 doTest("m9");
354 doTest("m10");
355 doTest("m11");
356 doTest("m12");
357 doTest("m13");
358 if (!success) {
359 throw new RuntimeException("Some tests failed");
360 }
361 assert(tests.isEmpty()) : tests;
362 }
363 }
|