You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2019/10/11 07:25:30 UTC
[groovy] branch master updated (5bf6b7e -> ce304c4)
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git.
from 5bf6b7e Disable github-actions CI for now
new b68bc43 minor fix-ups
new ce304c4 GROOVY-9270: add checks for invalid instanceof reference types
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../codehaus/groovy/control/CompilationUnit.java | 45 +++++-----
.../groovy/control/InstanceOfVerifier.java | 58 +++++++++++++
.../java/org/codehaus/groovy/syntax/Types.java | 19 ++---
.../{Groovy8046Bug.groovy => Groovy8046.groovy} | 36 ++++----
src/test/groovy/bugs/Groovy9270.groovy | 96 ++++++++++++++++++++++
5 files changed, 209 insertions(+), 45 deletions(-)
create mode 100644 src/main/java/org/codehaus/groovy/control/InstanceOfVerifier.java
rename src/test/groovy/bugs/{Groovy8046Bug.groovy => Groovy8046.groovy} (65%)
create mode 100644 src/test/groovy/bugs/Groovy9270.groovy
[groovy] 02/02: GROOVY-9270: add checks for invalid instanceof
reference types
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit ce304c48f60cad12c0721e6bf000ef5e3a938c6d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Oct 7 14:16:13 2019 -0500
GROOVY-9270: add checks for invalid instanceof reference types
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.20.2
---
.../codehaus/groovy/control/CompilationUnit.java | 8 ++
.../groovy/control/InstanceOfVerifier.java | 58 +++++++++++++
.../java/org/codehaus/groovy/syntax/Types.java | 4 +
src/test/groovy/bugs/Groovy9270.groovy | 96 ++++++++++++++++++++++
4 files changed, 166 insertions(+)
diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 14847e7..7d476b7 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -802,6 +802,14 @@ public class CompilationUnit extends ProcessingUnit {
visitor = new LabelVerifier(source);
visitor.visitClass(classNode);
+ visitor = new InstanceOfVerifier() {
+ @Override
+ protected SourceUnit getSourceUnit() {
+ return source;
+ }
+ };
+ visitor.visitClass(classNode);
+
visitor = new ClassCompletionVerifier(source);
visitor.visitClass(classNode);
diff --git a/src/main/java/org/codehaus/groovy/control/InstanceOfVerifier.java b/src/main/java/org/codehaus/groovy/control/InstanceOfVerifier.java
new file mode 100644
index 0000000..8eacaf2
--- /dev/null
+++ b/src/main/java/org/codehaus/groovy/control/InstanceOfVerifier.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.codehaus.groovy.control;
+
+import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.syntax.Types;
+
+public abstract class InstanceOfVerifier extends ClassCodeVisitorSupport {
+
+ @Override
+ public void visitBinaryExpression(BinaryExpression expression) {
+ if (expression.getOperation().isA(Types.INSTANCEOF_OPERATOR) &&
+ expression.getRightExpression() instanceof ClassExpression) {
+ ClassNode referenceType = expression.getRightExpression().getType();
+
+ if (ClassHelper.isPrimitiveType(referenceType)) {
+ addTypeError(expression.getRightExpression(), "primitive type " + referenceType.getName());
+ } else {
+ while (referenceType.isArray()) {
+ referenceType = referenceType.getComponentType();
+ }
+
+ if (referenceType.isGenericsPlaceHolder()) {
+ addTypeError(expression.getRightExpression(), "type parameter " + referenceType.getUnresolvedName() +
+ ". Use its erasure " + referenceType.getNameWithoutPackage() + " instead since further generic type information will be erased at runtime");
+ } else if (referenceType.getGenericsTypes() != null) {
+ // TODO: Cannot perform instanceof check against parameterized type Class<Type>. Use the form Class<?> instead since further eneric type information will be erased at runtime
+ }
+ }
+ }
+ super.visitBinaryExpression(expression);
+ }
+
+ private void addTypeError(Expression referenceExpr, String referenceType) {
+ addError("Cannot perform instanceof check against " + referenceType, referenceExpr);
+ }
+}
diff --git a/src/main/java/org/codehaus/groovy/syntax/Types.java b/src/main/java/org/codehaus/groovy/syntax/Types.java
index 26e12b9..0464dc6 100644
--- a/src/main/java/org/codehaus/groovy/syntax/Types.java
+++ b/src/main/java/org/codehaus/groovy/syntax/Types.java
@@ -304,6 +304,7 @@ public class Types {
public static final int REGEX_COMPARISON_OPERATOR = 1105; // =~, etc.
public static final int DEREFERENCE_OPERATOR = 1106; // ., ->
public static final int BITWISE_OPERATOR = 1107; // |, &, <<, >>, >>>, ^, ~
+ public static final int INSTANCEOF_OPERATOR = 1108; // instanceof, !instanceof
public static final int PREFIX_OPERATOR = 1200; // ++, !, etc.
public static final int POSTFIX_OPERATOR = 1210; // ++, etc.
@@ -414,6 +415,9 @@ public class Types {
case COMPARISON_OPERATOR:
return specific >= COMPARE_NOT_EQUAL && specific <= COMPARE_TO;
+ case INSTANCEOF_OPERATOR:
+ return specific == KEYWORD_INSTANCEOF || specific == COMPARE_NOT_INSTANCEOF;
+
case MATH_OPERATOR:
return (specific >= PLUS && specific <= RIGHT_SHIFT_UNSIGNED) || (specific >= NOT && specific <= LOGICAL_AND)
|| (specific >= BITWISE_OR && specific <= BITWISE_XOR);
diff --git a/src/test/groovy/bugs/Groovy9270.groovy b/src/test/groovy/bugs/Groovy9270.groovy
new file mode 100644
index 0000000..c4c794a
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9270.groovy
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy9270 {
+
+ @Test
+ void testInstanceOfPrimitive1() {
+ def err = shouldFail '''
+ void meth(obj) {
+ if (obj instanceof int) {
+ // ...
+ }
+ }
+ '''
+
+ assert err =~ / Cannot perform instanceof check against primitive type int/
+ }
+
+ @Test
+ void testInstanceOfPrimitive2() {
+ def err = shouldFail '''
+ void meth(obj) {
+ if (obj !instanceof int) {
+ // ...
+ }
+ }
+ '''
+
+ assert err =~ / Cannot perform instanceof check against primitive type int/
+ }
+
+ @Test
+ void testInstanceOfPrimitiveArray() {
+ assertScript '''
+ void meth(obj) {
+ if (obj instanceof double[]) {
+ // ...
+ }
+ }
+ '''
+ }
+
+ @Test
+ void testInstanceOfTypeParameter1() {
+ def err = shouldFail '''
+ class C<T extends Number> {
+ void meth(obj) {
+ if (obj instanceof T) {
+ // ...
+ }
+ }
+ }
+ '''
+
+ assert err =~ / Cannot perform instanceof check against type parameter T/
+ }
+
+ @Test
+ void testInstanceOfTypeParameter2() {
+ def err = shouldFail '''
+ class C<T> {
+ void meth(obj) {
+ if (obj instanceof T[]) {
+ // ...
+ }
+ }
+ }
+ '''
+
+ assert err =~ / Cannot perform instanceof check against type parameter T/
+ }
+}
[groovy] 01/02: minor fix-ups
Posted by su...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit b68bc43e72e57c2d285fbc34416e5eeed2ebd265
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Oct 7 13:21:20 2019 -0500
minor fix-ups
---
.../codehaus/groovy/control/CompilationUnit.java | 37 +++++++++++-----------
.../java/org/codehaus/groovy/syntax/Types.java | 15 ++-------
.../{Groovy8046Bug.groovy => Groovy8046.groovy} | 36 +++++++++++++--------
3 files changed, 43 insertions(+), 45 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
index 1aa5221..14847e7 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilationUnit.java
@@ -19,13 +19,12 @@
package org.codehaus.groovy.control;
import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyRuntimeException;
import groovy.transform.CompilationUnitAware;
import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ASTNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.CompileUnit;
+import org.codehaus.groovy.ast.GroovyClassVisitor;
import org.codehaus.groovy.ast.InnerClassNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.classgen.AsmClassGenerator;
@@ -44,6 +43,7 @@ import org.codehaus.groovy.control.io.ReaderSource;
import org.codehaus.groovy.control.messages.ExceptionMessage;
import org.codehaus.groovy.control.messages.Message;
import org.codehaus.groovy.control.messages.SimpleMessage;
+import org.codehaus.groovy.syntax.RuntimeParserException;
import org.codehaus.groovy.syntax.SyntaxException;
import org.codehaus.groovy.tools.GroovyClass;
import org.codehaus.groovy.transform.ASTTransformationVisitor;
@@ -792,24 +792,23 @@ public class CompilationUnit extends ProcessingUnit {
//
// Run the Verifier on the outer class
//
+ GroovyClassVisitor visitor = verifier;
try {
- verifier.visitClass(classNode);
- } catch (GroovyRuntimeException rpe) {
- ASTNode node = rpe.getNode();
- getErrorCollector().addError(
- new SyntaxException(rpe.getMessage(), node.getLineNumber(), node.getColumnNumber(), node.getLastLineNumber(), node.getLastColumnNumber()),
- source
- );
+ visitor.visitClass(classNode);
+ } catch (RuntimeParserException rpe) {
+ getErrorCollector().addError(new SyntaxException(rpe.getMessage(), rpe.getNode()), source);
}
- LabelVerifier lv = new LabelVerifier(source);
- lv.visitClass(classNode);
+ visitor = new LabelVerifier(source);
+ visitor.visitClass(classNode);
- ClassCompletionVerifier completionVerifier = new ClassCompletionVerifier(source);
- completionVerifier.visitClass(classNode);
+ visitor = new ClassCompletionVerifier(source);
+ visitor.visitClass(classNode);
- ExtendedVerifier xverifier = new ExtendedVerifier(source);
- xverifier.visitClass(classNode);
+ visitor = new ExtendedVerifier(source);
+ visitor.visitClass(classNode);
+
+ visitor = null;
// because the class may be generated even if a error was found
// and that class may have an invalid format we fail here if needed
@@ -818,28 +817,28 @@ public class CompilationUnit extends ProcessingUnit {
//
// Prep the generator machinery
//
- ClassVisitor visitor = createClassVisitor();
+ ClassVisitor classVisitor = createClassVisitor();
String sourceName = (source == null ? classNode.getModule().getDescription() : source.getName());
// only show the file name and its extension like javac does in its stacktraces rather than the full path
// also takes care of both \ and / depending on the host compiling environment
if (sourceName != null)
sourceName = sourceName.substring(Math.max(sourceName.lastIndexOf('\\'), sourceName.lastIndexOf('/')) + 1);
- AsmClassGenerator generator = new AsmClassGenerator(source, context, visitor, sourceName);
+ AsmClassGenerator generator = new AsmClassGenerator(source, context, classVisitor, sourceName);
//
// Run the generation and create the class (if required)
//
generator.visitClass(classNode);
- byte[] bytes = ((ClassWriter) visitor).toByteArray();
+ byte[] bytes = ((ClassWriter) classVisitor).toByteArray();
generatedClasses.add(new GroovyClass(classNode.getName(), bytes));
//
// Handle any callback that's been set
//
if (CompilationUnit.this.classgenCallback != null) {
- classgenCallback.call(visitor, classNode);
+ classgenCallback.call(classVisitor, classNode);
}
//
diff --git a/src/main/java/org/codehaus/groovy/syntax/Types.java b/src/main/java/org/codehaus/groovy/syntax/Types.java
index 91a98d1..26e12b9 100644
--- a/src/main/java/org/codehaus/groovy/syntax/Types.java
+++ b/src/main/java/org/codehaus/groovy/syntax/Types.java
@@ -20,7 +20,6 @@ package org.codehaus.groovy.syntax;
import org.codehaus.groovy.GroovyBugError;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -368,6 +367,9 @@ public class Types {
//---------------------------------------------------------------------------
// TYPE HIERARCHIES
+ public static boolean isAssignment(int type) {
+ return ofType(type, ASSIGNMENT_OPERATOR);
+ }
/**
* Given two types, returns true if the second describes the first.
@@ -1367,15 +1369,4 @@ public class Types {
addDescription(RIGHT_OF_MATCHED_CONTAINER, "<right of matched container>");
addDescription(SWITCH_ENTRIES, "<valid in a switch body>");
}
-
- private static final int[] ASSIGNMENT_TYPES;
-
- static {
- ASSIGNMENT_TYPES = new int[]{EQUAL, BITWISE_AND_EQUAL, BITWISE_OR_EQUAL, BITWISE_XOR_EQUAL, PLUS_EQUAL, MINUS_EQUAL, MULTIPLY_EQUAL, DIVIDE_EQUAL, INTDIV_EQUAL, MOD_EQUAL, POWER_EQUAL, LEFT_SHIFT_EQUAL, RIGHT_SHIFT_EQUAL, RIGHT_SHIFT_UNSIGNED_EQUAL, ELVIS_EQUAL};
- Arrays.sort(ASSIGNMENT_TYPES);
- }
-
- public static boolean isAssignment(int type) {
- return Arrays.binarySearch(ASSIGNMENT_TYPES, type) >= 0;
- }
}
diff --git a/src/test/groovy/bugs/Groovy8046Bug.groovy b/src/test/groovy/bugs/Groovy8046.groovy
similarity index 65%
rename from src/test/groovy/bugs/Groovy8046Bug.groovy
rename to src/test/groovy/bugs/Groovy8046.groovy
index 3b81814..ed7c653 100644
--- a/src/test/groovy/bugs/Groovy8046Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8046.groovy
@@ -18,38 +18,46 @@
*/
package groovy.bugs
-import gls.CompilableTestSupport
+import groovy.transform.CompileStatic
+import org.junit.Test
-class Groovy8046Bug extends CompilableTestSupport {
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy8046 {
+
+ @Test
void testFieldShouldNotHavePrimitiveVoidType() {
- def message = shouldNotCompile """
+ def err = shouldFail '''
class MyClass {
void field
}
- """
- assert message.contains("The field 'field' has invalid type void") ||
- message.contains("void is not allowed here")
+ '''
+
+ assert err =~ /The field 'field' has invalid type void|void is not allowed here/
}
+ @Test
void testParameterShouldNotHavePrimitiveVoidType() {
- def message = shouldNotCompile """
+ def err = shouldFail '''
class MyClass {
int foo(void param) {}
}
- """
- assert message.contains("The parameter 'param' in method 'int foo(void)' has invalid type void") ||
- message.contains("void is not allowed here")
+ '''
+
+ assert err =~ /The parameter 'param' in method 'int foo\(void\)' has invalid type void|void is not allowed here/
}
+ @Test
void testLocalVariableShouldNotHavePrimitiveVoidType() {
- def message = shouldNotCompile """
+ def err = shouldFail '''
class MyClass {
def foo() {
void bar = null
}
}
- """
- assert message.contains("The variable 'bar' has invalid type void") ||
- message.contains("void is not allowed here")
+ '''
+
+ assert err =~ /The variable 'bar' has invalid type void|void is not allowed here/
}
}