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

Add in missing nullptr check when calling std::slice::from_raw_parts #416

Merged
merged 2 commits into from
Sep 29, 2024

Conversation

maspe36
Copy link
Collaborator

@maspe36 maspe36 commented Sep 22, 2024

Seems like back in #407 we added a conditional to not call write_bytes() if the internal data buffer of a Sequence was a nullptr.

It is true that it is unsafe to pass a nullptr to write_bytes

the pointer must be non-null and properly aligned.

But this breaks our Sequence abstraction because now an empty sequence has a nullptr for its buffer. So later, when we may call from_raw_parts(), we panic if our Sequence is empty.

data must be non-null and aligned even for zero-length slices.

So this PR is a small hack for #411, but doesn't fundamentally address the issue.


Taking a deeper look at the BoundedSequence and Sequence structs, I think we should refactor them to use something like RawVec (The RawVec impl in the std lib actually uses Unique which is currently unstable 😞 ). We know the type that a Sequence or BoundedSequence is constructed with, so there should be no reason our internal buffer isn't non-zero and aligned.

Vec::<i32>::default().is_empty() doesn't panic so Sequence::<i32>::default().is_empty() shouldn't panic.

// isn't modified externally.
unsafe { std::slice::from_raw_parts_mut(self.data, self.size) }
if self.data.is_null() {
&mut []
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, now that I'm looking at this, I'm not sure this would work. If someone started pushing to this mutable slice self.data would never get updated, so this likely would compile but exhibit incorrect runtime behavior.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to write a unit test for this scenario? Just to make sure that it's working, and also as a warning sign in case future changes cause it to break?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to write a unit test for this scenario?

Good point, added a unit test for the base cases. But also, just digging around the slice API, doesn't seem like this is really a concern to mutate the slice as its empty, and the only mutation that can be done will be with the fixed size.

i.e.

let mut slice = Sequence::<i32>::default().as_mut_slice();

// I can't do anything useful with slice now
// slice[0] = 42 will segfault because the len of the slice is zero.
// I actually don't think it matters, its just not really idiomatic rust

// isn't modified externally.
unsafe { std::slice::from_raw_parts(self.data, self.size) }
if self.data.is_null() {
&[]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

esteve
esteve previously approved these changes Sep 23, 2024
Copy link
Collaborator

@esteve esteve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maspe36 good catch! Thanks.

Copy link
Collaborator

@jhdcs jhdcs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should probably work. After thinking about it a bit more, I don't think the mutating slice thing should be an issue since I think the borrow checker should protect against that. Right?

@maspe36
Copy link
Collaborator Author

maspe36 commented Sep 29, 2024

Yup, @jhdcs that was the same realization I came to. I've been writing too much C++ :)

@maspe36 maspe36 merged commit 5903d73 into ros2-rust:main Sep 29, 2024
3 checks passed
@maspe36 maspe36 deleted the bugfix/missing-raw-parts-null-check branch October 27, 2024 15:42
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

Successfully merging this pull request may close these issues.

3 participants