Commit 0b8763ea by Karl Schimpf

Fix pnacl-sz to not accept files containing multiple modules.

Previous code checked, after the fact, that there weren't multiple modules in the block. However, the code for TopLevelParser assumes that there is only on module block, allowing it to more efficiently test internal state. To fix the problem, modified TopLevelParser::ParseBlock to fail, and not attempt to parse the second block if the file contains more than one block. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4260 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1362643002 .
parent 55f2e6d3
...@@ -338,6 +338,9 @@ public: ...@@ -338,6 +338,9 @@ public:
return getGlobalVariableByID(Index - NumFunctionIds); return getGlobalVariableByID(Index - NumFunctionIds);
} }
/// Returns true if a module block has been parsed.
bool parsedModuleBlock() const { return ParsedModuleBlock; }
/// Returns the list of parsed global variable declarations. Releases /// Returns the list of parsed global variable declarations. Releases
/// ownership of the current list of global variables. Note: only returns /// ownership of the current list of global variables. Note: only returns
/// non-null pointer on first call. All successive calls return a null /// non-null pointer on first call. All successive calls return a null
...@@ -374,6 +377,8 @@ private: ...@@ -374,6 +377,8 @@ private:
Ice::FuncSigType UndefinedFuncSigType; Ice::FuncSigType UndefinedFuncSigType;
// The block parser currently being applied. Used for error reporting. // The block parser currently being applied. Used for error reporting.
BlockParserBaseClass *BlockParser = nullptr; BlockParserBaseClass *BlockParser = nullptr;
// Defines if a module block has already been parsed.
bool ParsedModuleBlock = false;
bool ParseBlock(unsigned BlockID) override; bool ParseBlock(unsigned BlockID) override;
...@@ -3220,8 +3225,12 @@ void ModuleParser::ProcessRecord() { ...@@ -3220,8 +3225,12 @@ void ModuleParser::ProcessRecord() {
bool TopLevelParser::ParseBlock(unsigned BlockID) { bool TopLevelParser::ParseBlock(unsigned BlockID) {
if (BlockID == naclbitc::MODULE_BLOCK_ID) { if (BlockID == naclbitc::MODULE_BLOCK_ID) {
if (ParsedModuleBlock)
Fatal("Input can't contain more than one module");
ModuleParser Parser(BlockID, this); ModuleParser Parser(BlockID, this);
return Parser.ParseThisBlock(); bool ParseFailed = Parser.ParseThisBlock();
ParsedModuleBlock = true;
return ParseFailed;
} }
// Generate error message by using default block implementation. // Generate error message by using default block implementation.
BlockParserBaseClass Parser(BlockID, this); BlockParserBaseClass Parser(BlockID, this);
...@@ -3248,14 +3257,13 @@ void PNaClTranslator::translate(const std::string &IRFilename, ...@@ -3248,14 +3257,13 @@ void PNaClTranslator::translate(const std::string &IRFilename,
// need a hook to tell the IceBrowserCompileServer to unblock its // need a hook to tell the IceBrowserCompileServer to unblock its
// QueueStreamer. // QueueStreamer.
// https://code.google.com/p/nativeclient/issues/detail?id=4163 // https://code.google.com/p/nativeclient/issues/detail?id=4163
Ostream &ErrStream = getContext()->getStrError();
// Read header and verify it is good. // Read header and verify it is good.
NaClBitcodeHeader Header; NaClBitcodeHeader Header;
if (Header.Read(MemObj.get())) { if (Header.Read(MemObj.get())) {
llvm::report_fatal_error("Invalid PNaCl bitcode header"); llvm::report_fatal_error("Invalid PNaCl bitcode header");
} }
if (!Header.IsSupported()) { if (!Header.IsSupported()) {
ErrStream << Header.Unsupported(); getContext()->getStrError() << Header.Unsupported();
if (!Header.IsReadable()) { if (!Header.IsReadable()) {
llvm::report_fatal_error("Invalid PNaCl bitcode header"); llvm::report_fatal_error("Invalid PNaCl bitcode header");
} }
...@@ -3266,25 +3274,20 @@ void PNaClTranslator::translate(const std::string &IRFilename, ...@@ -3266,25 +3274,20 @@ void PNaClTranslator::translate(const std::string &IRFilename,
NaClBitstreamCursor InputStream(InputStreamFile); NaClBitstreamCursor InputStream(InputStreamFile);
TopLevelParser Parser(*this, InputStream, ErrorStatus); TopLevelParser Parser(*this, InputStream, ErrorStatus);
int TopLevelBlocks = 0;
while (!InputStream.AtEndOfStream()) { while (!InputStream.AtEndOfStream()) {
if (Parser.Parse()) { if (Parser.Parse()) {
ErrorStatus.assign(EC_Bitcode); ErrorStatus.assign(EC_Bitcode);
return; return;
} }
++TopLevelBlocks;
} }
if (TopLevelBlocks != 1) { if (!Parser.parsedModuleBlock()) {
ErrStream << IRFilename std::string Buffer;
<< ": Contains more than one module. Found: " << TopLevelBlocks raw_string_ostream StrBuf(Buffer);
<< "\n"; StrBuf << IRFilename << ": Does not contain a module!";
llvm::report_fatal_error("Bitcode has more than one module"); llvm::report_fatal_error(StrBuf.str());
} }
if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) { if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) {
ErrStream
<< IRFilename
<< ": Bitcode stream should be a multiple of 4 bytes in length.\n";
llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes"); llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes");
} }
} }
......
65535,8,2;
1,1;
65534;
65535,8,2;
1,1;
65534;
; Tests that we check for multiple modules in the bitcode file.
; REQUIRES: no_minimal_build
; RUN: not %pnacl_sz -bitcode-as-text \
; RUN: %p/Inputs/multiple-modules.tbc \
; RUN: -bitcode-format=pnacl -notranslate -build-on-read 2>&1 \
; RUN: | FileCheck %s
; CHECK: Input can't contain more than one module
; RUN: pnacl-bcfuzz -bitcode-as-text \
; RUN: %p/Inputs/multiple-modules.tbc -output - \
; RUN: | not pnacl-bcdis -no-records | FileCheck -check-prefix=ASM %s
; ASM: module { // BlockID = 8
; ASM: version 1;
; ASM: }
; ASM: module { // BlockID = 8
; ASM: version 1;
; ASM: }
; ASM: Error(38:4): Expected 1 top level block in bitcode: Found:2
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment