Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 2c9a36e

Browse files
committed
Check for invalid abbreviation operators in munged bitcode.
Discovered (via fuzzing) that errors are generated by the PNaCl bitstream writer if the abbreviation is invalid. It also appplies operator-specific validity checks as each abbreviation operator is built. Updated the munged bitcode writer to check for these conditions and apply recoverable fixes if they occur. BUG=https://code.google.com/p/nativeclient/issues/detail?id=4169 [email protected] Review URL: https://codereview.chromium.org/1157273004
1 parent 0a7bbd1 commit 2c9a36e

File tree

2 files changed

+515
-376
lines changed

2 files changed

+515
-376
lines changed

lib/Bitcode/NaCl/TestUtils/NaClBitcodeMungeWriter.cpp

Lines changed: 79 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,32 @@ struct WriteState {
118118
BlocksWithOmittedAbbrevs.insert(SetBID);
119119
}
120120

121+
// Returns true if abbreviation operand is legal. If not, logs
122+
// a recoverable error message and returns false. Assumes that
123+
// the caller does the actual error recovery if applicable.
124+
bool verifyAbbrevOp(NaClBitCodeAbbrevOp::Encoding Encoding, uint64_t Value,
125+
const NaClBitcodeAbbrevRecord &Record);
126+
121127
// Converts the abbreviation record to the corresponding abbreviation.
122128
// Returns nullptr if unable to build abbreviation.
123129
NaClBitCodeAbbrev *buildAbbrev(const NaClBitcodeAbbrevRecord &Record);
124130

131+
// Gets the next value (based on Index) from the record values,
132+
// assigns it to ExtractedValue, and returns true. Otherwise, logs a
133+
// recoverable error message and returns false. Assumes that the
134+
// caller does the actual error recovery if applicable.
135+
bool LLVM_ATTRIBUTE_UNUSED_RESULT
136+
nextAbbrevValue(uint64_t &ExtractedValue,
137+
const NaClBitcodeAbbrevRecord &Record, size_t &Index) {
138+
if (Index >= Record.Values.size()) {
139+
RecoverableError()
140+
<< "Malformed abbreviation found: " << Record << "\n";
141+
return false;
142+
}
143+
ExtractedValue = Record.Values[Index++];
144+
return true;
145+
}
146+
125147
// Emits the given record to the bitcode file. Returns true if
126148
// successful.
127149
bool LLVM_ATTRIBUTE_UNUSED_RESULT
@@ -465,68 +487,71 @@ static NaClBitCodeAbbrev *deleteAbbrev(NaClBitCodeAbbrev *Abbrev) {
465487
return nullptr;
466488
}
467489

