@@ -713,7 +713,7 @@ impl Iterator for ReadDir {
713713 // thread safety for readdir() as long an individual DIR* is not accessed
714714 // concurrently, which is sufficient for Rust.
715715 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 ) ;
717717 if entry_ptr. is_null ( ) {
718718 // We either encountered an error, or reached the end. Either way,
719719 // the next call to next() should return None.
@@ -739,44 +739,37 @@ impl Iterator for ReadDir {
739739 // contents were "simply" partially initialized data.
740740 //
741741 // 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
760753 } } ;
761754 }
762755
763756 // 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 ( ) ) ;
765758 let name_bytes = name. to_bytes ( ) ;
766759 if name_bytes == b"." || name_bytes == b".." {
767760 continue ;
768761 }
769762
770763 #[ cfg( not( target_os = "vita" ) ) ]
771764 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 ,
773766 #[ cfg( not( any(
774767 target_os = "solaris" ,
775768 target_os = "illumos" ,
776769 target_os = "aix" ,
777770 target_os = "nto" ,
778771 ) ) ) ]
779- d_type : * offset_ptr ! ( entry_ptr , d_type) as u8 ,
772+ d_type : * entry_field_ptr ! ( d_type) as u8 ,
780773 } ;
781774
782775 #[ cfg( target_os = "vita" ) ]
0 commit comments