Skip to content

Commit

Permalink
Improve timezone handling in 'localtime_r()' using 'allocate_bytes()'
Browse files Browse the repository at this point in the history
Signed-off-by: shamb0 <[email protected]>
  • Loading branch information
shamb0 committed Dec 4, 2024
1 parent 6f0a78a commit 2925226
Showing 1 changed file with 11 additions and 17 deletions.
28 changes: 11 additions & 17 deletions src/shims/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
if !matches!(&*this.tcx.sess.target.os, "solaris" | "illumos") {
// 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.
const TZ_MAX_LEN: u64 = 6; // 5 chars max + null terminator
static TIMEZONE_PTR: OnceLock<Pointer> = OnceLock::new();

let offset_in_seconds = dt.offset().fix().local_minus_utc();
let tm_gmtoff = offset_in_seconds;
Expand All @@ -201,21 +199,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
write!(tm_zone, "{:02}", offset_min).unwrap();
}

// Ensure string deduplication by allocating the buffer only once,
// even if the function is called multiple times.
let tm_zone_ptr = TIMEZONE_PTR.get_or_init(|| {
let arg_type = Ty::new_array(this.tcx.tcx, this.tcx.types.u8, TZ_MAX_LEN);
let arg_place = this
.allocate(this.layout_of(arg_type).unwrap(), MiriMemoryKind::Machine.into())
.expect("timezone buffer allocation failed");
arg_place.ptr()
});

// Write the `tm_zone` string into the allocated buffer.
let (written, _) =
this.write_os_str_to_c_str(&OsString::from(tm_zone), *tm_zone_ptr, TZ_MAX_LEN)?;
assert!(written);

// Add null terminator for C string compatibility
tm_zone.push('\0');

// Deduplicate and allocate the string.
let tm_zone_ptr = this.allocate_bytes(
&tm_zone.as_bytes(),
Align::ONE,
MiriMemoryKind::Machine.into(),
Mutability::Not,
)?;

// Write the timezone pointer and offset into the result structure.
this.write_pointer(*tm_zone_ptr, &this.project_field_named(&result, "tm_zone")?)?;
this.write_int_fields_named(&[("tm_gmtoff", tm_gmtoff.into())], &result)?;
Expand Down

0 comments on commit 2925226

Please sign in to comment.