Skip to content

Commit 7d227f2

Browse files
committed
Check metadata hash when loading transitive dependent crates
Fix issue #2138
1 parent 18597b2 commit 7d227f2

File tree

3 files changed

+58
-24
lines changed

3 files changed

+58
-24
lines changed

src/rustc/metadata/creader.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ fn read_crates(sess: session::session, crate: ast::crate) {
3434
type cache_entry = {
3535
cnum: int,
3636
span: span,
37+
hash: str,
3738
metas: @[@ast::meta_item]
3839
};
3940

@@ -77,7 +78,7 @@ type env = @{sess: session::session,
7778
fn visit_view_item(e: env, i: @ast::view_item) {
7879
alt i.node {
7980
ast::view_item_use(ident, meta_items, id) {
80-
let cnum = resolve_crate(e, ident, meta_items, i.span);
81+
let cnum = resolve_crate(e, ident, meta_items, "", i.span);
8182
cstore::add_use_stmt_cnum(e.sess.cstore, id, cnum);
8283
}
8384
_ { }
@@ -140,9 +141,14 @@ fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
140141
}
141142
}
142143

143-
fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item]) -> bool {
144+
fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
145+
bool {
144146
let attrs = decoder::get_crate_attributes(crate_data);
145147
let linkage_metas = attr::find_linkage_metas(attrs);
148+
if hash.is_not_empty() {
149+
let chash = decoder::get_crate_hash(crate_data);
150+
if chash != hash { ret false; }
151+
}
146152
metadata_matches(linkage_metas, metas)
147153
}
148154

@@ -194,30 +200,30 @@ fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
194200
}
195201

