Skip to content

Commit

Permalink
Fix alignment handling for packed structs
Browse files Browse the repository at this point in the history
  • Loading branch information
chipshort committed Jan 26, 2024
1 parent 5ceb431 commit 5c982e9
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 8 deletions.
10 changes: 6 additions & 4 deletions boxify-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ fn fill_ptr(ptr: &Expr, value: &Expr) -> proc_macro2::TokenStream {

quote! {
#validate_not_struct
unsafe { #ptr.write(#value); }
// unsafe { #ptr.write(#value); }
unsafe { #ptr.write_unaligned(#value); }
}
}
} else {
Expand All @@ -226,7 +227,8 @@ fn fill_ptr(ptr: &Expr, value: &Expr) -> proc_macro2::TokenStream {
// fallback to creating the value on the stack and writing it to
// the pointer from there
quote! {
unsafe { #ptr.write(#e); }
// unsafe { #ptr.write(#e); }
unsafe { #ptr.write_unaligned(#e); }
}
}
}
Expand All @@ -239,7 +241,7 @@ fn fill_struct_fields(strct_ptr: &Expr, strct: &syn::ExprStruct) -> proc_macro2:
let expr = &field.expr;

let field_ptr = parse_quote! {
core::ptr::addr_of_mut!((*#strct_ptr).#ident)
::core::ptr::addr_of_mut!((*#strct_ptr).#ident)
};
fill_ptr(&field_ptr, expr)
});
Expand All @@ -265,7 +267,7 @@ fn fill_tuple(
let instantiation_codes = elems.iter().enumerate().map(|(index, value)| {
let index = syn::Index::from(index);
let field_ptr = parse_quote_spanned! {value.span()=>
core::ptr::addr_of_mut!((*#ptr).#index)
::core::ptr::addr_of_mut!((*#ptr).#index)
};
fill_ptr(&field_ptr, value)
});
Expand Down
10 changes: 6 additions & 4 deletions boxify/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,15 @@ pub unsafe fn fill_array<T: Copy, const SIZE: usize>(array: *mut [T; SIZE], valu

if size_of::<T>() == 1 {
// in this case, we can use `ptr::write_bytes` instead of `ptr::write`
// SAFETY: we just checked that T is 1 byte, so transmuting to u8 is safe
let value_byte = core::ptr::addr_of!(value) as *const u8;
core::ptr::write_bytes(array, *value_byte, SIZE);
// SAFETY: we just checked that T is 1 byte, so casting to *const u8 is valid
let value_byte: *const u8 = core::ptr::addr_of!(value) as *const u8;
// also casting array to *mut u8 for alignment reasons
core::ptr::write_bytes(array as *mut u8, *value_byte, SIZE);
} else {
for i in 0..SIZE {
// write the value to the array
array.add(i).write(value);
// array.add(i).write(value);
array.add(i).write_unaligned(value);
}
}
}
Expand Down

0 comments on commit 5c982e9

Please sign in to comment.