Skip to content

Commit d6b750e

Browse files
committed
Auto merge of rust-lang#2467 - RalfJung:home, r=RalfJung
add support for env::home_dir and a bit of cleanup
2 parents 4208764 + 889c073 commit d6b750e

File tree

7 files changed

+101
-36
lines changed

7 files changed

+101
-36
lines changed

src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
clippy::useless_format,
2323
clippy::derive_partial_eq_without_eq,
2424
clippy::derive_hash_xor_eq,
25-
clippy::too_many_arguments
25+
clippy::too_many_arguments,
26+
clippy::type_complexity
2627
)]
2728
#![warn(
2829
rust_2018_idioms,

src/shims/unix/foreign_items.rs

+24-12
Original file line numberDiff line numberDiff line change
@@ -228,16 +228,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
228228
let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
229229
let name = this.read_scalar(name)?.to_i32()?;
230230

231-
let sysconfs = &[
232-
("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, this.pointer_size())),
233-
("_SC_NPROCESSORS_CONF", Scalar::from_int(NUM_CPUS, this.pointer_size())),
234-
("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, this.pointer_size())),
231+
// FIXME: Which of these are POSIX, and which are GNU/Linux?
232+
// At least the names seem to all also exist on macOS.
233+
let sysconfs: &[(&str, fn(&MiriEvalContext<'_, '_>) -> Scalar<Provenance>)] = &[
234+
("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())),
235+
("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())),
236+
("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())),
237+
// 512 seems to be a reasonable default. The value is not critical, in
238+
// the sense that getpwuid_r takes and checks the buffer length.
239+
("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size()))
235240
];
236241
let mut result = None;
237242
for &(sysconf_name, value) in sysconfs {
238243
let sysconf_name = this.eval_libc_i32(sysconf_name)?;
239244
if sysconf_name == name {
240-
result = Some(value);
245+
result = Some(value(this));
241246
break;
242247
}
243248
}
@@ -474,6 +479,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
474479
let ret = if complete { 0 } else { this.eval_libc_i32("ERANGE")? };
475480
this.write_int(ret, dest)?;
476481
}
482+
"getpid" => {
483+
let [] = this.check_shim(abi, Abi::C { unwind: false}, link_name, args)?;
484+
let result = this.getpid()?;
485+
this.write_scalar(Scalar::from_i32(result), dest)?;
486+
}
477487

478488
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
479489
// These shims are enabled only when the caller is in the standard library.
@@ -500,9 +510,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
500510
this.write_null(dest)?;
501511
}
502512

503-
// Querying system information
504-
"pthread_attr_getstack" => {
505-
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here. Hence we can mostly ignore the input `attr_place`.
513+
"pthread_attr_getstack"
514+
if this.frame_in_std() => {
515+
// We don't support "pthread_attr_setstack", so we just pretend all stacks have the same values here.
516+
// Hence we can mostly ignore the input `attr_place`.
506517
let [attr_place, addr_place, size_place] =
507518
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
508519
let _attr_place = this.deref_operand(attr_place)?;
@@ -535,10 +546,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
535546
this.write_null(dest)?;
536547
}
537548

538-
"getpid" => {
539-
let [] = this.check_shim(abi, Abi::C { unwind: false}, link_name, args)?;
540-
let result = this.getpid()?;
541-
this.write_scalar(Scalar::from_i32(result), dest)?;
549+
"getuid"
550+
if this.frame_in_std() => {
551+
let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
552+
// FOr now, just pretend we always have this fixed UID.
553+
this.write_int(super::UID, dest)?;
542554
}
543555

544556
// Platform-specific shims

src/shims/unix/fs.rs

+27-23
Original file line numberDiff line numberDiff line change
@@ -1091,31 +1091,35 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
10911091
],
10921092
&statxbuf,
10931093
)?;
1094-
this.write_int_fields(
1094+
#[rustfmt::skip]
1095+
this.write_int_fields_named(
10951096
&[
1096-
access_sec.into(), // stx_atime.tv_sec
1097-
access_nsec.into(), // stx_atime.tv_nsec
1097+
("tv_sec", access_sec.into()),
1098+
("tv_nsec", access_nsec.into()),
10981099
],
10991100
&this.mplace_field_named(&statxbuf, "stx_atime")?,
11001101
)?;
1101-
this.write_int_fields(
1102+
#[rustfmt::skip]
1103+
this.write_int_fields_named(
11021104
&[
1103-
created_sec.into(), // stx_btime.tv_sec
1104-
created_nsec.into(), // stx_btime.tv_nsec
1105+
("tv_sec", created_sec.into()),
1106+
("tv_nsec", created_nsec.into()),
11051107
],
11061108
&this.mplace_field_named(&statxbuf, "stx_btime")?,
11071109
)?;
1108-
this.write_int_fields(
1110+
#[rustfmt::skip]
1111+
this.write_int_fields_named(
11091112
&[
1110-
0.into(), // stx_ctime.tv_sec
1111-
0.into(), // stx_ctime.tv_nsec
1113+
("tv_sec", 0.into()),
1114+
("tv_nsec", 0.into()),
11121115
],
11131116
&this.mplace_field_named(&statxbuf, "stx_ctime")?,
11141117
)?;
1115-
this.write_int_fields(
1118+
#[rustfmt::skip]
1119+
this.write_int_fields_named(
11161120
&[
1117-
modified_sec.into(), // stx_mtime.tv_sec
1118-
modified_nsec.into(), // stx_mtime.tv_nsec
1121+
("tv_sec", modified_sec.into()),
1122+
("tv_nsec", modified_nsec.into()),
11191123
],
11201124
&this.mplace_field_named(&statxbuf, "stx_mtime")?,
11211125
)?;
@@ -1302,12 +1306,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
13021306

13031307
let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
13041308

1305-
this.write_int_fields(
1309+
this.write_int_fields_named(
13061310
&[
1307-
ino.into(), // d_ino
1308-
0, // d_off
1309-
size.into(), // d_reclen
1310-
file_type.into(), // d_type
1311+
("d_ino", ino.into()),
1312+
("d_off", 0),
1313+
("d_reclen", size.into()),
1314+
("d_type", file_type.into()),
13111315
],
13121316
&MPlaceTy::from_aligned_ptr(entry, dirent64_layout),
13131317
)?;
@@ -1398,13 +1402,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
13981402

13991403
let file_type = this.file_type_to_d_type(dir_entry.file_type())?;
14001404

1401-
this.write_int_fields(
1405+
this.write_int_fields_named(
14021406
&[
1403-
ino.into(), // d_ino
1404-
0, // d_seekoff
1405-
0, // d_reclen
1406-
file_name_len.into(), // d_namlen
1407-
file_type.into(), // d_type
1407+
("d_ino", ino.into()),
1408+
("d_seekoff", 0),
1409+
("d_reclen", 0),
1410+
("d_namlen", file_name_len.into()),
1411+
("d_type", file_type.into()),
14081412
],
14091413
&entry_place,
14101414
)?;

src/shims/unix/linux/foreign_items.rs

+35
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,41 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
155155
this.write_null(dest)?;
156156
}
157157

158+
"getpwuid_r" if this.frame_in_std() => {
159+
let [uid, pwd, buf, buflen, result] =
160+
this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
161+
this.check_no_isolation("`getpwuid_r`")?;
162+
163+
let uid = this.read_scalar(uid)?.to_u32()?;
164+
let pwd = this.deref_operand(pwd)?;
165+
let buf = this.read_pointer(buf)?;
166+
let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?;
167+
let result = this.deref_operand(result)?;
168+
169+
// Must be for "us".
170+
if uid != crate::shims::unix::UID {
171+
throw_unsup_format!("`getpwuid_r` on other users is not supported");
172+
}
173+
174+
// Reset all fields to `uninit` to make sure nobody reads them.
175+
this.write_uninit(&pwd.into())?;
176+
177+
// We only set the home_dir field.
178+
#[allow(deprecated)]
179+
let home_dir = std::env::home_dir().unwrap();
180+
let (written, _) = this.write_path_to_c_str(&home_dir, buf, buflen)?;
181+
let pw_dir = this.mplace_field_named(&pwd, "pw_dir")?;
182+
this.write_pointer(buf, &pw_dir.into())?;
183+
184+
if written {
185+
this.write_pointer(pwd.ptr, &result.into())?;
186+
this.write_null(dest)?;
187+
} else {
188+
this.write_null(&result.into())?;
189+
this.write_scalar(this.eval_libc("ERANGE")?, dest)?;
190+
}
191+
}
192+
158193
_ => return Ok(EmulateByNameResult::NotSupported),
159194
};
160195

src/shims/unix/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,6 @@ mod linux;
1010
mod macos;
1111

1212
pub use fs::{DirHandler, FileHandler};
13+
14+
// Make up some constants.
15+
const UID: u32 = 1000;

src/shims/windows/foreign_items.rs

+1
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
110110

111111
// Querying system information
112112
"GetSystemInfo" => {
113+
// Also called from `page_size` crate.
113114
let [system_info] =
114115
this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
115116
let system_info = this.deref_operand(system_info)?;

tests/pass/home.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
//@only-target-linux: home_dir is only supported on Linux
2+
//@compile-flags: -Zmiri-disable-isolation
3+
use std::env;
4+
5+
fn main() {
6+
env::remove_var("HOME"); // make sure we enter the interesting codepath
7+
#[allow(deprecated)]
8+
env::home_dir().unwrap();
9+
}

0 commit comments

Comments
 (0)