CVE-2019-16882
Description
A use-after-free vulnerability in the string-interner Rust crate allows attackers to read memory via dangling pointers due to a flawed clone implementation.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A use-after-free vulnerability in the string-interner Rust crate allows attackers to read memory via dangling pointers due to a flawed clone implementation.
Vulnerability
Description
The string-interner crate before version 0.7.1 for Rust contains a use-after-free vulnerability arising from a flawed Clone implementation [1]. When an interner is cloned, the derived #[derive(Clone)] macro did not properly duplicate the underlying string storage, causing the cloned interner to retain InternalStrRef pointers that referenced the original interner's memory [2]. After the original interner is dropped, those pointers become dangling, leading to undefined behavior [3].
Exploitation
An attacker can trigger this vulnerability by cloning a StringInterner and then dropping the original instance, leaving the clone with dangling references [2]. No special privileges or user interaction are required; the attack vector is network-based with low complexity [3]. The flaw is exploitable in any application that uses the affected crate version and performs clone-and-drop operations on interners.
Impact
Successful exploitation allows an attacker to read from memory locations that were previously occupied by interned strings, potentially leaking sensitive data [1]. The confidentiality impact is high, while integrity and availability are not affected [3]. The vulnerability is classified as CWE-416 (Use After Free) and has a CVSS v3.1 base score of 7.5 (HIGH) [3].
Mitigation
The issue was fixed in commit d91dac0, which manually implements Clone for StringInterner to recreate the internal HashMap with fresh InternalStrRef pointers pointing to newly cloned strings [4]. Patched versions are 0.6.4 and 0.7.1 [3]. Users should update to these or later versions. No workarounds are documented.
- NVD - CVE-2019-16882
- Fix use after free bug around `StringInterner::clone()` by lo48576 · Pull Request #10 · Robbepop/string-interner
- Cloned interners may read already dropped strings › RustSec Advisory Database
- Fix use after free bug around `StringInterner::clone()` (#10) · Robbepop/string-interner@d91dac0
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
string-internercrates.io | >= 0.7.0, < 0.7.1 | 0.7.1 |
string-internercrates.io | < 0.6.4 | 0.6.4 |
Affected products
2- Rust/string-interner cratedescription
Patches
1d91dac0cfe42Fix use after free bug around `StringInterner::clone()` (#10)
2 files changed · +63 −1
src/lib.rs+23 −1 modified@@ -192,7 +192,7 @@ pub type DefaultStringInterner = StringInterner<Sym>; /// Caches strings efficiently, with minimal memory footprint and associates them with unique symbols. /// These symbols allow constant time comparisons and look-ups to the underlying interned strings. -#[derive(Debug, Clone, Eq)] +#[derive(Debug, Eq)] pub struct StringInterner<S, H = RandomState> where S: Symbol, @@ -219,6 +219,28 @@ impl Default for StringInterner<Sym, RandomState> { } } +// Should be manually cloned. +// See <https://github.com/Robbepop/string-interner/issues/9>. +impl<S, H> Clone for StringInterner<S, H> +where + S: Symbol, + H: Clone + BuildHasher, +{ + fn clone(&self) -> Self { + let values = self.values.clone(); + let mut map = HashMap::with_capacity_and_hasher(values.len(), self.map.hasher().clone()); + // Recreate `InternalStrRef` from the newly cloned `Box<str>`s. + // Use `extend()` to avoid `H: Default` trait bound required by `FromIterator for HashMap`. + map.extend( + values + .iter() + .enumerate() + .map(|(i, s)| (InternalStrRef::from_str(s), S::from_usize(i))), + ); + Self { values, map } + } +} + // About `Send` and `Sync` impls for `StringInterner` // -------------------------------------------------- //
src/tests.rs+40 −0 modified@@ -373,3 +373,43 @@ mod from_iterator { ); } } + +// See <https://github.com/Robbepop/string-interner/issues/9>. +mod clone_and_drop { + use super::*; + + fn clone_and_drop() -> (DefaultStringInterner, Sym) { + let mut old = DefaultStringInterner::new(); + let foo = old.get_or_intern("foo"); + + // Return newly created (cloned) interner, and drop the original `old` itself. + (old.clone(), foo) + } + + #[test] + fn no_use_after_free() { + let (mut new, foo) = clone_and_drop(); + + // This assert may fail if there are use after free bug. + // See <https://github.com/Robbepop/string-interner/issues/9> for detail. + assert_eq!( + new.get_or_intern("foo"), + foo, + "`foo` should represent the string \"foo\" so they should be equal" + ); + } + + #[test] + // Test for new (non-`derive`) `Clone` impl. + fn clone() { + let mut old = DefaultStringInterner::new(); + let strings = &["foo", "bar", "baz", "qux", "quux", "corge"]; + let syms = strings.iter().map(|&s| old.get_or_intern(s)).collect::<Vec<_>>(); + + let mut new = old.clone(); + for (&s, &sym) in strings.iter().zip(&syms) { + assert_eq!(new.resolve(sym), Some(s)); + assert_eq!(new.get_or_intern(s), sym); + } + } +}
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-49fq-pw77-6qxjghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2019-16882ghsaADVISORY
- github.com/Robbepop/string-interner/commit/d91dac0cfe42512526879cdfaac0b81beff54089ghsaWEB
- github.com/Robbepop/string-interner/issues/9ghsaWEB
- github.com/Robbepop/string-interner/pull/10ghsaWEB
- rustsec.org/advisories/RUSTSEC-2019-0023.htmlghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.