Skip to content

Commit 0af0886

Browse files
committed
Write back to the pointer and add a test
1 parent 0e9306f commit 0af0886

File tree

3 files changed

+46
-6
lines changed

3 files changed

+46
-6
lines changed

src/shims/unix/fs.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
17381738
// Get the raw bytes from the template. This is passed to us from `std` as an `OsString`.
17391739
// These bytes represent a string in _target_ OS encoding, which may or may not match
17401740
// the _host_ OS encoding.
1741-
let template_bytes = this.eval_context_ref().read_c_str(this.read_pointer(template_op)?)?;
1741+
let template_ptr = this.read_pointer(template_op)?;
1742+
let mut template = this.eval_context_ref().read_c_str(template_ptr)?.to_owned();
1743+
let template_bytes = template.as_mut_slice();
17421744

17431745
// Reject if isolation is enabled.
17441746
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
@@ -1804,13 +1806,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
18041806
// Generate a random unique suffix.
18051807
let unique_suffix = SUBSTITUTIONS.choose_multiple(&mut rng, 6).collect::<String>();
18061808

1807-
// The passed in template encoding may or may not match the host.
1808-
let mut base = bytes_to_os_str(&template_bytes[..start_pos])?.to_os_string();
1809+
// Replace the template string with the random string.
1810+
template_bytes[start_pos..end_pos].copy_from_slice(unique_suffix.as_bytes());
1811+
1812+
// Write the modified template back to the passed in pointer to maintain POSIX semantics.
1813+
this.write_bytes_ptr(template_ptr, template_bytes.to_owned())?;
18091814

1810-
// Add the randomly generated suffix to the given static prefix.
1811-
base.push(unique_suffix);
1815+
// The passed in template encoding may or may not match the host.
1816+
let p = bytes_to_os_str(template_bytes)?.to_os_string();
18121817

1813-
let possibly_unique = std::env::temp_dir().join::<PathBuf>(base.into());
1818+
let possibly_unique = std::env::temp_dir().join::<PathBuf>(p.into());
18141819

18151820
let file = fopts.open(&possibly_unique);
18161821

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ignore-windows: No libc on Windows
2+
//@compile-flags: -Zmiri-disable-isolation
3+
4+
#![feature(rustc_private)]
5+
6+
extern crate libc;
7+
8+
fn main() {
9+
test_mkstemp_immutable_arg();
10+
}
11+
12+
fn test_mkstemp_immutable_arg() {
13+
let s: *mut libc::c_char = b"fooXXXXXX\0" as *const _ as *mut _;
14+
let _fd = unsafe { libc::mkstemp(s) }; //~ ERROR: Undefined Behavior: writing to alloc1 which is read-only
15+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: Undefined Behavior: writing to ALLOC which is read-only
2+
--> $DIR/mkstemp_immutable_arg.rs:LL:CC
3+
|
4+
LL | let _fd = unsafe { libc::mkstemp(s) };
5+
| ^^^^^^^^^^^^^^^^ writing to ALLOC which is read-only
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: backtrace:
10+
= note: inside `test_mkstemp_immutable_arg` at $DIR/mkstemp_immutable_arg.rs:LL:CC
11+
note: inside `main` at $DIR/mkstemp_immutable_arg.rs:LL:CC
12+
--> $DIR/mkstemp_immutable_arg.rs:LL:CC
13+
|
14+
LL | test_mkstemp_immutable_arg();
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
18+
19+
error: aborting due to previous error
20+

0 commit comments

Comments
 (0)