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

as_ptr returns a read-only pointer #60443

Merged
merged 2 commits into from
May 14, 2019
Merged

as_ptr returns a read-only pointer #60443

merged 2 commits into from
May 14, 2019

Conversation

RalfJung
Copy link
Member

@RalfJung RalfJung commented May 1, 2019

Add comments to as_ptr methods to warn that these are read-only pointers, and writing to them is UB.

It was pointed out that CStr does not even have an as_mut_ptr. I originally was going to add one, but there is no method at all that would mutate a CStr. Was that a deliberate choice or should I add an as_mut_ptr (similar to what I did for str)?

@rust-highfive
Copy link
Collaborator

r? @Kimundi

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label May 1, 2019
@cuviper
Copy link
Member

cuviper commented May 1, 2019

It was pointed out that CStr does not even have an as_mut_ptr.

I believe the correct way is to use CString::into_raw followed by CString::from_raw to recalculate the length, as shown in the example here:
https://doc.rust-lang.org/std/ffi/struct.CString.html#method.from_raw

However, it seems to me this would not know the right length of the allocation to free, no? That doesn't matter for system free, but maybe it would for other allocators...

@RalfJung
Copy link
Member Author

RalfJung commented May 2, 2019

as_mut_ptr would anyway only permit non-length-changing mutations. It's a slice, after all.

@@ -359,6 +359,10 @@ impl<T> [T] {
/// The caller must ensure that the slice outlives the pointer this
/// function returns, or else it will end up pointing to garbage.
///
/// The caller must also ensure that the memory the pointer (non-transitively) points to
/// is never written to (except inside an `UnsafeCell`). If you need to mutate
Copy link
Contributor

Choose a reason for hiding this comment

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

Unsure if this qualifies as too pedantic or not, but "is never written to" sounds like it'd include the time after you stop using this pointer and any (raw?) reborrows thereof, the same way that (iiuc) constructing a Pin must guarantee the underlying value is never moved again for the rest of the program including after the Pin itself goes away.

Would "is never written to using this pointer" be better, or wrong in other ways?

Copy link
Member Author

Choose a reason for hiding this comment

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

Would "is never written to using this pointer" be better, or wrong in other ways?

"using this pointer or any pointer derived from it" would be correct and should cover your case?

@cuviper
Copy link
Member

cuviper commented May 2, 2019

as_mut_ptr would anyway only permit non-length-changing mutations.

OK... but I expect the most common reason to want *mut c_char is for FFI to write something there, and I doubt that length-preserving would usually be guaranteed. This seems like a giant footgun.

@RalfJung
Copy link
Member Author

RalfJung commented May 2, 2019

How would anyone ever think they can perform length-changing changes in-place? (And the fact that this is in-place should be quite clear with a slice.)

But anyway, this PR does not even propose to add an as_mut_ptr, so I guess we're good?

@cuviper
Copy link
Member

cuviper commented May 2, 2019

You asked if you should add as_mut_ptr, so I guess I'm saying "no". :)

@RalfJung
Copy link
Member Author

RalfJung commented May 3, 2019

Fair. :)

@RalfJung
Copy link
Member Author

Cc @rust-lang/libs -- needs someone to review.

@SimonSapin
Copy link
Contributor

It feels sort of bad to say “don’t do this” in the CStr case without providing an alternative like in other cases. Especially since a typical use case might be to interact with an existing C library whose API cannot easily be changed.

@RalfJung
Copy link
Member Author

Well, this PR just documents the already existing reality. ;)

So are you saying we should also have CStr::as_mut_ptr, but with the requirement that whoever writes to this must not insert interior NULL bytes or break the UTF-8?

@SimonSapin
Copy link
Contributor

(CStr doesn’t have str’s UTF-8 invariant, as shown by CStr::to_str returning a Result.)

Documenting the existing reality sounds good, I just wonder how often this is misused in the wild. Maybe someone more familar with C API conventions can comment: how uncommon is it to write to a caller-allocated, null-terminated buffer?

In the mean time:

@bors r+

@bors
Copy link
Contributor

bors commented May 14, 2019

📌 Commit 30cf0e4 has been approved by SimonSapin

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 14, 2019
Centril added a commit to Centril/rust that referenced this pull request May 14, 2019
as_ptr returns a read-only pointer

Add comments to `as_ptr` methods to warn that these are read-only pointers, and writing to them is UB.

[It was pointed out](https://internals.rust-lang.org/t/as-ptr-vs-as-mut-ptr/9940) that `CStr` does not even have an `as_mut_ptr`. I originally was going to add one, but there is no method at all that would mutate a `CStr`. Was that a deliberate choice or should I add an `as_mut_ptr` (similar to [what I did for `str`](rust-lang#58200))?
bors added a commit that referenced this pull request May 14, 2019
Rollup of 9 pull requests

Successful merges:

 - #60130 (Add implementations of last in terms of next_back on a bunch of DoubleEndedIterators)
 - #60443 (as_ptr returns a read-only pointer)
 - #60444 (forego caching for all participants in cycles, apart from root node)
 - #60719 (Allow subdirectories to be tested by x.py test)
 - #60780 (fix Miri)
 - #60788 (default to $ARCH-apple-macosx10.7.0 LLVM triple for darwin targets)
 - #60799 (Allow late-bound regions in existential types)
 - #60808 (Improve the "must use" lint for `Future`)
 - #60819 (submodules: update clippy from 3710ec5 to ad3269c)

Failed merges:

r? @ghost
@bors bors merged commit 30cf0e4 into rust-lang:master May 14, 2019
@RalfJung RalfJung deleted the as_ptr branch June 10, 2019 11:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants