Skip to content

LDEV-6354 don't abort S3 bundle listing on a malformed version or key#2792

Open
bpamiri wants to merge 1 commit into
lucee:7.0from
bpamiri:fix/osgi-toversion-illegal-qualifier
Open

LDEV-6354 don't abort S3 bundle listing on a malformed version or key#2792
bpamiri wants to merge 1 commit into
lucee:7.0from
bpamiri:fix/osgi-toversion-illegal-qualifier

Conversation

@bpamiri

@bpamiri bpamiri commented May 27, 2026

Copy link
Copy Markdown

LDEV-6354

https://luceeserver.atlassian.net/browse/LDEV-6354

Problem

Lucee's S3 BundleProvider (the fallback resolver that lists bundle-download.s3.amazonaws.com when a bundle isn't found locally or on update.lucee.org) aborts the entire listing walk when the bucket contains a single entry whose name yields a malformed OSGi version. Resolution of every S3-hosted bundle then fails — a request for e.g. org.xerial.sqlite-jdbc surfaces a parse error about javassist:

java.io.IOException: java.lang.IllegalArgumentException: invalid version "3.9.0.GA copy": invalid qualifier "GA copy"
    at org.osgi.framework.Version.validate(Version.java:203)
    at lucee.runtime.config.s3.BundleProvider.read(BundleProvider.java:520)
    at lucee.runtime.config.s3.BundleProvider.getBundleAsURL(BundleProvider.java:267)
    ...
Caused by: java.lang.IllegalArgumentException: Illegal character in query at index 67:
    https://bundle-download.s3.amazonaws.com/?marker=javassist-3.9.0.GA copy.jar

The bucket currently contains javassist-3.9.0.GA copy.jar (a Finder-style "copy" duplicate) plus several space-containing .meta-cache/*.json keys.

Root cause & fix

1. OSGiUtil.toVersion(String, boolean, Version) violated its default-return contract. For 3.9.0.GA copy it parses major/minor/micro, then calls new Version(3, 9, 0, "GA copy"), whose constructor validate() rejects the space and throws IllegalArgumentException. That construction (the restrictive path) wasn't guarded — unlike the non-restrictive branch immediately above it. Because this overload takes a defaultValue, callers expect it never to throw; instead the exception escaped the SAX parse in BundleProvider.read(). Fixed by wrapping the construction in try/catch (IllegalArgumentException) returning defaultValue.

2. BundleProvider.read() built the pagination URL by naive concatenation ("?marker=" + lastKey), throwing Illegal character in query when a key contains a space. The listing is truncated (>1000 keys) so ?marker= pagination runs in normal operation. Fixed by URL-encoding the marker.

Either fix alone resolves the reported crash; together they make S3 bundle resolution resilient to any single malformed listing entry.

Test

test/tickets/LDEV6354.cfc asserts OSGiUtil.toVersion("3.9.0.GA copy", default) returns the default instead of throwing, and that a well-formed qualifier still parses.

Note

The malformed bucket entries should also be cleaned up server-side (tracked in LDEV-6354) — that fixes already-released versions immediately; this PR prevents recurrence from any future malformed entry.

Downstream report: wheels-dev/wheels#2312

OSGiUtil.toVersion(String, Version) threw IllegalArgumentException for a
malformed qualifier (e.g. "3.9.0.GA copy" from bucket entry
"javassist-3.9.0.GA copy.jar") instead of honoring its default-return
contract, aborting the entire BundleProvider listing walk. Guard the
restrictive-path Version construction, matching the non-restrictive branch.

Also URL-encode the S3 ?marker= pagination parameter in BundleProvider.read()
so keys with spaces/illegal URI characters don't break paginated listing.

Adds test/tickets/LDEV6354.cfc.

Signed-off-by: Peter Amiri <peter@alurium.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant