Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Obstack generates unaligned references #4

Closed
Qwaz opened this issue Sep 3, 2020 · 2 comments
Closed

Obstack generates unaligned references #4

Qwaz opened this issue Sep 3, 2020 · 2 comments

Comments

@Qwaz
Copy link

Qwaz commented Sep 3, 2020

rust-obstack/src/lib.rs

Lines 317 to 337 in e1dde0d

#[inline]
unsafe fn alloc(&mut self, size: usize, alignment: usize) -> *mut A {
let start_ptr = self.tip.as_mut_ptr()
.offset(self.tip.len_items() as isize);
let padding = start_ptr as usize % alignment;
debug_assert!(padding < alignment);
debug_assert_eq!(padding, 0);
let start_ptr = start_ptr.offset(AlignedVec::<A>::bytes_to_items(padding) as isize);
let new_used = self.tip.len_items() + padding + AlignedVec::<A>::bytes_to_items(size);
if new_used <= self.tip.capacity_items() {
self.tip.set_len_items(new_used);
start_ptr as *mut A
} else {
self.alloc_from_new_slab(size, alignment)
}
}

Description

Obstack generates unaligned references for types that require a large alignment.

Demonstration

  • Crate: obstack
  • Version: 0.1.3
  • OS: Ubuntu 18.04.5 LTS
  • Rust: rustc 1.46.0 (04488afe3 2020-08-24)
  • Cargo flags: --release
#![forbid(unsafe_code)]

use obstack::Obstack;

#[repr(align(256))]
#[derive(Copy, Clone)]
struct LargeAlign(u8);

fn main() {
    // https://github.com/petertodd/rust-obstack/blob/e1dde0dbed709ebdea9bd1f79ec718e80c5d0bf6/src/lib.rs#L317-L337
    // Line 322: Incorrect padding bytes calculation. It should be `(alignment - (start_ptr % alignment)) % alignment`.
    // Line 329: Wasted memory due to `bytes_to_item()` not being applied to `padding`.

    // Due to the incorrect padding calculation, the code generates unaligned reference in release mode.
    let obstack = Obstack::new();
    let val_ref = obstack.push_copy(LargeAlign(0));

    let address = val_ref as *mut _ as usize;
    println!("{:x}", address);
    assert!(address % std::mem::align_of::<LargeAlign>() == 0);
}

Output:

55bc0c2fc520
thread 'main' panicked at 'assertion failed: address % std::mem::align_of::<LargeAlign>() == 0', src/main.rs:39:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Return Code: 101

@petertodd
Copy link
Owner

Thanks!

Looks like in debug mode it'd bail if alignment padding was needed at all; obviously forgot to finish that part or something.

Made a new release, v0.1.4, which fixes this.

@Qwaz
Copy link
Author

Qwaz commented Sep 4, 2020

Thank you for a quick fix :)

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

No branches or pull requests

2 participants