mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Clone the reader to prevent cursor misplacement in ReadCString
This commit is contained in:
parent
f4e79d99d0
commit
1846c680fc
@ -204,13 +204,15 @@ impl ReadCString for VmReader<'_, Fallible> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Handle the rest of the bytes in bulk
|
// Handle the rest of the bytes in bulk
|
||||||
|
let mut cloned_reader = self.clone();
|
||||||
while (buffer.len() + mem::size_of::<usize>()) <= max_len {
|
while (buffer.len() + mem::size_of::<usize>()) <= max_len {
|
||||||
let Ok(word) = self.read_val::<usize>() else {
|
let Ok(word) = cloned_reader.read_val::<usize>() else {
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
if has_zero(word) {
|
if has_zero(word) {
|
||||||
for byte in word.to_ne_bytes() {
|
for byte in word.to_ne_bytes() {
|
||||||
|
self.skip(1);
|
||||||
buffer.push(byte);
|
buffer.push(byte);
|
||||||
if byte == 0 {
|
if byte == 0 {
|
||||||
return Ok(CString::from_vec_with_nul(buffer)
|
return Ok(CString::from_vec_with_nul(buffer)
|
||||||
@ -220,6 +222,7 @@ impl ReadCString for VmReader<'_, Fallible> {
|
|||||||
unreachable!("The branch should never be reached unless `has_zero` has bugs.")
|
unreachable!("The branch should never be reached unless `has_zero` has bugs.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.skip(size_of::<usize>());
|
||||||
buffer.extend_from_slice(&word.to_ne_bytes());
|
buffer.extend_from_slice(&word.to_ne_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,3 +270,29 @@ fn check_vaddr(va: Vaddr) -> Result<()> {
|
|||||||
const fn is_addr_aligned(addr: usize) -> bool {
|
const fn is_addr_aligned(addr: usize) -> bool {
|
||||||
(addr & (mem::size_of::<usize>() - 1)) == 0
|
(addr & (mem::size_of::<usize>() - 1)) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(ktest)]
|
||||||
|
mod test {
|
||||||
|
use ostd::prelude::*;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[ktest]
|
||||||
|
fn read_multiple_cstring() {
|
||||||
|
let mut buffer = vec![0u8; 100];
|
||||||
|
|
||||||
|
let str1 = CString::new("hello").unwrap();
|
||||||
|
let str2 = CString::new("world!").unwrap();
|
||||||
|
|
||||||
|
let mut writer = VmWriter::from(buffer.as_mut_slice());
|
||||||
|
writer.write(&mut VmReader::from(str1.as_bytes_with_nul()));
|
||||||
|
writer.write(&mut VmReader::from(str2.as_bytes_with_nul()));
|
||||||
|
drop(writer);
|
||||||
|
|
||||||
|
let mut reader = VmReader::from(buffer.as_slice()).to_fallible();
|
||||||
|
let read_str1 = reader.read_cstring().unwrap();
|
||||||
|
assert_eq!(read_str1, str1);
|
||||||
|
let read_str2 = reader.read_cstring().unwrap();
|
||||||
|
assert_eq!(read_str2, str2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -275,12 +275,13 @@ impl_vm_io_once_pointer!(&mut T, "(**self)");
|
|||||||
impl_vm_io_once_pointer!(Box<T>, "(**self)");
|
impl_vm_io_once_pointer!(Box<T>, "(**self)");
|
||||||
impl_vm_io_once_pointer!(Arc<T>, "(**self)");
|
impl_vm_io_once_pointer!(Arc<T>, "(**self)");
|
||||||
|
|
||||||
/// A marker structure used for [`VmReader`] and [`VmWriter`],
|
/// A marker type used for [`VmReader`] and [`VmWriter`],
|
||||||
/// representing whether reads or writes on the underlying memory region are fallible.
|
/// representing whether reads or writes on the underlying memory region are fallible.
|
||||||
pub struct Fallible;
|
pub enum Fallible {}
|
||||||
/// A marker structure used for [`VmReader`] and [`VmWriter`],
|
|
||||||
|
/// A marker type used for [`VmReader`] and [`VmWriter`],
|
||||||
/// representing whether reads or writes on the underlying memory region are infallible.
|
/// representing whether reads or writes on the underlying memory region are infallible.
|
||||||
pub struct Infallible;
|
pub enum Infallible {}
|
||||||
|
|
||||||
/// Copies `len` bytes from `src` to `dst`.
|
/// Copies `len` bytes from `src` to `dst`.
|
||||||
///
|
///
|
||||||
@ -393,6 +394,20 @@ pub struct VmReader<'a, Fallibility = Fallible> {
|
|||||||
phantom: PhantomData<(&'a [u8], Fallibility)>,
|
phantom: PhantomData<(&'a [u8], Fallibility)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `Clone` can be implemented for `VmReader`
|
||||||
|
// because it either points to untyped memory or represents immutable references.
|
||||||
|
// Note that we cannot implement `Clone` for `VmWriter`
|
||||||
|
// because it can represent mutable references, which must remain exclusive.
|
||||||
|
impl<Fallibility> Clone for VmReader<'_, Fallibility> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
cursor: self.cursor,
|
||||||
|
end: self.end,
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_read_fallible {
|
macro_rules! impl_read_fallible {
|
||||||
($reader_fallibility:ty, $writer_fallibility:ty) => {
|
($reader_fallibility:ty, $writer_fallibility:ty) => {
|
||||||
impl<'a> FallibleVmRead<$writer_fallibility> for VmReader<'a, $reader_fallibility> {
|
impl<'a> FallibleVmRead<$writer_fallibility> for VmReader<'a, $reader_fallibility> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user