Skip to content

Commit dd00e58

Browse files
committed
Use ID numbers in lieu of allocations for DIR*
1 parent 89cbe0a commit dd00e58

File tree

1 file changed

+38
-27
lines changed

1 file changed

+38
-27
lines changed

src/shims/fs.rs

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,39 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '
204204
}
205205
}
206206

207-
#[derive(Debug, Default)]
207+
#[derive(Debug)]
208208
pub struct DirHandler {
209209
/// Directory iterators used to emulate libc "directory streams", as used in opendir, readdir,
210210
/// and closedir.
211211
///
212-
/// When opendir is called, a new allocation is made, a directory iterator is created on the
213-
/// host for the target directory, and an entry is stored in this hash map, indexed by a
214-
/// pointer to the allocation which represents the directory stream. When readdir is called,
215-
/// the directory stream pointer is used to look up the corresponding ReadDir iterator from
216-
/// this HashMap, and information from the next directory entry is returned. When closedir is
217-
/// called, the ReadDir iterator is removed from this HashMap, and the allocation that
218-
/// represented the directory stream is deallocated.
219-
streams: HashMap<Pointer<Tag>, ReadDir>,
212+
/// When opendir is called, a directory iterator is created on the host for the target
213+
/// directory, and an entry is stored in this hash map, indexed by an ID which represents
214+
/// the directory stream. When readdir is called, the directory stream ID is used to look up
215+
/// the corresponding ReadDir iterator from this HashMap, and information from the next
216+
/// directory entry is returned. When closedir is called, the ReadDir iterator is removed from
217+
/// this HashMap.
218+
streams: HashMap<u64, ReadDir>,
219+
/// ID number to be used by the next call to opendir
220+
next_id: u64,
221+
}
222+
223+
impl DirHandler {
224+
fn insert_new(&mut self, read_dir: ReadDir) -> u64 {
225+
let id = self.next_id;
226+
self.next_id += 1;
227+
self.streams.insert(id, read_dir).unwrap_none();
228+
id
229+
}
230+
}
231+
232+
impl Default for DirHandler {
233+
fn default() -> DirHandler {
234+
DirHandler {
235+
streams: HashMap::new(),
236+
// Skip 0 as an ID, because it looks like a null pointer to libc
237+
next_id: 1,
238+
}
239+
}
220240
}
221241

222242
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@@ -838,20 +858,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
838858

839859
match result {
840860
Ok(dir_iter) => {
841-
let size = 1;
842-
let kind = MiriMemoryKind::Env;
843-
let align = this.min_align(size, kind);
844-
let dir_ptr = this.memory.allocate(Size::from_bytes(size), align, kind.into());
845-
let prev = this
846-
.machine
847-
.dir_handler
848-
.streams
849-
.insert(dir_ptr, dir_iter);
850-
if let Some(_) = prev {
851-
panic!("The pointer allocated for opendir was already registered by a previous call to opendir")
852-
} else {
853-
Ok(Scalar::Ptr(dir_ptr))
854-
}
861+
let id = this.machine.dir_handler.insert_new(dir_iter);
862+
863+
// The libc API for opendir says that this method returns a pointer to an opaque
864+
// structure, but we are returning an ID number. Thus, pass it as a scalar of
865+
// pointer width.
866+
Ok(Scalar::from_int(id, this.pointer_size()))
855867
}
856868
Err(e) => {
857869
this.set_last_error_from_io_error(e)?;
@@ -870,7 +882,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
870882

871883
this.check_no_isolation("readdir64_r")?;
872884

873-
let dirp = this.force_ptr(this.read_scalar(dirp_op)?.not_undef()?)?;
885+
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
874886

875887
let entry_ptr = this.force_ptr(this.read_scalar(entry_op)?.not_undef()?)?;
876888
let dirent64_layout = this.libc_ty_layout("dirent64")?;
@@ -946,7 +958,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
946958

947959
this.check_no_isolation("readdir_r")?;
948960

949-
let dirp = this.force_ptr(this.read_scalar(dirp_op)?.not_undef()?)?;
961+
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
950962

951963
let entry_ptr = this.force_ptr(this.read_scalar(entry_op)?.not_undef()?)?;
952964
let dirent_layout = this.libc_ty_layout("dirent")?;
@@ -1020,11 +1032,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
10201032

10211033
this.check_no_isolation("closedir")?;
10221034

1023-
let dirp = this.force_ptr(this.read_scalar(dirp_op)?.not_undef()?)?;
1035+
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
10241036

10251037
if let Some(dir_iter) = this.machine.dir_handler.streams.remove(&dirp) {
10261038
drop(dir_iter);
1027-
this.memory.deallocate(dirp, None, MiriMemoryKind::Env.into())?;
10281039
Ok(0)
10291040
} else {
10301041
this.handle_not_found()

0 commit comments

Comments
 (0)