mirror of https://github.com/apache/lucene.git
LUCENE-6577: Give earlier and better error message for invalid CRC
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1685927 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5a0c012250
commit
f047b54425
|
@ -85,6 +85,9 @@ New Features
|
||||||
quite slow and are only fast in specific cases. (Adrien Grand,
|
quite slow and are only fast in specific cases. (Adrien Grand,
|
||||||
Robert Muir, Mike McCandless)
|
Robert Muir, Mike McCandless)
|
||||||
|
|
||||||
|
* LUCENE-6577: Give earlier and better error message for invalid CRC.
|
||||||
|
(Robert Muir)
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
|
|
||||||
* LUCENE-6508: Simplify Lock api, there is now just
|
* LUCENE-6508: Simplify Lock api, there is now just
|
||||||
|
|
|
@ -307,7 +307,7 @@ public final class CodecUtil {
|
||||||
public static void writeFooter(IndexOutput out) throws IOException {
|
public static void writeFooter(IndexOutput out) throws IOException {
|
||||||
out.writeInt(FOOTER_MAGIC);
|
out.writeInt(FOOTER_MAGIC);
|
||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
out.writeLong(out.getChecksum());
|
writeCRC(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -330,7 +330,7 @@ public final class CodecUtil {
|
||||||
public static long checkFooter(ChecksumIndexInput in) throws IOException {
|
public static long checkFooter(ChecksumIndexInput in) throws IOException {
|
||||||
validateFooter(in);
|
validateFooter(in);
|
||||||
long actualChecksum = in.getChecksum();
|
long actualChecksum = in.getChecksum();
|
||||||
long expectedChecksum = in.readLong();
|
long expectedChecksum = readCRC(in);
|
||||||
if (expectedChecksum != actualChecksum) {
|
if (expectedChecksum != actualChecksum) {
|
||||||
throw new CorruptIndexException("checksum failed (hardware problem?) : expected=" + Long.toHexString(expectedChecksum) +
|
throw new CorruptIndexException("checksum failed (hardware problem?) : expected=" + Long.toHexString(expectedChecksum) +
|
||||||
" actual=" + Long.toHexString(actualChecksum), in);
|
" actual=" + Long.toHexString(actualChecksum), in);
|
||||||
|
@ -399,7 +399,7 @@ public final class CodecUtil {
|
||||||
public static long retrieveChecksum(IndexInput in) throws IOException {
|
public static long retrieveChecksum(IndexInput in) throws IOException {
|
||||||
in.seek(in.length() - footerLength());
|
in.seek(in.length() - footerLength());
|
||||||
validateFooter(in);
|
validateFooter(in);
|
||||||
return in.readLong();
|
return readCRC(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateFooter(IndexInput in) throws IOException {
|
private static void validateFooter(IndexInput in) throws IOException {
|
||||||
|
@ -436,4 +436,30 @@ public final class CodecUtil {
|
||||||
in.seek(in.length() - footerLength());
|
in.seek(in.length() - footerLength());
|
||||||
return checkFooter(in);
|
return checkFooter(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads CRC32 value as a 64-bit long from the input.
|
||||||
|
* @throws CorruptIndexException if CRC is formatted incorrectly (wrong bits set)
|
||||||
|
* @throws IOException if an i/o error occurs
|
||||||
|
*/
|
||||||
|
public static long readCRC(IndexInput input) throws IOException {
|
||||||
|
long value = input.readLong();
|
||||||
|
if ((value & 0xFFFFFFFF00000000L) != 0) {
|
||||||
|
throw new CorruptIndexException("Illegal CRC-32 checksum: " + value, input);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes CRC32 value as a 64-bit long to the output.
|
||||||
|
* @throws IllegalStateException if CRC is formatted incorrectly (wrong bits set)
|
||||||
|
* @throws IOException if an i/o error occurs
|
||||||
|
*/
|
||||||
|
public static void writeCRC(IndexOutput output) throws IOException {
|
||||||
|
long value = output.getChecksum();
|
||||||
|
if ((value & 0xFFFFFFFF00000000L) != 0) {
|
||||||
|
throw new IllegalStateException("Illegal CRC-32 checksum: " + value + " (resource=" + output + ")");
|
||||||
|
}
|
||||||
|
output.writeLong(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ package org.apache.lucene.index;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import org.apache.lucene.codecs.CodecUtil;
|
import org.apache.lucene.codecs.CodecUtil;
|
||||||
import org.apache.lucene.store.BufferedChecksumIndexInput;
|
import org.apache.lucene.store.BufferedChecksumIndexInput;
|
||||||
import org.apache.lucene.store.ChecksumIndexInput;
|
import org.apache.lucene.store.ChecksumIndexInput;
|
||||||
|
@ -252,4 +255,86 @@ public class TestCodecUtil extends LuceneTestCase {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testReadBogusCRC() throws Exception {
|
||||||
|
RAMFile file = new RAMFile();
|
||||||
|
IndexOutput output = new RAMOutputStream(file, false);
|
||||||
|
output.writeLong(-1L); // bad
|
||||||
|
output.writeLong(1L << 32); // bad
|
||||||
|
output.writeLong(-(1L << 32)); // bad
|
||||||
|
output.writeLong((1L << 32) - 1); // ok
|
||||||
|
output.close();
|
||||||
|
IndexInput input = new RAMInputStream("file", file);
|
||||||
|
// read 3 bogus values
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
try {
|
||||||
|
CodecUtil.readCRC(input);
|
||||||
|
fail("didn't get expected exception");
|
||||||
|
} catch (CorruptIndexException expected) {
|
||||||
|
// expected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// good value
|
||||||
|
CodecUtil.readCRC(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testWriteBogusCRC() throws Exception {
|
||||||
|
RAMFile file = new RAMFile();
|
||||||
|
final IndexOutput output = new RAMOutputStream(file, false);
|
||||||
|
AtomicLong fakeChecksum = new AtomicLong();
|
||||||
|
// wrap the index input where we control the checksum for mocking
|
||||||
|
IndexOutput fakeOutput = new IndexOutput("fake") {
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
output.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getFilePointer() {
|
||||||
|
return output.getFilePointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getChecksum() throws IOException {
|
||||||
|
return fakeChecksum.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeByte(byte b) throws IOException {
|
||||||
|
output.writeByte(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeBytes(byte[] b, int offset, int length) throws IOException {
|
||||||
|
output.writeBytes(b, offset, length);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fakeChecksum.set(-1L); // bad
|
||||||
|
try {
|
||||||
|
CodecUtil.writeCRC(fakeOutput);
|
||||||
|
fail("didn't get expected exception");
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
// expected exception
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeChecksum.set(1L << 32); // bad
|
||||||
|
try {
|
||||||
|
CodecUtil.writeCRC(fakeOutput);
|
||||||
|
fail("didn't get expected exception");
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
// expected exception
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeChecksum.set(-(1L << 32)); // bad
|
||||||
|
try {
|
||||||
|
CodecUtil.writeCRC(fakeOutput);
|
||||||
|
fail("didn't get expected exception");
|
||||||
|
} catch (IllegalStateException expected) {
|
||||||
|
// expected exception
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeChecksum.set((1L << 32) - 1); // ok
|
||||||
|
CodecUtil.writeCRC(fakeOutput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue