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

Document unsafe code #524

Merged
merged 2 commits into from
Nov 24, 2022
Merged

Conversation

tcharding
Copy link
Member

@tcharding tcharding commented Nov 21, 2022

Functions that are unsafe should include a # Safety section.

  • Patch 1: Documents unsafe methods in secp256k1-sys. Please not this includes a minor refactor.
  • Patch 2: Documents the unsafe Context trait

Together these two patches remove #![allow(clippy::missing_safety_doc)] from the repo.

Fix: #447

Note to reviewers

The only function that was curly to understand the safety of was secp256k1_context_create, all the other stuff should be trivial to review.

@tcharding tcharding force-pushed the 11-22-document-unsafe branch from a53b59c to 7e00f4b Compare November 21, 2022 21:38
///
/// # Safety
///
/// For safety constraints see [`std::slice::from_raw_parts`] and [`std::str::from_utf8_unchecked`].
Copy link
Member

@apoelstra apoelstra Nov 22, 2022

Choose a reason for hiding this comment

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

In 6e19635:

I don't understand what std::str::from_utf8_unchecked has to do with anything here. slice::from_raw_parts is sorta relevant but it's really overkill because it's talking in terms of an anbitrary T but we're using C characters, which are one byte in size, have one-byte alignment, and have no trap representatons.

It would be clearer I think to just say that message must be a valid pointer to an initialized null-terminated C string.

Copy link
Member

Choose a reason for hiding this comment

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

Ah, I see, the reason you're citing these is because in our default callback function we call from_utf8_unchecked after using strlen to compute a bound on the string in order to convert it to a u8 slice.

So we should add the additional requirement then that the string, up to the first null byte, must be valid UTF8.

Alternately we could call CStr::from_ptr (and copy its safety bounds which are sensible for this funciton) and then CStr::to_str which is safe but returns a Result, which we could just .unwrap_or("<invalid UTF8>" or something.

Copy link
Member

Choose a reason for hiding this comment

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

Interestingly, doing this would eliminate our strlen funciton entirely, which is nice.

Copy link
Member Author

Choose a reason for hiding this comment

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

Cool, that turned out nice. Pushed as a separate patch.

@tcharding
Copy link
Member Author

The docs say that CStr::from_ptr takes a *const c_char [0] and that a c_char is type aliased to i8 [1]. I'm confused by the CI fails, we have a function that takes a *const c_char and passes it to CStr::from_ptr but on some architectures there is some sort of mix up between u8 and i8?

[0] https://doc.rust-lang.org/stable/core/ffi/struct.CStr.html#method.from_ptr
[1] https://doc.rust-lang.org/stable/core/ffi/type.c_char.html

@apoelstra
Copy link
Member

[1] is not the right reference. Our actual code uses https://github.com/rust-bitcoin/rust-secp256k1/blob/master/secp256k1-sys/src/types.rs#L8-L10 because, as your docs show, the official c_char has only been stable since 1.64.

I think we should just add a comment and do a cast/transmute here.

@tcharding
Copy link
Member Author

tcharding commented Nov 23, 2022

Ah of course, masked behind us always importing types::*. Thanks for the answer.

@tcharding
Copy link
Member Author

Oh bother, the CStr type is also only available in Rust 1.64

Functions that are `unsafe` should include a `# Safety` section. Because
we have wrapper functions to handle symbol renaming we essentially have
duplicate functions i.e., they require the same docs, instead of
duplicating the docs put the symbol renamed function below the
non-renamed function and add a docs linking to the non-renamed function.
Also add attribute to stop the linter warning about the missing safety
docs section.

Remove the clippy attribute for `missing_safety_doc`.
Add a `# Safety` section to all unsafe traits, methods, and functions.

Remove the clippy attribute for `missing_safety_doc`.
@tcharding tcharding force-pushed the 11-22-document-unsafe branch from 4b1e8c3 to 6d74730 Compare November 23, 2022 22:17
@tcharding
Copy link
Member Author

I've removed the CStr usage and attempted to improve the docs in patch 1.

@apoelstra
Copy link
Member

Oh bother, the CStr type is also only available in Rust 1.64

Oh, derp.

I feel like all this C interop stuff showed up 8 years later than I would've expected it to.

@apoelstra
Copy link
Member

Looks good now!

Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 6d74730

@elichai
Copy link
Member

elichai commented Nov 24, 2022

Oh bother, the CStr type is also only available in Rust 1.64

Yeah it wasn't available in core at the time that I've wrote this code, and it's still higher than our MSRV

Copy link
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 6d74730

@apoelstra apoelstra merged commit 5c15a49 into rust-bitcoin:master Nov 24, 2022
@tcharding tcharding deleted the 11-22-document-unsafe branch November 30, 2022 01:23
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.

Document unsafe code
3 participants