rcore-os / rcore-os/buddy_system_allocator

`FrameAllocator` treats zero-sized requests as real allocations and panics on zero-sized deallocation

Open Beginner friendly
#52 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
145
Forks
34
PR merge metrics
No merged PRs in 30d

Description

FrameAllocator currently does not reject zero-sized requests at the API boundary.

Relevant code:

  • src/frame.rs:86-89 for alloc
  • src/frame.rs:95-98 for alloc_aligned
  • src/frame.rs:107-110 for alloc_at
  • src/frame.rs:178-181 for dealloc
  • src/frame.rs:186-189 for dealloc_aligned

Because 0usize.next_power_of_two() == 1, a zero-sized request is internally treated as size 1.

That causes two problems:

  1. zero-sized allocation requests can consume a real frame
  2. zero-sized deallocation can panic due to self.allocated -= size
Reproduction

Allocation side:

use buddy_system_allocator::FrameAllocator;
use core::alloc::Layout;

#[test]
fn frame_allocator_zero_sized_allocations_should_be_rejected() {
    let mut frame = FrameAllocator::<8>::new();
    frame.add_frame(0, 8);

    // These currently succeed instead of returning None.
    assert_eq!(frame.alloc(0), None);
    assert_eq!(frame.alloc_at(3, 0), None);
    assert_eq!(
        frame.alloc_aligned(Layout::from_size_align(0, 1).unwrap()),
        None,
    );

    // Zero-sized calls should not affect allocator state.
    assert_eq!(frame.alloc(8), Some(0));
}

Deallocation side:

use buddy_system_allocator::FrameAllocator;
use core::alloc::Layout;

#[test]
fn frame_allocator_zero_sized_deallocations_should_be_noop() {
    let mut frame = FrameAllocator::<8>::new();
    frame.add_frame(0, 1);

    // Currently panics with subtract overflow.
    frame.dealloc(0, 0);
    frame.dealloc_aligned(0, Layout::from_size_align(0, 1).unwrap());

    assert_eq!(frame.alloc(1), Some(0));
}
Why this matters

This is not just a semantic edge case. The current behavior is inconsistent and unsafe:

  • zero-sized allocation unexpectedly consumes a real resource
  • zero-sized deallocation can panic
  • accounting can also be polluted by these calls

alloc_aligned / dealloc_aligned are especially awkward here because a zero-sized layout can still be expanded by alignment.

Suggested fix

Handle zero-sized inputs explicitly at the public API boundary:

  • alloc(0) returns None
  • alloc_at(_, 0) returns None
  • alloc_aligned(layout) returns None when layout.size() == 0
  • dealloc(_, 0) is a no-op
  • dealloc_aligned(_, layout) is a no-op when layout.size() == 0

Optionally, internal helpers can also add:

debug_assert!(size > 0);

But the public behavior should avoid panicking on zero-sized requests.

If it is confirmed to be a bug, I can submit a PR to help fix it.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the alloc, alloc_aligned, alloc_at, dealloc, and dealloc_aligned implementations in src/frame.rs at the line ranges listed in the issue. Run the supplied zero-sized allocation and deallocation reproductions, then verify that allocation returns None, deallocation is a no-op, and a subsequent real allocation still succeeds without consuming or corrupting allocator state.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
operating-systems
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.