Skip to content

Enforce OS errors are in the allowed range.#441

Merged
newpavlov merged 1 commit intorust-random:masterfrom
briansmith:b/new_os
Jun 4, 2024
Merged

Enforce OS errors are in the allowed range.#441
newpavlov merged 1 commit intorust-random:masterfrom
briansmith:b/new_os

Conversation

@briansmith
Copy link
Copy Markdown
Contributor

@briansmith briansmith commented May 31, 2024

Avoid the From<NonZeroU32> implementation in favor of a constructor that centralizes all the range checking in one place. Consistently use ERRNO_NOT_POSITIVE for nonpositive values and Self::UNEXPECTED for too-large values.

Besides being more consistent in the range checking, this also reduces the boilerplate in callers, which makes it easier to maintain the ports to less-common operating systems.

src/error.rs Outdated
pub const CUSTOM_START: u32 = (1 << 31) + (1 << 30);

#[cold]
pub(super) fn new_os(code: u32) -> Self {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In the future we might consider adding a public new_custom constructor and then deprecating the From<NonZeroU32> that does the non-range-checked conversion.

@briansmith briansmith force-pushed the b/new_os branch 3 times, most recently from 53d8f46 to 0af5ac5 Compare June 4, 2024 17:09
@briansmith
Copy link
Copy Markdown
Contributor Author

I updated this to be cleaner. I also removed the #[cold] since that's an unrelated change.

@newpavlov
Copy link
Copy Markdown
Member

What about my suggestion above?

@briansmith
Copy link
Copy Markdown
Contributor Author

What about my suggestion above?

Sorry, I don't see it. Maybe it is still a draft?

@newpavlov
Copy link
Copy Markdown
Member

Oh, oops. You are right.

src/error.rs Outdated

#[allow(dead_code)]
#[cold]
pub(super) fn new_os(code: u32) -> Self {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you add some docs for this method?

I also think we can write it like this:

pub(crate) fn from_os_code(code: impl TryInto<u32>) -> Self {
    code.try_into()
        .ok()
        .and_then(NonZeroU32::new)
        .and_then(|code| {
            if code.get() < Self::INTERNAL_START {
                Some(Self(code))
            } else {
                None
            }
        })
        .unwrap_or(Self::UNEXPECTED)
}

This will make backend code a bit nicer.

I don't think we need to distinguish between ERRNO_NOT_POSITIVE and UNEXPECTED. Both cases should never happen in practice in the first place. Plus the former was used only for codes from errno.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Could you add some docs for this method?

OK. But...

pub(crate) fn from_os_code(code: impl TryInto) -> Self {

Unfortunately that would allow passing a usize or similar, which really shouldn't be implicitly converted. So I think we should not do that.

I don't think we need to distinguish between ERRNO_NOT_POSITIVE and UNEXPECTED

I am OK with making that change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Unfortunately that would allow passing a usize or similar, which really shouldn't be implicitly converted.

Since it's a private API, I think it's fine to allow this. If you want to make this more explicit, you could use Error::from_os_code::<isize>(code) at call sites. Either way, I do not insist on it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well, I think the main goal here is to ensure that the result is well-defined, rather than to increase convenience.

I do hope this API can be improved further and then made public to replace the From<NonZeroU32> implementation as discussed elsewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added the documentation, moved the ERRNO_NOT_POSITIVE logic back to where it belongs, and renamed the function to be more like the analogous std::io::Error function.

@briansmith briansmith force-pushed the b/new_os branch 2 times, most recently from 5391cbc to 52bcd6d Compare June 4, 2024 23:20
Avoid the `From<NonZeroU32>` implementation in favor of a constructor
that centralizes all the range checking in one place. Consistently use
 `Self::UNEXPECTED` for out-of-rnage values.

Besides being more consistent in the range checking, this also reduces
the boilerplate in callers, which makes it easier to maintain the ports
to less-common operating systems.

This is a step towards deprecating the `impl From<NonZeroU32> for Error`
implementation.
@newpavlov newpavlov merged commit 05cdf6f into rust-random:master Jun 4, 2024
@briansmith briansmith deleted the b/new_os branch June 4, 2024 23:36
takumi-earth pushed a commit to earthlings-dev/getrandom that referenced this pull request Jan 27, 2026
Avoid the `From<NonZeroU32>` implementation in favor of a constructor
that centralizes all the range checking in one place.

Besides being more consistent in the range checking, this also reduces
the boilerplate in callers, which makes it easier to maintain the ports
to less-common operating systems.
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.

2 participants