diff --git a/core/src/main/java/lucee/runtime/config/s3/BundleProvider.java b/core/src/main/java/lucee/runtime/config/s3/BundleProvider.java index 17edff1259e..d758a61fc50 100644 --- a/core/src/main/java/lucee/runtime/config/s3/BundleProvider.java +++ b/core/src/main/java/lucee/runtime/config/s3/BundleProvider.java @@ -12,7 +12,9 @@ import java.io.Reader; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLEncoder; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.security.CodeSource; import java.security.GeneralSecurityException; import java.util.ArrayList; @@ -452,16 +454,22 @@ private File deployBundledBundle(File bundleDirectory, String symbolicName, Stri // 1146:size:305198;bundle:name:xmlgraphics.batik.awt.util;version:version EQ 1.8.0;;last-mod:{ts // '2024-01-14 22:32:05'}; + private URL markerURL(String key) throws MalformedURLException { + // S3 object keys can contain characters (e.g. spaces) that are illegal in a URI + // query and would otherwise abort the entire paginated listing walk. + return new URL(this.url.toExternalForm() + "?marker=" + URLEncoder.encode(key, StandardCharsets.UTF_8)); + } + public List read(boolean flush) throws IOException, GeneralSecurityException, SAXException { if (elementsSorted == null) { synchronized (elements) { if (elementsSorted == null) { int count = 100; URL url = null; - if (lastKey != null) url = new URL(this.url.toExternalForm() + "?marker=" + lastKey); + if (lastKey != null) url = markerURL(lastKey); do { - if (url == null) url = isTruncated ? new URL(this.url.toExternalForm() + "?marker=" + this.lastKey) : this.url; + if (url == null) url = isTruncated ? markerURL(this.lastKey) : this.url; HTTPResponse rsp = HTTPEngine4Impl.get(url, null, null, BundleProvider.CONNECTION_TIMEOUT, true, null, null, null, null); if (rsp != null) { int sc = rsp.getStatusCode(); diff --git a/core/src/main/java/lucee/runtime/osgi/OSGiUtil.java b/core/src/main/java/lucee/runtime/osgi/OSGiUtil.java index a235ddea8d3..90eb0104f69 100644 --- a/core/src/main/java/lucee/runtime/osgi/OSGiUtil.java +++ b/core/src/main/java/lucee/runtime/osgi/OSGiUtil.java @@ -326,8 +326,15 @@ else if (arr.length == 3) { return defaultValue; } - if (qualifier == null) return new Version(major, minor, micro); - return new Version(major, minor, micro, qualifier); + try { + if (qualifier == null) return new Version(major, minor, micro); + return new Version(major, minor, micro, qualifier); + } + catch (IllegalArgumentException e) { + // a malformed qualifier (e.g. a space in an S3 listing entry) makes the OSGi + // Version constructor throw; this overload must return defaultValue instead. + return defaultValue; + } } public static Version toVersion(String version) throws BundleException { diff --git a/test/tickets/LDEV6354.cfc b/test/tickets/LDEV6354.cfc new file mode 100644 index 00000000000..b47f834a1c7 --- /dev/null +++ b/test/tickets/LDEV6354.cfc @@ -0,0 +1,22 @@ +component extends="org.lucee.cfml.test.LuceeTestCase" { + public function run( testResults, testBox ) { + describe( title="LDEV-6354 OSGiUtil.toVersion tolerates a malformed qualifier instead of throwing", body=function() { + + it( title="returns the default for a qualifier containing a space (the S3 'GA copy' entry)", body=function( currentSpec ) { + var OSGiUtil = createObject( "java", "lucee.runtime.osgi.OSGiUtil" ); + var fallback = createObject( "java", "org.osgi.framework.Version" ).init( "9.9.9" ); + // must NOT throw IllegalArgumentException; this overload contractually returns the default + var result = OSGiUtil.toVersion( "3.9.0.GA copy", fallback ); + expect( result.toString() ).toBe( "9.9.9" ); + }); + + it( title="still parses a well-formed OSGi version + qualifier", body=function( currentSpec ) { + var OSGiUtil = createObject( "java", "lucee.runtime.osgi.OSGiUtil" ); + var fallback = createObject( "java", "org.osgi.framework.Version" ).init( "9.9.9" ); + var result = OSGiUtil.toVersion( "3.9.0.GA", fallback ); + expect( result.toString() ).toBe( "3.9.0.GA" ); + }); + + }); + } +}