Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Memory leak in core_utils_rs::trampoline::create_left_trampoline #13

@yaokunzhang

Description

@yaokunzhang

Hello, our detector has flagged what appears to be a soundness issue, potentially leading to undefined behavior

Summary

The create_left_trampoline function in core-utils-rs creates heap-allocated closures via Box::into_raw but provides no mechanism to clean up the allocated memory, leading to guaranteed memory leaks in normal usage.

Reproduction

Minimal example:

use core_utils_rs::trampoline::*;

fn main() {
    let important_data = String::from("this will be freed correctly");
    let (callback, context) = create_left_trampoline(move |_: ()| {
        println!("    Closure logic running. It owns: '{}'", important_data);
    });
}

after excute "cargo miri run"

error: memory leaked: alloc1030 (Rust heap, size: 24, align: 8), allocated here:
  --> .cargo/registry/src/rsproxy.cn-e3de039b2554c837/core-utils-rs-0.3.5/src/trampoline.rs:30:40
   |
30 |         TrampolineRefcon(Box::into_raw(Box::new(wrapped_closure)).cast()),
   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: BACKTRACE:
   = note: inside `core_utils_rs::trampoline::create_left_trampoline::<'_, (), (), {closure@src/main.rs:5:54: 5:66}>` at .cargo/registry/src/rsproxy.cn-e3de039b2554c837/core-utils-rs-0.3.5/src/trampoline.rs:30:40: 30:65
note: inside `main`
  --> src/main.rs:5:31
   |
5  |       let (callback, context) = create_left_trampoline(move |_: ()| {
   |  _______________________________^
6  | |         println!("    Closure logic running. It owns: '{}'", important_data);
7  | |     });
   | |______^

error: memory leaked: alloc882 (Rust heap, size: 28, align: 1), allocated here:
   --> .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/raw_vec/mod.rs:476:41
    |
476 |             AllocInit::Uninitialized => alloc.allocate(layout),
    |                                         ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: BACKTRACE:
    = note: inside `alloc::raw_vec::RawVecInner::try_allocate_in` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/raw_vec/mod.rs:476:41: 476:63
    = note: inside `<u8 as std::slice::<impl [T]>::to_vec_in::ConvertVec>::to_vec::<std::alloc::Global>` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/slice.rs:446:29: 446:66
    = note: inside `std::slice::<impl [u8]>::to_vec_in::<std::alloc::Global>` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/slice.rs:399:16: 399:38
    = note: inside `std::slice::<impl [u8]>::to_vec` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/slice.rs:375:9: 375:31
    = note: inside `std::slice::<impl std::borrow::ToOwned for [u8]>::to_owned` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/slice.rs:841:9: 841:22
    = note: inside `std::str::<impl std::borrow::ToOwned for str>::to_owned` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/str.rs:211:46: 211:72
    = note: inside `<std::string::String as std::convert::From<&str>>::from` at .rustup/toolchains/nightly-2025-05-09-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/alloc/src/string.rs:2974:9: 2974:21
note: inside `main`
   --> src/main.rs:4:26
    |
4   |     let important_data = String::from("this will be freed correctly");
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

note: set `MIRIFLAGS=-Zmiri-ignore-leaks` to disable this check

error: aborting due to 2 previous errors; 2 warnings emitted

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions