[serialization] Validate the control block -- is the module too new?

Not so interesting right now, but eventually we'll be validating other
things as well, and it's best not to have FIXMEs lying around.

Swift SVN r5175
This commit is contained in:
Jordan Rose
2013-05-16 00:23:13 +00:00
parent 3109d8c830
commit f9c4046896
6 changed files with 79 additions and 21 deletions

View File

@@ -15,6 +15,51 @@
#include "llvm/Support/MemoryBuffer.h"
using namespace swift;
using namespace swift::serialization;
static ModuleStatus
validateControlBlock(llvm::BitstreamCursor &cursor,
llvm::SmallVectorImpl<uint64_t> &scratch) {
// The control block is malformed until we've at least read a major version
// number.
ModuleStatus result = ModuleStatus::Malformed;
auto next = cursor.advance();
while (next.Kind != llvm::BitstreamEntry::EndBlock) {
if (next.Kind == llvm::BitstreamEntry::Error)
return ModuleStatus::Malformed;
if (next.Kind == llvm::BitstreamEntry::SubBlock) {
// Unknown metadata sub-block, possibly for use by a future version of the
// module format.
if (cursor.SkipBlock())
return ModuleStatus::Malformed;
next = cursor.advance();
continue;
}
scratch.clear();
StringRef blobData;
unsigned kind = cursor.readRecord(next.ID, scratch, &blobData);
switch (kind) {
case control_block::METADATA: {
uint16_t versionMajor = scratch[0];
if (versionMajor > VERSION_MAJOR)
return ModuleStatus::FormatTooNew;
result = ModuleStatus::Valid;
break;
}
default:
// Unknown metadata record, possibly for use by a future version of the
// module format.
break;
}
next = cursor.advance();
}
return result;
}
ModuleFile::ModuleFile(llvm::OwningPtr<llvm::MemoryBuffer> &&input)
: InputFile(std::move(input)),
@@ -23,7 +68,6 @@ ModuleFile::ModuleFile(llvm::OwningPtr<llvm::MemoryBuffer> &&input)
Status(ModuleStatus::FallBackToTranslationUnit) {
llvm::BitstreamCursor cursor{InputReader};
using namespace serialization;
for (unsigned char byte : SIGNATURE) {
if (cursor.AtEndOfStream() || cursor.Read(8) != byte)
return error();
@@ -42,12 +86,16 @@ ModuleFile::ModuleFile(llvm::OwningPtr<llvm::MemoryBuffer> &&input)
return error();
break;
case CONTROL_BLOCK_ID:
// FIXME: Actually validate the control block.
if (cursor.SkipBlock())
return error();
case CONTROL_BLOCK_ID: {
cursor.EnterSubBlock(CONTROL_BLOCK_ID);
ModuleStatus err = validateControlBlock(cursor, scratch);
if (err != ModuleStatus::Valid)
return error(err);
hasValidControlBlock = true;
break;
}
case INPUT_BLOCK_ID: {
if (!hasValidControlBlock)