Skip to content

Commit 9657cca

Browse files
committed
Fix Use After Free
The String Pool now uses just a HashSet, that stores the actual Interned Strings. The old code also stored the str slices that we where looking for as keys, but there were never interned properly, so they were super likely to get freed at some point and cause a Use after Free. Fixes #47
1 parent 1d6c4db commit 9657cca

1 file changed

Lines changed: 8 additions & 5 deletions

File tree

src/string_pool.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::borrow::Borrow;
66
use std::cell::{Cell,RefCell};
77
use std::cmp::max;
88
use std::collections::LinkedList;
9-
use std::collections::hash_map::HashMap;
9+
use std::collections::hash_set::HashSet;
1010
use std::default::Default;
1111
use std::ops::Deref;
1212
use std::slice;
@@ -131,7 +131,7 @@ pub struct StringPool {
131131
start: Cell<*mut u8>,
132132
end: Cell<*const u8>,
133133
chunks: RefCell<LinkedList<Chunk>>,
134-
index: RefCell<HashMap<InternedString, InternedString>>,
134+
index: RefCell<HashSet<InternedString>>,
135135
}
136136

137137
static CAPACITY: usize = 10240;
@@ -149,10 +149,13 @@ impl StringPool {
149149
pub fn intern<'s>(&'s self, s: &str) -> &'s str {
150150
if s == "" { return ""; }
151151

152-
let search_string = InternedString::from_str(s);
153-
154152
let mut index = self.index.borrow_mut();
155-
let interned_str = *index.entry(search_string).or_insert_with(|| self.do_intern(s));
153+
if let Some(interned) = index.get(s) {
154+
return unsafe { mem::transmute(interned as &str) };
155+
}
156+
157+
let interned_str = self.do_intern(s);
158+
index.insert(interned_str);
156159

157160
// The lifetime is really matched to us
158161
unsafe { mem::transmute(interned_str) }

0 commit comments

Comments
 (0)