@@ -9,15 +9,22 @@ pub mod msg;
9
9
mod process;
10
10
mod rpc;
11
11
12
- use std:: { ffi:: OsStr , fs:: read as fsread, io:: { self , Read } , path:: { Path , PathBuf } , sync:: Arc } ;
13
-
14
12
use base_db:: { Env , ProcMacro } ;
13
+ use std:: {
14
+ ffi:: OsStr ,
15
+ fs:: File ,
16
+ io:: { self , Read } ,
17
+ path:: { Path , PathBuf } ,
18
+ sync:: Arc ,
19
+ } ;
20
+
15
21
use tt:: { SmolStr , Subtree } ;
16
22
17
23
use crate :: process:: { ProcMacroProcessSrv , ProcMacroProcessThread } ;
18
24
19
25
pub use rpc:: { ExpansionResult , ExpansionTask , ListMacrosResult , ListMacrosTask , ProcMacroKind } ;
20
26
27
+ use memmap:: Mmap ;
21
28
use object:: read:: { File as BinaryFile , Object , ObjectSection } ;
22
29
use snap:: read:: FrameDecoder as SnapDecoder ;
23
30
@@ -110,13 +117,13 @@ impl ProcMacroClient {
110
117
111
118
// This is used inside self.read_version() to locate the ".rustc" section
112
119
// from a proc macro crate's binary file.
113
- fn read_section < ' a > ( & self , dylib_binary : & ' a [ u8 ] , section_name : & str ) -> & ' a [ u8 ] {
120
+ fn read_section < ' a > ( & self , dylib_binary : & ' a [ u8 ] , section_name : & str ) -> io :: Result < & ' a [ u8 ] > {
114
121
BinaryFile :: parse ( dylib_binary)
115
- . unwrap ( )
122
+ . map_err ( |e| io :: Error :: new ( io :: ErrorKind :: InvalidData , e ) ) ?
116
123
. section_by_name ( section_name)
117
- . unwrap ( )
124
+ . ok_or_else ( || io :: Error :: new ( io :: ErrorKind :: InvalidData , "section read error" ) ) ?
118
125
. data ( )
119
- . unwrap ( )
126
+ . map_err ( |e| io :: Error :: new ( io :: ErrorKind :: InvalidData , e ) )
120
127
}
121
128
122
129
// Check the version of rustc that was used to compile a proc macro crate's
@@ -138,10 +145,19 @@ impl ProcMacroClient {
138
145
// * [some more bytes that we don really care but still there] :-)
139
146
// Check this issue for more about the bytes layout:
140
147
// https://github.com/rust-analyzer/rust-analyzer/issues/6174
141
- fn read_version ( & self , dylib_path : & Path ) -> String {
142
- let dylib_binary = fsread ( dylib_path) . unwrap ( ) ;
148
+ #[ allow( unused) ]
149
+ fn read_version ( & self , dylib_path : & Path ) -> io:: Result < String > {
150
+ let dylib_file = File :: open ( dylib_path) ?;
151
+ let dylib_mmaped = unsafe { Mmap :: map ( & dylib_file) } ?;
152
+
153
+ let dot_rustc = self . read_section ( & dylib_mmaped, ".rustc" ) ?;
143
154
144
- let dot_rustc = self . read_section ( & dylib_binary, ".rustc" ) ;
155
+ let header = & dot_rustc[ ..8 ] ;
156
+ const EXPECTED_HEADER : [ u8 ; 8 ] = [ b'r' , b'u' , b's' , b't' , 0 , 0 , 0 , 5 ] ;
157
+ // check if header is valid
158
+ if !( header == EXPECTED_HEADER ) {
159
+ return Err ( io:: Error :: new ( io:: ErrorKind :: InvalidData , format ! ( ".rustc section should start with header {:?}; header {:?} is actually presented." , EXPECTED_HEADER , header) ) ) ;
160
+ }
145
161
146
162
let snappy_portion = & dot_rustc[ 8 ..] ;
147
163
@@ -154,14 +170,12 @@ impl ProcMacroClient {
154
170
// so 13 bytes in total, and we should check the 13th byte
155
171
// to know the length
156
172
let mut bytes_before_version = [ 0u8 ; 13 ] ;
157
- snappy_decoder
158
- . read_exact ( & mut bytes_before_version)
159
- . unwrap ( ) ;
173
+ snappy_decoder. read_exact ( & mut bytes_before_version) ?;
160
174
let length = bytes_before_version[ 12 ] ; // what? can't use -1 indexing?
161
175
162
176
let mut version_string_utf8 = vec ! [ 0u8 ; length as usize ] ;
163
- snappy_decoder. read_exact ( & mut version_string_utf8) . unwrap ( ) ;
164
- let version_string = String :: from_utf8 ( version_string_utf8) . unwrap ( ) ;
165
- version_string
177
+ snappy_decoder. read_exact ( & mut version_string_utf8) ? ;
178
+ let version_string = String :: from_utf8 ( version_string_utf8) ;
179
+ version_string. map_err ( |e| io :: Error :: new ( io :: ErrorKind :: InvalidData , e ) )
166
180
}
167
181
}
0 commit comments