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

CFI: Fix encode_region: unexpected ReEarlyBound(0, 'a) #111851

Merged
merged 1 commit into from
May 23, 2023

Conversation

rcvalle
Copy link
Member

@rcvalle rcvalle commented May 22, 2023

Fixes #111515 and complements #106547 by adding support for encoding early bound regions and also excluding projections when transforming trait objects' traits into their identities before emitting type checks.

@rustbot
Copy link
Collaborator

rustbot commented May 22, 2023

r? @b-naber

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

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 22, 2023
@rcvalle
Copy link
Member Author

rcvalle commented May 22, 2023

r? @bjorn3

@rustbot rustbot assigned bjorn3 and unassigned b-naber May 22, 2023
@rcvalle rcvalle added the PG-exploit-mitigations Project group: Exploit mitigations label May 22, 2023
@rcvalle rcvalle changed the title CFI: Fix encode_region: unexpected ReEarlyBound(0, 'a) #111515 CFI: Fix encode_region: unexpected ReEarlyBound(0, 'a) May 22, 2023
@rcvalle rcvalle force-pushed the rust-cfi-fix-111515 branch 3 times, most recently from d4a3915 to 03df1cc Compare May 22, 2023 23:25
@rust-log-analyzer

This comment has been minimized.

@rcvalle rcvalle force-pushed the rust-cfi-fix-111515 branch from 03df1cc to 1a40c78 Compare May 23, 2023 04:14
@rust-log-analyzer

This comment has been minimized.

Fixes rust-lang#111515 and complements rust-lang#106547 by adding support for encoding
early bound regions and also excluding projections when transforming
trait objects' traits into their identities before emitting type checks.
@rcvalle rcvalle force-pushed the rust-cfi-fix-111515 branch from 1a40c78 to 9bbdfea Compare May 23, 2023 16:44
@bjorn3
Copy link
Member

bjorn3 commented May 23, 2023

@bors r+

@bors
Copy link
Contributor

bors commented May 23, 2023

📌 Commit 9bbdfea has been approved by bjorn3

It is now in the queue for this repository.

@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 23, 2023
bors added a commit to rust-lang-ci/rust that referenced this pull request May 23, 2023
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#111427 ([rustdoc][JSON] Use exclusively externally tagged enums in the JSON representation)
 - rust-lang#111486 (Pretty-print inherent projections correctly)
 - rust-lang#111722 (Document stack-protector option)
 - rust-lang#111761 (fix(resolve): not defined `extern crate shadow_name`)
 - rust-lang#111845 (Update books)
 - rust-lang#111851 (CFI: Fix encode_region: unexpected ReEarlyBound(0, 'a))
 - rust-lang#111871 (Migrate GUI colors test to original CSS color format)

r? `@ghost`
`@rustbot` modify labels: rollup
@@ -272,12 +272,11 @@ fn encode_region<'tcx>(
s.push('E');
compress(dict, DictKey::Region(region), &mut s);
}
RegionKind::ReErased => {
RegionKind::ReEarlyBound(..) | RegionKind::ReErased => {
Copy link
Member

@compiler-errors compiler-errors May 23, 2023

Choose a reason for hiding this comment

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

Why are we not just erasing regions somewhere up the callstack? I don't think we should be handing early-bound vars here.

Copy link
Member Author

Choose a reason for hiding this comment

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

See below.

@@ -704,14 +703,15 @@ fn transform_predicates<'tcx>(
) -> &'tcx List<ty::PolyExistentialPredicate<'tcx>> {
let predicates: Vec<ty::PolyExistentialPredicate<'tcx>> = predicates
.iter()
.map(|predicate| match predicate.skip_binder() {
.filter_map(|predicate| match predicate.skip_binder() {
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated, but why are we erasing projection predicates here? Those distinguish object types in a meaningful way?

Copy link
Member Author

Choose a reason for hiding this comment

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

The reason for this is when transforming the concrete self into a reference to a trait object before emitting type metadata identifiers for trait methods (in typeid_for_instance, called in predefine_fn), the trait resolved from the method is the identity trait (i.e., early bound), and this is also necessary for trait objects with generic type parameters (see Trait3 in tests).

Unless there is a way to bind the traits at that time, we'll need to work with identity traits (i.e., early bound, and that is the reason why predicates are excluded from the encoding) and add support for encoding early bound types both when emitting type metadata identifiers for trait methods and when emitting type checks.

It's okay to work with early bound types for CFI since we're not encoding/mangling names for linking. (Surely it'd be better if we could bind those traits when doing the method to trait resolution in typeid_for_instance so we'd get better granularity, but I haven't found a way to do that.)

Copy link
Member

@compiler-errors compiler-errors May 23, 2023

Choose a reason for hiding this comment

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

I'm sorry, I'm not really sure if I follow.

What I mean is that you should be passing this trait ref through tcx.erase_regions:

if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id.unwrap()) {

Copy link
Member

Choose a reason for hiding this comment

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

what is an "identity trait" I have never heard this terminology before.

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 you mind providing more information? I think that for CFI we want to know and encode that there was an (erased) region there so trait methods are properly grouped together.

Copy link
Member Author

Choose a reason for hiding this comment

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

what is an "identity trait" I have never heard this terminology before.

The trait (reference) returned by https://doc.rust-lang.org/beta/nightly-rustc/rustc_middle/ty/struct.TraitRef.html#method.identity (which is early bound). (I'm not sure if identity trait is the actual correct name/terminology, but I've been using that to refer to it.)

Copy link
Member

Choose a reason for hiding this comment

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

Why are you using the trait ref without substituting it?

existential_predicate.skip_binder(),

This seems like it's accidentally throwing away the substs that are carried by the instance:

https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Instance.html#structfield.substs

Copy link
Member Author

Choose a reason for hiding this comment

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

It's intentional--but probably due to my lack of understanding--for grouping trait methods together for CFI. It's currently grouping methods per trait identity (i.e., early bound), but it surely would be better to group them per trait implementation and specialization (i.e., bound).

However, the instance has a concrete self (i.e., it was monomorphized already), and I'm transforming the concrete self into a reference to a trait object (for grouping trait methods together for CFI) by doing the method to trait resolution in typeid_for_instance. Are the subts from the instance there, the substs expected by the trait identity resolved from the method to trait resolution also there?

Copy link
Member Author

Choose a reason for hiding this comment

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

Even though this was merged, lets continue the discussion because I'm interested in finding out a way to group trait methods more granularly, and if the substs from the monomorphized instance can be used in the trait ref returned from the method to trait resolution that would be great--and I can follow up with a PR to increase the granularity for trait objects using that.

@bors bors merged commit 20b6e5a into rust-lang:master May 23, 2023
@rustbot rustbot added this to the 1.71.0 milestone May 23, 2023
@rcvalle rcvalle deleted the rust-cfi-fix-111515 branch April 22, 2024 23:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
PG-exploit-mitigations Project group: Exploit mitigations S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ice: cfi: encode_region: unexpected ReEarlyBound(0, 'a)
8 participants