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

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-vfs.git

commit c59cf83c046d3712a9a550a161083c2a79bac85f
Author: Gary Gregory <[email protected]>
AuthorDate: Wed Jul 22 09:40:32 2026 -0400

    Reject non-ascii hex digits in UriParser percent-decoding (#774).
---
 .../apache/commons/vfs2/provider/UriParser.java    | 38 +++++++++++-----------
 src/changes/changes.xml                            |  1 +
 2 files changed, 20 insertions(+), 19 deletions(-)

diff --git 
a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java 
b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
index 9133873f1..aeac1ea4b 100644
--- a/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
+++ b/commons-vfs2/src/main/java/org/apache/commons/vfs2/provider/UriParser.java
@@ -48,21 +48,6 @@ public final class UriParser {
 
     private static final char LOW_MASK = 0x0F;
 
-    /**
-     * Returns the value of an ASCII hexadecimal digit, or {@code -1} if the 
character is not one.
-     * <p>
-     * Unlike {@link Character#digit(char, int)}, this only accepts the ASCII 
digits {@code 0-9}, {@code a-f} and
-     * {@code A-F} that RFC 3986 permits in a percent-encoding, so Unicode 
look-alikes such as the fullwidth digits are
-     * rejected instead of silently decoded.
-     * </p>
-     *
-     * @param ch the character to convert.
-     * @return the value 0-15, or {@code -1} if {@code ch} is not an ASCII 
hexadecimal digit.
-     */
-    private static int hexDigit(final char ch) {
-        return CharUtils.isHex(ch) ? Character.digit(ch, HEX_BASE) : -1;
-    }
-
     /**
      * Encodes and appends a string to a StringBuilder.
      *
@@ -104,8 +89,8 @@ public final class UriParser {
                 }
 
                 // Decode
-                final int dig1 = hexDigit(buffer.charAt(index + 1));
-                final int dig2 = hexDigit(buffer.charAt(index + 2));
+                final int dig1 = toHexDigit(buffer.charAt(index + 1));
+                final int dig2 = toHexDigit(buffer.charAt(index + 2));
                 if (dig1 == -1 || dig2 == -1) {
                     throw new 
FileSystemException("vfs.provider/invalid-escape-sequence.error",
                             buffer.substring(index, index + 3));
@@ -220,8 +205,8 @@ public final class UriParser {
             }
 
             // Decode
-            final int dig1 = hexDigit(buffer.charAt(index + 1));
-            final int dig2 = hexDigit(buffer.charAt(index + 2));
+            final int dig1 = toHexDigit(buffer.charAt(index + 1));
+            final int dig2 = toHexDigit(buffer.charAt(index + 2));
             if (dig1 == -1 || dig2 == -1) {
                 throw new 
FileSystemException("vfs.provider/invalid-escape-sequence.error",
                         buffer.substring(index, index + 3));
@@ -617,6 +602,21 @@ public final class UriParser {
         return fileType;
     }
 
+    /**
+     * Returns the value of an ASCII hexadecimal digit, or {@code -1} if the 
character is not one.
+     * <p>
+     * Unlike {@link Character#digit(char, int)}, this only accepts the ASCII 
digits {@code 0-9}, {@code a-f} and
+     * {@code A-F} that RFC 3986 permits in a percent-encoding, so Unicode 
look-alikes such as the fullwidth digits are
+     * rejected instead of silently decoded.
+     * </p>
+     *
+     * @param ch the character to convert.
+     * @return the value 0-15, or {@code -1} if {@code ch} is not an ASCII 
hexadecimal digit.
+     */
+    private static int toHexDigit(final char ch) {
+        return CharUtils.isHex(ch) ? Character.digit(ch, HEX_BASE) : -1;
+    }
+
     private UriParser() {
     }
 }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index a37dd99f9..ee0d69995 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -69,6 +69,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action type="fix" dev="ggregory" due-to="VaishKumbhar, Gary 
Gregory">Port SFTP tests from Apache Mina SSHD 0.8.0 to 3.0.0-M3 #754.</action>
       <action type="fix" dev="ggregory" due-to="Naveed Khan, Gary 
Gregory">Restrict reflective class loading in webdav ExceptionConverter 
(#771).</action>
       <action type="fix" dev="ggregory" due-to="Nick Tarallo, Gary Gregory" 
issue="VFS-863">Content inside brackets in directory/file names is not decoded 
(#773).</action>
+      <action type="fix" dev="ggregory" due-to="Naveed Khan, Gary 
Gregory">Reject non-ascii hex digits in UriParser percent-decoding 
(#774).</action>
       <!-- ADD -->
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
org.apache.commons.vfs2.provider.ftp.FTPClientWrapper.sendOptions(String, 
String).</action>
       <action type="add" dev="ggregory" due-to="Gary Gregory">Add 
FtpFileSystemConfigBuilder.getControlEncodingCharset(FileSystemOptions) and 
deprecate getControlEncoding(FileSystemOptions).</action>

Reply via email to