Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp |
diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp |
index 7ed2dc8f3e875480681af7ab9c9b222ceb71e881..78a81e36e41b1bf3c926bbfb65666a1e407238e9 100644 |
--- a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp |
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMunge.cpp |
@@ -218,6 +218,8 @@ void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex, |
<< Values.size(); |
ReportFatalError(); |
} |
+ uint64_t MaxAbbrev = (static_cast<uint64_t>(1) << NumBits) - 1; |
+ AbbrevIndexLimitStack.push_back(MaxAbbrev); |
if (WriteBlockID == naclbitc::BLOCKINFO_BLOCK_ID) { |
if (NumBits != naclbitc::DEFAULT_MAX_ABBREV) { |
Fatal() |
@@ -227,7 +229,8 @@ void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex, |
} |
Writer->EnterBlockInfoBlock(); |
} else { |
- Writer->EnterSubblock(WriteBlockID, NumBits); |
+ NaClBitcodeSelectorAbbrev CurCodeLen(MaxAbbrev); |
+ Writer->EnterSubblock(WriteBlockID, CurCodeLen); |
} |
return; |
} |
@@ -242,6 +245,8 @@ void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex, |
<< Values.size() << "\n"; |
ReportFatalError(); |
} |
+ if (!AbbrevIndexLimitStack.empty()) |
+ AbbrevIndexLimitStack.pop_back(); |
Writer->ExitBlock(); |
return; |
case naclbitc::BLK_CODE_DEFINE_ABBREV: { |
@@ -270,9 +275,31 @@ void NaClBitcodeMunger::emitRecord(unsigned AbbrevIndex, |
default: |
if ((AbbrevIndex != naclbitc::UNABBREV_RECORD |
&& !Writer->isUserRecordAbbreviation(AbbrevIndex))) { |
- Fatal() << "Error: Record code " << RecordCode |
- << " uses illegal abbreviation index " << AbbrevIndex << "\n"; |
- ReportFatalError(); |
+ uint64_t BlockAbbrevIndexLimit = 0; |
+ if (!AbbrevIndexLimitStack.empty()) |
+ BlockAbbrevIndexLimit = AbbrevIndexLimitStack.back(); |
+ if (AbbrevIndex > BlockAbbrevIndexLimit) { |
+ Fatal() << "Error: Record code " << RecordCode |
+ << " uses illegal abbreviation index " << AbbrevIndex |
+ << ". Must not exceed " << BlockAbbrevIndexLimit << "\n"; |
+ ReportFatalError(); |
+ } |
+ // Note: If this point is reached, the abbreviation is |
+ // bad. However, that may be the point of munge being |
+ // applied. Hence, emit the bad abbreviation and the data so |
+ // that the reader can be tested on this bad input. For |
+ // simplicity, we output the record data using the default |
+ // abbreviation pattern. |
+ errs() << "Warning: Record code " << RecordCode |
+ << " uses illegal abbreviation index " << AbbrevIndex << "\n"; |
+ Writer->EmitCode(AbbrevIndex); |
+ Writer->EmitVBR(RecordCode, 6); |
+ uint32_t NumValues = static_cast<uint32_t>(Values.size()); |
+ Writer->EmitVBR(NumValues, 6); |
+ for (uint32_t i = 0; i < NumValues; ++i) { |
+ Writer->EmitVBR64(Values[i], 6); |
+ } |
+ return; |
} |
if (AbbrevIndex == naclbitc::UNABBREV_RECORD) |
Writer->EmitRecord(RecordCode, Values); |
@@ -348,7 +375,12 @@ bool NaClObjDumpMunger::runTestWithFlags( |
const char *Name, const uint64_t Munges[], size_t MungesSize, |
bool AddHeader, bool NoRecords, bool NoAssembly) { |
setupTest(Name, Munges, MungesSize, AddHeader); |
- if (NaClObjDump(MungedInput.get(), *DumpStream, NoRecords, NoAssembly)) |
+ |
+ /// If running in death mode, redirect output directly to the |
+ /// error stream (rather than buffering in DumpStream), so that |
+ /// output can be seen in gtest death test. |
+ raw_ostream &Output = RunAsDeathTest ? errs() : *DumpStream; |
+ if (NaClObjDump(MungedInput.get(), Output, NoRecords, NoAssembly)) |
FoundErrors = true; |
cleanupTest(); |
return !FoundErrors; |