From 56eec6628e3d5eea430bfcb8b5ba6fa801ec80ce Mon Sep 17 00:00:00 2001 From: Karol Bucek Date: Mon, 30 Oct 2023 09:56:00 +0100 Subject: [PATCH] [fix] infinite loop calling Java super from Ruby (#7991) back-port of #7990 --- .../jruby/java/proxies/ConcreteJavaProxy.java | 1 + .../java/org/jruby/javasupport/TestJava.java | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/core/src/main/java/org/jruby/java/proxies/ConcreteJavaProxy.java b/core/src/main/java/org/jruby/java/proxies/ConcreteJavaProxy.java index c91a6658867..abccea732d5 100644 --- a/core/src/main/java/org/jruby/java/proxies/ConcreteJavaProxy.java +++ b/core/src/main/java/org/jruby/java/proxies/ConcreteJavaProxy.java @@ -391,6 +391,7 @@ private static boolean isClassOrIncludedPrependedModule(final RubyModule methodS RubyClass candidate = klass.getSuperClass(); while (candidate != null && (candidate.isIncluded() || candidate.isPrepended())) { // up till 'real' superclass if (candidate == klass) return true; + candidate = candidate.getSuperClass(); } return false; diff --git a/core/src/test/java/org/jruby/javasupport/TestJava.java b/core/src/test/java/org/jruby/javasupport/TestJava.java index 5ef079c0490..9c41bf85be4 100644 --- a/core/src/test/java/org/jruby/javasupport/TestJava.java +++ b/core/src/test/java/org/jruby/javasupport/TestJava.java @@ -1,6 +1,7 @@ package org.jruby.javasupport; import java.lang.reflect.Method; +import java.text.SimpleDateFormat; import org.jruby.*; import org.jruby.exceptions.RaiseException; @@ -140,4 +141,23 @@ public void testJavaConstructorExceptionHandling() throws Exception { } } + @Test + public void testOverrideNewOnConcreteJavaProxySubClassRegression() { + String script = + "class FormatImpl < java.text.SimpleDateFormat\n" + + " include Enumerable\n" + + " public_class_method :new\n" + + " class << self\n" + + " def new(thread_provider: true)\n" + + " super()\n" + + " end\n" + + " end\n" + + "end\n"; + + final Ruby runtime = Ruby.newInstance(); + runtime.evalScriptlet(script); + + assertNotNull(runtime.evalScriptlet("FormatImpl.new")); // used to cause an infinite loop + assertTrue(runtime.evalScriptlet("FormatImpl.new").toJava(Object.class) instanceof SimpleDateFormat); + } }