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

Integers and pointers sometimes incorrectly preserve provenance on typed copies #2182

Closed
Tracked by #2159
RalfJung opened this issue Jun 3, 2022 · 3 comments · Fixed by rust-lang/rust#129778
Closed
Tracked by #2159
Labels
A-interpreter Area: affects the core interpreter A-validation Area: This affects enforcing the validity invariant, and related UB checking C-bug Category: This is a bug. I-misses-UB Impact: makes Miri miss UB, i.e., a false negative (with default settings)

Comments

@RalfJung
Copy link
Member

RalfJung commented Jun 3, 2022

Miri currently does not properly implement what happens to provenance during a typed copy:

  • When doing a copy at integer type, provenance should be stripped. Instead, we will currently complain during validation that provenance on an integer is UB.
  • When doing a copy at pointer type, if the provenance is not the same for all bytes of a pointer, it should be stripped. Instead, we will currently just preserve it.

The best way I see to solve this is to make validation mutating, so that during validation we can adjust integer and pointer values following these rules. Mutating validation is also needed for #845.

@RalfJung
Copy link
Member Author

RalfJung commented Jun 3, 2022

Testcase for the first problem.

This should fail.

use std::mem;

fn main() {
    let ptrs = [&42];
    let ints: [usize; 1] = unsafe { mem::transmute(ptrs) };
    let ptr = ints.as_ptr().cast::<&i32>();
    let _val = unsafe { *ptr.read() }; //~ERROR
}

Testcase for the second problem.

This should fail.

fn main() { unsafe {
    let mut bytes = [1u8; 16];
    let bytes = bytes.as_mut_ptr();
    
    // Put a pointer in the middle.
    bytes.add(4).cast::<&i32>().write_unaligned(&42);
    // Copy the entire thing as two pointers but not perfectly
    // overlapping with the pointer we have in there.
    let copy = bytes.cast::<[*const (); 2]>().read_unaligned();
    let copy_bytes = copy.as_ptr().cast::<u8>();
    // Now go to the middle of the copy and get the pointer back out.
    let ptr = copy_bytes.add(4).cast::<*const i32>().read_unaligned();
    // Dereferencing this should fail as the copy has removed the provenance.
    let _val = *ptr; //~ERROR
} }

@RalfJung RalfJung added C-bug Category: This is a bug. A-validation Area: This affects enforcing the validity invariant, and related UB checking A-interpreter Area: affects the core interpreter labels Jun 5, 2022
@nia-e
Copy link
Contributor

nia-e commented Dec 11, 2022

Seems like testcase 1 currently passes but I didn't dig too deep to see why/since when; maybe this issue is worth updating for anyone coming to work on it in the future?

@RalfJung
Copy link
Member Author

RalfJung commented Dec 11, 2022

Ah right that got fixed by rust-lang/rust#104054 (or maybe even earlier).

bors added a commit that referenced this issue Dec 11, 2022
add provenance-related test

One of the cases in #2182 actually works as intended since rust-lang/rust#104054 (or maybe even earlier); make sure we test that.
@RalfJung RalfJung added the I-misses-UB Impact: makes Miri miss UB, i.e., a false negative (with default settings) label Dec 11, 2022
RalfJung pushed a commit to RalfJung/rust that referenced this issue Dec 24, 2022
add provenance-related test

One of the cases in rust-lang/miri#2182 actually works as intended since rust-lang#104054 (or maybe even earlier); make sure we test that.
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 8, 2024
…saethlin

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 9, 2024
…<try>

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182

try-job: x86_64-gnu-aux
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 9, 2024
…<try>

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182

try-job: x86_64-gnu-aux
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 9, 2024
…<try>

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182

try-job: x86_64-gnu-aux
bors added a commit to rust-lang-ci/rust that referenced this issue Sep 9, 2024
…saethlin

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 10, 2024
…r=saethlin

interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang/miri#845
Fixes rust-lang/miri#2182
RalfJung pushed a commit to RalfJung/miri that referenced this issue Sep 10, 2024
interpret: make typed copies lossy wrt provenance and padding

A "typed copy" in Rust can be a lossy process: when copying at type `usize` (or any other non-pointer type), if the original memory had any provenance, that provenance is lost. When copying at pointer type, if the original memory had partial provenance (i.e., not the same provenance for all bytes), that provenance is lost. When copying any type with padding, the contents of padding are lost.

This PR equips our validity-checking pass with the ability to reset provenance and padding according to those rules. Can be reviewed commit-by-commit. The first three commits are just preparation without any functional change.

Fixes rust-lang#845
Fixes rust-lang#2182
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-interpreter Area: affects the core interpreter A-validation Area: This affects enforcing the validity invariant, and related UB checking C-bug Category: This is a bug. I-misses-UB Impact: makes Miri miss UB, i.e., a false negative (with default settings)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants