This is an automated email from the ASF dual-hosted git repository.

sebastian-nagel pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nutch.git


The following commit(s) were added to refs/heads/master by this push:
     new 5bcb0ab87 NUTCH-3180 BasicURLNormalizer missing catching 
ICUInputTooLongException  (#923)
5bcb0ab87 is described below

commit 5bcb0ab87d263d3700b835113d6ee7facbe3d7e7
Author: Luca <[email protected]>
AuthorDate: Fri Jun 12 15:24:49 2026 +0200

    NUTCH-3180 BasicURLNormalizer missing catching ICUInputTooLongException  
(#923)
    
    * fix: wrap the exceptions of host validation and rethrow 
MalformedURLException
    * test: cover exception chain
---
 src/java/org/apache/nutch/util/URLUtil.java     | 21 ++++++++++++++++-----
 src/test/org/apache/nutch/util/TestURLUtil.java | 16 ++++++++++++++++
 2 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/src/java/org/apache/nutch/util/URLUtil.java 
b/src/java/org/apache/nutch/util/URLUtil.java
index fd036480a..851d10bef 100644
--- a/src/java/org/apache/nutch/util/URLUtil.java
+++ b/src/java/org/apache/nutch/util/URLUtil.java
@@ -24,6 +24,7 @@ import java.net.URL;
 import java.util.Locale;
 import java.util.regex.Pattern;
 
+import com.ibm.icu.util.ICUException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -652,7 +653,6 @@ public class URLUtil {
       // IndexOutOfBoundsException: thrown (undocumented) if one "label"
       // (non-ASCII dot-separated segment) is longer than 256 characters,
       // cf. https://bugs.openjdk.java.net/browse/JDK-6806873
-      LOG.debug("Failed to convert IDN host {}: ", host, e);
       throw (MalformedURLException) new MalformedURLException(
           "Invalid IDN " + host + ": " + e.getMessage()).initCause(e);
     }
@@ -675,11 +675,22 @@ public class URLUtil {
       throws MalformedURLException {
     final IDNA.Info idnaInfo = new IDNA.Info();
     final StringBuilder hostConverted = new StringBuilder();
-    if (toAscii) {
-      idna.nameToASCII(host, hostConverted, idnaInfo);
-    } else {
-      idna.nameToUnicode(host, hostConverted, idnaInfo);
+    try {
+      if (toAscii) {
+        idna.nameToASCII(host, hostConverted, idnaInfo);
+      } else {
+        idna.nameToUnicode(host, hostConverted, idnaInfo);
+      }
+    } catch (ICUException | IllegalStateException  e) {
+      // ICU's UTS46 + Punycode conversion throws these unchecked exceptions:
+      // ICUException (incl. ICUInputTooLongException from Punycode.encode on 
an
+      // over-long label), IllegalStateException (Punycode).
+      // Convert to MalformedURLException so callers (e.g. BasicURLNormalizer)
+      // reject the URL instead of crashing the task.
+      throw (MalformedURLException) new MalformedURLException(
+          "Invalid IDN host " + host + ": " + e.getMessage()).initCause(e);
     }
+
     if (idnaInfo.hasErrors()) {
       StringBuilder msg = new StringBuilder();
       for (IDNA.Error error : idnaInfo.getErrors()) {
diff --git a/src/test/org/apache/nutch/util/TestURLUtil.java 
b/src/test/org/apache/nutch/util/TestURLUtil.java
index 200ea59a0..7c7267ce8 100644
--- a/src/test/org/apache/nutch/util/TestURLUtil.java
+++ b/src/test/org/apache/nutch/util/TestURLUtil.java
@@ -444,6 +444,22 @@ public class TestURLUtil {
         () -> URLUtil.convertIDNA2008("xn--a-ä.pt", false));
     assertThrows(MalformedURLException.class,
         () -> URLUtil.convertIDNA2008("xn--a-ä.pt", true));
+
+    assertThrows(MalformedURLException.class, // Thai, 1001 units
+        () -> URLUtil.convertIDNA2008("ก".repeat(1001), true));
+    assertThrows(MalformedURLException.class, // emoji (surrogate pairs), 1002 
units
+        () -> URLUtil.convertIDNA2008("😀".repeat(501), true));
+    assertThrows(MalformedURLException.class, // CJK Ext-B, 1200 units
+        () -> URLUtil.convertIDNA2008(
+            new String(Character.toChars(0x20000)).repeat(600), true));
+
+    // boundary: exactly 1000 units does not throw; rejected via LABEL_TOO_LONG
+    assertThrows(MalformedURLException.class,
+        () -> URLUtil.convertIDNA2008("ก".repeat(1000), true));
+
+    // EMPTY_LABEL: a bare dot (empty label) is rejected via IDNA.Info errors
+    assertThrows(MalformedURLException.class,
+        () -> URLUtil.convertIDNA2008(".", true));
   }
 
   @Test

Reply via email to