From 6081db5c346d239e2a1295e53fc3ceb035ffd605 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 19 Jun 2018 16:44:08 +0100 Subject: [PATCH] Make ZipHeaderInputStream read sub 5 byte entries correctly Closes gh-13525 --- .../boot/loader/tools/JarWriter.java | 22 +++++--- .../tools/ZipHeaderPeekInputStreamTests.java | 52 +++++++++++++++++++ 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java index c0f0334bb8..9d6608c33c 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JarWriter.java @@ -357,15 +357,15 @@ public class JarWriter implements LoaderClassesWriter { 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; @@ -377,6 +377,14 @@ public class JarWriter implements LoaderClassesWriter { 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-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java index 32dace058c..32347bb85a 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/ZipHeaderPeekInputStreamTests.java @@ -142,4 +142,56 @@ public class ZipHeaderPeekInputStreamTests { } } + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsLessThanZipHeaderLength() + throws IOException { + ZipHeaderPeekInputStream in = null; + try { + 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); + } + finally { + if (in != null) { + in.close(); + } + } + } + + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsSameAsHeaderLength() + throws IOException { + ZipHeaderPeekInputStream in = null; + try { + 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); + } + finally { + if (in != null) { + in.close(); + } + } + } + + @Test + public void readMoreThanEntireStreamWhenStreamLengthIsZero() throws IOException { + ZipHeaderPeekInputStream in = null; + try { + 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); + } + finally { + if (in != null) { + in.close(); + } + } + } + }