From 997ff7abd4f3b803575a7bfa4af3fb05569b1f75 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sat, 1 Mar 2014 11:09:30 -0800 Subject: [PATCH] rustc: Better error when loading invalid libraries When the metadata format changes, old libraries often cause librustc to abort when reading their metadata. This should all change with the introduction of SVH markers, but the loader for crates should gracefully handle libraries without SVH markers still. This commit adds support for tripping fewer assertions when loading libraries by using maybe_get_doc when initially parsing metadata. It's still possible for some libraries to fall through the cracks, but this should deal with a fairly large number of them up front. --- src/librustc/metadata/decoder.rs | 14 ++++++++++++++ src/librustc/metadata/loader.rs | 13 +++++++++---- src/test/run-make/invalid-library/Makefile | 6 ++++++ src/test/run-make/invalid-library/foo.rs | 13 +++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 src/test/run-make/invalid-library/Makefile create mode 100644 src/test/run-make/invalid-library/foo.rs diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 42754aedba704..8cfda93bd8451 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1145,12 +1145,26 @@ fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> { Ok(()) } +pub fn maybe_get_crate_hash(data: &[u8]) -> Option { + let cratedoc = reader::Doc(data); + reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| { + Svh::new(doc.as_str_slice()) + }) +} + pub fn get_crate_hash(data: &[u8]) -> Svh { let cratedoc = reader::Doc(data); let hashdoc = reader::get_doc(cratedoc, tag_crate_hash); Svh::new(hashdoc.as_str_slice()) } +pub fn maybe_get_crate_id(data: &[u8]) -> Option { + let cratedoc = reader::Doc(data); + reader::maybe_get_doc(cratedoc, tag_crate_crateid).map(|doc| { + from_str(doc.as_str_slice()).unwrap() + }) +} + pub fn get_crate_id(data: &[u8]) -> CrateId { let cratedoc = reader::Doc(data); let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 9c61191ff9916..617a8654eedab 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -318,12 +318,17 @@ impl<'a> Context<'a> { } fn crate_matches(&mut self, crate_data: &[u8]) -> bool { - let other_id = decoder::get_crate_id(crate_data); - if !self.crate_id.matches(&other_id) { return false } + match decoder::maybe_get_crate_id(crate_data) { + Some(ref id) if self.crate_id.matches(id) => {} + _ => return false + } + let hash = match decoder::maybe_get_crate_hash(crate_data) { + Some(hash) => hash, None => return false + }; match self.hash { None => true, - Some(hash) => { - if *hash != decoder::get_crate_hash(crate_data) { + Some(myhash) => { + if *myhash != hash { self.rejected_via_hash = true; false } else { diff --git a/src/test/run-make/invalid-library/Makefile b/src/test/run-make/invalid-library/Makefile new file mode 100644 index 0000000000000..0dbe655b77dfd --- /dev/null +++ b/src/test/run-make/invalid-library/Makefile @@ -0,0 +1,6 @@ +-include ../tools.mk + +all: + touch $(TMPDIR)/rust.metadata.bin + ar crus $(TMPDIR)/libfoo-ffffffff-1.0.rlib $(TMPDIR)/rust.metadata.bin + $(RUSTC) foo.rs 2>&1 | grep "can't find crate for" diff --git a/src/test/run-make/invalid-library/foo.rs b/src/test/run-make/invalid-library/foo.rs new file mode 100644 index 0000000000000..6316cfa3bba08 --- /dev/null +++ b/src/test/run-make/invalid-library/foo.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +fn main() {}