490+
bool WriteState::verifyAbbrevOp(NaClBitCodeAbbrevOp::Encoding Encoding,
491+
uint64_t Value,
492+
const NaClBitcodeAbbrevRecord &Record) {
493+
if (NaClBitCodeAbbrevOp::isValid(Encoding, Value))
494+
return true;
495+
RecoverableError() << "Invalid abbreviation "
496+
<< NaClBitCodeAbbrevOp::getEncodingName(Encoding)
497+
<< "(" << static_cast<int64_t>(Value)
498+
<< ") in: " << Record << "\n";
499+
return false;
500+
}
501+
468502
NaClBitCodeAbbrev *WriteState::buildAbbrev(
469503
const NaClBitcodeAbbrevRecord &Record) {
470504
// Note: Recover by removing abbreviation.
471505
NaClBitCodeAbbrev *Abbrev = new NaClBitCodeAbbrev();
472506
size_t Index = 0;
473-
size_t NumValues = Record.Values.size();
474-
if (NumValues == 0) {
475-
RecoverableError() << "Empty abbreviation record not allowed: "
476-
<< Record << "\n";
507+
size_t NumAbbrevOps;
508+
if (!nextAbbrevValue(NumAbbrevOps, Record, Index))
477509
return deleteAbbrev(Abbrev);
478-
}
479-
size_t NumAbbreviations = Record.Values[Index++];
480-
if (NumAbbreviations == 0) {
510+
if (NumAbbrevOps == 0) {
481511
RecoverableError() << "Abbreviation must contain at least one operator: "
482512
<< Record << "\n";
483513
return deleteAbbrev(Abbrev);
484514
}
485-
for (size_t Count = 0; Count < NumAbbreviations; ++Count) {
486-
if (Index >= NumValues) {
487-
RecoverableError()
488-
<< "Malformed abbreviation found. Expects " << NumAbbreviations
489-
<< " operands but found " << Count << ": " << Record << "\n";
515+
for (size_t Count = 0; Count < NumAbbrevOps; ++Count) {
516+
uint64_t IsLiteral;
517+
if (!nextAbbrevValue(IsLiteral, Record, Index))
490518
return deleteAbbrev(Abbrev);
491-
}
492-
switch (Record.Values[Index++]) {
493-
case 1:
494-
if (Index >= NumValues) {
495-
RecoverableError() << "Malformed literal abbreviation: "
496-
<< Record << "\n";
519+
switch (IsLiteral) {
520+
case 1: {
521+
uint64_t Value;
522+
if (!nextAbbrevValue(Value, Record, Index))
497523
return deleteAbbrev(Abbrev);
498-
}
499-
Abbrev->Add(NaClBitCodeAbbrevOp(Record.Values[Index++]));
524+
if (!verifyAbbrevOp(NaClBitCodeAbbrevOp::Literal, Value, Record))
525+
return deleteAbbrev(Abbrev);
526+
Abbrev->Add(NaClBitCodeAbbrevOp(Value));
500527
break;
528+
}
501529
case 0: {
502-
if (Index >= NumValues) {
503-
RecoverableError() << "Malformed abbreviation found: "
504-
<< Record << "\n";
530+
uint64_t Kind;
531+
if (!nextAbbrevValue(Kind, Record, Index))
505532
return deleteAbbrev(Abbrev);
506-
}
507-
unsigned Kind = Record.Values[Index++];
508533
switch (Kind) {
509-
case NaClBitCodeAbbrevOp::Fixed:
510-
if (Index >= NumValues) {
511-
RecoverableError() << "Malformed fixed abbreviation found: "
512-
<< Record << "\n";
534+
case NaClBitCodeAbbrevOp::Fixed: {
535+
uint64_t Value;
536+
if (!nextAbbrevValue(Value, Record, Index))
513537
return deleteAbbrev(Abbrev);
514-
}
515-
Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed,
516-
Record.Values[Index++]));
538+
if (!verifyAbbrevOp(NaClBitCodeAbbrevOp::Fixed, Value, Record))
539+
return deleteAbbrev(Abbrev);
540+
Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::Fixed, Value));
517541
break;
518-
case NaClBitCodeAbbrevOp::VBR:
519-
if (Index >= NumValues) {
520-
RecoverableError() << "Malformed vbr abbreviation found: "
521-
<< Record << "\n";
542+
}
543+
case NaClBitCodeAbbrevOp::VBR: {
544+
uint64_t Value;
545+
if (!nextAbbrevValue(Value, Record, Index))
522546
return deleteAbbrev(Abbrev);
523-
}
524-
Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR,
525-
Record.Values[Index++]));
547+
if (!verifyAbbrevOp(NaClBitCodeAbbrevOp::VBR, Value, Record))
548+
return deleteAbbrev(Abbrev);
549+
Abbrev->Add(NaClBitCodeAbbrevOp(NaClBitCodeAbbrevOp::VBR, Value));
526550
break;
551+
}
527552
case NaClBitCodeAbbrevOp::Array:
528-
if (Index >= NumValues) {
529-
RecoverableError() << "Malformed array abbreviation found: "
553+
if (Count + 2 != NumAbbrevOps) {
554+
RecoverableError() << "Array abbreviation must be second to last: "
530555
<< Record << "\n";
531556
return deleteAbbrev(Abbrev);
532557
}
@@ -543,11 +568,23 @@ NaClBitCodeAbbrev *WriteState::buildAbbrev(
543568
break;
544569
}
545570
default:
546-
RecoverableError() << "Error: Bad abbreviation operand encoding "
571+
RecoverableError() << "Bad abbreviation operand encoding "
547572
<< Record.Values[Index-1] << ": " << Record << "\n";
548573
return deleteAbbrev(Abbrev);
549574
}
550575
}
576+
if (Index != Record.Values.size()) {
577+
RecoverableError() << "Error: Too many values for number of operands ("
578+
<< NumAbbrevOps << "): "
579+
<< Record << "\n";
580+
return deleteAbbrev(Abbrev);
581+
}
582+
if (!Abbrev->isValid()) {
583+
raw_ostream &Out = RecoverableError();
584+
Abbrev->Print(Out << "Abbreviation ");
585+
Out << " not valid: " << Record << "\n";
586+
return deleteAbbrev(Abbrev);
587+
}
551588
return Abbrev;
552589
}
553590

0 commit comments

Comments
 (0)