Skip to content

Fix truncated reads from compressed JAR data sources - #3661

Open
git-jxj wants to merge 1 commit into
alibaba:1.8from
git-jxj:fix/jar-datasource-complete-read
Open

git-jxj wants to merge 1 commit into
alibaba:1.8from
git-jxj:fix/jar-datasource-complete-read

Conversation

@git-jxj

@git-jxj git-jxj commented Oct 8, 2026

Copy link
Copy Markdown

Describe what this PR does / why we need it

Compressed JAR entries can return fewer bytes than requested from a single InputStream.read(). FileInJarReadableDataSource currently truncates those configurations; empty entries also fail because the read returns -1.

Does this pull request fix one issue?

Fixes #3659

Describe how you did it

Read until EOF or the configured buffer is filled, preserving the existing oversized-entry check. Decode the accumulated bytes once.

Describe how to verify it

The regression tests create real compressed JARs and cover a 64 KiB entry, an empty entry, UTF-8 content, and the buffer limit. The unmodified implementation fails the compressed and empty-entry tests; the patch passes all four.

Validation on JDK 17: all 223 core tests and the four new datasource tests pass. The matching module build, including the configured PMD check, also passes.

mvn -B -pl sentinel-extension/sentinel-datasource-extension -am test
mvn -B -pl sentinel-extension/sentinel-datasource-extension -am install -DskipTests=true -Dmaven.javadoc.skip=true -DminimumPriority=1

Special notes for reviews

Signed-off-by: xinjun.jiang <xinjun.jiang@daocloud.io>

@konlue konlue left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified locally on 1.8 (a3f40ba, JDK 17): with the patch the new tests pass 4/4; reverting only FileInJarReadableDataSource.java reproduces the bug concretely — testReadCompleteCompressedEntry fails with expected:<65536> but was:<13072>, i.e. a single read(buf) on my machine returned a genuinely partial chunk, so the truncation premise is confirmed empirically, not just by the InputStream contract. The empty-entry case fails on old code with StringIndexOutOfBoundsException: count -1 as well.

The fix itself is the standard read-fully loop (EOF and buffer-capacity exits) and the tests are built the right way: real deflate-compressed jars via JarOutputStream so the inflater path is exercised, the 64KiB-equals-bufferSize boundary is a nice choice, and asserting through loadConfig() pins the converter path too.

One gap worth closing, non-blocking:

The available() pre-check leaves a silent-truncation path. InputStream#available() is an estimate by contract and varies by implementation. If an implementation under-reports (actual entry > buf.length but available() <= buf.length), the pre-check passes, the new loop happily fills the whole buffer, and readSource() returns a silently truncated string — which breaks the class javadoc's promise that oversized files throw. Notably, testRejectEntryLargerThanBuffer also passes on the old code, so it pins the available() behavior rather than anything this PR adds. A single precise check after the loop would make the guarantee implementation-independent:

if (len == buf.length && inputStream.read() != -1) {
    throw new IllegalStateException(...); // entry is larger than bufSize
}

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.

[BUG] FileInJarReadableDataSource truncates compressed entries on short reads

2 participants