undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8307683
|
||||
* @library /test/lib /
|
||||
* @requires vm.compiler2.enabled
|
||||
* @summary Tests that IfNode is not wrongly chosen as range check by Loop Predication leading to crashes and wrong executions.
|
||||
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.predicates.TestHoistedPredicateForNonRangeCheck::test*
|
||||
* compiler.predicates.TestHoistedPredicateForNonRangeCheck
|
||||
* @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.predicates.TestHoistedPredicateForNonRangeCheck::test*
|
||||
* -XX:LoopMaxUnroll=0 compiler.predicates.TestHoistedPredicateForNonRangeCheck
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8307683
|
||||
* @library /test/lib /
|
||||
* @summary Tests that IfNode is not wrongly chosen as range check by Loop Predication leading to crashes and wrong executions.
|
||||
* @run main/othervm -Xbatch compiler.predicates.TestHoistedPredicateForNonRangeCheck calendar
|
||||
*/
|
||||
|
||||
package compiler.predicates;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
public class TestHoistedPredicateForNonRangeCheck {
|
||||
static int iFld, iFld2;
|
||||
static int[] iArr = new int[100];
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length == 0) {
|
||||
Integer.compareUnsigned(34, 34); // Ensure Integer class is loaded and we do not emit a trap inside test() for it.
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
iFld = 0;
|
||||
iFld2 = 0;
|
||||
test();
|
||||
Asserts.assertEQ(iFld, 3604, "wrong value");
|
||||
Asserts.assertEQ(iFld2, 400, "wrong value");
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2000; i++) {
|
||||
iFld = -100;
|
||||
testRangeCheckNode();
|
||||
}
|
||||
iFld = -1;
|
||||
iFld2 = 0;
|
||||
testRangeCheckNode();
|
||||
Asserts.assertEQ(iFld2, 36, "wrong value");
|
||||
} else {
|
||||
boolean flag = false;
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
testCalendar1();
|
||||
testCalendar2(flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void test() {
|
||||
for (int i = -1; i < 1000; i++) {
|
||||
// We hoist this check and insert a Hoisted Predicate for the lower and upper bound:
|
||||
// -1 >=u 100 && 1000 >= u 100 -> always true and the predicates are removed.
|
||||
// Template Assertion Predicates, however, are kept. When splitting this loop further, we insert an Assertion
|
||||
// Predicate which fails for i = 0 and we halt.
|
||||
// When not splitting this loop (with LoopMaxUnroll=0), we have a wrong execution due to never executing
|
||||
// iFld2++ (we remove the check and the branch with the trap when creating the Hoisted Predicates).
|
||||
if (Integer.compareUnsigned(i, 100) < 0) {
|
||||
iFld2++;
|
||||
Float.isNaN(34); // Float class is unloaded with -Xcomp -> inserts trap
|
||||
} else {
|
||||
iFld++;
|
||||
}
|
||||
|
||||
// Same but flipped condition and moved trap to other branch - result is the same.
|
||||
if (Integer.compareUnsigned(i, 100) >= 0) { // Loop Predication creates a Hoisted Range Check Predicate due to trap with Float.isNan().
|
||||
iFld++;
|
||||
} else {
|
||||
iFld2++;
|
||||
Float.isNaN(34); // Float class is unloaded with -Xcomp -> inserts trap
|
||||
}
|
||||
|
||||
// Same but with LoadRangeNode.
|
||||
if (Integer.compareUnsigned(i, iArr.length) >= 0) { // Loop Predication creates a Hoisted Range Check Predicate due to trap with Float.isNan().
|
||||
iFld++;
|
||||
} else {
|
||||
iFld2++;
|
||||
Float.isNaN(34); // Float class is unloaded with -Xcomp -> inserts trap
|
||||
}
|
||||
|
||||
// Same but with LoadRangeNode and flipped condition and moved trap to other branch - result is the same.
|
||||
if (Integer.compareUnsigned(i, iArr.length) >= 0) { // Loop Predication creates a Hoisted Range Check Predicate due to trap with Float.isNan().
|
||||
iFld++;
|
||||
} else {
|
||||
iFld2++;
|
||||
Float.isNaN(34); // Float class is unloaded with -Xcomp -> inserts trap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void testRangeCheckNode() {
|
||||
int array[] = new int[34];
|
||||
// Hoisted Range Check Predicate with flipped bool because trap is on success proj and no trap on false proj due
|
||||
// to catching exception:
|
||||
// iFld >=u 34 && iFld+36 >=u 34
|
||||
// This is always false for first 2000 iterations where, initially, iFld = -100
|
||||
// It is still true in the last iteration where, initially, iFld = -1. But suddenly, in the second iteration,
|
||||
// where iFld = 0, we would take the true projection for the first time - but we removed that branch when
|
||||
// creating the Hoisted Range Check Predicate. We therefore run into the same problem as with test(): We either
|
||||
// halt due to Assertion Predicates catching this case or we have a wrong execution (iFld2 never updated).
|
||||
for (int i = 0; i < 37; i++) {
|
||||
try {
|
||||
array[iFld] = 34; // Normal RangeCheckNode
|
||||
iFld2++;
|
||||
Math.ceil(34); // Never taken and unloaded -> trap
|
||||
} catch (Exception e) {
|
||||
// False Proj of RangeCheckNode
|
||||
iFld++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reported in JDK-8307683
|
||||
static void testCalendar1() {
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setLenient(false);
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.getTime();
|
||||
}
|
||||
|
||||
// Reported in JDK-8307978
|
||||
static void testCalendar2(boolean flag) {
|
||||
flag = !flag;
|
||||
Calendar timespan = removeTime(new Date(), flag);
|
||||
timespan.getTime();
|
||||
}
|
||||
|
||||
static Calendar removeTime(Date date, boolean flag) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (flag) {
|
||||
calendar.setLenient(false);
|
||||
}
|
||||
calendar.setTime(date);
|
||||
calendar = removeTime(calendar);
|
||||
return calendar;
|
||||
}
|
||||
|
||||
static Calendar removeTime(Calendar calendar) {
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
return calendar;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue