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

Prevent String::retain from creating non-utf8 strings when abusing panic #78499

Merged
merged 2 commits into from
Oct 30, 2020

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
Collaborator

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
Contributor

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