diff --git a/src/cache/intern.rs b/src/cache/intern.rs index f5ff6ced..de5aa030 100644 --- a/src/cache/intern.rs +++ b/src/cache/intern.rs @@ -8,6 +8,7 @@ cfg_if! { use std::borrow::ToOwned; use std::cell::RefCell; use crate::JsValue; + use crate::convert::IntoWasmAbi; use uluru::{LRUCache, Entry}; @@ -33,13 +34,14 @@ cfg_if! { cache.find(|p| p.key == key).map(|x| &x.value) } - pub(crate) fn get_str(s: &str) -> Option<JsValue> { + /// This returns the raw index of the cached JsValue, so you must take care + /// so that you don't use it after it is freed. + pub(crate) fn unsafe_get_str(s: &str) -> Option<<JsValue as IntoWasmAbi>::Abi> { CACHE.with(|cache| { let mut cache = cache.entries.borrow_mut(); if let Some(value) = get_js_string(&mut cache, s) { - // This is safe because the cache values are never removed - Some(value._unsafe_clone()) + Some(value.into_abi()) } else { None diff --git a/src/convert/slices.rs b/src/convert/slices.rs index b5045868..182cfdbd 100644 --- a/src/convert/slices.rs +++ b/src/convert/slices.rs @@ -129,8 +129,11 @@ cfg_if! { if #[cfg(feature = "enable-interning")] { #[inline] fn get_cached_str(x: &str) -> Option<WasmSlice> { - // This uses 0 for the ptr as an indication that it is a JsValue and not a str - crate::cache::intern::get_str(x).map(|x| WasmSlice { ptr: 0, len: x.into_abi() }) + // This is safe because the JsValue is immediately converted into a JS string, + // so use-after-free cannot occur. + // + // This uses 0 for the ptr as an indication that it is a JsValue and not a str. + crate::cache::intern::unsafe_get_str(x).map(|x| WasmSlice { ptr: 0, len: x }) } } else { diff --git a/src/lib.rs b/src/lib.rs index 151fd6c9..a65a0930 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -125,11 +125,6 @@ impl JsValue { } } - #[inline] - fn _unsafe_clone(&self) -> JsValue { - Self::_new(self.idx) - } - /// Creates a new JS value which is a string. /// /// The utf-8 string provided is copied to the JS heap and the string will