diff options
author | Filipe Cabecinhas <me@filcab.net> | 2015-04-23 13:25:35 +0000 |
---|---|---|
committer | Filipe Cabecinhas <me@filcab.net> | 2015-04-23 13:25:35 +0000 |
commit | 81f9bd3e1997bde935f834ed7be143b4b91088d1 (patch) | |
tree | 349d7d194f01cc70479be15af33d0cea5bb9af7a | |
parent | 77aa4a8c4df240caa043b84e5340fe31eaa0962d (diff) |
Verify sizes when trying to read a BitcodeAbbrevOp
Summary:
Make sure the abbrev operands are valid and that we can read/skip them
afterwards.
Bug found with AFL fuzz.
Reviewers: rafael
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D9030
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235595 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/llvm/Bitcode/BitstreamReader.h | 4 | ||||
-rw-r--r-- | lib/Bitcode/Reader/BitstreamReader.cpp | 9 | ||||
-rw-r--r-- | test/Bitcode/Inputs/invalid-abbrev-fixed-size-too-big.bc | bin | 0 -> 612 bytes | |||
-rw-r--r-- | test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc | bin | 0 -> 612 bytes | |||
-rw-r--r-- | test/Bitcode/invalid.test | 7 |
5 files changed, 19 insertions, 1 deletions
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 18f6b9e011..46e64d112e 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -198,6 +198,8 @@ class BitstreamCursor { public: + static const size_t MaxChunkSize = sizeof(word_t) * 8; + BitstreamCursor() { init(nullptr); } explicit BitstreamCursor(BitstreamReader &R) { init(&R); } @@ -335,7 +337,7 @@ public: } word_t Read(unsigned NumBits) { - static const unsigned BitsInWord = sizeof(word_t) * 8; + static const unsigned BitsInWord = MaxChunkSize; assert(NumBits && NumBits <= BitsInWord && "Cannot return zero or more than BitsInWord bits!"); diff --git a/lib/Bitcode/Reader/BitstreamReader.cpp b/lib/Bitcode/Reader/BitstreamReader.cpp index beaaf7a7d6..ff37b8e4cf 100644 --- a/lib/Bitcode/Reader/BitstreamReader.cpp +++ b/lib/Bitcode/Reader/BitstreamReader.cpp @@ -60,8 +60,10 @@ static uint64_t readAbbreviatedField(BitstreamCursor &Cursor, case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.Read((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::VBR: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); return Cursor.ReadVBR64((unsigned)Op.getEncodingData()); case BitCodeAbbrevOp::Char6: return BitCodeAbbrevOp::DecodeChar6(Cursor.Read(6)); @@ -79,9 +81,11 @@ static void skipAbbreviatedField(BitstreamCursor &Cursor, case BitCodeAbbrevOp::Blob: llvm_unreachable("Should not reach here"); case BitCodeAbbrevOp::Fixed: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); Cursor.Read((unsigned)Op.getEncodingData()); break; case BitCodeAbbrevOp::VBR: + assert((unsigned)Op.getEncodingData() <= Cursor.MaxChunkSize); Cursor.ReadVBR64((unsigned)Op.getEncodingData()); break; case BitCodeAbbrevOp::Char6: @@ -264,6 +268,11 @@ void BitstreamCursor::ReadAbbrevRecord() { continue; } + if ((E == BitCodeAbbrevOp::Fixed || E == BitCodeAbbrevOp::VBR) && + Data > MaxChunkSize) + report_fatal_error( + "Fixed or VBR abbrev record with size > MaxChunkData"); + Abbv->Add(BitCodeAbbrevOp(E, Data)); } else Abbv->Add(BitCodeAbbrevOp(E)); diff --git a/test/Bitcode/Inputs/invalid-abbrev-fixed-size-too-big.bc b/test/Bitcode/Inputs/invalid-abbrev-fixed-size-too-big.bc Binary files differnew file mode 100644 index 0000000000..8fa28960d7 --- /dev/null +++ b/test/Bitcode/Inputs/invalid-abbrev-fixed-size-too-big.bc diff --git a/test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc b/test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc Binary files differnew file mode 100644 index 0000000000..35d00ba154 --- /dev/null +++ b/test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc diff --git a/test/Bitcode/invalid.test b/test/Bitcode/invalid.test index 5431368a0a..b6c2ed3e8d 100644 --- a/test/Bitcode/invalid.test +++ b/test/Bitcode/invalid.test @@ -66,3 +66,10 @@ RUN: not llvm-dis -disable-output %p/Inputs/invalid-fp-shift.bc 2>&1 | \ RUN: FileCheck --check-prefix=FP-SHIFT %s FP-SHIFT: Invalid record + +RUN: not llvm-dis -disable-output %p/Inputs/invalid-abbrev-vbr-size-too-big.bc 2>&1 | \ +RUN: FileCheck --check-prefix=HUGE-ABBREV-OP %s +RUN: not llvm-dis -disable-output %p/Inputs/invalid-abbrev-fixed-size-too-big.bc 2>&1 | \ +RUN: FileCheck --check-prefix=HUGE-ABBREV-OP %s + +HUGE-ABBREV-OP: Fixed or VBR abbrev record with size > MaxChunkData |