Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StreamUtils.copyRange overreads source stream in some cases #32695

Closed
icguy opened this issue Apr 23, 2024 · 1 comment
Closed

StreamUtils.copyRange overreads source stream in some cases #32695

icguy opened this issue Apr 23, 2024 · 1 comment
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Milestone

Comments

@icguy
Copy link

icguy commented Apr 23, 2024

Description

StreamUtils.copyRange copies the input stream with a buffer size of 4096 bytes. If the desired range is not divisible by 4096, copyRange will overread the input stream by reading whole buffers at a time. This will result in skipping the bytes in the input stream that were read into the buffer but not copied.

Consider the following kotlin code:

val a = ByteArrayInputStream(ByteArray(6000))
val b = ByteArrayOutputStream(6000)

val copied = StreamUtils.copyRange(a, b, 0, 5000) // copied == 5001
val rest = a.readAllBytes().size // rest == 0, should equal 999
val total = copied + rest // total == 5001, should equal 6000

Because the input stream spans over two buffers, copyRange will consume the whole stream even though the requested range was 1000 bytes smaller than the stream length.

Actual behavior

When the requested range is not divisible by 4096 and the input stream is longer than the range copyRange will consume extra bytes after the end of the range. This advances the stream unnecessarily and results in those bytes being skipped.

Expected behavior

StreamUtils.copyRange should only read the requested number of bytes from the input stream.

Suggested fix

The number of remaining bytes to be read should be taken into account instead of reading the whole buffer:

int bytesRead = in.read(buffer, 0, Math.min(buffer.size, numRemainingBytes));
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 23, 2024
@jhoeller jhoeller added in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Apr 23, 2024
@jhoeller jhoeller self-assigned this Apr 23, 2024
@jhoeller jhoeller added this to the 6.1.7 milestone Apr 23, 2024
@icguy
Copy link
Author

icguy commented Apr 23, 2024

Wow, that was some response time! Thanks a lot for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

3 participants