- os_str: &OsStr,
- scalar: Scalar<Tag>,
- size: u64,
- ) -> InterpResult<'tcx, (bool, u64)> {
- #[cfg(unix)]
- fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
- Ok(std::os::unix::ffi::OsStrExt::as_bytes(os_str))
- }
- #[cfg(not(unix))]
- fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
- // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
- // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
- // valid.
- os_str
- .to_str()
- .map(|s| s.as_bytes())
- .ok_or_else(|| err_unsup_format!("{:?} is not a valid utf-8 string", os_str).into())
- }
-
- let bytes = os_str_to_bytes(os_str)?;
- // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
- // terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
- let string_length = u64::try_from(bytes.len()).unwrap();
- if size <= string_length {
- return Ok((false, string_length));
- }
- self.eval_context_mut()
- .memory
- .write_bytes(scalar, bytes.iter().copied().chain(iter::once(0u8)))?;
- Ok((true, string_length))
+ op: OpTy<'tcx, Tag>,
+ offset: u64,
+ value: impl Into<ScalarMaybeUninit<Tag>>,
+ layout: TyAndLayout<'tcx>,
+ ) -> InterpResult<'tcx, ()> {
+ let this = self.eval_context_mut();
+ let op_place = this.deref_operand(op)?;
+ let offset = Size::from_bytes(offset);
+ // Ensure that the following read at an offset is within bounds
+ assert!(op_place.layout.size >= offset + layout.size);
+ let value_place = op_place.offset(offset, MemPlaceMeta::None, layout, this)?;
+ this.write_scalar(value, value_place.into())