about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBen Kimock <kimockb@gmail.com>2024-04-27 14:55:39 -0400
committerBen Kimock <kimockb@gmail.com>2024-04-28 11:09:29 -0400
commit622f697f5dbb1489eb568638fd3f07a477a51958 (patch)
tree473b0bed971cd6783eace5ae15d77c14ce923653
parent45d93945ad031b18cb723e8d4c65aa717366dd57 (diff)
downloadrust-622f697f5dbb1489eb568638fd3f07a477a51958.tar.gz
rust-622f697f5dbb1489eb568638fd3f07a477a51958.zip
Use the interpreted program's TZ variable in localtime_r
-rw-r--r--src/tools/miri/Cargo.lock201
-rw-r--r--src/tools/miri/Cargo.toml3
-rw-r--r--src/tools/miri/src/shims/env.rs15
-rw-r--r--src/tools/miri/src/shims/time.rs26
-rw-r--r--src/tools/miri/src/shims/unix/env.rs21
-rw-r--r--src/tools/miri/src/shims/windows/env.rs9
6 files changed, 137 insertions, 138 deletions
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 293b937a5e5..3a282e89312 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -38,21 +38,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[package]]
-name = "android_system_properties"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
-dependencies = [
- "libc",
-]
-
-[[package]]
 name = "annotate-snippets"
 version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -122,12 +107,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "bumpalo"
-version = "3.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
-
-[[package]]
 name = "camino"
 version = "1.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -177,10 +156,29 @@ version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
 dependencies = [
- "android-tzdata",
- "iana-time-zone",
  "num-traits",
- "windows-targets 0.52.3",
+]
+
+[[package]]
+name = "chrono-tz"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb"
+dependencies = [
+ "chrono",
+ "chrono-tz-build",
+ "phf",
+]
+
+[[package]]
+name = "chrono-tz-build"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1"
+dependencies = [
+ "parse-zoneinfo",
+ "phf",
+ "phf_codegen",
 ]
 
 [[package]]
@@ -250,12 +248,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "core-foundation-sys"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
-
-[[package]]
 name = "cpufeatures"
 version = "0.2.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -380,29 +372,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
-name = "iana-time-zone"
-version = "0.1.60"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
-dependencies = [
- "android_system_properties",
- "core-foundation-sys",
- "iana-time-zone-haiku",
- "js-sys",
- "wasm-bindgen",
- "windows-core",
-]
-
-[[package]]
-name = "iana-time-zone-haiku"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
-dependencies = [
- "cc",
-]
-
-[[package]]
 name = "indenter"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -456,15 +425,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "js-sys"
