diff --git a/src/core/index/FieldsReader.cpp b/src/core/index/FieldsReader.cpp index 439b917c..2b2aba9e 100644 --- a/src/core/index/FieldsReader.cpp +++ b/src/core/index/FieldsReader.cpp @@ -168,6 +168,10 @@ DocumentPtr FieldsReader::doc(int32_t n, const FieldSelectorPtr& fieldSelector) for (int32_t i = 0; i < numFields; ++i) { int32_t fieldNumber = fieldsStream->readVInt(); FieldInfoPtr fi = fieldInfos->fieldInfo(fieldNumber); + if (!fi) { + boost::throw_exception(CorruptIndexException(L"invalid field number " + StringUtils::toString(fieldNumber) + + L" while reading stored fields for doc " + StringUtils::toString(n))); + } FieldSelector::FieldSelectorResult acceptField = fieldSelector ? fieldSelector->accept(fi->name) : FieldSelector::SELECTOR_LOAD; uint8_t bits = fieldsStream->readByte(); diff --git a/src/test/index/FieldsReaderTest.cpp b/src/test/index/FieldsReaderTest.cpp index d7c4d4d4..c4ffa8bd 100644 --- a/src/test/index/FieldsReaderTest.cpp +++ b/src/test/index/FieldsReaderTest.cpp @@ -22,6 +22,8 @@ #include "IndexReader.h" #include "MiscUtils.h" #include "FileUtils.h" +#include "IndexFileNames.h" +#include "IndexOutput.h" using namespace Lucene; @@ -378,6 +380,43 @@ class TestableFieldSelector : public FieldSelector { } +static void writeCorruptedStoredFieldsIndex(const DirectoryPtr& sourceDir, + const DirectoryPtr& corruptDir, + const String& segmentName) +{ + String fieldsName = segmentName + L"." + IndexFileNames::FIELDS_EXTENSION(); + IndexInputPtr in = sourceDir->openInput(fieldsName); + ByteArray data(ByteArray::newInstance((int32_t)in->length())); + in->readBytes(data.get(), 0, (int32_t)in->length()); + in->close(); + + // Overwrite the first stored field number with an invalid VInt. + data[5] = 0x7f; + data[6] = 0x7f; + + IndexOutputPtr out = corruptDir->createOutput(fieldsName); + out->writeBytes(data.get(), 0, (int32_t)data.size()); + out->close(); +} + +TEST_F(FieldsReaderTest, testCorruptFieldNumber) { + String indexDir(FileUtils::joinPath(getTempDir(), L"testfieldreaderbadfieldnumber")); + RAMDirectoryPtr sourceDir = newLucene(); + IndexWriterPtr writer = newLucene(sourceDir, newLucene(), true, IndexWriter::MaxFieldLengthLIMITED); + writer->setUseCompoundFile(false); + writer->addDocument(testDoc); + writer->close(); + + RAMDirectoryPtr corruptDir = newLucene(sourceDir); + writeCorruptedStoredFieldsIndex(sourceDir, corruptDir, TEST_SEGMENT_NAME); + + FieldsReaderPtr reader = newLucene(corruptDir, TEST_SEGMENT_NAME, fieldInfos); + EXPECT_THROW(reader->doc(0, FieldSelectorPtr()), CorruptIndexException); + reader->close(); + sourceDir->close(); + corruptDir->close(); +} + TEST_F(FieldsReaderTest, testLoadSize) { FieldsReaderPtr reader = newLucene(dir, TEST_SEGMENT_NAME, fieldInfos); DocumentPtr doc = reader->doc(0, newLucene());