You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/11/11 19:47:27 UTC
[groovy] 01/02: GROOVY-7722: prevent stack overflow resolving
generics placeholders
This is an automated email from the ASF dual-hosted git repository.
paulk pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 3f2632f9a05457f28ad7e8423223a41eaaa1d558
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 9 10:16:10 2019 -0600
GROOVY-7722: prevent stack overflow resolving generics placeholders
GROOVY-7864
---
.../codehaus/groovy/ast/tools/GenericsUtils.java | 2 +
src/test/groovy/bugs/Groovy7722.groovy | 83 ++++++++++++++++++++++
2 files changed, 85 insertions(+)
diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 7a1d21c..adc1fc4 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -55,6 +55,7 @@ import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import static org.codehaus.groovy.ast.GenericsType.GenericsTypeName;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.plus;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
@@ -356,6 +357,7 @@ public class GenericsUtils {
}
if (type.isGenericsPlaceHolder() && !exclusions.contains(type.getUnresolvedName())) {
String name = type.getGenericsTypes()[0].getName();
+ exclusions = plus(exclusions, name); // GROOVY-7722
type = genericsSpec.get(name);
if (type != null && type.isGenericsPlaceHolder() && type.getGenericsTypes() == null) {
ClassNode placeholder = ClassHelper.makeWithoutCaching(type.getUnresolvedName());
diff --git a/src/test/groovy/bugs/Groovy7722.groovy b/src/test/groovy/bugs/Groovy7722.groovy
new file mode 100644
index 0000000..1fd017c
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7722.groovy
@@ -0,0 +1,83 @@
+/*
+ * 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
+
+@CompileStatic
+final class Groovy7722 {
+
+ @Test
+ void testGenericsStackOverflow1() {
+ assertScript '''
+ interface Action1<T> {
+ void call(T t)
+ }
+ abstract class Subscriber<T> {
+ }
+ interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
+ }
+
+ new OnSubscribe<List>() {
+ @Override
+ void call(Subscriber<? super List> o) {
+ println 'called'
+ }
+ }.call(null)
+ '''
+ }
+
+ @Test // GROOVY-7864
+ void testGenericsStackOverflow2() {
+ assertScript '''
+ // from RxJava 1.x
+ class Observable<T> {
+ interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
+ }
+ static <T> Observable<T> create(OnSubscribe<T> f) {
+ return new Observable<T>(/*RxJavaHooks.onCreate(f)*/);
+ }
+ }
+ abstract class Subscriber<T> implements Observer<T>, Subscription {
+ }
+ interface Action1<T> /*extends Action*/ {
+ void call(T t)
+ }
+ interface Observer<T> {
+ void onNext(T t)
+ void onCompleted()
+ void onError(Throwable t)
+ }
+ public interface Subscription {
+ void unsubscribe()
+ boolean isUnsubscribed()
+ }
+
+ Observable.create(new Observable.OnSubscribe() {
+ @Override
+ void call(Subscriber subscriber) {
+ //...
+ }
+ })
+ '''
+ }
+}