-version = "0.3.69"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
-dependencies = [
- "wasm-bindgen",
-]
-
-[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -587,6 +547,7 @@ version = "0.1.0"
 dependencies = [
  "aes",
  "chrono",
+ "chrono-tz",
  "colored",
  "ctrlc",
  "directories",
@@ -691,6 +652,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "parse-zoneinfo"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41"
+dependencies = [
+ "regex",
+]
+
+[[package]]
 name = "perf-event-open-sys"
 version = "3.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -700,6 +670,44 @@ dependencies = [
 ]
 
 [[package]]
+name = "phf"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
+dependencies = [
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_codegen"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
+[[package]]
+name = "phf_generator"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
+dependencies = [
+ "phf_shared",
+ "rand",
+]
+
+[[package]]
+name = "phf_shared"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -932,6 +940,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "siphasher"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
+
+[[package]]
 name = "smallvec"
 version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1095,60 +1109,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
-name = "wasm-bindgen"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
-dependencies = [
- "cfg-if",
- "wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
-dependencies = [
- "bumpalo",
- "log",
- "once_cell",
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-macro"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
-dependencies = [
- "quote",
- "wasm-bindgen-macro-support",
-]
-
-[[package]]
-name = "wasm-bindgen-macro-support"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "wasm-bindgen-backend",
- "wasm-bindgen-shared",
-]
-
-[[package]]
-name = "wasm-bindgen-shared"
-version = "0.2.92"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
-
-[[package]]
 name = "winapi"
 version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1171,15 +1131,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
-name = "windows-core"
-version = "0.52.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
-dependencies = [
- "windows-targets 0.52.3",
-]
-
-[[package]]
 name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index b00dae784d2..de7a6de9e3e 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -24,7 +24,8 @@ smallvec = "1.7"
 aes = { version = "0.8.3", features = ["hazmat"] }
 measureme = "11"
 ctrlc = "3.2.5"
-chrono = { version = "0.4.38", default-features = false, features = ["clock"] }
+chrono = { version = "0.4.38", default-features = false }
+chrono-tz = "0.9"
 directories = "5"
 
 # Copied from `compiler/rustc/Cargo.toml`.
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index fc0160fdf21..395a1ca62c6 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -1,4 +1,4 @@
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 
 use rustc_data_structures::fx::FxHashMap;
 
@@ -99,4 +99,15 @@ impl<'tcx> EnvVars<'tcx> {
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
-pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {}
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
+    /// Try to get an environment variable from the interpreted program's environment. This is
+    /// useful for implementing shims which are documented to read from the environment.
+    fn get_var(&mut self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>> {
+        let this = self.eval_context_ref();
+        match &this.machine.env_vars {
+            EnvVars::Uninit => return Ok(None),
+            EnvVars::Unix(vars) => vars.get(this, name),
+            EnvVars::Windows(vars) => vars.get(name),
+        }
+    }
+}
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index dfdf58470d6..05dbdef1ba1 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -1,8 +1,10 @@
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::fmt::Write;
+use std::str::FromStr;
 use std::time::{Duration, SystemTime};
 
-use chrono::{DateTime, Datelike, Local, Timelike, Utc};
+use chrono::{DateTime, Datelike, Offset, Timelike, Utc};
+use chrono_tz::Tz;
 
 use crate::concurrency::thread::MachineCallback;
 use crate::*;
@@ -136,8 +138,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             .unwrap();
         let dt_utc: DateTime<Utc> =
             DateTime::from_timestamp(sec_since_epoch, 0).expect("Invalid timestamp");
+
+        // Figure out what time zone is in use
+        let tz = this.get_var(OsStr::new("TZ"))?.unwrap_or_else(|| OsString::from("UTC"));
+        let tz = match tz.into_string() {
+            Ok(tz) => Tz::from_str(&tz).unwrap_or(Tz::UTC),
+            _ => Tz::UTC,
+        };
+
         // Convert that to local time, then return the broken-down time value.
-        let dt: DateTime<Local> = DateTime::from(dt_utc);
+        let dt: DateTime<Tz> = dt_utc.with_timezone(&tz);
 
         // This value is always set to -1, because there is no way to know if dst is in effect with
         // chrono crate yet.
@@ -146,17 +156,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // tm_zone represents the timezone value in the form of: +0730, +08, -0730 or -08.
         // This may not be consistent with libc::localtime_r's result.
-        let offset_in_second = Local::now().offset().local_minus_utc();
-        let tm_gmtoff = offset_in_second;
+        let offset_in_seconds = dt.offset().fix().local_minus_utc();
+        let tm_gmtoff = offset_in_seconds;
         let mut tm_zone = String::new();
-        if offset_in_second < 0 {
+        if offset_in_seconds < 0 {
             tm_zone.push('-');
         } else {
             tm_zone.push('+');
         }
-        let offset_hour = offset_in_second.abs() / 3600;
+        let offset_hour = offset_in_seconds.abs() / 3600;
         write!(tm_zone, "{:02}", offset_hour).unwrap();
-        let offset_min = (offset_in_second.abs() % 3600) / 60;
+        let offset_min = (offset_in_seconds.abs() % 3600) / 60;
         if offset_min != 0 {
             write!(tm_zone, "{:02}", offset_min).unwrap();
         }
diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs
index 128f0dcafa9..f61a81b07cb 100644
--- a/src/tools/miri/src/shims/unix/env.rs
+++ b/src/tools/miri/src/shims/unix/env.rs
@@ -70,6 +70,27 @@ impl<'tcx> UnixEnvVars<'tcx> {
     pub(crate) fn environ(&self) -> Pointer<Option<Provenance>> {
         self.environ.ptr()
     }
+
+    /// Implementation detail for [`InterpCx::get_var`]. This basically does `getenv`, complete
+    /// with the reads of the environment, but returns an [`OsString`] instead of a pointer.
+    pub(crate) fn get<'mir>(
+        &self,
+        ecx: &InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>,
+        name: &OsStr,
+    ) -> InterpResult<'tcx, Option<OsString>> {
+        // We don't care about the value as we have the `map` to keep track of everything,
+        // but we do want to do this read so it shows up as a data race.
+        let _vars_ptr = ecx.read_pointer(&self.environ)?;
+        let Some(var_ptr) = self.map.get(name) else {
+            return Ok(None);
+        };
+        // The offset is used to strip the "{name}=" part of the string.
+        let var_ptr = var_ptr.offset(
+            Size::from_bytes(u64::try_from(name.len()).unwrap().checked_add(1).unwrap()),
+            ecx,
+        )?;
+        ecx.read_os_str_from_c_str(var_ptr).map(|s| Some(s.to_owned()))
+    }
 }
 
 fn alloc_env_var<'mir, 'tcx>(
diff --git a/src/tools/miri/src/shims/windows/env.rs b/src/tools/miri/src/shims/windows/env.rs
index e91623ac871..a8b0a77b23b 100644
--- a/src/tools/miri/src/shims/windows/env.rs
+++ b/src/tools/miri/src/shims/windows/env.rs
@@ -1,5 +1,5 @@
 use std::env;
-use std::ffi::OsString;
+use std::ffi::{OsStr, OsString};
 use std::io::ErrorKind;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -9,7 +9,7 @@ use helpers::windows_check_buffer_size;
 
 #[derive(Default)]
 pub struct WindowsEnvVars {
-    /// Stores the environment varialbles.
+    /// Stores the environment variables.
     map: FxHashMap<OsString, OsString>,
 }
 
@@ -26,6 +26,11 @@ impl WindowsEnvVars {
     ) -> InterpResult<'tcx, Self> {
         Ok(Self { map: env_vars })
     }
+
+    /// Implementation detail for [`InterpCx::get_var`].
+    pub(crate) fn get<'tcx>(&self, name: &OsStr) -> InterpResult<'tcx, Option<OsString>> {
+        Ok(self.map.get(name).cloned())
+    }
 }
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}