@@ -713,7 +713,7 @@ impl Iterator for ReadDir {
713
713
// thread safety for readdir() as long an individual DIR* is not accessed
714
714
// concurrently, which is sufficient for Rust.
715
715
super :: os:: set_errno ( 0 ) ;
716
- let entry_ptr = readdir64 ( self . inner . dirp . 0 ) ;
716
+ let entry_ptr: * const dirent64 = readdir64 ( self . inner . dirp . 0 ) ;
717
717
if entry_ptr. is_null ( ) {
718
718
// We either encountered an error, or reached the end. Either way,
719
719
// the next call to next() should return None.
@@ -739,44 +739,37 @@ impl Iterator for ReadDir {
739
739
// contents were "simply" partially initialized data.
740
740
//
741
741
// Like for uninitialized contents, converting entry_ptr to `&dirent64`
742
- // would not be legal. However, unique to dirent64 is that we don't even
743
- // get to use `&raw const (*entry_ptr).d_name` because that operation
744
- // requires the full extent of *entry_ptr to be in bounds of the same
745
- // allocation, which is not necessarily the case here.
746
- //
747
- // Instead we must access fields individually through their offsets.
748
- macro_rules! offset_ptr {
749
- ( $entry_ptr: expr, $field: ident) => { {
750
- const OFFSET : isize = mem:: offset_of!( dirent64, $field) as isize ;
751
- if true {
752
- // Cast to the same type determined by the else branch.
753
- $entry_ptr. byte_offset( OFFSET ) . cast:: <_>( )
754
- } else {
755
- #[ allow( deref_nullptr) ]
756
- {
757
- & raw const ( * ptr:: null:: <dirent64>( ) ) . $field
758
- }
759
- }
742
+ // would not be legal. However, we can use `&raw const (*entry_ptr).d_name`
743
+ // to refer the fields individually, because that operation is equivalent
744
+ // to `byte_offset` and thus does not require the full extent of `*entry_ptr`
745
+ // to be in bounds of the same allocation, only the offset of the field
746
+ // being referenced.
747
+ macro_rules! entry_field_ptr {
748
+ ( $field: ident) => { {
749
+ // To make sure the field actually exists and is visible,
750
+ // and we aren't silently doing any Deref coercion.
751
+ const _: usize = mem:: offset_of!( dirent64, $field) ;
752
+ & raw const ( * entry_ptr) . $field
760
753
} } ;
761
754
}
762
755
763
756
// d_name is guaranteed to be null-terminated.
764
- let name = CStr :: from_ptr ( offset_ptr ! ( entry_ptr , d_name) . cast ( ) ) ;
757
+ let name = CStr :: from_ptr ( entry_field_ptr ! ( d_name) . cast ( ) ) ;
765
758
let name_bytes = name. to_bytes ( ) ;
766
759
if name_bytes == b"." || name_bytes == b".." {
767
760
continue ;
768
761
}
769
762
770
763
#[ cfg( not( target_os = "vita" ) ) ]
771
764
let entry = dirent64_min {
772
- d_ino : * offset_ptr ! ( entry_ptr , d_ino) as u64 ,
765
+ d_ino : * entry_field_ptr ! ( d_ino) as u64 ,
773
766
#[ cfg( not( any(
774
767
target_os = "solaris" ,
775
768
target_os = "illumos" ,
776
769
target_os = "aix" ,
777
770
target_os = "nto" ,
778
771
) ) ) ]
779
- d_type : * offset_ptr ! ( entry_ptr , d_type) as u8 ,
772
+ d_type : * entry_field_ptr ! ( d_type) as u8 ,
780
773
} ;
781
774
782
775
#[ cfg( target_os = "vita" ) ]
0 commit comments