Mercurial > hg4j
annotate 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 |
rev | line source |
---|---|
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
1 /* |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
2 * Copyright (c) 2011 TMate Software Ltd |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
3 * |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
4 * This program is free software; you can redistribute it and/or modify |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
6 * the Free Software Foundation; version 2 of the License. |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
7 * |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
8 * This program is distributed in the hope that it will be useful, |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
11 * GNU General Public License for more details. |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
12 * |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
13 * For information on how to redistribute this software under |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
14 * the terms of a license other than GNU General Public License |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
15 * contact TMate Software at support@hg4j.com |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
16 */ |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
17 package org.tmatesoft.hg.internal; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
18 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
19 import java.io.EOFException; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
20 import java.io.IOException; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
21 import java.util.zip.DataFormatException; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
22 import java.util.zip.Inflater; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
23 import java.util.zip.ZipException; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
24 |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
25 import org.tmatesoft.hg.core.HgBadStateException; |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
26 |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
27 |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
28 /** |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
29 * DataAccess counterpart for InflaterInputStream. |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
30 * XXX is it really needed to be subclass of FilterDataAccess? |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
31 * |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
32 * @author Artem Tikhomirov |
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
33 * @author TMate Software Ltd. |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
34 */ |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
35 public class InflaterDataAccess extends FilterDataAccess { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
36 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
37 private final Inflater inflater; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
38 private final byte[] buffer; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
39 private final byte[] singleByte = new byte[1]; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
40 private int decompressedPos = 0; |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
41 private int decompressedLength; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
42 |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
43 public InflaterDataAccess(DataAccess dataAccess, int offset, int compressedLength) { |
263
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
44 this(dataAccess, offset, compressedLength, -1, new Inflater(), new byte[512]); |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
45 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
46 |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
47 public InflaterDataAccess(DataAccess dataAccess, int offset, int compressedLength, int actualLength) { |
263
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
48 this(dataAccess, offset, compressedLength, actualLength, new Inflater(), new byte[512]); |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
49 } |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
50 |
263
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
51 public InflaterDataAccess(DataAccess dataAccess, int offset, int compressedLength, int actualLength, Inflater inflater, byte[] buf) { |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
52 super(dataAccess, offset, compressedLength); |
263
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
53 if (inflater == null || buf == null) { |
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
54 throw new IllegalArgumentException(); |
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
55 } |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
56 this.inflater = inflater; |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
57 this.decompressedLength = actualLength; |
263
31f67be94e71
RevlogStream - reduce number of object instances, reuse when possible
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
158
diff
changeset
|
58 buffer = buf; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
59 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
60 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
61 @Override |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
62 public InflaterDataAccess reset() throws IOException { |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
63 super.reset(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
64 inflater.reset(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
65 decompressedPos = 0; |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
66 return this; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
67 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
68 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
69 @Override |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
70 protected int available() { |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
71 return length() - decompressedPos; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
72 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
73 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
74 @Override |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
75 public boolean isEmpty() { |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
76 // can't use super.available() <= 0 because even when 0 < super.count < 6(?) |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
77 // decompressedPos might be already == length() |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
78 return available() <= 0; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
79 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
80 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
81 @Override |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
82 public int length() { |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
83 if (decompressedLength != -1) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
84 return decompressedLength; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
85 } |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
86 decompressedLength = 0; // guard to avoid endless loop in case length() would get invoked from below. |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
87 int c = 0; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
88 try { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
89 int oldPos = decompressedPos; |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
90 byte[] dummy = new byte[buffer.length]; |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
91 int toRead; |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
92 while ((toRead = super.available()) > 0) { |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
93 if (toRead > buffer.length) { |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
94 toRead = buffer.length; |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
95 } |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
96 super.readBytes(buffer, 0, toRead); |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
97 inflater.setInput(buffer, 0, toRead); |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
98 try { |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
99 while (!inflater.needsInput()) { |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
100 c += inflater.inflate(dummy, 0, dummy.length); |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
101 } |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
102 } catch (DataFormatException ex) { |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
103 throw new HgBadStateException(ex); |
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
104 } |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
105 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
106 decompressedLength = c + oldPos; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
107 reset(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
108 seek(oldPos); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
109 return decompressedLength; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
110 } catch (IOException ex) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
111 decompressedLength = -1; // better luck next time? |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
112 throw new HgBadStateException(ex); // XXX perhaps, checked exception |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
113 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
114 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
115 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
116 @Override |
158
b413b16d10a5
Integer offsets and file length explictly, rather than casts throughout code. Inflater may benefit from total length hint, but shall calculate it by its own if needed
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
157
diff
changeset
|
117 public void seek(int localOffset) throws IOException { |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
118 if (localOffset < 0 /* || localOffset >= length() */) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
119 throw new IllegalArgumentException(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
120 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
121 if (localOffset >= decompressedPos) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
122 skip((int) (localOffset - decompressedPos)); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
123 } else { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
124 reset(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
125 skip((int) localOffset); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
126 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
127 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
128 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
129 @Override |
391
856517285256
Provide more details about exception
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
263
diff
changeset
|
130 public void skip(final int bytesToSkip) throws IOException { |
856517285256
Provide more details about exception
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
263
diff
changeset
|
131 int bytes = bytesToSkip; |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
132 if (bytes < 0) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
133 bytes += decompressedPos; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
134 if (bytes < 0) { |
391
856517285256
Provide more details about exception
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
263
diff
changeset
|
135 throw new IOException(String.format("Underflow. Rewind past start of the slice. To skip:%d, decPos:%d, decLen:%d. Left:%d", bytesToSkip, decompressedPos, decompressedLength, bytes)); |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
136 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
137 reset(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
138 // fall-through |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
139 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
140 while (!isEmpty() && bytes > 0) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
141 readByte(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
142 bytes--; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
143 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
144 if (bytes != 0) { |
391
856517285256
Provide more details about exception
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
263
diff
changeset
|
145 throw new IOException(String.format("Underflow. Rewind past end of the slice. To skip:%d, decPos:%d, decLen:%d. Left:%d", bytesToSkip, decompressedPos, decompressedLength, bytes)); |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
146 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
147 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
148 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
149 @Override |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
150 public byte readByte() throws IOException { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
151 readBytes(singleByte, 0, 1); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
152 return singleByte[0]; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
153 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
154 |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
155 @Override |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
156 public void readBytes(byte[] b, int off, int len) throws IOException { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
157 try { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
158 int n; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
159 while (len > 0) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
160 while ((n = inflater.inflate(b, off, len)) == 0) { |
399
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
161 // XXX few last bytes (checksum?) may be ignored by inflater, thus inflate may return 0 in |
157
d5268ca7715b
Merged branch wrap-data-access into default for resource-friendly data access. Updated API to promote that friendliness to clients (channels, not byte[]). More exceptions
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
51
diff
changeset
|
162 // perfectly legal conditions (when all data already expanded, but there are still some bytes |
399
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
163 // in the input stream) |
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
164 int toRead = -1; |
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
165 if (inflater.needsInput() && (toRead = super.available()) > 0) { |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
166 // fill: |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
167 if (toRead > buffer.length) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
168 toRead = buffer.length; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
169 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
170 super.readBytes(buffer, 0, toRead); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
171 inflater.setInput(buffer, 0, toRead); |
399
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
172 } else { |
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
173 // prevent hang up in this cycle if no more data is available, see Issue 25 |
fdc1db8f7f61
Issue 25: Underflow in InflaterDataAccess; test and fix for hang up when reading past end of compressed data (or zero-length data)
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
391
diff
changeset
|
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)); |
51
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
175 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
176 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
177 off += n; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
178 len -= n; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
179 decompressedPos += n; |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
180 if (len == 0) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
181 return; // filled |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
182 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
183 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
184 } catch (DataFormatException e) { |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
185 String s = e.getMessage(); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
186 throw new ZipException(s != null ? s : "Invalid ZLIB data format"); |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
187 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
188 } |
9429c7bd1920
Try DataAccess to reach revision data instead of plain byte arrays
Artem Tikhomirov <tikhomirov.artem@gmail.com>
parents:
diff
changeset
|
189 } |