Skip to content

Conversation

SkiFire13
Copy link
Contributor

Fixes #78498

The idea is the same as Vec::drain, set the len to 0 so that nobody can observe the broken invariant if it escapes the function (in this case if f panics)

@rust-highfive
Copy link
Contributor

r? @shepmaster

(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 Oct 28, 2020
@jonas-schievink
Copy link
Contributor

Won't this result in an empty string if you do s.retain(|_| true) now?

@camelid camelid added T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Oct 28, 2020
@m-ou-se
Copy link
Member

m-ou-se commented Oct 28, 2020

Can you add a test that fails without this change, but passes with?

@jonas-schievink
Copy link
Contributor

A test for s.retain(|_| true) would also be good, since I don't think the existing tests caught that bug

@SkiFire13
Copy link
Contributor Author

Can you add a test that fails without this change, but passes with?

Done. I added it in the same function of the other tests for String::retain. Is that ok or should I make it separate?

A test for s.retain(|_| true) would also be good, since I don't think the existing tests caught that bug

There's already a test for that, which in fact initially failed in the CI. The reason I didn't catch it before opening the pull request is that I naively ran ./x.py test library/std expecting it to also test alloc, but to be fair the rustc book is pretty misleading about that.

@m-ou-se
Copy link
Member

m-ou-se commented Oct 29, 2020

Thanks!

@bors r+

@bors
Copy link
Collaborator

bors commented Oct 29, 2020

📌 Commit 1f6f917 has been approved by m-ou-se

@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 Oct 29, 2020
@m-ou-se m-ou-se assigned m-ou-se and unassigned shepmaster Oct 29, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 29, 2020
…as-schievink

Rollup of 11 pull requests

Successful merges:

 - rust-lang#75078 (Improve documentation for slice strip_* functions)
 - rust-lang#76138 (Explain fully qualified syntax for `Rc` and `Arc`)
 - rust-lang#78244 (Dogfood {exclusive,half-open} ranges in compiler (nfc))
 - rust-lang#78422 (Do not ICE on invalid input)
 - rust-lang#78423 (rustc_span: improve bounds checks in byte_pos_to_line_and_col)
 - rust-lang#78431 (Prefer new associated numeric consts in float error messages)
 - rust-lang#78462 (Use unwrapDIPtr because the Scope may be null.)
 - rust-lang#78493 (Update cargo)
 - rust-lang#78499 (Prevent String::retain from creating non-utf8 strings when abusing panic)
 - rust-lang#78505 (Update Clippy - temporary_cstring_as_ptr deprecation)
 - rust-lang#78527 (Fix some more typos)

Failed merges:

r? `@ghost`
@bors bors merged commit 48c4afb into rust-lang:master Oct 30, 2020
@rustbot rustbot added this to the 1.49.0 milestone Oct 30, 2020
@SkiFire13 SkiFire13 deleted the fix-string-retain branch October 30, 2020 08:33
Comment on lines +1238 to 1243
unsafe {
self.vec.set_len(0);
}

while idx < len {
let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap() };
Copy link
Member

Choose a reason for hiding this comment

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

@RalfJung this was brought to my attention by @DJMcNab (the author of retain_more), as somewhat suspicious - it's calling get_unchecked on a &str obtained via auto-deref which is zero-length now. So we more or less expect this needs to go through a raw pointer directly or something similar.

Copy link
Contributor Author

@SkiFire13 SkiFire13 Feb 26, 2021

Choose a reason for hiding this comment

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

Good catch! I guess another fix would be using a DropGuard for setting the length at the end of the loop. This way it's not necessary to set the length to 0 anymore because its drop implementation would called even in case of panic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've opened #82554, let me know what you think about it

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 21, 2021
…ness, r=m-ou-se

Fix invalid slice access in String::retain

As noted in rust-lang#78499, the previous fix was technically still unsound because it accessed elements of a slice outside its bounds (even though they were still inside the same allocation). This PR addresses that concern by switching to a dropguard approach.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Mar 22, 2021
…ness, r=m-ou-se

Fix invalid slice access in String::retain

As noted in rust-lang#78499, the previous fix was technically still unsound because it accessed elements of a slice outside its bounds (even though they were still inside the same allocation). This PR addresses that concern by switching to a dropguard approach.
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. T-libs Relevant to the library team, which will review and decide on the PR/issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

String::retain allows safely creating invalid (non-utf8) strings when abusing panic
9 participants