Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new API to read wide_strings from Memory (for Windows) #66470

Closed
wants to merge 12 commits into from
29 changes: 29 additions & 0 deletions src/librustc/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,35 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
})
}

/// Reads bytes until a `0x0000` is encountered. Will error if the end of the allocation
/// is reached before a `0x0000` is found.
///
/// Most likely, you want to call `Memory::read_wide_str` instead of this method.
pub fn read_wide_str(
&self,
cx: &impl HasDataLayout,
ptr : Pointer<Tag>
) -> InterpResult<'tcx, &[u8]>
{
assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
let offset = ptr.offset.bytes() as usize;
// The iterator below yields pairs of adjacent bytes, in order to find 0x0000.
Ok(match
self.bytes[offset..].iter().step_by(2)
.zip(self.bytes[(offset+1)..].iter().step_by(2))
JOE1994 marked this conversation as resolved.
Show resolved Hide resolved
.position(|(&l, &r)| l == 0 && r == 0) {
Some(size) => {
let size_with_null = Size::from_bytes((size + 2) as u64);
// Go through `get_bytes` for checks and AllocationExtra hooks.
// We read the null, so we include it in the request, but we want it removed
// from the result, so we do subslicing.
&self.get_bytes(cx, ptr, size_with_null)?[..size]
}
// This includes the case where `offset` is out-of-bounds to begin with.
None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
})
}

/// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
/// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the
/// given range contains neither relocations nor undef bytes.
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_mir/interpret/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,6 +792,15 @@ 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 sequence of bytes from memory. Returns them as a slice.
/// Needed for reading wide-strings in Windows-OS
///
/// Performs appropriate bounds checks.
pub fn read_wide_str(&self, ptr: Scalar<M::PointerTag>) -> InterpResult<'tcx, &[u8]> {
let ptr = self.force_ptr(ptr)?; // We need to read at least 1 byte, so we *need* a ptr.
self.get_raw(ptr.alloc_id)?.read_wide_str(self, ptr)
}

/// Writes the given stream of bytes into memory.
///
/// Performs appropriate bounds checks.
Expand Down