8138840: NPE when compiling bitwise operations with illegal operand types
8139243: compiler crashes with exception on sum operation of String var and void method call result
8139249: Compiler crashes on unary bitwise complement with non-integral operand
Summary: Certain binary operator checks are accepting more operands than required.
Reviewed-by: jlahoda
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Wed Jul 05 20:53:25 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Type.java Mon Oct 12 12:24:33 2015 +0100
@@ -142,6 +142,10 @@
return false;
}
+ public boolean isIntegral() {
+ return false;
+ }
+
public boolean isPrimitive() {
return false;
}
@@ -697,6 +701,20 @@
}
@Override
+ public boolean isIntegral() {
+ switch (tag) {
+ case CHAR:
+ case BYTE:
+ case SHORT:
+ case INT:
+ case LONG:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
public boolean isPrimitive() {
return true;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java Wed Jul 05 20:53:25 2017 +0200
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java Mon Oct 12 12:24:33 2015 +0100
@@ -404,13 +404,20 @@
*/
class UnaryNumericOperator extends UnaryOperatorHelper {
+ Predicate<Type> numericTest;
+
UnaryNumericOperator(Tag tag) {
+ this(tag, Type::isNumeric);
+ }
+
+ UnaryNumericOperator(Tag tag, Predicate<Type> numericTest) {
super(tag);
+ this.numericTest = numericTest;
}
@Override
public boolean test(Type type) {
- return unaryPromotion(type).isNumeric();
+ return numericTest.test(unaryPromotion(type));
}
@Override
@@ -462,8 +469,15 @@
*/
class BinaryNumericOperator extends BinaryOperatorHelper {
+ Predicate<Type> numericTest;
+
BinaryNumericOperator(Tag tag) {
+ this(tag, Type::isNumeric);
+ }
+
+ BinaryNumericOperator(Tag tag, Predicate<Type> numericTest) {
super(tag);
+ this.numericTest = numericTest;
}
@Override
@@ -474,7 +488,8 @@
@Override
public boolean test(Type arg1, Type arg2) {
- return unaryPromotion(arg1).isNumeric() && unaryPromotion(arg2).isNumeric();
+ return numericTest.test(unaryPromotion(arg1)) &&
+ numericTest.test(unaryPromotion(arg2));
}
}
@@ -518,20 +533,22 @@
@Override
public boolean test(Type arg1, Type arg2) {
- return types.isSameType(arg1, syms.stringType) ||
+ boolean hasStringOp = types.isSameType(arg1, syms.stringType) ||
types.isSameType(arg2, syms.stringType);
+ boolean hasVoidOp = arg1.hasTag(TypeTag.VOID) || arg2.hasTag(TypeTag.VOID);
+ return hasStringOp && !hasVoidOp;
}
/**
* This routine applies following mappings:
* - if input type is primitive, apply numeric promotion
- * - if input type is either 'null' or 'String' leave it untouched
+ * - if input type is either 'void', 'null' or 'String' leave it untouched
* - otherwise return 'Object'
*/
private Type stringPromotion(Type t) {
if (t.isPrimitive()) {
return unaryPromotion(t);
- } else if (t.hasTag(TypeTag.BOT) ||
+ } else if (t.hasTag(TypeTag.VOID) || t.hasTag(TypeTag.BOT) ||
types.isSameType(t, syms.stringType)) {
return t;
} else if (t.hasTag(TypeTag.TYPEVAR)) {
@@ -640,7 +657,7 @@
.addUnaryOperator(FLOAT, FLOAT, fneg)
.addUnaryOperator(LONG, LONG, lneg)
.addUnaryOperator(INT, INT, ineg),
- new UnaryNumericOperator(Tag.COMPL)
+ new UnaryNumericOperator(Tag.COMPL, Type::isIntegral)
.addUnaryOperator(LONG, LONG, lxor)
.addUnaryOperator(INT, INT, ixor),
new UnaryPrefixPostfixOperator(Tag.POSTINC)
@@ -713,17 +730,17 @@
.addBinaryOperator(INT, INT, INT, imod),
new BinaryBooleanOperator(Tag.BITAND)
.addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, iand),
- new BinaryNumericOperator(Tag.BITAND)
+ new BinaryNumericOperator(Tag.BITAND, Type::isIntegral)
.addBinaryOperator(LONG, LONG, LONG, land)
.addBinaryOperator(INT, INT, INT, iand),
new BinaryBooleanOperator(Tag.BITOR)
.addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ior),
- new BinaryNumericOperator(Tag.BITOR)
+ new BinaryNumericOperator(Tag.BITOR, Type::isIntegral)
.addBinaryOperator(LONG, LONG, LONG, lor)
.addBinaryOperator(INT, INT, INT, ior),
new BinaryBooleanOperator(Tag.BITXOR)
.addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ixor),
- new BinaryNumericOperator(Tag.BITXOR)
+ new BinaryNumericOperator(Tag.BITXOR, Type::isIntegral)
.addBinaryOperator(LONG, LONG, LONG, lxor)
.addBinaryOperator(INT, INT, INT, ixor),
new BinaryShiftOperator(Tag.SL)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8138840.java Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,12 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+ * @compile/fail/ref=T8138840.out -XDrawDiagnostics T8138840.java
+ */
+
+class T8138840 {
+ void test(int x, double d) {
+ Object o = x & d;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8138840.out Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,2 @@
+T8138840.java:10:22: compiler.err.operator.cant.be.applied.1: &, int, double
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139243.java Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,16 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+ * 'void' is erroneously accepted as a possible operand for string concatenation
+ * @compile/fail/ref=T8139243.out -XDrawDiagnostics T8139243.java
+ */
+
+class T8139243 {
+
+ void test(String s) {
+ s += m(); // compile time error
+ }
+
+ void m() { }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139243.out Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,2 @@
+T8139243.java:12:11: compiler.err.operator.cant.be.applied.1: +, java.lang.String, void
+1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139249.java Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug 8138840 8139243 8139249
+ * @summary Compiler crashes when compiling bitwise operations with illegal operand types
+* Unary operator erroneously applied to non-integral type operand
+ * @compile/fail/ref=T8139249.out -XDrawDiagnostics T8139249.java
+ */
+
+class T8139249 {
+ void test(float f2) {
+ float f1 = ~f2;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/8138840/T8139249.out Mon Oct 12 12:24:33 2015 +0100
@@ -0,0 +1,2 @@
+T8139249.java:11:20: compiler.err.operator.cant.be.applied: ~, float
+1 error