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]