Skip to content
New issue

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

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

Already on GitHub? # to your account

Audit suffix_array #56

Closed
nbraud opened this issue Nov 26, 2019 · 7 comments
Closed

Audit suffix_array #56

nbraud opened this issue Nov 26, 2019 · 7 comments

Comments

@nbraud
Copy link

nbraud commented Nov 26, 2019

Dependency of qbsdiff by the same author.

Noticed 2 patterns:

  • std::ptr::copy_nonoverlapping(&src_slice[i] as *const T, &mut dst_slice[j] as *mut T, n)
    All non-UB uses can be replaced with dst.slice[j..j+n].copy_from_slice(src_slice[i..i+n]).
  • std::ptr::copy(&s[i] as *const T, &mut s[j] as *mut T, n)
    Same idea, non-UB uses can be replaced with s.copy_within(i..i+n, j).
    If the ranges are non-overlapping, it might be faster to use slice::split_at_mut and copy_from_slice (resulting in a call to std::ptr::copy_nonoverlapping)

Should we request a clippy lint?

Fixes sent upstream: hucsmn/suffix_array#1

@nbraud
Copy link
Author

nbraud commented Nov 26, 2019

@hucsmn merged those changes; there are still unsafe functions in src/sa.rs (unchecked_{from_parts,load,load_{bytes,file}}) but they do not seem to contain potential memory unsafety themselves.

@Shnatsel
Copy link
Member

Nice! This one is going to be easy to lint, too: when ptr::copy_nonoverlapping() is used on two slices of Copy types, it can be safely replaced with slice::copy_from_slice(). Same for ptr::copy and slice::copy_within().

@nbraud
Copy link
Author

nbraud commented Nov 29, 2019

This one is going to be easy to lint, too: when ptr::copy_nonoverlapping() is used on two slices of Copy types, it can be safely replaced with slice::copy_from_slice(). Same for ptr::copy and slice::copy_within().

Yes, and there is slice::clone_from_slice when the type isn't Copy.

@Shnatsel
Copy link
Member

slice::clone_from_slice() has different semantics than ptr::copy_nonoverlapping(): the former calls clone() on the objects, while the latter does not.

@nbraud
Copy link
Author

nbraud commented Nov 29, 2019

@Shnatsel Sure, my point was that in the case of non-copy types, the use of ptr::copy_nonoverlapping (or ptr::copy) is UB; in those cases, the lint shouldn't suggest a replacement which doesn't work, but instead notify the user that there is UB afoot and suggest a sound (but slower) replacement.

Update: moving that discussion to the Clippy issue, your example there was fairly enlightening.

@slightlyoutofphase
Copy link

slightlyoutofphase commented Dec 18, 2019

FYI, the use of ptr::copy_nonoverlapping and ptr::copy on non-Copy types is not UB in any way.

It's just... particularly unsafe, as it requires you to ensure that you're properly avoiding any double-drops that might result from it (depending on the particular way it's being used) as well as ensure that you're not actually directly exposing bitwise copies of non-Copy types to safe code at any time.

See the append_elements function that Vec::append calls internally for a perfectly valid use on not-necessarily-Copy types, for example.

@Shnatsel
Copy link
Member

The upstream code is now 100% safe, Clippy lint is requested. Closing this issue.

I've also opened a PR to showcase these improvements in safety-dance trophy case: #62

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants