From 05f6482f435c498b19f3af56d1017c84323683f5 Mon Sep 17 00:00:00 2001 From: JOE1994 Date: Thu, 20 Feb 2020 14:29:40 -0500 Subject: [PATCH] mir-interpret: add method Memory::read wide_string --- src/librustc/mir/interpret/value.rs | 10 ++++++++++ src/librustc_mir/interpret/memory.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2be36ad418a5b..8a02f47accb5d 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -590,6 +590,11 @@ impl<'tcx, Tag> ScalarMaybeUndef { self.not_undef()?.to_u8() } + #[inline(always)] + pub fn to_u16(self) -> InterpResult<'tcx, u16> { + self.not_undef()?.to_u16() + } + #[inline(always)] pub fn to_u32(self) -> InterpResult<'tcx, u32> { self.not_undef()?.to_u32() @@ -610,6 +615,11 @@ impl<'tcx, Tag> ScalarMaybeUndef { self.not_undef()?.to_i8() } + #[inline(always)] + pub fn to_i16(self) -> InterpResult<'tcx, i16> { + self.not_undef()?.to_i16() + } + #[inline(always)] pub fn to_i32(self) -> InterpResult<'tcx, i32> { self.not_undef()?.to_i32() diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0bcdf9ae3c1f2..4b668500e7c93 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -791,6 +791,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr) } + /// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec. + /// Terminator 0x0000 is not included in the returned Vec. + /// + /// Performs appropriate bounds checks. + pub fn read_wide_str(&self, ptr: Scalar) -> InterpResult<'tcx, Vec> { + let size_2bytes = Size::from_bytes(2); + let align_2bytes = Align::from_bytes(2).unwrap(); + // We need to read at least 2 bytes, so we *need* a ptr. + let mut ptr = self.force_ptr(ptr)?; + let allocation = self.get_raw(ptr.alloc_id)?; + let mut u16_seq = Vec::new(); + + loop { + ptr = self + .check_ptr_access(ptr.into(), size_2bytes, align_2bytes)? + .expect("cannot be a ZST"); + let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?; + if single_u16 != 0x0000 { + u16_seq.push(single_u16); + ptr = ptr.offset(size_2bytes, self)?; + } else { + break; + } + } + Ok(u16_seq) + } + /// Writes the given stream of bytes into memory. /// /// Performs appropriate bounds checks.