@@ -3631,7 +3631,12 @@ impl From<User> for libc::passwd {
36313631
36323632#[ cfg( not( target_os = "redox" ) ) ] // RedoxFS does not support passwd
36333633impl User {
3634- fn from_anything<F >( f: F ) -> Result <Option <Self >>
3634+ /// # Safety
3635+ ///
3636+ /// If `f` writes to its `*mut *mut libc::passwd` parameter, then it must
3637+ /// also initialize the value pointed to by its `*mut libc::group`
3638+ /// parameter.
3639+ unsafe fn from_anything<F >( f: F ) -> Result <Option <Self >>
36353640 where
36363641 F : Fn (
36373642 * mut libc:: passwd,
@@ -3661,7 +3666,9 @@ impl User {
36613666 if res. is_null( ) {
36623667 return Ok ( None ) ;
36633668 } else {
3664- let pwd = unsafe { pwd. assume_init( ) } ;
3669+ // SAFETY: `f` guarantees that `pwd` is initialized if `res`
3670+ // is not null.
3671+ let pwd = pwd. assume_init( ) ;
36653672 return Ok ( Some ( User :: from( & pwd) ) ) ;
36663673 }
36673674 } else if Errno :: last( ) == Errno :: ERANGE {
@@ -3687,9 +3694,13 @@ impl User {
36873694 /// assert_eq!(res.name, "root");
36883695 /// ```
36893696 pub fn from_uid( uid: Uid ) -> Result <Option <Self >> {
3690- User :: from_anything( |pwd, cbuf, cap, res| unsafe {
3691- libc:: getpwuid_r( uid. 0 , pwd, cbuf, cap, res)
3692- } )
3697+ // SAFETY: `getpwuid_r` will write to `res` if it initializes the value
3698+ // at `pwd`.
3699+ unsafe {
3700+ User :: from_anything( |pwd, cbuf, cap, res| {
3701+ libc:: getpwuid_r( uid. 0 , pwd, cbuf, cap, res)
3702+ } )
3703+ }
36933704 }
36943705
36953706 /// Get a user by name.
@@ -3710,9 +3721,13 @@ impl User {
37103721 Ok ( c_str) => c_str,
37113722 Err ( _nul_error) => return Ok ( None ) ,
37123723 } ;
3713- User :: from_anything( |pwd, cbuf, cap, res| unsafe {
3714- libc:: getpwnam_r( name. as_ptr( ) , pwd, cbuf, cap, res)
3715- } )
3724+ // SAFETY: `getpwnam_r` will write to `res` if it initializes the value
3725+ // at `pwd`.
3726+ unsafe {
3727+ User :: from_anything( |pwd, cbuf, cap, res| {
3728+ libc:: getpwnam_r( name. as_ptr( ) , pwd, cbuf, cap, res)
3729+ } )
3730+ }
37163731 }
37173732}
37183733
@@ -3763,7 +3778,12 @@ impl Group {
37633778 ret
37643779 }
37653780
3766- fn from_anything<F >( f: F ) -> Result <Option <Self >>
3781+ /// # Safety
3782+ ///
3783+ /// If `f` writes to its `*mut *mut libc::group` parameter, then it must
3784+ /// also initialize the value pointed to by its `*mut libc::group`
3785+ /// parameter.
3786+ unsafe fn from_anything<F >( f: F ) -> Result <Option <Self >>
37673787 where
37683788 F : Fn (
37693789 * mut libc:: group,
@@ -3793,7 +3813,9 @@ impl Group {
37933813 if res. is_null( ) {
37943814 return Ok ( None ) ;
37953815 } else {
3796- let grp = unsafe { grp. assume_init( ) } ;
3816+ // SAFETY: `f` guarantees that `grp` is initialized if `res`
3817+ // is not null.
3818+ let grp = grp. assume_init( ) ;
37973819 return Ok ( Some ( Group :: from( & grp) ) ) ;
37983820 }
37993821 } else if Errno :: last( ) == Errno :: ERANGE {
@@ -3821,9 +3843,13 @@ impl Group {
38213843 /// assert!(res.name == "root");
38223844 /// ```
38233845 pub fn from_gid( gid: Gid ) -> Result <Option <Self >> {
3824- Group :: from_anything( |grp, cbuf, cap, res| unsafe {
3825- libc:: getgrgid_r( gid. 0 , grp, cbuf, cap, res)
3826- } )
3846+ // SAFETY: `getgrgid_r` will write to `res` if it initializes the value
3847+ // at `grp`.
3848+ unsafe {
3849+ Group :: from_anything( |grp, cbuf, cap, res| {
3850+ libc:: getgrgid_r( gid. 0 , grp, cbuf, cap, res)
3851+ } )
3852+ }
38273853 }
38283854
38293855 /// Get a group by name.
@@ -3846,9 +3872,13 @@ impl Group {
38463872 Ok ( c_str) => c_str,
38473873 Err ( _nul_error) => return Ok ( None ) ,
38483874 } ;
3849- Group :: from_anything( |grp, cbuf, cap, res| unsafe {
3850- libc:: getgrnam_r( name. as_ptr( ) , grp, cbuf, cap, res)
3851- } )
3875+ // SAFETY: `getgrnam_r` will write to `res` if it initializes the value
3876+ // at `grp`.
3877+ unsafe {
3878+ Group :: from_anything( |grp, cbuf, cap, res| {
3879+ libc:: getgrnam_r( name. as_ptr( ) , grp, cbuf, cap, res)
3880+ } )
3881+ }
38523882 }
38533883}
38543884}
0 commit comments