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

smengcl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 63a45965ca4 HDDS-16749. Avoid regex compilation when splitting 
canonical URIs for S3 signatures (#11460)
63a45965ca4 is described below

commit 63a45965ca4a20df9f61d8df1cb8431a120f8049
Author: KUAN-HAO HUANG <[email protected]>
AuthorDate: Sat Oct 10 12:48:21 2026 +0800

    HDDS-16749. Avoid regex compilation when splitting canonical URIs for S3 
signatures (#11460)
---
 .../ozone/s3/signature/StringToSignProducer.java   | 25 +-------------------
 .../s3/signature/TestStringToSignProducer.java     | 27 ++++++++++++++++++----
 2 files changed, 24 insertions(+), 28 deletions(-)

diff --git 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
index 793669beda8..c6edbd30a10 100644
--- 
a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
+++ 
b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/signature/StringToSignProducer.java
@@ -34,8 +34,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.core.MultivaluedMap;
@@ -154,9 +152,8 @@ public static String buildCanonicalRequest(
       String payloadHash
   ) throws OS3Exception {
 
-    Iterable<String> parts = split("/", uri);
     List<String> encParts = new ArrayList<>();
-    for (String p : parts) {
+    for (String p : StringUtils.splitPreserveAllTokens(uri, '/')) {
       encParts.add(urlEncode(p));
     }
     String canonicalUri = join("/", encParts);
@@ -210,26 +207,6 @@ private static String join(String glue, List<String> 
parts) {
     return result.toString();
   }
 
-  /**
-   * Returns matching strings.
-   *
-   * @param regex Regular expression to split by
-   * @param whole The string to split
-   * @return pieces
-   */
-  private static Iterable<String> split(String regex, String whole) {
-    Pattern p = Pattern.compile(regex);
-    Matcher m = p.matcher(whole);
-    List<String> result = new ArrayList<>();
-    int pos = 0;
-    while (m.find()) {
-      result.add(whole.substring(pos, m.start()));
-      pos = m.end();
-    }
-    result.add(whole.substring(pos));
-    return result;
-  }
-
   private static String urlEncode(String str) {
     try {
       return StringUtils.replaceEach(S3Utils.urlEncode(str), 
URL_ENCODE_SEARCH_CHARS, URL_ENCODE_REPLACE_CHARS);
diff --git 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
index ba95cab32c6..565293fe907 100644
--- 
a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
+++ 
b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/signature/TestStringToSignProducer.java
@@ -118,8 +118,27 @@ public void test() throws Exception {
         signatureBase, "String to sign is invalid");
   }
 
-  @Test
-  public void testUrlEncodeInCanonicalRequest() {
+  private static Stream<Arguments> testUrlEncodeInCanonicalRequestInput() {
+    return Stream.of(
+        arguments("/bucket/a+b*c~d/foo bar", "/bucket/a%2Bb%2Ac~d/foo%20bar"),
+        arguments("", ""),
+        arguments("/", "/"),
+        arguments("//", "//"),
+        arguments("/bucket/", "/bucket/"),
+        arguments("//bucket/key", "//bucket/key"),
+        arguments("/bucket//key/", "/bucket//key/"),
+        arguments("/bucket/a/.././b", "/bucket/a/.././b"),
+        arguments("bucket/key", "bucket/key"),
+        // A literal %2F in the decoded path corresponds to %252F in the wire 
path.
+        arguments("/bucket/a%2Fb", "/bucket/a%252Fb"),
+        arguments("/bucket/雪/😀", "/bucket/%E9%9B%AA/%F0%9F%98%80"),
+        arguments("/bucket/?#", "/bucket/%3F%23")
+    );
+  }
+
+  @ParameterizedTest
+  @MethodSource("testUrlEncodeInCanonicalRequestInput")
+  public void testUrlEncodeInCanonicalRequest(String uri, String 
expectedCanonicalUri) {
     final Map<String, String> headers = new HashMap<>();
     headers.put("host", "example.com");
     headers.put("x-amz-content-sha256", UNSIGNED_PAYLOAD);
@@ -129,12 +148,12 @@ public void testUrlEncodeInCanonicalRequest() {
     queryParams.put("q+1*2~3", "v 4*5~6");
 
     final String canonicalRequest = StringToSignProducer.buildCanonicalRequest(
-        "GET", "/bucket/a+b*c~d/foo bar", 
"host;x-amz-content-sha256;x-amz-date",
+        "GET", uri, "host;x-amz-content-sha256;x-amz-date",
         headers, queryParams, UNSIGNED_PAYLOAD);
 
     assertEquals(
         "GET\n"
-            + "/bucket/a%2Bb%2Ac~d/foo%20bar\n"
+            + expectedCanonicalUri + "\n"
             + "q%2B1%2A2~3=v%204%2A5~6\n"
             + "host:example.com\n"
             + "x-amz-content-sha256:" + UNSIGNED_PAYLOAD + "\n"


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to