Skip to content

Commit 1edfa6c

Browse files
committed
Use a weak lang item for hashmap_random_keys
1 parent 9363342 commit 1edfa6c

File tree

4 files changed

+45
-22
lines changed

4 files changed

+45
-22
lines changed

src/librustc/middle/lang_items.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ language_item_table! {
355355
AlignOffsetLangItem, "align_offset", align_offset_fn;
356356

357357
TerminationTraitLangItem, "termination", termination;
358+
359+
HashMapRandomKeysLangItem, "hashmap_random_keys", hashmap_random_keys;
358360
}
359361

360362
impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {

src/librustc/middle/weak_lang_items.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,5 @@ weak_lang_items! {
166166
eh_personality, EhPersonalityLangItem, rust_eh_personality;
167167
eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume;
168168
oom, OomLangItem, rust_oom;
169+
hashmap_random_keys,HashMapRandomKeysLangItem, rust_hashmap_random_keys;
169170
}

src/libstd/collections/hash/map.rs

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use self::Entry::*;
1212
use self::VacantEntryState::*;
1313

1414
use collections::CollectionAllocErr;
15-
use cell::Cell;
1615
use borrow::Borrow;
1716
use cmp::max;
1817
use fmt::{self, Debug};
@@ -21,7 +20,6 @@ use hash::{Hash, Hasher, BuildHasher, SipHasher13};
2120
use iter::{FromIterator, FusedIterator};
2221
use mem::{self, replace};
2322
use ops::{Deref, Index};
24-
use sys;
2523

2624
use super::table::{self, Bucket, EmptyBucket, Fallibility, FullBucket, FullBucketMut, RawTable,
2725
SafeHash};
@@ -2592,29 +2590,22 @@ impl RandomState {
25922590
/// ```
25932591
#[inline]
25942592
#[allow(deprecated)]
2595-
// rand
25962593
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
25972594
pub fn new() -> RandomState {
2598-
// Historically this function did not cache keys from the OS and instead
2599-
// simply always called `rand::thread_rng().gen()` twice. In #31356 it
2600-
// was discovered, however, that because we re-seed the thread-local RNG
2601-
// from the OS periodically that this can cause excessive slowdown when
2602-
// many hash maps are created on a thread. To solve this performance
2603-
// trap we cache the first set of randomly generated keys per-thread.
2604-
//
2605-
// Later in #36481 it was discovered that exposing a deterministic
2606-
// iteration order allows a form of DOS attack. To counter that we
2607-
// increment one of the seeds on every RandomState creation, giving
2608-
// every corresponding HashMap a different iteration order.
2609-
thread_local!(static KEYS: Cell<(u64, u64)> = {
2610-
Cell::new(sys::hashmap_random_keys())
2611-
});
2595+
// Use a weak lang item to get random keys without a hard dependency
2596+
// on libstd.
2597+
#[cfg(not(stage0))]
2598+
#[allow(improper_ctypes)]
2599+
extern {
2600+
#[lang = "hashmap_random_keys"]
2601+
#[unwind(allowed)]
2602+
fn hashmap_random_keys() -> (u64, u64);
2603+
}
2604+
#[cfg(stage0)]
2605+
unsafe fn hashmap_random_keys() -> (u64, u64) { (0, 0) }
26122606

2613-
KEYS.with(|keys| {
2614-
let (k0, k1) = keys.get();
2615-
keys.set((k0.wrapping_add(1), k1));
2616-
RandomState { k0: k0, k1: k1 }
2617-
})
2607+
let (k0, k1) = unsafe { hashmap_random_keys() };
2608+
RandomState { k0: k0, k1: k1 }
26182609
}
26192610
}
26202611

src/libstd/collections/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,3 +455,32 @@ pub mod hash_set {
455455
#[stable(feature = "rust1", since = "1.0.0")]
456456
pub use super::hash::set::*;
457457
}
458+
459+
#[cfg(not(stage0))]
460+
#[cfg_attr(not(test), lang = "hashmap_random_keys")]
461+
#[cfg_attr(test, allow(dead_code))]
462+
fn hashmap_random_keys() -> (u64, u64) {
463+
use sys;
464+
use cell::Cell;
465+
466+
// Historically this function did not cache keys from the OS and instead
467+
// simply always called `rand::thread_rng().gen()` twice. In #31356 it
468+
// was discovered, however, that because we re-seed the thread-local RNG
469+
// from the OS periodically that this can cause excessive slowdown when
470+
// many hash maps are created on a thread. To solve this performance
471+
// trap we cache the first set of randomly generated keys per-thread.
472+
//
473+
// Later in #36481 it was discovered that exposing a deterministic
474+
// iteration order allows a form of DOS attack. To counter that we
475+
// increment one of the seeds on every RandomState creation, giving
476+
// every corresponding HashMap a different iteration order.
477+
thread_local!(static KEYS: Cell<(u64, u64)> = {
478+
Cell::new(sys::hashmap_random_keys())
479+
});
480+
481+
KEYS.with(|keys| {
482+
let (k0, k1) = keys.get();
483+
keys.set((k0.wrapping_add(1), k1));
484+
(k0, k1)
485+
})
486+
}

0 commit comments

Comments
 (0)