Skip to content

Fix try_grow_raw lead memory leak - #450

Merged
mbrubeck merged 1 commit into
servo:v2from
dDostalker:fix_leak
Aug 26, 2026
Merged

Fix try_grow_raw lead memory leak#450
mbrubeck merged 1 commit into
servo:v2from
dDostalker:fix_leak

Conversation

@dDostalker

Copy link
Copy Markdown
Contributor

There is an issue in the current logic where memory is not correctly released before dropping the last reference. In try_grow_raw, new_ptr decides between reallocating (in-place growth) and allocating fresh memory based on the condition len == 0 || !was_on_heap. However, len == 0 is not equivalent to an empty heap, so the pointer of the abandoned memory block gets overwritten by the newly allocated memory before it is freed — leading to a memory leak.

Sample:

use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering};
use smallvec::SmallVec;

struct CountingAllocator;
static ALLOCS: AtomicUsize = AtomicUsize::new(0);
static DEALLOCS: AtomicUsize = AtomicUsize::new(0);

unsafe impl GlobalAlloc for CountingAllocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        ALLOCS.fetch_add(1, Ordering::SeqCst);
        unsafe { System.alloc(layout) }
    }
    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        DEALLOCS.fetch_add(1, Ordering::SeqCst);
        unsafe { System.dealloc(ptr, layout) }
    }
    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
        unsafe { System.realloc(ptr, layout, new_size) }
    }
}

#[global_allocator]
static GLOBAL: CountingAllocator = CountingAllocator;

fn outstanding() -> isize {
    ALLOCS.load(Ordering::SeqCst) as isize - DEALLOCS.load(Ordering::SeqCst) as isize
}

fn main() {
    let before = outstanding();
    {
        let mut v: SmallVec<u8, 4> = SmallVec::with_capacity(16); // 堆上,len == 0
        v.grow(32);
        drop(v);  
    }
    println!(
        "unfree {:>2}",
        outstanding() - before
    );

    let before = outstanding();
    {
        let mut v: SmallVec<u8, 4> = SmallVec::new();
        for i in 0..8 {
            v.grow(8 << i); 
            v.clear();
        }
        drop(v);
    }
    println!(
        "unfree = {:>2} ",
        outstanding() - before
    );
}

output

   Compiling smallvec v2.0.0-alpha.12 (D:\GitHubPull\rust-smallvec)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.48s
     Running `target\debug\examples\leak_demo.exe`
unfree  1
unfree =  7

@alejandro-vaz

Copy link
Copy Markdown
Collaborator

AI contributions are not allowed in any @servo repository as indicated on the contributing guidelines

https://book.servo.org/contributing/getting-started.html#ai-contributions

this PR will subsequently be closed

@jdm

jdm commented Aug 26, 2026

Copy link
Copy Markdown
Member

@alejandro-vaz What signal did you use to decide this is an AI contribution?

@alejandro-vaz

alejandro-vaz commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

@jdm em-dashes here, perfect syntax, to be honest. maybe I was a bit strict on that

@servo guidelines specifically say that comments and PR summaries with AI aren't allowed

@dDostalker

Copy link
Copy Markdown
Contributor Author

I have to admit that this PR did make use of an LLM. But I’m also cautious about using LLMs, so in this PR, the LLM only handled translating my comments, while I personally did all the code understanding, modifications, and writing of the PR content.
It just translated my PR content into English. The reason for using the LLM was to avoid ambiguities and grammar mistakes that come from mechanical translation. I’m sorry for any inconvenience my actions caused, and I understand the strictness around LLMs as a maintainer. I also hope there will be better solutions in the future to overcome language barriers.

@alejandro-vaz alejandro-vaz reopened this Aug 26, 2026
@alejandro-vaz

Copy link
Copy Markdown
Collaborator

@dDostalker sorry for the precipitated decision to close it

I'll review your PR, but please don't use LLMs, bad English is better than AI English

thanks for contributing

@mbrubeck
mbrubeck enabled auto-merge August 26, 2026 18:08
@mbrubeck
mbrubeck added this pull request to the merge queue Aug 26, 2026
Merged via the queue into servo:v2 with commit e926d96 Aug 26, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants