@@ -38,7 +38,7 @@ pub mod native_cpuid {
38
38
39
39
use core:: cmp:: min;
40
40
use core:: fmt;
41
- use core:: mem:: transmute ;
41
+ use core:: mem:: size_of ;
42
42
use core:: slice;
43
43
use core:: str;
44
44
@@ -115,6 +115,7 @@ pub struct CpuId {
115
115
/// Low-level data-structure to store result of cpuid instruction.
116
116
#[ derive( Copy , Clone , Debug , Default ) ]
117
117
#[ cfg_attr( feature = "serialize" , derive( Serialize , Deserialize ) ) ]
118
+ #[ repr( C ) ]
118
119
pub struct CpuIdResult {
119
120
/// Return value EAX register
120
121
pub eax : u32 ,
@@ -563,6 +564,7 @@ impl CpuId {
563
564
564
565
#[ derive( Debug , Default ) ]
565
566
#[ cfg_attr( feature = "serialize" , derive( Serialize , Deserialize ) ) ]
567
+ #[ repr( C ) ]
566
568
pub struct VendorInfo {
567
569
ebx : u32 ,
568
570
edx : u32 ,
@@ -572,11 +574,14 @@ pub struct VendorInfo {
572
574
impl VendorInfo {
573
575
/// Return vendor identification as human readable string.
574
576
pub fn as_string < ' a > ( & ' a self ) -> & ' a str {
577
+ let brand_string_start = self as * const VendorInfo as * const u8 ;
575
578
unsafe {
576
- let brand_string_start = self as * const VendorInfo as * const u8 ;
577
- let slice = slice:: from_raw_parts ( brand_string_start, 3 * 4 ) ;
578
- let byte_array: & ' a [ u8 ] = transmute ( slice) ;
579
- str:: from_utf8_unchecked ( byte_array)
579
+ // Safety: VendorInfo is laid out with repr(C).
580
+ let slice: & ' a [ u8 ] = slice:: from_raw_parts ( brand_string_start, size_of :: < VendorInfo > ( ) ) ;
581
+ // Safety: The field is specified to be ASCII, and the only safe
582
+ // way to construct VendorInfo is from real CPUID data or the
583
+ // Default implementation.
584
+ str:: from_utf8_unchecked ( slice)
580
585
}
581
586
}
582
587
}
@@ -4005,19 +4010,21 @@ impl Iterator for SoCVendorAttributesIter {
4005
4010
4006
4011
#[ derive( Debug , Default ) ]
4007
4012
#[ cfg_attr( feature = "serialize" , derive( Serialize , Deserialize ) ) ]
4013
+ #[ repr( C ) ]
4008
4014
pub struct SoCVendorBrand {
4009
- #[ allow( dead_code) ]
4010
4015
data : [ CpuIdResult ; 3 ] ,
4011
4016
}
4012
4017
4013
4018
impl SoCVendorBrand {
4014
4019
pub fn as_string < ' a > ( & ' a self ) -> & ' a str {
4020
+ let brand_string_start = self as * const SoCVendorBrand as * const u8 ;
4015
4021
unsafe {
4016
- let brand_string_start = self as * const SoCVendorBrand as * const u8 ;
4017
- let slice =
4018
- slice:: from_raw_parts ( brand_string_start, core:: mem:: size_of :: < SoCVendorBrand > ( ) ) ;
4019
- let byte_array: & ' a [ u8 ] = transmute ( slice) ;
4020
- str:: from_utf8_unchecked ( byte_array)
4022
+ // Safety: SoCVendorBrand is laid out with repr(C).
4023
+ let slice: & ' a [ u8 ] = slice:: from_raw_parts ( brand_string_start, size_of :: < SoCVendorBrand > ( ) ) ;
4024
+ // Safety: The field is specified to be ASCII, and the only safe
4025
+ // way to construct SoCVendorBrand is from real CPUID data or the
4026
+ // Default implementation.
4027
+ str:: from_utf8_unchecked ( slice)
4021
4028
}
4022
4029
}
4023
4030
}
@@ -4130,18 +4137,18 @@ impl ExtendedFunctionInfo {
4130
4137
/// Retrieve processor brand string.
4131
4138
pub fn processor_brand_string < ' a > ( & ' a self ) -> Option < & ' a str > {
4132
4139
if self . leaf_is_supported ( EAX_EXTENDED_BRAND_STRING ) {
4133
- Some ( unsafe {
4134
- let brand_string_start = & self . data [ 2 ] as * const CpuIdResult as * const u8 ;
4135
- let mut slice = slice :: from_raw_parts ( brand_string_start , 3 * 4 * 4 ) ;
4136
-
4137
- match slice . iter ( ) . position ( | & x| x == 0 ) {
4138
- Some ( index ) => slice = slice :: from_raw_parts ( brand_string_start , index ) ,
4139
- None => ( ) ,
4140
- }
4141
-
4142
- let byte_array : & ' a [ u8 ] = transmute ( slice ) ;
4143
- str :: from_utf8_unchecked ( byte_array )
4144
- } )
4140
+ let brand_string_start = & self . data [ 2 ] as * const CpuIdResult as * const u8 ;
4141
+ // Safety: CpuIdResult is laid out with repr(C), and the array
4142
+ // self.data contains 9 continguous elements.
4143
+ let slice : & ' a [ u8 ] = unsafe { slice :: from_raw_parts ( brand_string_start , 3 * size_of :: < CpuIdResult > ( ) ) } ;
4144
+
4145
+ // Brand terminated at nul byte or end, whichever comes first.
4146
+ let slice = slice . split ( | & x| x == 0 ) . next ( ) . unwrap ( ) ;
4147
+
4148
+ // Safety: Field is specified to be ASCII, and the only safe way
4149
+ // to construct ExtendedFunctionInfo is from real CPUID data
4150
+ // or the Default implementation.
4151
+ Some ( unsafe { str :: from_utf8_unchecked ( slice ) } )
4145
4152
} else {
4146
4153
None
4147
4154
}
0 commit comments