From 9657cca5bb5f84dbd7e517073f90e3cf54007b2f Mon Sep 17 00:00:00 2001 From: Christopher Serr Date: Thu, 29 Jun 2017 14:30:19 +0200 Subject: [PATCH] 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 --- src/string_pool.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/string_pool.rs b/src/string_pool.rs index 65b6f88..9e73921 100644 --- a/src/string_pool.rs +++ b/src/string_pool.rs @@ -6,7 +6,7 @@ use std::borrow::Borrow; use std::cell::{Cell,RefCell}; use std::cmp::max; use std::collections::LinkedList; -use std::collections::hash_map::HashMap; +use std::collections::hash_set::HashSet; use std::default::Default; use std::ops::Deref; use std::slice; @@ -131,7 +131,7 @@ pub struct StringPool { start: Cell<*mut u8>, end: Cell<*const u8>, chunks: RefCell>, - index: RefCell>, + index: RefCell>, } static CAPACITY: usize = 10240; @@ -149,10 +149,13 @@ impl StringPool { pub fn intern<'s>(&'s self, s: &str) -> &'s str { if s == "" { return ""; } - let search_string = InternedString::from_str(s); - let mut index = self.index.borrow_mut(); - let interned_str = *index.entry(search_string).or_insert_with(|| self.do_intern(s)); + if let Some(interned) = index.get(s) { + return unsafe { mem::transmute(interned as &str) }; + } + + let interned_str = self.do_intern(s); + index.insert(interned_str); // The lifetime is really matched to us unsafe { mem::transmute(interned_str) }