comparison src/org/tmatesoft/hg/internal/InflaterDataAccess.java @ 399:fdc1db8f7f61 smartgit3

Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Sat, 25 Feb 2012 19:31:57 +0100
parents 856517285256
children 6c22bdc0bdfd
comparison
equal deleted inserted replaced
397:5e95b0da26f2 399:fdc1db8f7f61
156 public void readBytes(byte[] b, int off, int len) throws IOException { 156 public void readBytes(byte[] b, int off, int len) throws IOException {
157 try { 157 try {
158 int n; 158 int n;
159 while (len > 0) { 159 while (len > 0) {
160 while ((n = inflater.inflate(b, off, len)) == 0) { 160 while ((n = inflater.inflate(b, off, len)) == 0) {
161 // FIXME few last bytes (checksum?) may be ignored by inflater, thus inflate may return 0 in 161 // XXX few last bytes (checksum?) may be ignored by inflater, thus inflate may return 0 in
162 // perfectly legal conditions (when all data already expanded, but there are still some bytes 162 // perfectly legal conditions (when all data already expanded, but there are still some bytes
163 // in the input stream 163 // in the input stream)
164 if (inflater.finished() || inflater.needsDictionary()) { 164 int toRead = -1;
165 throw new EOFException(); 165 if (inflater.needsInput() && (toRead = super.available()) > 0) {
166 }
167 if (inflater.needsInput()) {
168 // fill: 166 // fill:
169 int toRead = super.available();
170 if (toRead > buffer.length) { 167 if (toRead > buffer.length) {
171 toRead = buffer.length; 168 toRead = buffer.length;
172 } 169 }
173 super.readBytes(buffer, 0, toRead); 170 super.readBytes(buffer, 0, toRead);
174 inflater.setInput(buffer, 0, toRead); 171 inflater.setInput(buffer, 0, toRead);
172 } else {
173 // prevent hang up in this cycle if no more data is available, see Issue 25
174 throw new EOFException(String.format("No more compressed data is available to satisfy request for %d bytes. [finished:%b, needDict:%b, needInp:%b, available:%d", len, inflater.finished(), inflater.needsDictionary(), inflater.needsInput(), toRead));
175 } 175 }
176 } 176 }
177 off += n; 177 off += n;
178 len -= n; 178 len -= n;
179 decompressedPos += n; 179 decompressedPos += n;