Skip to content

Commit ff96178

Browse files
authored
Rollup merge of #69326 - JOE1994:os_str_widestring, r=RalfJung
mir-interpret: add method to read wide strings from Memory Implemented *step2* from [instructions](rust-lang/miri#707 (comment)) laid out in rust-lang/miri#707. Added 2 new methods to struct `rustc_mir::interpret::InterpCx`. * `read_os_str_from_wide_str` (src/librustc_mir/interpret/operand.rs) * `write_os_str_to_wide_str` (src/librustc_mir/interpret/place.rs) - used existing logic implemented in [MIRI/src/eval.rs](https://github.com/rust-lang/miri/blob/94732aaf7bf79fd01a4a48d11155c6586b937514/src/eval.rs#L132-L141) These methods are intended to be used for environment variable emulation in Windows.
2 parents 85241b5 + 05f6482 commit ff96178

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/librustc/mir/interpret/value.rs

+10
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,11 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
612612
self.not_undef()?.to_u8()
613613
}
614614

615+
#[inline(always)]
616+
pub fn to_u16(self) -> InterpResult<'tcx, u16> {
617+
self.not_undef()?.to_u16()
618+
}
619+
615620
#[inline(always)]
616621
pub fn to_u32(self) -> InterpResult<'tcx, u32> {
617622
self.not_undef()?.to_u32()
@@ -632,6 +637,11 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
632637
self.not_undef()?.to_i8()
633638
}
634639

640+
#[inline(always)]
641+
pub fn to_i16(self) -> InterpResult<'tcx, i16> {
642+
self.not_undef()?.to_i16()
643+
}
644+
635645
#[inline(always)]
636646
pub fn to_i32(self) -> InterpResult<'tcx, i32> {
637647
self.not_undef()?.to_i32()

src/librustc_mir/interpret/memory.rs

+27
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
798798
self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr)
799799
}
800800

801+
/// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec<u16>.
802+
/// Terminator 0x0000 is not included in the returned Vec<u16>.
803+
///
804+
/// Performs appropriate bounds checks.
805+
pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, Vec<u16>> {
806+
let size_2bytes = Size::from_bytes(2);
807+
let align_2bytes = Align::from_bytes(2).unwrap();
808+
// We need to read at least 2 bytes, so we *need* a ptr.
809+
let mut ptr = self.force_ptr(ptr)?;
810+
let allocation = self.get_raw(ptr.alloc_id)?;
811+
let mut u16_seq = Vec::new();
812+
813+
loop {
814+
ptr = self
815+
.check_ptr_access(ptr.into(), size_2bytes, align_2bytes)?
816+
.expect("cannot be a ZST");
817+
let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?;
818+
if single_u16 != 0x0000 {
819+
u16_seq.push(single_u16);
820+
ptr = ptr.offset(size_2bytes, self)?;
821+
} else {
822+
break;
823+
}
824+
}
825+
Ok(u16_seq)
826+
}
827+
801828
/// Writes the given stream of bytes into memory.
802829
///
803830
/// Performs appropriate bounds checks.

0 commit comments

Comments
 (0)