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

Fixing UB in construction code #17

Merged
merged 1 commit into from
Sep 12, 2023
Merged

Conversation

bazhenov
Copy link
Contributor

As stated in #16 miri complains about undefined behavior in eytzinger_walk(). As far as I can tell this is indeed UB because get_unchecked_mut() is UB when accessing out-of-bounds index (even without dereferencing). Out-of-bounds I interpret as "after length", not "after capacity".

The issue goes away if appropriate resize() call has been done on a Vec before writing elements to it. This agrees with the hypothesis that uninitialized vector is the issue.

I rewrite construction code using MaybeUninit, resize_with (which is zero cost in conjunction with MaybeUninit) and mem::transmute to mitigate this issue. mem::transmute may seems scary but it is the analog of set_len() in old code.

The alternative would be to fill the Vec with default values, but it does have performance impact.

@jonhoo
Copy link
Owner

jonhoo commented Sep 11, 2023

Hmm, given that we only ever write to this value, wouldn't it be easier to just use

v.as_mut_ptr().offset(i).write(iter.next().unwrap())

?

@bazhenov bazhenov changed the title Using MaybeUninit in construction code (see #16) Fixing UB in construction code (see #16) Sep 12, 2023
@codecov-commenter
Copy link

Codecov Report

Merging #17 (7636bda) into main (ec4cbab) will increase coverage by 0.0%.
The diff coverage is 100.0%.

Files Changed Coverage
src/lib.rs 100.0%

@bazhenov
Copy link
Contributor Author

I'm somewhat skeptical about the contract between eytzinger_walk() and from_sorted_iter(). One need to remember how exactly those two functions need to behave to stay sound. My thought was to be more explicit with MaybeUninit to prevent possible problems in the future.

But in terms of simplicity, yes I agree – pointer arithmetic is much simpler. I've implemented your approach.

@bazhenov bazhenov changed the title Fixing UB in construction code (see #16) Fixing UB in construction code Sep 12, 2023
Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

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

You're not wrong, but at the same time I worry that the code with MaybeUninit is also more complex, and so easier to accidentally get subtly wrong. We also now have miri to keep us honest, which helps!

@jonhoo jonhoo merged commit 65eff48 into jonhoo:main Sep 12, 2023
17 checks passed
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