Skip to content

Panic on free() if initial heap was not aligned #121

Description

@jannic

While debugging #119, I saw some other panics that looked like a different issue and that were not fixed by #120.

When the initial allocation used for the pool is not 32-byte aligned, free() panics:

thread 'main' (54590) panicked at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rlsf-0.2.1/src/tlsf.rs:1545:17:
attempt to subtract with overflow
stack backtrace:
   0: __rustc::rust_begin_unwind
             at /rustc/9b1f8ff42d110b0ca138116745be921df5dc97e7/library/std/src/panicking.rs:689:5
   1: core::panicking::panic_fmt
             at /rustc/9b1f8ff42d110b0ca138116745be921df5dc97e7/library/core/src/panicking.rs:80:14
   2: core::panicking::panic_const::panic_const_sub_overflow
             at /rustc/9b1f8ff42d110b0ca138116745be921df5dc97e7/library/core/src/panicking.rs:175:17
   3: rlsf::tlsf::Tlsf<FLBitmap,SLBitmap,_,_>::iter_blocks::{{closure}}
             at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rlsf-0.2.1/src/tlsf.rs:1545:17
   4: <core::iter::sources::from_fn::FromFn<F> as core::iter::traits::iterator::Iterator>::next
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/sources/from_fn.rs:71:9
   5: core::iter::traits::iterator::Iterator::fold
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:2609:34
   6: <core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::fold
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/filter.rs:165:19
   7: <core::iter::adapters::filter::Filter<I,P> as core::iter::traits::iterator::Iterator>::fold
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/filter.rs:165:19
   8: <core::iter::adapters::map::Map<I,F> as core::iter::traits::iterator::Iterator>::fold
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/adapters/map.rs:128:19
   9: <usize as core::iter::traits::accum::Sum>::sum
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/accum.rs:50:22
  10: core::iter::traits::iterator::Iterator::sum
             at /home/jan/.rustup/toolchains/beta-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/iterator.rs:3599:9
  11: embedded_alloc::tlsf::Heap::free_with_cs
             at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embedded-alloc-0.7.0/src/tlsf.rs:126:18
  12: embedded_alloc::tlsf::Heap::free::{{closure}}
             at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embedded-alloc-0.7.0/src/tlsf.rs:110:42
  13: critical_section::with
             at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/critical-section-1.2.0/src/lib.rs:248:14
  14: embedded_alloc::tlsf::Heap::free
             at /home/jan/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embedded-alloc-0.7.0/src/tlsf.rs:110:9
  15: embedded_alloc_test::main
             at ./src/main.rs:26:31

Code leading to this panic:

use std::mem::MaybeUninit;

use embedded_alloc::TlsfHeap;


fn main() {
    let local_heap: TlsfHeap = TlsfHeap::empty();

    // For values 0<MISALIGN<32, free() panics
    const MISALIGN: usize = 16;

    // The usable size should not shrink due to misalignment, so grow the allocation accordingly
    const HEAP_SIZE: usize = 256+MISALIGN;

    // The overall allocation should be aligned
    #[repr(align(32))]
    struct Wrapper([MaybeUninit<u8>; HEAP_SIZE]);
    let mut heap_mem = Wrapper([MaybeUninit::uninit(); HEAP_SIZE]);

    let addr = heap_mem.0.as_mut_ptr() as usize + MISALIGN;
    let size = HEAP_SIZE - MISALIGN;

    println!("{:x} {:x}", addr, size);
    unsafe { local_heap.init(addr, size) }

    println!("{}", local_heap.free());
}

Full repo reproducing the issue: https://github.com/jannic/embedded-alloc-test

Activity

  1. fko-kuptec commented on Jan 28, 2026

    @fko-kuptec

    I came across the same issue yesterday after finding the bug with TlsfHeap::used. Thanks for the hint that the alignment is the issue!

  2. jannic commented on Jan 29, 2026

    @jannic
    MemberAuthor

    It looks like iter_blocks is called with a block of the wrong length, as explained in
    yvt/rlsf#21 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions