@@ -29,12 +29,12 @@ use rustc_hir::LangItem;
2929use rustc_middle:: dep_graph:: WorkProduct ;
3030use rustc_middle:: middle:: dependency_format:: Dependencies ;
3131use rustc_middle:: ty:: query:: { ExternProviders , Providers } ;
32+ use rustc_serialize:: { opaque, Decodable , Decoder , Encoder } ;
3233use rustc_session:: config:: { CrateType , OutputFilenames , OutputType , RUST_CGU_EXT } ;
3334use rustc_session:: cstore:: { self , CrateSource } ;
3435use rustc_session:: utils:: NativeLibKind ;
3536use rustc_span:: symbol:: Symbol ;
3637use std:: path:: { Path , PathBuf } ;
37- use rustc_serialize:: { Decodable , Decoder , Encoder , opaque} ;
3838
3939pub mod back;
4040pub mod base;
@@ -192,13 +192,18 @@ pub fn looks_like_rust_object_file(filename: &str) -> bool {
192192 ext2 == Some ( RUST_CGU_EXT )
193193}
194194
195- const RLINK_MAGIC : & ' static [ u8 ; 5 ] = b"rlink" ;
195+ const RLINK_VERSION : u32 = 1 ;
196+ const RLINK_MAGIC : & [ u8 ] = b"rustlink" ;
197+
196198const RUSTC_VERSION : Option < & str > = option_env ! ( "CFG_VERSION" ) ;
197199
198200impl CodegenResults {
199201 pub fn serialize_rlink ( codegen_results : & CodegenResults ) -> Vec < u8 > {
200202 let mut encoder = opaque:: Encoder :: new ( vec ! [ ] ) ;
201203 encoder. emit_raw_bytes ( RLINK_MAGIC ) . unwrap ( ) ;
204+ // `emit_raw_bytes` is used to make sure that the version representation does not depend on
205+ // Encoder's inner representation of `u32`.
206+ encoder. emit_raw_bytes ( & RLINK_VERSION . to_be_bytes ( ) ) . unwrap ( ) ;
202207 encoder. emit_str ( RUSTC_VERSION . unwrap ( ) ) . unwrap ( ) ;
203208
204209 let mut encoder = rustc_serialize:: opaque:: Encoder :: new ( encoder. into_inner ( ) ) ;
@@ -207,14 +212,29 @@ impl CodegenResults {
207212 }
208213
209214 pub fn deserialize_rlink ( data : Vec < u8 > ) -> Result < Self , String > {
215+ // The Decodable machinery is not used here because it panics if the input data is invalid
216+ // and because its internal representation may change.
210217 if !data. starts_with ( RLINK_MAGIC ) {
211218 return Err ( "The input does not look like a .rlink file" . to_string ( ) ) ;
212219 }
213- let mut decoder = opaque:: Decoder :: new ( & data[ RLINK_MAGIC . len ( ) ..] , 0 ) ;
220+ let data = & data[ RLINK_MAGIC . len ( ) ..] ;
221+ if data. len ( ) < 4 {
222+ return Err ( "The input does not contain version number" . to_string ( ) ) ;
223+ }
224+
225+ let mut version_array: [ u8 ; 4 ] = Default :: default ( ) ;
226+ version_array. copy_from_slice ( & data[ ..4 ] ) ;
227+ if u32:: from_be_bytes ( version_array) != RLINK_VERSION {
228+ return Err ( ".rlink file was produced with encoding version {version_array}, but the current version is {RLINK_VERSION}" . to_string ( ) ) ;
229+ }
230+
231+ let mut decoder = opaque:: Decoder :: new ( & data[ 4 ..] , 0 ) ;
214232 let rustc_version = decoder. read_str ( ) ;
215233 let current_version = RUSTC_VERSION . unwrap ( ) ;
216234 if rustc_version != current_version {
217- return Err ( format ! ( ".rlink file was produced by rustc version {rustc_version}, but the current version is {current_version}." ) ) ;
235+ return Err ( format ! (
236+ ".rlink file was produced by rustc version {rustc_version}, but the current version is {current_version}."
237+ ) ) ;
218238 }
219239
220240 let codegen_results = CodegenResults :: decode ( & mut decoder) ;
0 commit comments