Make helper functions freestanding

This commit is contained in:
Aaron Hill 2020-10-04 08:00:26 -04:00
parent 5fc5490bc8
commit 462f58298a
No known key found for this signature in database
GPG Key ID: B4087E510E98B164
2 changed files with 31 additions and 30 deletions

View File

@ -60,20 +60,36 @@ fn convert_path_separator<'a>(
};
}
#[cfg(unix)]
pub fn os_str_to_bytes<'a, 'tcx>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
Ok(os_str.as_bytes())
}
#[cfg(not(unix))]
pub fn os_str_to_bytes<'a, 'tcx>(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())
}
#[cfg(unix)]
pub fn bytes_to_os_str<'a, 'tcx>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
Ok(OsStr::from_bytes(bytes))
}
#[cfg(not(unix))]
pub fn bytes_to_os_str<'a, 'tcx>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
let s = std::str::from_utf8(bytes)
.map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
Ok(OsStr::new(s))
}
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
#[cfg(unix)]
fn bytes_to_os_str<'a>(&self, bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
Ok(OsStr::from_bytes(bytes))
}
#[cfg(not(unix))]
fn bytes_to_os_str<'a>(&self, bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
let s = std::str::from_utf8(bytes)
.map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
Ok(OsStr::new(s))
}
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
/// the Unix APIs usually handle.
fn read_os_str_from_c_str<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, &'a OsStr>
@ -83,7 +99,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
{
let this = self.eval_context_ref();
let bytes = this.memory.read_c_str(scalar)?;
self.bytes_to_os_str(bytes)
bytes_to_os_str(bytes)
}
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
@ -108,22 +124,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
u16vec_to_osstring(u16_vec)
}
#[cfg(unix)]
fn os_str_to_bytes<'a>(&self, os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
Ok(os_str.as_bytes())
}
#[cfg(not(unix))]
fn os_str_to_bytes<'a>(&self, 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())
}
/// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
/// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
/// to write if `size` is not large enough to fit the contents of `os_string` plus a null
@ -136,7 +136,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
size: u64,
) -> InterpResult<'tcx, (bool, u64)> {
let bytes = self.os_str_to_bytes(os_str)?;
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();
@ -269,3 +269,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
this.write_os_str_to_wide_str(&os_str, scalar, size)
}
}

View File

@ -1371,7 +1371,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
let result = std::fs::read_link(pathname);
match result {
Ok(resolved) => {
let mut path_bytes = this.os_str_to_bytes(resolved.as_ref())?;
let mut path_bytes = crate::shims::os_str::os_str_to_bytes(resolved.as_ref())?;
let bufsize: usize = bufsize.try_into().unwrap();
if path_bytes.len() > bufsize {
path_bytes = &path_bytes[..bufsize]