VYPR
Critical severityNVD Advisory· Published Aug 26, 2019· Updated Aug 5, 2024

CVE-2019-15551

CVE-2019-15551

Description

An issue was discovered in the smallvec crate before 0.6.10 for Rust. There is a double free for certain grow attempts with the current capacity.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Double-free vulnerability in Rust's smallvec crate before 0.6.10 when calling grow() with certain capacity values, leading to potential memory corruption.

The smallvec crate for Rust provides a vector-like container that can store a small number of elements on the stack before spilling to the heap. A double-free vulnerability exists in versions before 0.6.10 in the grow() method when the new capacity is less than the current capacity but still larger than the inline size. Specifically, when shrinking from a spilled state back to an inline state, the internal capacity field was not updated, causing the heap allocation to be freed twice upon drop or reallocation [1][2].

Exploitation requires no authentication and can be triggered over the network (CVSS 9.8, critical). The bug is exercised by calling grow() with a size that is within the inline capacity after the vector has spilled, as demonstrated in a GitHub issue [3]. Any Rust application that processes untrusted input and uses smallvec with such a grow() call is potentially vulnerable.

A successful exploit can lead to a double-free, resulting in memory corruption. This may be leveraged for arbitrary code execution or denial of service, depending on the heap layout and application context [2].

The issue was patched in smallvec version 0.6.10. The fix ensures that when shrinking to inline, the capacity is correctly set to the new value, preventing the double-free [4]. Users are advised to update to the latest version.

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.

PackageAffected versionsPatched versions
smallveccrates.io
>= 0.6.5, < 0.6.100.6.10

Affected products

2

Patches

2
c20cfa8584e6

Auto merge of #151 - ehuss:grow-same-size, r=jdm

https://github.com/servo/rust-smallvecbors-servoJun 8, 2019via ghsa
1 file changed · +16 0
  • lib.rs+16 0 modified
    @@ -665,6 +665,8 @@ impl<A: Array> SmallVec<A> {
                     if unspilled {
                         return;
                     }
    +            } else {
    +                return;
                 }
                 deallocate(ptr, cap);
             }
    @@ -2341,4 +2343,18 @@ mod tests {
             v.extend(it);
             assert_eq!(v[..], ['a']);
         }
    +
    +    #[test]
    +    fn grow_spilled_same_size() {
    +        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
    +        v.push(0);
    +        v.push(1);
    +        v.push(2);
    +        assert!(v.spilled());
    +        assert_eq!(v.capacity(), 4);
    +        // grow with the same capacity
    +        v.grow(4);
    +        assert_eq!(v.capacity(), 4);
    +        assert_eq!(v[..], [0, 1, 2]);
    +    }
     }
    
f96322b92434

Auto merge of #152 - ehuss:grow-to-shrink, r=emilio

https://github.com/servo/rust-smallvecbors-servoJun 7, 2019via ghsa
1 file changed · +18 0
  • lib.rs+18 0 modified
    @@ -654,6 +654,7 @@ impl<A: Array> SmallVec<A> {
                     }
                     self.data = SmallVecData::from_inline(mem::uninitialized());
                     ptr::copy_nonoverlapping(ptr, self.data.inline_mut().ptr_mut(), len);
    +                self.capacity = len;
                 } else if new_cap != cap {
                     let mut vec = Vec::with_capacity(new_cap);
                     let new_alloc = vec.as_mut_ptr();
    @@ -2311,4 +2312,21 @@ mod tests {
             let decoded: SmallVec<[i32; 2]> = deserialize(&encoded).unwrap();
             assert_eq!(small_vec, decoded);
         }
    +
    +    #[test]
    +    fn grow_to_shrink() {
    +        let mut v: SmallVec<[u8; 2]> = SmallVec::new();
    +        v.push(1);
    +        v.push(2);
    +        v.push(3);
    +        assert!(v.spilled());
    +        v.clear();
    +        // Shrink to inline.
    +        v.grow(2);
    +        assert!(!v.spilled());
    +        assert_eq!(v.capacity(), 2);
    +        assert_eq!(v.len(), 0);
    +        v.push(4);
    +        assert_eq!(v[..], [4]);
    +    }
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

7

News mentions

0

No linked articles in our index yet.