Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upundefined behavior in safe code with public Response<'static> field #30
Comments
This comment has been minimized.
This comment has been minimized.
|
Thanks for creating an issue about this. So do you think this way would be safe? diff --git a/tokio-imap/src/proto.rs b/tokio-imap/src/proto.rs
index 4ef8fc1..45a5ddd 100644
--- a/tokio-imap/src/proto.rs
+++ b/tokio-imap/src/proto.rs
@@ -82,7 +82,7 @@ pub struct ResponseData {
// is transmuted to `'static` by the `Decoder`, instead, and
// references returned to callers of `ResponseData` are limited
// to the lifetime of the `ResponseData` struct.
- pub response: Response<'static>,
+ response: Response<'static>,
}
impl ResponseData { |
This comment has been minimized.
This comment has been minimized.
|
Thanks for responding! Short answer: I think so. Long answer: So, the things I know of that you need to watch out for when using this pattern are:
Considering these in order:
Two other off-side comments:
---
tokio-imap/src/proto.rs | 21 +++++++++++++--------
1 file changed, 13 insertions(+), 8 deletions(-)
diff --git a/tokio-imap/src/proto.rs b/tokio-imap/src/proto.rs
index 4ef8fc1..11c01f1 100644
--- a/tokio-imap/src/proto.rs
+++ b/tokio-imap/src/proto.rs
@@ -26,7 +26,7 @@ impl Default for ImapCodec {
}
}
-impl<'a> Decoder for ImapCodec {
+impl Decoder for ImapCodec {
type Item = ResponseData;
type Error = io::Error;
fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
@@ -35,11 +35,13 @@ impl<'a> Decoder for ImapCodec {
}
let (response, rsp_len) = match imap_proto::parse_response(buf) {
Ok((remaining, response)) => {
- // This SHOULD be acceptable/safe: BytesMut storage memory is
- // allocated on the heap and should not move. It will not be
- // freed as long as we keep a reference alive, which we do
- // by retaining a reference to the split buffer, below.
- let response = unsafe { mem::transmute(response) };
+ let response = unsafe {
+ // This SHOULD be acceptable/safe: BytesMut storage memory is
+ // allocated on the heap and should not move. It will not be
+ // freed as long as we keep a reference alive, which we do
+ // by retaining a reference to the split buffer, below.
+ mem::transmute::<Response<'_>, Response<'static>>(response)
+ };
(response, buf.len() - remaining.len())
}
Err(nom::Err::Incomplete(Needed::Size(min))) => {
@@ -82,7 +84,10 @@ pub struct ResponseData {
// is transmuted to `'static` by the `Decoder`, instead, and
// references returned to callers of `ResponseData` are limited
// to the lifetime of the `ResponseData` struct.
- pub response: Response<'static>,
+ //
+ // `raw` is never mutated prior to being dropped, and `Response`
+ // does not try to access the borrowed data in its drop glue.
+ response: Response<'static>,
}
impl ResponseData {
@@ -93,7 +98,7 @@ impl ResponseData {
}
}
pub fn parsed(&self) -> &Response {
- unsafe { mem::transmute(&self.response) }
+ &self.response
}
}
--
2.19.0 |
djc
closed this
in
804009e
Nov 6, 2018
This comment has been minimized.
This comment has been minimized.
|
Thanks for the review! I've pushed a more minimal version and will push out a release shortly. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ExpHP commentedNov 3, 2018
•
edited
Release output: