-
Notifications
You must be signed in to change notification settings - Fork 67
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
Propose changes to address undefined behavior #58
Conversation
Thank you for taking the time to open a pull request. Nice that you also verified the assembly for I have two small comments, but overall this looks like a nice improvement. For If you address my comments, I’ll merge this, but also to set some expectations, |
src/read.rs
Outdated
@@ -193,7 +191,7 @@ impl<R> ReadExt for R | |||
|
|||
#[inline(always)] | |||
fn read_le_f32(&mut self) -> io::Result<f32> { | |||
self.read_le_u32().map(|u| unsafe { mem::transmute(u) }) | |||
self.read_le_u32().map(|u| unsafe { mem::transmute::<u32, f32>(u) }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is also from_le_bytes
since Rust 1.40. If you are concerned about the unsafe
, and we are bumping the minimum supported Rust version to 1.36 for the MaybeUninit
anyway, then it’s a small step to go to 1.40, and then we can use from_le_bytes
here, and get rid of the unsafe
and transmute
entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
from_le_bytes
looks good. I also called read_into
directly instead of calling read_le_u32
to avoid going from [0u8; 4]
to u32
to [0u8; 4]
back to f32
. If you'd rather keep the call to read_le_u32
I can change it back.
5f535fb
to
124628d
Compare
Propose changes to unsafe code in hound repository
fff16c7
to
e284521
Compare
Thanks! |
Absolutely! Regarding the current state of Regarding fuzzing, do you just want to run the existing fuzz harness on |
Interested in picking up these changes! @ruuda , would these changes be able to release out in a new crate version? |
So, @maxwellmckinnon backported these changes on top of v3.5.0, and I published those to crates.io as v3.5.1. As far as I am aware, the undefined behavior did not cause rustc to compile programs in a problematic way, but for good measure I submitted a RustSec advisory either way. |
Hello, thank you for making this crate. Here are some proposed changes to unsafe code that avoid undefined behavior. These changes either maintain the optimizations that the original versions contained or incur minimal overhead in the existing context.
For
src/read.rs::read_bytes
, creating a reference to uninitialized memory is considered undefined behavior (tracked issue). Since the function is called with n = 4 bytes, the initialization overhead should be minimal.For calls to
mem::transmute
, we can add explicit return types to avoid possible unpredicted types from inference.For the buffer fields in
ChunksWriter
andSampleWriter16
, we can useMaybeUninit<u8>
to be explicit about when the values are initialized to avoid undefined behavior of creating references to uninitialized memory.In
write_sample<S: Sample>
the calls towrite
onMaybeUninit<u8>
's behave the same as writing theu8
values as before.For
write_u16_le_unchecked
, we can useMaybeUninit::write()
like we did forwrite_sample
but instead of referencing a bounds checked element at an index, we can get an unchecked reference as before.Assmebly code for
write_u16_unchecked
can be found here.Thanks again for maintaining this awesome crate, I hope you find these proposed changes useful for future development and use.