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

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


The following commit(s) were added to refs/heads/master by this push:
     new 47925aa0998 fix: Close exposure to potential NPE in S3Utils.useHttps 
(#19504)
47925aa0998 is described below

commit 47925aa0998756f0137ec35b4202d2851ca9819d
Author: Lucas Capistrant <[email protected]>
AuthorDate: Fri May 22 12:13:21 2026 -0500

    fix: Close exposure to potential NPE in S3Utils.useHttps (#19504)
---
 .../java/org/apache/druid/storage/s3/S3Utils.java  |  4 +--
 .../druid/data/input/s3/S3InputSourceTest.java     | 35 ++++++++++++++++++
 .../org/apache/druid/storage/s3/S3UtilsTest.java   | 41 ++++++++++++++++++++++
 3 files changed, 78 insertions(+), 2 deletions(-)

diff --git 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
index 2cac95a200b..82412fe412c 100644
--- 
a/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
+++ 
b/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3Utils.java
@@ -417,9 +417,9 @@ public class S3Utils
   /**
    * Determines whether to use HTTP or HTTPS protocol based on configuration.
    */
-  public static boolean useHttps(AWSClientConfig clientConfig, 
AWSEndpointConfig endpointConfig)
+  public static boolean useHttps(@Nullable AWSClientConfig clientConfig, 
AWSEndpointConfig endpointConfig)
   {
-    String protocol = clientConfig.getProtocol();
+    final String protocol = clientConfig == null ? null : 
clientConfig.getProtocol();
     final String endpointUrl = endpointConfig.getUrl();
 
     if (org.apache.commons.lang3.StringUtils.isNotEmpty(endpointUrl)) {
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
index 168216affdc..96db444aa08 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/data/input/s3/S3InputSourceTest.java
@@ -404,6 +404,41 @@ public class S3InputSourceTest extends 
InitializedNullHandlingTest
     EasyMock.verify(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
   }
 
+  @Test
+  public void 
testSchemelessEndpointConfigUrlWithNullClientConfigResolvesSupplier() throws 
Exception
+  {
+    EasyMock.reset(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+    
EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.setS3ClientSupplier(EasyMock.anyObject()))
+            .andReturn(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+    EasyMock.expect(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER.build())
+            .andReturn(SERVICE);
+    EasyMock.replay(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+
+    final AWSEndpointConfig schemelessEndpoint = MAPPER.readValue(
+        "{\"url\":\"s3.example.com\",\"signingRegion\":\"us-east-1\"}",
+        AWSEndpointConfig.class
+    );
+
+    final S3InputSource inputSource = new S3InputSource(
+        SERVICE,
+        SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER,
+        INPUT_DATA_CONFIG,
+        null,
+        null,
+        EXPECTED_LOCATION,
+        null,
+        CLOUD_CONFIG_PROPERTIES,
+        null,
+        schemelessEndpoint,
+        null
+    );
+
+    // Forces s3ClientSupplier evaluation, which hits S3Utils.useHttps and 
confirms a null client config does not blow up.
+    inputSource.createEntity(new CloudObjectLocation("bucket", "path"));
+
+    EasyMock.verify(SERVER_SIDE_ENCRYPTING_AMAZON_S3_BUILDER);
+  }
+
   @Test
   public void testGetSetSessionToken()
   {
diff --git 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
index 6c46df7d993..16b8c20d0f2 100644
--- 
a/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
+++ 
b/extensions-core/s3-extensions/src/test/java/org/apache/druid/storage/s3/S3UtilsTest.java
@@ -19,6 +19,9 @@
 
 package org.apache.druid.storage.s3;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.druid.common.aws.AWSClientConfig;
+import org.apache.druid.common.aws.AWSEndpointConfig;
 import org.easymock.Capture;
 import org.easymock.CaptureType;
 import org.easymock.EasyMock;
@@ -382,4 +385,42 @@ public class S3UtilsTest
     );
     Assert.assertEquals(maxRetries, count.get());
   }
+
+  private static final ObjectMapper JSON = new ObjectMapper();
+
+  private static AWSEndpointConfig endpointWith(String json) throws IOException
+  {
+    return JSON.readValue(json, AWSEndpointConfig.class);
+  }
+
+  @Test
+  public void testUseHttpsNullClientConfigSchemelessEndpointReturnsTrue() 
throws IOException
+  {
+    Assert.assertTrue(S3Utils.useHttps(null, 
endpointWith("{\"url\":\"s3.example.com\"}")));
+  }
+
+  @Test
+  public void testUseHttpsNullClientConfigHttpEndpointReturnsFalse() throws 
IOException
+  {
+    Assert.assertFalse(S3Utils.useHttps(null, 
endpointWith("{\"url\":\"http://s3.example.com\"}";)));
+  }
+
+  @Test
+  public void testUseHttpsNullClientConfigHttpsEndpointReturnsTrue() throws 
IOException
+  {
+    Assert.assertTrue(S3Utils.useHttps(null, 
endpointWith("{\"url\":\"https://s3.example.com\"}";)));
+  }
+
+  @Test
+  public void testUseHttpsNullClientConfigNullEndpointUrlReturnsTrue() throws 
IOException
+  {
+    Assert.assertTrue(S3Utils.useHttps(null, new AWSEndpointConfig()));
+  }
+
+  @Test
+  public void testUseHttpsDefaultClientConfigSchemelessEndpointReturnsTrue() 
throws IOException
+  {
+    // Sanity check: default AWSClientConfig protocol is "https"; schemeless 
URL inherits "https".
+    Assert.assertTrue(S3Utils.useHttps(new AWSClientConfig(), 
endpointWith("{\"url\":\"s3.example.com\"}")));
+  }
 }


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

Reply via email to