quick-protobuf icon indicating copy to clipboard operation
quick-protobuf copied to clipboard

Fix owned deref

Open nerdrew opened this issue 4 years ago • 5 comments

BREAKING CHANGE: remove *Owned Deref

The Owned PR was broken. The lifetimes of the Cow fields are wrong. The Cow str fields of an owned proto can end up referring to garbage if field.to_owned() is called and then the original field is modified or the Owned proto is dropped.

For example, this should not compile:

let proto = FooOwned::try_from(&buf)?;
let owned_copy = proto.str_field.to_owned();
drop(proto);
println!("this code should not be valid {}", owned_copy);

owned_copy refers to nothing now.

The fix seems to be to tie the transmuted lifetime of the proto to the lifetime of &self.

Here's a reduced example of the issue: https://github.com/nerdrew/rust-self-referential-struct/blob/master/src/main.rs#L77

When you remove the &'b self lifetime, the code compiles and the cow variable is garbage on the last line.

Without the &'b self lifetime:

% cargo run
   Compiling rust-self-referential-struct v0.1.0 (/home/lazarus/dev/tmp/rust-self-referential-struct)
    Finished dev [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/rust-self-referential-struct`
[src/main.rs:72] owned.buf() = "I see you"
[src/main.rs:73] &cow = "I see you"
[src/main.rs:77] &cow = "\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}u"

With it:

% cargo run
   Compiling rust-self-referential-struct v0.1.0 (/home/lazarus/dev/tmp/rust-self-referential-struct)
error[E0505]: cannot move out of `owned` because it is borrowed
  --> src/main.rs:75:10
   |
68 |     let cow = owned.cow().to_owned();
   |               ----- borrow of `owned` occurs here
...
75 |     drop(owned);
   |          ^^^^^ move out of `owned` occurs here
76 | 
77 |     dbg!(&cow);
   |          ---- borrow later used here

error: aborting due to previous error

Unfortunately, I don't think this is fixable while keeping the Deref and DerefMut` (at least I don't know how to, though I introduced this mess...).

This fix includes 3 commits:

  • fix for the unsoundness issue (Sorry about that, totally my bad!)
  • replace MaybeUninit with Option (much easier to think about Option for me)
  • Improve the "test helper" From<MyProto> impl.

I can break this into multiple PRs if you want, since the unsoundness is a critical fix and the other two are nice-to-haves (though I think MaybeUninit was giving me errors or warnings with a recent nightly).

nerdrew avatar Dec 15 '19 05:12 nerdrew

I'll get back to you soon. I am not a fan of transmute Thanks!

tafia avatar Dec 17 '19 08:12 tafia

Any thoughts on this?

nerdrew avatar Jan 11 '20 22:01 nerdrew

Friendly bump :)

nerdrew avatar Mar 19 '20 21:03 nerdrew

There are some merge conflicts that I'll fix if you are open to this PR. I'd like to fix the implementation of Owned.

nerdrew avatar Sep 14 '20 06:09 nerdrew

Yes I'm fine with it sorry!

tafia avatar Sep 14 '20 07:09 tafia

There are some merge conflicts that I'll fix if you are open to this PR. I'd like to fix the implementation of Owned.

Hi @nerdrew! I'm currently working on a fix for the merge conflicts, but do let me know if you'd still like to finish it yourself haha

snproj avatar Oct 20 '22 08:10 snproj

Sorry for the delayed response! Thanks for merging. I think I have a bunch of other changes on my branch. I'll open some PRs if I think they look useful!

nerdrew avatar Nov 22 '22 05:11 nerdrew

Ooops. I think I have a better fix for this. Let me see if I can rebase. I'll open another PR.

nerdrew avatar Nov 22 '22 05:11 nerdrew