1 | /*
|
---|
2 | * IndexHash
|
---|
3 | *
|
---|
4 | * Author: Lasse Collin <lasse.collin@tukaani.org>
|
---|
5 | *
|
---|
6 | * This file has been put into the public domain.
|
---|
7 | * You can do whatever you want with this file.
|
---|
8 | */
|
---|
9 |
|
---|
10 | package org.tukaani.xz.index;
|
---|
11 |
|
---|
12 | import java.io.InputStream;
|
---|
13 | import java.io.DataInputStream;
|
---|
14 | import java.io.IOException;
|
---|
15 | import java.nio.ByteBuffer;
|
---|
16 | import java.util.Arrays;
|
---|
17 | import java.util.zip.CheckedInputStream;
|
---|
18 | import org.tukaani.xz.common.DecoderUtil;
|
---|
19 | import org.tukaani.xz.XZIOException;
|
---|
20 | import org.tukaani.xz.CorruptedInputException;
|
---|
21 |
|
---|
22 | public class IndexHash extends IndexBase {
|
---|
23 | private org.tukaani.xz.check.Check hash;
|
---|
24 |
|
---|
25 | public IndexHash() {
|
---|
26 | super(new CorruptedInputException());
|
---|
27 |
|
---|
28 | try {
|
---|
29 | hash = new org.tukaani.xz.check.SHA256();
|
---|
30 | } catch (java.security.NoSuchAlgorithmException e) {
|
---|
31 | hash = new org.tukaani.xz.check.CRC32();
|
---|
32 | }
|
---|
33 | }
|
---|
34 |
|
---|
35 | public void add(long unpaddedSize, long uncompressedSize)
|
---|
36 | throws XZIOException {
|
---|
37 | super.add(unpaddedSize, uncompressedSize);
|
---|
38 |
|
---|
39 | ByteBuffer buf = ByteBuffer.allocate(2 * 8);
|
---|
40 | buf.putLong(unpaddedSize);
|
---|
41 | buf.putLong(uncompressedSize);
|
---|
42 | hash.update(buf.array());
|
---|
43 | }
|
---|
44 |
|
---|
45 | public void validate(InputStream in) throws IOException {
|
---|
46 | // Index Indicator (0x00) has already been read by BlockInputStream
|
---|
47 | // so add 0x00 to the CRC32 here.
|
---|
48 | java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
|
---|
49 | crc32.update('\0');
|
---|
50 | CheckedInputStream inChecked = new CheckedInputStream(in, crc32);
|
---|
51 |
|
---|
52 | // Get and validate the Number of Records field.
|
---|
53 | // If Block Header Size was corrupt and became Index Indicator,
|
---|
54 | // this error would actually be about corrupt Block Header.
|
---|
55 | // This is why the error message mentions both possibilities.
|
---|
56 | long storedRecordCount = DecoderUtil.decodeVLI(inChecked);
|
---|
57 | if (storedRecordCount != recordCount)
|
---|
58 | throw new CorruptedInputException(
|
---|
59 | "XZ Block Header or the start of XZ Index is corrupt");
|
---|
60 |
|
---|
61 | // Decode and hash the Index field and compare it to
|
---|
62 | // the hash value calculated from the decoded Blocks.
|
---|
63 | IndexHash stored = new IndexHash();
|
---|
64 | for (long i = 0; i < recordCount; ++i) {
|
---|
65 | long unpaddedSize = DecoderUtil.decodeVLI(inChecked);
|
---|
66 | long uncompressedSize = DecoderUtil.decodeVLI(inChecked);
|
---|
67 |
|
---|
68 | try {
|
---|
69 | stored.add(unpaddedSize, uncompressedSize);
|
---|
70 | } catch (XZIOException e) {
|
---|
71 | throw new CorruptedInputException("XZ Index is corrupt");
|
---|
72 | }
|
---|
73 |
|
---|
74 | if (stored.blocksSum > blocksSum
|
---|
75 | || stored.uncompressedSum > uncompressedSum
|
---|
76 | || stored.indexListSize > indexListSize)
|
---|
77 | throw new CorruptedInputException("XZ Index is corrupt");
|
---|
78 | }
|
---|
79 |
|
---|
80 | if (stored.blocksSum != blocksSum
|
---|
81 | || stored.uncompressedSum != uncompressedSum
|
---|
82 | || stored.indexListSize != indexListSize
|
---|
83 | || !Arrays.equals(stored.hash.finish(), hash.finish()))
|
---|
84 | throw new CorruptedInputException("XZ Index is corrupt");
|
---|
85 |
|
---|
86 | // Index Padding
|
---|
87 | DataInputStream inData = new DataInputStream(inChecked);
|
---|
88 | for (int i = getIndexPaddingSize(); i > 0; --i)
|
---|
89 | if (inData.readUnsignedByte() != 0x00)
|
---|
90 | throw new CorruptedInputException("XZ Index is corrupt");
|
---|
91 |
|
---|
92 | // CRC32
|
---|
93 | long value = crc32.getValue();
|
---|
94 | for (int i = 0; i < 4; ++i)
|
---|
95 | if (((value >>> (i * 8)) & 0xFF) != inData.readUnsignedByte())
|
---|
96 | throw new CorruptedInputException("XZ Index is corrupt");
|
---|
97 | }
|
---|
98 | }
|
---|