From 81f9bd3e1997bde935f834ed7be143b4b91088d1 Mon Sep 17 00:00:00 2001 From: Filipe Cabecinhas Date: Thu, 23 Apr 2015 13:25:35 +0000 Subject: [PATCH] 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 --- include/llvm/Bitcode/BitstreamReader.h | 4 +++- lib/Bitcode/Reader/BitstreamReader.cpp | 9 +++++++++ .../Inputs/invalid-abbrev-fixed-size-too-big.bc | Bin 0 -> 612 bytes .../Inputs/invalid-abbrev-vbr-size-too-big.bc | Bin 0 -> 612 bytes test/Bitcode/invalid.test | 7 +++++++ 5 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 test/Bitcode/Inputs/invalid-abbrev-fixed-size-too-big.bc create mode 100644 test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 18f6b9e011e..46e64d112ea 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 beaaf7a7d66..ff37b8e4cfc 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 new file mode 100644 index 0000000000000000000000000000000000000000..8fa28960d727881a59828a365b8fe9d44e958b7c GIT binary patch literal 612 zcmZ>AK5$Qwhk;=l0|NthlL7-1kQM@B_D1E2jwe_=*#wL%Co#70sIqc!$}x2(HSoAH zIZfhrN)a#;vEY#K)3syKB`@je^r&ED}feT0* zDV^X@NNHu6thl5FNIY&?I6*|nr>%#(CB;WTK$)SK#Y0d4XtDDYkS-vQSOjzx2pkYd zg)kV}G?*bQ0~bjMqe1Z$RPIS41A`!tZOqXibL62+nh2w9hqFb?;U1?3_R0$O;u(cJ z&lvdM3h;et;4|iNk~?%z_S{05Gy_(!vS#Ts%(f?-ZF`t)fo2pcFfeccX*UIniM%`x z#u5hN z4-hyjl9;9tvsG3=Q1NP;gG))hQo~vY(PFX uy-?qS?S<)aoTZRLtR9e?K=w2ySqQLT+5r@SxCf^0Ad%`AlX05|G7|s=d48S% literal 0 HcmV?d00001 diff --git a/test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc b/test/Bitcode/Inputs/invalid-abbrev-vbr-size-too-big.bc new file mode 100644 index 0000000000000000000000000000000000000000..35d00ba154b5eb9dc4a6e06f94db7ea3c0202667 GIT binary patch literal 612 zcmZ>AK5$Qwhk;=l0|NthlL7-1kQM@B_D1E2jwe_=*#wL%Co#70sIqc!%CU4OHSoAH zIZfhrN)a#;vEY#K)3syKB`@je^r&ED}feT0* zDV^X@NNHu6thl5FNIY&?I6*|nr>%#(CB;WTK$)SK#Y0d4XtDDYkS-vQSOjzx2pkYd zg)kV}G?*bQ0~bjMqe1Z$RPIS41A`!tZOqXibL62+nh2w9hqFb?;U1?3_R0$O;u(cJ z&lvdM3h;et;4|iNk~?%z_S{05Gy_(!vS#Ts%(f?-ZF`t)fo2pcFfeccX*UIniM%`x z#u5hN z4-hyjl9;9tvsG3=Q1NP;gG))hQo~vY(PFX uy-?qS?S<)aoTZRLtR9e?K=w2ySqQLT+5r@SxCf^0Ad%`AlX05|G7|s^=YF67 literal 0 HcmV?d00001 diff --git a/test/Bitcode/invalid.test b/test/Bitcode/invalid.test index 5431368a0ad..b6c2ed3e8d6 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 -- 2.34.1