Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(566)

Unified Diff: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp

Issue 1146203003: Fix abbreviation handling in munged bitcode writer. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Don't allow application of abbreviation if index out of range. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
diff --git a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
index b536fe3c848a4d81241cb4b7f6e39c49313451de..6ad7ac6536ba755d570ee4a04438c4e9f457c3ec 100644
--- a/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
+++ b/lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp
@@ -16,6 +16,8 @@
#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
#include "llvm/Support/raw_ostream.h"
+#include <set>
+
using namespace llvm;
namespace {
@@ -24,16 +26,26 @@ namespace {
// bitcode.
static bool DebugEmit = false;
+// Maximum bits that can be printed out using method
+// NaClBitstreamWriter::Emit().
jvoung (off chromium) 2015/05/20 22:40:09 Seems like this should be part of NaClBitstreamWri
Karl 2015/05/21 18:22:07 I agree. I originally put it there, but I didn't l
+static const unsigned MaxEmitFixedBits = 32;
+
// Description of current block scope
struct BlockScope {
BlockScope(unsigned CurBlockID, size_t AbbrevIndexLimit)
- : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit) {}
+ : CurBlockID(CurBlockID), AbbrevIndexLimit(AbbrevIndexLimit),
+ OmittedAbbreviations(false) {}
unsigned CurBlockID;
// Defines the maximum value for abbreviation indices in block.
size_t AbbrevIndexLimit;
+ // Defines if an abbreviation definition was omitted (i.e. not
+ // written) from this block. Used to turn off writing further
+ // abbreviation definitions for this block.
+ bool OmittedAbbreviations;
void print(raw_ostream &Out) const {
Out << "BlockScope(ID=" << CurBlockID << ", AbbrevIndexLimit="
- << AbbrevIndexLimit << ")";
+ << AbbrevIndexLimit << "OmittedAbbreviations = "
jvoung (off chromium) 2015/05/20 22:40:10 = spacing consistency previous ones just did X=Y
Karl 2015/05/21 18:22:08 Done.
+ << OmittedAbbreviations << ")";
}
};
@@ -56,6 +68,9 @@ struct WriteState {
NaClMungedBitcode::WriteResults Results;
// The minimum number of bits allowed to be specified in a block.
const unsigned BlockMinBits;
+ // The set of block IDs for which abbreviation definitions have been
+ // omitted in the blockinfo block.
+ std::set<unsigned> BlocksWithOmittedAbbrevs;
jvoung (off chromium) 2015/05/20 22:40:10 Would DenseSet be better? I suppose there are onl
Karl 2015/05/21 18:22:07 I did not expect the set to get much larger than 8
WriteState(const NaClMungedBitcode::WriteFlags &Flags)
: Flags(Flags),
@@ -90,6 +105,24 @@ struct WriteState {
return ScopeStack.back().AbbrevIndexLimit;
}
+ // Returns whether any abbreviation definitions were not written to
+ // the bitcode buffer.
+ bool curBlockHasOmittedAbbreviations() const {
+ assert(!ScopeStack.empty());
+ return ScopeStack.back().OmittedAbbreviations
+ || BlocksWithOmittedAbbrevs.count(getCurWriteBlockID());
+ }
+
+ // Marks that an abbreviation definition is being omitted (i.e. not
+ // written) for the current block.
+ void markCurrentBlockWithOmittedAbbreviations() {
+ assert(!ScopeStack.empty());
+ ScopeStack.back().OmittedAbbreviations = true;
+ if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID)
+ BlocksWithOmittedAbbrevs.insert(SetBID);
+ return;
jvoung (off chromium) 2015/05/20 22:40:10 The return doesn't seem to do much so may be bette
Karl 2015/05/21 18:22:08 Hmm. I guess this is a leftover of an earlier vers
+ }
+
// Converts the abbreviation record to the corresponding abbreviation.
// Returns nullptr if unable to build abbreviation.
NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record);
@@ -97,7 +130,8 @@ struct WriteState {
// Emits the given record to the bitcode file. Returns true if
// successful.
bool LLVM_ATTRIBUTE_UNUSED_RESULT
- emitRecord(NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record);
+ emitRecord(NaClBitstreamWriter &Writer,
+ const NaClBitcodeAbbrevRecord &Record);
// Enter the given block
bool LLVM_ATTRIBUTE_UNUSED_RESULT
@@ -118,6 +152,22 @@ struct WriteState {
return true;
}
+ void WriteRecord(NaClBitstreamWriter &Writer,
+ const NaClBitcodeAbbrevRecord &Record,
+ bool UsesDefaultAbbrev) {
+ if (UsesDefaultAbbrev)
+ Writer.EmitRecord(Record.Code, Record.Values);
+ else
+ Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev);
+
+ }
+
+ // Returns true if the abbreviation index defines an anbbreviation
jvoung (off chromium) 2015/05/20 22:40:09 anbbreviation -> ?
Karl 2015/05/21 18:22:07 Fixed.
+ // that can be applied to the record.
+ bool LLVM_ATTRIBUTE_UNUSED_RESULT
+ canApplyAbbreviation(NaClBitstreamWriter &Writer,
+ const NaClBitcodeAbbrevRecord &Record);
+
// Completes the write.
NaClMungedBitcode::WriteResults &finish(NaClBitstreamWriter &Writer,
bool RecoverSilently);
@@ -185,6 +235,58 @@ bool WriteState::enterBlock(NaClBitstreamWriter &Writer, uint64_t WriteBlockID,
return true;
}
+bool WriteState::canApplyAbbreviation(
+ NaClBitstreamWriter &Writer, const NaClBitcodeAbbrevRecord &Record) {
Karl 2015/05/20 20:32:04 Added following two lines to make sure that the bl
jvoung (off chromium) 2015/05/20 22:40:09 Does the Writer.getAbbreviation(...); if (Abbrev =
Karl 2015/05/21 18:22:07 This check helps. I didn't see the case until the
+ if (Record.Abbrev > getCurAbbrevIndexLimit())
+ return false;
+
+ const NaClBitCodeAbbrev *Abbrev = Writer.getAbbreviation(Record.Abbrev);
+ if (Abbrev == nullptr)
+ return false;
+
+ // Merge record code into values and then match abbreviation.
+ NaClBitcodeValues Values(Record);
+ size_t ValueIndex = 0;
+ size_t ValuesSize = Values.size();
+ size_t AbbrevIndex = 0;
+ size_t AbbrevSize = Abbrev->getNumOperandInfos();
+ bool FoundArray = false;
+ while (ValueIndex < ValuesSize && AbbrevIndex < AbbrevSize) {
+ const NaClBitCodeAbbrevOp *Op = &Abbrev->getOperandInfo(AbbrevIndex++);
+ uint64_t Value = Values[ValueIndex++];
+ if (Op->getEncoding() == NaClBitCodeAbbrevOp::Array) {
+ if (AbbrevIndex + 1 != AbbrevSize)
+ return false;
+ Op = &Abbrev->getOperandInfo(AbbrevIndex);
+ --AbbrevIndex; // i.e. don't advance to next abbreviation op.
+ FoundArray = true;
+ }
+ switch (Op->getEncoding()) {
+ case NaClBitCodeAbbrevOp::Literal:
+ if (Value != Op->getValue())
+ return false;
+ continue;
+ case NaClBitCodeAbbrevOp::Fixed:
+ if (Value >= (static_cast<uint64_t>(1) < MaxEmitFixedBits)
jvoung (off chromium) 2015/05/20 22:40:10 I assume this should actually be a shift and not (
Karl 2015/05/21 18:22:07 Yes. Fixing.
+ || NaClBitsNeededForValue(Value) > Op->getValue())
+ return false;
+ continue;
+ case NaClBitCodeAbbrevOp::VBR:
+ if (Op->getValue() < 2)
+ return false;
+ continue;
+ case NaClBitCodeAbbrevOp::Array:
+ // This should not happen
jvoung (off chromium) 2015/05/20 22:40:10 llvm_unreachable(...);
Karl 2015/05/21 18:22:08 Done.
+ return false;
+ case NaClBitCodeAbbrevOp::Char6:
+ if (!Op->isChar6(Value))
+ return false;
+ continue;
+ }
+ }
+ return ValueIndex == ValuesSize && (FoundArray || AbbrevIndex == AbbrevSize);
+}
+
NaClMungedBitcode::WriteResults &WriteState::finish(
NaClBitstreamWriter &Writer, bool RecoverSilently) {
// Be sure blocks are balanced.
@@ -275,19 +377,29 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
RecoverableError()
<< "Uses illegal abbreviation index in define abbreviation record: "
<< Record << "\n";
+ markCurrentBlockWithOmittedAbbreviations();
if (!Flags.getTryToRecover())
jvoung (off chromium) 2015/05/20 22:40:10 Might be simpler to just return now like the other
Karl 2015/05/21 18:22:07 I agree that the check for omitted abbreviations s
return false;
}
+ if (curBlockHasOmittedAbbreviations()) {
+ // If reached, a previous abbreviation for the block was omitted. Can't
+ // generate more abbreviations without having to fix abbreviation indices.
+ RecoverableError() << "Ignoring abbreviation: " << Record << "\n";
+ return Flags.getTryToRecover();
+ }
if (getCurWriteBlockID() != naclbitc::BLOCKINFO_BLOCK_ID
&& Writer.getMaxCurAbbrevIndex() >= getCurAbbrevIndexLimit()) {
RecoverableError() << "Exceeds abbreviation index limit of "
<< getCurAbbrevIndexLimit() << ": " << Record << "\n";
// Recover by not writing.
+ markCurrentBlockWithOmittedAbbreviations();
return Flags.getTryToRecover();
}
NaClBitCodeAbbrev *Abbrev = buildAbbrev(Record);
- if (Abbrev == NULL)
+ if (Abbrev == nullptr) {
+ markCurrentBlockWithOmittedAbbreviations();
return Flags.getTryToRecover();
+ }
if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) {
Writer.EmitBlockInfoAbbrev(SetBID, Abbrev);
} else {
@@ -314,9 +426,15 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
}
UsesDefaultAbbrev = true;
}
- if (!UsesDefaultAbbrev
- && !Writer.isUserRecordAbbreviation(Record.Abbrev)) {
- // Illegal abbreviation index found.
+ if (!UsesDefaultAbbrev && !canApplyAbbreviation(Writer, Record)) {
+ // Can't apply abbreviation, figure out why.
+ if (Writer.getAbbreviation(Record.Abbrev) != nullptr) {
+ RecoverableError() << "Abbreviation doesn't apply to record: "
jvoung (off chromium) 2015/05/20 22:40:09 So here the abbreviation exists, but doesn't apply
Karl 2015/05/21 18:22:07 Yes.
+ << Record << "\n";
+ UsesDefaultAbbrev = true;
+ WriteRecord(Writer, Record, UsesDefaultAbbrev);
jvoung (off chromium) 2015/05/20 22:40:09 This and the one below might be the first case whe
Karl 2015/05/21 18:22:08 Done.
+ return Flags.getTryToRecover();
+ }
if (Flags.getWriteBadAbbrevIndex()) {
jvoung (off chromium) 2015/05/20 22:40:10 Maybe add a comment here. This CL adds the "figure
Karl 2015/05/21 18:22:08 Removed the first comment, and added a comment to
Error() << "Uses illegal abbreviation index: " << Record << "\n";
// Generate bad abbreviation index so that the bitcode reader
@@ -329,9 +447,9 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
}
RecoverableError() << "Uses illegal abbreviation index: "
<< Record << "\n";
- if (!Flags.getTryToRecover())
- return false;
UsesDefaultAbbrev = true;
+ WriteRecord(Writer, Record, UsesDefaultAbbrev);
+ return Flags.getTryToRecover();
}
if (getCurWriteBlockID() == naclbitc::BLOCKINFO_BLOCK_ID
&& Record.Code == naclbitc::BLOCKINFO_CODE_SETBID) {
@@ -347,10 +465,8 @@ bool WriteState::emitRecord(NaClBitstreamWriter &Writer,
SetBID = Record.Values[0];
return true;
}
- if (UsesDefaultAbbrev)
- Writer.EmitRecord(Record.Code, Record.Values);
- else
- Writer.EmitRecord(Record.Code, Record.Values, Record.Abbrev);
+ WriteRecord(Writer, Record, UsesDefaultAbbrev);
+ break;
}
return true;
}
@@ -381,7 +497,7 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
if (Index >= NumValues) {
RecoverableError()
<< "Malformed abbreviation found. Expects " << NumAbbreviations
- << " operands but ound " << Count << ": " << Record << "\n";
+ << " operands but found " << Count << ": " << Record << "\n";
return deleteAbbrev(Abbrev);
}
switch (Record.Values[Index++]) {
@@ -438,8 +554,8 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
break;
}
default:
- RecoverableError() << "Error: Bad literal flag " << Record.Values[Index]
- << ": " << Record << "\n";
+ RecoverableError() << "Error: Bad abbreviation operand encoding "
+ << Record.Values[Index-1] << ": " << Record << "\n";
return deleteAbbrev(Abbrev);
}
}

Powered by Google App Engine
This is Rietveld 408576698