196202
fn find_library_crate(sess: session::session, span: span,
197-
metas: [@ast::meta_item])
203+
metas: [@ast::meta_item], hash: str)
198204
-> option<{ident: str, data: @[u8]}> {
199205

200206
attr::require_unique_names(sess.diagnostic(), metas);
201207
let metas = metas;
202-
let crate_name = crate_name_from_metas(metas);
203208

204209
let nn = default_native_lib_naming(sess, sess.opts.static);
205210
let x =
206-
find_library_crate_aux(sess, span, nn, crate_name,
207-
metas, sess.filesearch);
211+
find_library_crate_aux(sess, span, nn,
212+
metas, hash, sess.filesearch);
208213
if x != none || sess.opts.static { ret x; }
209214
let nn2 = default_native_lib_naming(sess, true);
210-
ret find_library_crate_aux(sess, span, nn2, crate_name, metas,
215+
ret find_library_crate_aux(sess, span, nn2, metas, hash,
211216
sess.filesearch);
212217
}
213218

214219
fn find_library_crate_aux(sess: session::session,
215220
span: span,
216221
nn: {prefix: str, suffix: str},
217-
crate_name: str,
218222
metas: [@ast::meta_item],
223+
hash: str,
219224
filesearch: filesearch::filesearch) ->
220225
option<{ident: str, data: @[u8]}> {
226+
let crate_name = crate_name_from_metas(metas);
221227
let prefix: str = nn.prefix + crate_name + "-";
222228
let suffix: str = nn.suffix;
223229

@@ -233,7 +239,7 @@ fn find_library_crate_aux(sess: session::session,
233239
#debug("%s is a candidate", path);
234240
alt get_metadata_section(sess, path) {
235241
option::some(cvec) {
236-
if !crate_matches(cvec, metas) {
242+
if !crate_matches(cvec, metas, hash) {
237243
#debug("skipping %s, metadata doesn't match", path);
238244
option::none
239245
} else {
@@ -302,11 +308,11 @@ fn get_metadata_section(sess: session::session,
302308
}
303309

304310
fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
305-
metas: [@ast::meta_item])
311+
metas: [@ast::meta_item], hash: str)
306312
-> {ident: str, data: @[u8]} {
307313

308314

309-
alt find_library_crate(sess, span, metas) {
315+
alt find_library_crate(sess, span, metas, hash) {
310316
some(t) { ret t; }
311317
none {
312318
sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
@@ -329,32 +335,36 @@ fn metas_with_ident(ident: ast::ident,
329335
metas_with(ident, "name", metas)
330336
}
331337

332-
fn existing_match(e: env, metas: [@ast::meta_item]) -> option<int> {
338+
fn existing_match(e: env, metas: [@ast::meta_item], hash: str) ->
339+
option<int> {
333340
let maybe_entry = e.crate_cache.find {|c|
334-
metadata_matches(*c.metas, metas)
341+
metadata_matches(*c.metas, metas) &&
342+
(hash.is_empty() || c.hash == hash)
335343
};
336344

337345
maybe_entry.map {|c| c.cnum }
338346
}
339347

340348
fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
341-
span: span) -> ast::crate_num {
349+
hash: str, span: span) -> ast::crate_num {
342350
let metas = metas_with_ident(ident, metas);
343351

344-
alt existing_match(e, metas) {
352+
alt existing_match(e, metas, hash) {
345353
none {
346354
let cinfo =
347-
load_library_crate(e.sess, ident, span, metas);
355+
load_library_crate(e.sess, ident, span, metas, hash);
348356

349357
let cfilename = cinfo.ident;
350358
let cdata = cinfo.data;
351359

352360
let attrs = decoder::get_crate_attributes(cdata);
353361
let linkage_metas = attr::find_linkage_metas(attrs);
362+
let hash = decoder::get_crate_hash(cdata);
354363

355364
// Claim this crate number and cache it
356365
let cnum = e.next_crate_num;
357-
e.crate_cache += [{cnum: cnum, span: span, metas: @linkage_metas}];
366+
e.crate_cache += [{cnum: cnum, span: span,
367+
hash: hash, metas: @linkage_metas}];
358368
e.next_crate_num += 1;
359369

360370
// Now resolve the crates referenced by this crate
@@ -387,12 +397,10 @@ fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
387397
for decoder::get_crate_deps(cdata).each {|dep|
388398
let extrn_cnum = dep.cnum;
389399
let cname = dep.name;
390-
let cvers = dep.vers;
391-
// FIXME: We really need to know the linkage metas of our transitive
392-
// dependencies in order to resolve them correctly.
393-
let cmetas = metas_with(cvers, "vers", []);
394-
#debug("resolving dep %s ver: %s", cname, dep.vers);
395-
alt existing_match(e, metas_with_ident(cname, cmetas)) {
400+
let cmetas = metas_with(dep.vers, "vers", []);
401+
#debug("resolving dep crate %s ver: %s hash: %s",
402+
dep.name, dep.vers, dep.hash);
403+
alt existing_match(e, metas_with_ident(cname, cmetas), dep.hash) {
396404
some(local_cnum) {
397405
#debug("already have it");
398406
// We've already seen this crate
@@ -403,7 +411,8 @@ fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
403411
// This is a new one so we've got to load it
404412
// FIXME: Need better error reporting than just a bogus span
405413
let fake_span = ast_util::dummy_sp();
406-
let local_cnum = resolve_crate(e, cname, cmetas, fake_span);
414+
let local_cnum =
415+
resolve_crate(e, cname, cmetas, dep.hash, fake_span);
407416
cnum_map.insert(extrn_cnum, local_cnum);
408417
}
409418
}

src/test/auxiliary/crateresolve7x.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// xfail-fast
2+
// aux-build:crateresolve6-1.rs
3+
// aux-build:crateresolve6-2.rs
4+
5+
// These both have the same version but differ in other metadata
6+
mod a {
7+
use cr6_1 (name = "crateresolve6", vers = "0.1", calories="100");
8+
fn f() -> int { cr6_1::f() }
9+
}
10+
11+
mod b {
12+
use cr6_2 (name = "crateresolve6", vers = "0.1", calories="200");
13+
fn f() -> int { cr6_2::f() }
14+
}

src/test/run-pass/crateresolve7.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// xfail-fast
2+
// aux-build:crateresolve6-1.rs
3+
// aux-build:crateresolve6-2.rs
4+
// aux-build:crateresolve7x.rs
5+
6+
use crateresolve7x;
7+
8+
fn main() {
9+
assert crateresolve7x::a::f() == 100;
10+
assert crateresolve7x::b::f() == 200;
11+
}

0 commit comments

Comments
 (0)