@@ -204,19 +204,39 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '
204
204
}
205
205
}
206
206
207
- #[ derive( Debug , Default ) ]
207
+ #[ derive( Debug ) ]
208
208
pub struct DirHandler {
209
209
/// Directory iterators used to emulate libc "directory streams", as used in opendir, readdir,
210
210
/// and closedir.
211
211
///
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
+ }
220
240
}
221
241
222
242
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
838
858
839
859
match result {
840
860
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 ( ) ) )
855
867
}
856
868
Err ( e) => {
857
869
this. set_last_error_from_io_error ( e) ?;
@@ -870,7 +882,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
870
882
871
883
this. check_no_isolation ( "readdir64_r" ) ?;
872
884
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 ) ?;
874
886
875
887
let entry_ptr = this. force_ptr ( this. read_scalar ( entry_op) ?. not_undef ( ) ?) ?;
876
888
let dirent64_layout = this. libc_ty_layout ( "dirent64" ) ?;
@@ -946,7 +958,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
946
958
947
959
this. check_no_isolation ( "readdir_r" ) ?;
948
960
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 ) ?;
950
962
951
963
let entry_ptr = this. force_ptr ( this. read_scalar ( entry_op) ?. not_undef ( ) ?) ?;
952
964
let dirent_layout = this. libc_ty_layout ( "dirent" ) ?;
@@ -1020,11 +1032,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1020
1032
1021
1033
this. check_no_isolation ( "closedir" ) ?;
1022
1034
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 ) ?;
1024
1036
1025
1037
if let Some ( dir_iter) = this. machine . dir_handler . streams . remove ( & dirp) {
1026
1038
drop ( dir_iter) ;
1027
- this. memory . deallocate ( dirp, None , MiriMemoryKind :: Env . into ( ) ) ?;
1028
1039
Ok ( 0 )
1029
1040
} else {
1030
1041
this. handle_not_found ( )
0 commit comments