diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java index 3f8b2d5802..caedb7fffc 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java @@ -381,15 +381,15 @@ public class JarWriter implements LoaderClassesWriter, AutoCloseable { public int read(byte[] b, int off, int len) throws IOException { int read = (this.headerStream != null ? this.headerStream.read(b, off, len) : -1); - if (read > 0) { - this.position += read; - } - else { - read = 0; + if (read <= 0) { + return readRemainder(b, off, len); } + this.position += read; if (read < len) { - read += super.read(b, off + read, len - read); - this.position += read; + int remainderRead = readRemainder(b, off + read, len - read); + if (remainderRead > 0) { + read += remainderRead; + } } if (this.position >= this.headerLength) { this.headerStream = null; @@ -401,6 +401,14 @@ public class JarWriter implements LoaderClassesWriter, AutoCloseable { return Arrays.equals(this.header, ZIP_HEADER); } + private int readRemainder(byte[] b, int off, int len) throws IOException { + int read = super.read(b, off, len); + if (read > 0) { + this.position += read; + } + return read; + } + } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java index 4eb15d2ba1..0166f221af 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java @@ -100,4 +100,36 @@ public class ZipHeaderPeekInputStreamTests { } } + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsLessThanZipHeaderLength() + throws IOException { + try (ZipHeaderPeekInputStream in = new ZipHeaderPeekInputStream( + new ByteArrayInputStream(new byte[] { 10 }))) { + byte[] bytes = new byte[8]; + assertThat(in.read(bytes)).isEqualTo(1); + assertThat(bytes).containsExactly(10, 0, 0, 0, 0, 0, 0, 0); + } + } + + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsSameAsHeaderLength() + throws IOException { + try (ZipHeaderPeekInputStream in = new ZipHeaderPeekInputStream( + new ByteArrayInputStream(new byte[] { 1, 2, 3, 4 }))) { + byte[] bytes = new byte[8]; + assertThat(in.read(bytes)).isEqualTo(4); + assertThat(bytes).containsExactly(1, 2, 3, 4, 0, 0, 0, 0); + } + } + + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsZero() throws IOException { + try (ZipHeaderPeekInputStream in = new ZipHeaderPeekInputStream( + new ByteArrayInputStream(new byte[0]))) { + byte[] bytes = new byte[8]; + assertThat(in.read(bytes)).isEqualTo(-1); + assertThat(bytes).containsExactly(0, 0, 0, 0, 0, 0, 0, 0); + } + } + }