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

Side by Side Diff: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Issue 932953002: Fix the NaCl bitstream reader to report fatal errors. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Fix issues raised in patch set 8. Created 5 years, 10 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 unified diff | Download patch
OLDNEW
1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// 1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===//
2 // Low-level bitstream reader interface 2 // Low-level bitstream reader interface
3 // 3 //
4 // The LLVM Compiler Infrastructure 4 // The LLVM Compiler Infrastructure
5 // 5 //
6 // This file is distributed under the University of Illinois Open Source 6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details. 7 // License. See LICENSE.TXT for details.
8 // 8 //
9 //===----------------------------------------------------------------------===// 9 //===----------------------------------------------------------------------===//
10 // 10 //
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 Info.Abbrevs[i]->dropRef(); 83 Info.Abbrevs[i]->dropRef();
84 BlockInfoRecords.pop_back(); 84 BlockInfoRecords.pop_back();
85 } 85 }
86 } 86 }
87 87
88 /// \brief Returns the initial address (after the header) of the input stream. 88 /// \brief Returns the initial address (after the header) of the input stream.
89 size_t getInitialAddress() const { 89 size_t getInitialAddress() const {
90 return InitialAddress; 90 return InitialAddress;
91 } 91 }
92 92
93 /// Returns the Bit as a Byte:BitInByte string. MinByteWidth is the
94 /// minimum number of characters to print out the Byte value (blank
95 /// fills).
96 static std::string getBitAddress(uint64_t Bit, unsigned MinByteWidth=1);
97
93 //===--------------------------------------------------------------------===// 98 //===--------------------------------------------------------------------===//
94 // Block Manipulation 99 // Block Manipulation
95 //===--------------------------------------------------------------------===// 100 //===--------------------------------------------------------------------===//
96 101
97 /// hasBlockInfoRecords - Return true if we've already read and processed the 102 /// hasBlockInfoRecords - Return true if we've already read and processed the
98 /// block info block for this Bitstream. We only process it for the first 103 /// block info block for this Bitstream. We only process it for the first
99 /// cursor that walks over it. 104 /// cursor that walks over it.
100 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } 105 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
101 106
102 /// getBlockInfo - If there is block info for the specified ID, return it, 107 /// getBlockInfo - If there is block info for the specified ID, return it,
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 uint64_t StartBit; 207 uint64_t StartBit;
203 }; 208 };
204 209
205 /// NaClBitstreamCursor - This represents a position within a bitcode 210 /// NaClBitstreamCursor - This represents a position within a bitcode
206 /// file. There may be multiple independent cursors reading within 211 /// file. There may be multiple independent cursors reading within
207 /// one bitstream, each maintaining their own local state. 212 /// one bitstream, each maintaining their own local state.
208 /// 213 ///
209 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects 214 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
210 /// that should not be passed by value. 215 /// that should not be passed by value.
211 class NaClBitstreamCursor { 216 class NaClBitstreamCursor {
217 public:
218 /// This class handles errors in the bitstream reader. Redirects
219 /// fatal error messages to virtual method Fatal.
220 class ErrorHandler {
221 ErrorHandler(const ErrorHandler &) = delete;
222 ErrorHandler &operator=(const ErrorHandler &) = delete;
223 public:
224 explicit ErrorHandler(NaClBitstreamCursor &Cursor) : Cursor(Cursor) {}
225 LLVM_ATTRIBUTE_NORETURN
226 virtual void Fatal(const std::string &ErrorMessage) const;
227 virtual ~ErrorHandler() {}
228 uint64_t getCurrentBitNo() const {
229 return Cursor.GetCurrentBitNo();
230 }
231 private:
232 NaClBitstreamCursor &Cursor;
233 };
234
235 private:
212 friend class Deserializer; 236 friend class Deserializer;
213 NaClBitstreamReader *BitStream; 237 NaClBitstreamReader *BitStream;
214 size_t NextChar; 238 size_t NextChar;
239 // The current error handler for the bitstream reader.
240 std::unique_ptr<ErrorHandler> ErrHandler;
215 241
216 /// CurWord/word_t - This is the current data we have pulled from the stream 242 /// CurWord/word_t - This is the current data we have pulled from the stream
217 /// but have not returned to the client. This is specifically and 243 /// but have not returned to the client. This is specifically and
218 /// intentionally defined to follow the word size of the host machine for 244 /// intentionally defined to follow the word size of the host machine for
219 /// efficiency. We use word_t in places that are aware of this to make it 245 /// efficiency. We use word_t in places that are aware of this to make it
220 /// perfectly explicit what is going on. 246 /// perfectly explicit what is going on.
221 typedef uint32_t word_t; 247 typedef uint32_t word_t;
222 word_t CurWord; 248 word_t CurWord;
223 249
224 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This 250 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This
(...skipping 16 matching lines...) Expand all
241 }; 267 };
242 268
243 /// BlockScope - This tracks the codesize of parent blocks. 269 /// BlockScope - This tracks the codesize of parent blocks.
244 SmallVector<Block, 8> BlockScope; 270 SmallVector<Block, 8> BlockScope;
245 271
246 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; 272 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION;
247 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION; 273 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION;
248 274
249 public: 275 public:
250 276
251 NaClBitstreamCursor() { 277 NaClBitstreamCursor() : ErrHandler(new ErrorHandler(*this)) {
252 init(nullptr); 278 init(nullptr);
253 } 279 }
254 280
255 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } 281 explicit NaClBitstreamCursor(NaClBitstreamReader &R)
282 : ErrHandler(new ErrorHandler(*this)) { init(&R); }
256 283
257 void init(NaClBitstreamReader *R) { 284 void init(NaClBitstreamReader *R) {
258 freeState(); 285 freeState();
259 BitStream = R; 286 BitStream = R;
260 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); 287 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress();
261 CurWord = 0; 288 CurWord = 0;
262 BitsInCurWord = 0; 289 BitsInCurWord = 0;
263 } 290 }
264 291
265 ~NaClBitstreamCursor() { 292 ~NaClBitstreamCursor() {
266 freeState(); 293 freeState();
267 } 294 }
268 295
269 void freeState(); 296 void freeState();
270 297
298 // Replaces the current bitstream error handler with the new
299 // handler. Takes ownership of the new handler and deletes it when
300 // it is no longer needed.
301 void setErrorHandler(std::unique_ptr<ErrorHandler> &NewHandler) {
302 ErrHandler = std::move(NewHandler);
303 }
304
271 bool isEndPos(size_t pos) { 305 bool isEndPos(size_t pos) {
272 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); 306 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
273 } 307 }
274 308
275 bool canSkipToPos(size_t pos) const { 309 bool canSkipToPos(size_t pos) const {
276 // pos can be skipped to if it is a valid address or one byte past the end. 310 // pos can be skipped to if it is a valid address or one byte past the end.
277 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( 311 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
278 static_cast<uint64_t>(pos - 1)); 312 static_cast<uint64_t>(pos - 1));
279 } 313 }
280 314
281 bool AtEndOfStream() { 315 bool AtEndOfStream() {
282 return BitsInCurWord == 0 && isEndPos(NextChar); 316 return BitsInCurWord == 0 && isEndPos(NextChar);
283 } 317 }
284 318
285 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. 319 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
286 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } 320 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; }
287 321
288 /// GetCurrentBitNo - Return the bit # of the bit we are reading. 322 /// GetCurrentBitNo - Return the bit # of the bit we are reading.
289 uint64_t GetCurrentBitNo() const { 323 uint64_t GetCurrentBitNo() const {
290 return NextChar*CHAR_BIT - BitsInCurWord; 324 return NextChar*CHAR_BIT - BitsInCurWord;
291 } 325 }
292 326
293 NaClBitstreamReader *getBitStreamReader() { 327 NaClBitstreamReader *getBitStreamReader() {
294 return BitStream; 328 return BitStream;
295 } 329 }
296 const NaClBitstreamReader *getBitStreamReader() const { 330 const NaClBitstreamReader *getBitStreamReader() const {
297 return BitStream; 331 return BitStream;
298 } 332 }
299 333
334 /// Returns the current bit address (string) of the bit cursor.
335 /// MinByteWidth is the minimum number of characters to print out
336 /// the Byte value (blank fills).
337 std::string getCurrentBitAddress(unsigned MinByteWidth=1) const {
338 return BitStream->getBitAddress(GetCurrentBitNo(), MinByteWidth);
339 }
340
300 /// Flags that modify the behavior of advance(). 341 /// Flags that modify the behavior of advance().
301 enum { 342 enum {
302 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does 343 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does
303 /// not automatically pop the block scope when the end of a block is 344 /// not automatically pop the block scope when the end of a block is
304 /// reached. 345 /// reached.
305 AF_DontPopBlockAtEnd = 1, 346 AF_DontPopBlockAtEnd = 1,
306 347
307 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are 348 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are
308 /// returned just like normal records. 349 /// returned just like normal records.
309 AF_DontAutoprocessAbbrevs = 2 350 AF_DontAutoprocessAbbrevs = 2
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 // If we found a sub-block, just skip over it and check the next entry. 389 // If we found a sub-block, just skip over it and check the next entry.
349 if (SkipBlock()) 390 if (SkipBlock())
350 return NaClBitstreamEntry::getError(); 391 return NaClBitstreamEntry::getError();
351 } 392 }
352 } 393 }
353 394
354 /// JumpToBit - Reset the stream to the specified bit number. 395 /// JumpToBit - Reset the stream to the specified bit number.
355 void JumpToBit(uint64_t BitNo) { 396 void JumpToBit(uint64_t BitNo) {
356 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); 397 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
357 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); 398 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
358 assert(canSkipToPos(ByteNo) && "Invalid location"); 399 if (!canSkipToPos(ByteNo))
400 reportInvalidJumpToBit(BitNo);
359 401
360 // Move the cursor to the right word. 402 // Move the cursor to the right word.
361 NextChar = ByteNo; 403 NextChar = ByteNo;
362 BitsInCurWord = 0; 404 BitsInCurWord = 0;
363 CurWord = 0; 405 CurWord = 0;
364 406
365 // Skip over any bits that are already consumed. 407 // Skip over any bits that are already consumed.
366 if (WordBitNo) { 408 if (WordBitNo) {
367 if (sizeof(word_t) > 4) 409 if (sizeof(word_t) > 4)
368 Read64(WordBitNo); 410 Read64(WordBitNo);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 588
547 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 589 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
548 BlockScope.pop_back(); 590 BlockScope.pop_back();
549 } 591 }
550 592
551 //===--------------------------------------------------------------------===// 593 //===--------------------------------------------------------------------===//
552 // Record Processing 594 // Record Processing
553 //===--------------------------------------------------------------------===// 595 //===--------------------------------------------------------------------===//
554 596
555 private: 597 private:
598 // Returns abbreviation encoding associated with Value.
599 NaClBitCodeAbbrevOp::Encoding getEncoding(uint64_t Value);
600
556 void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op); 601 void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
557 602
558 // Reads the next Value using the abbreviation Op. Returns true only 603 // Reads the next Value using the abbreviation Op. Returns true only
559 // if Op is an array (and sets Value to the number of elements in the 604 // if Op is an array (and sets Value to the number of elements in the
560 // array). 605 // array).
561 inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op, 606 inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op,
562 uint64_t &Value); 607 uint64_t &Value);
563 608
564 // Reads and returns the next value using the abbreviation Op, 609 // Reads and returns the next value using the abbreviation Op,
565 // assuming Op appears after an array abbreviation. 610 // assuming Op appears after an array abbreviation.
566 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op); 611 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
567 612
568 // Reads the array abbreviation Op, NumArrayElements times, putting 613 // Reads the array abbreviation Op, NumArrayElements times, putting
569 // the read values in Vals. 614 // the read values in Vals.
570 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op, 615 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
571 unsigned NumArrayElements, 616 unsigned NumArrayElements,
572 SmallVectorImpl<uint64_t> &Vals); 617 SmallVectorImpl<uint64_t> &Vals);
573 618
619 // Reports that that abbreviation Index is not valid.
620 void reportInvalidAbbrevNumber(unsigned Index) const;
621
622 // Reports that jumping to Bit is not valid.
623 void reportInvalidJumpToBit(uint64_t Bit) const;
624
574 public: 625 public:
575 626
576 /// getAbbrev - Return the abbreviation for the specified AbbrevId. 627 /// getAbbrev - Return the abbreviation for the specified AbbrevId.
577 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { 628 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const {
578 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; 629 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV;
579 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 630 if (AbbrevNo >= CurAbbrevs.size())
631 reportInvalidAbbrevNumber(AbbrevID);
580 return CurAbbrevs[AbbrevNo]; 632 return CurAbbrevs[AbbrevNo];
581 } 633 }
582 634
583 /// skipRecord - Read the current record and discard it. 635 /// skipRecord - Read the current record and discard it.
584 void skipRecord(unsigned AbbrevID); 636 void skipRecord(unsigned AbbrevID);
585 637
586 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals); 638 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals);
587 639
588 //===--------------------------------------------------------------------===// 640 //===--------------------------------------------------------------------===//
589 // Abbrev Processing 641 // Abbrev Processing
590 //===--------------------------------------------------------------------===// 642 //===--------------------------------------------------------------------===//
591 // IsLocal indicates where the abbreviation occurs. If it is in the 643 // IsLocal indicates where the abbreviation occurs. If it is in the
592 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is 644 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is
593 // true. 645 // true.
594 void ReadAbbrevRecord(bool IsLocal, 646 void ReadAbbrevRecord(bool IsLocal,
595 NaClAbbrevListener *Listener); 647 NaClAbbrevListener *Listener);
596 648
597 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, 649 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord,
598 // except that no abbreviation is built. 650 // except that no abbreviation is built.
599 void SkipAbbrevRecord(); 651 void SkipAbbrevRecord();
600 652
601 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); 653 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener);
602 }; 654 };
603 655
604 } // End llvm namespace 656 } // End llvm namespace
605 657
606 #endif 658 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698