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

Remove uses of Pin::new_unchecked in h1 Dispatcher #1374

Merged
merged 2 commits into from Feb 25, 2020

Conversation

Aaron1011
Copy link
Contributor

This removes the last uses of unsafe Pin functions in actix-web.

This PR adds a Pin<Box<_>> wrapper to DispatcherState::Upgrade,
State::ExpectCall, and State::ServiceCall.

The previous uses of the futures State::ExpectCall and State::ServiceCall
were Undefined Behavior - a future was obtained from self.expect.call
or self.service.call, pinned on the stack, and then immediately
returned from handle_request. The only alternative to using Box::pin
would be to refactor handle_request to write the futures directly into
their final location, or avoid polling them before they are returned.

The previous use of DispatcherState::Upgrade doesn't seem to be
unsound. However, having data pinned inside an enum that we
std::mem::replace would require some careful unsafe code to ensure
that we never call std::mem::replace when the active variant contains
pinned data. By using Box::pin, we any possibility of future
refactoring accidentally introducing undefined behavior.

This removes the last uses of unsafe `Pin` functions in actix-web.

This PR adds a `Pin<Box<_>>` wrapper to `DispatcherState::Upgrade`,
`State::ExpectCall`, and `State::ServiceCall`.

The previous uses of the futures `State::ExpectCall` and `State::ServiceCall`
were Undefined Behavior - a future was obtained from `self.expect.call`
or `self.service.call`, pinned on the stack, and then immediately
returned from `handle_request`. The only alternative to using `Box::pin`
would be to refactor `handle_request` to write the futures directly into
their final location, or avoid polling them before they are returned.

The previous use of `DispatcherState::Upgrade` doesn't seem to be
unsound. However, having data pinned inside an enum that we
`std::mem::replace` would require some careful `unsafe` code to ensure
that we never call `std::mem::replace` when the active variant contains
pinned data. By using `Box::pin`, we any possibility of future
refactoring accidentally introducing undefined behavior.
@Aaron1011
Copy link
Contributor Author

The test failures seem unrelated.

@JohnTitor
Copy link
Member

Yeah, will be fixed by #1372.

@JohnTitor JohnTitor requested a review from a team February 25, 2020 09:06
@cetra3
Copy link
Contributor

cetra3 commented Feb 25, 2020

LGTM!

@JohnTitor JohnTitor merged commit 71c4bd1 into actix:master Feb 25, 2020
@JohnTitor
Copy link
Member

Thanks!

@Aaron1011 Aaron1011 deleted the fix/new-remove-pin-unsafe branch February 25, 2020 23:29
Aaron1011 added a commit to Aaron1011/actix-web that referenced this pull request Mar 4, 2020
This ended up getting reverted by actix#1367, which re-introduced an unsound
use of `Pin::new_unchecked`

See my original PR actix#1374 for the reasoning behind this change.
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.

None yet

3 participants