@@ -21,13 +21,32 @@ use crate::{ProcMacroKind, ProcMacroSrvSpan, proc_macros::ProcMacros, server_imp
21
21
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
22
22
///
23
23
/// It seems that on Windows that behaviour is default, so we do nothing in that case.
24
+ ///
25
+ /// # Safety
26
+ ///
27
+ /// The caller is responsible for ensuring that the path is valid proc-macro library
24
28
#[ cfg( windows) ]
25
- fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
29
+ unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
30
+ // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
26
31
unsafe { Library :: new ( file) }
27
32
}
28
33
34
+ /// Loads dynamic library in platform dependent manner.
35
+ ///
36
+ /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
37
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
38
+ /// and [here](https://github.com/rust-lang/rust/issues/60593).
39
+ ///
40
+ /// Usage of RTLD_DEEPBIND
41
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
42
+ ///
43
+ /// It seems that on Windows that behaviour is default, so we do nothing in that case.
44
+ ///
45
+ /// # Safety
46
+ ///
47
+ /// The caller is responsible for ensuring that the path is valid proc-macro library
29
48
#[ cfg( unix) ]
30
- fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
49
+ unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
31
50
// not defined by POSIX, different values on mips vs other targets
32
51
#[ cfg( target_env = "gnu" ) ]
33
52
use libc:: RTLD_DEEPBIND ;
@@ -39,6 +58,7 @@ fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
39
58
#[ cfg( not( target_env = "gnu" ) ) ]
40
59
const RTLD_DEEPBIND : std:: os:: raw:: c_int = 0x0 ;
41
60
61
+ // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
42
62
unsafe { UnixLibrary :: open ( Some ( file) , RTLD_NOW | RTLD_DEEPBIND ) . map ( |lib| lib. into ( ) ) }
43
63
}
44
64
@@ -84,26 +104,32 @@ struct ProcMacroLibrary {
84
104
impl ProcMacroLibrary {
85
105
fn open ( path : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
86
106
let file = fs:: File :: open ( path) ?;
107
+ #[ allow( clippy:: undocumented_unsafe_blocks) ] // FIXME
87
108
let file = unsafe { memmap2:: Mmap :: map ( & file) } ?;
88
109
let obj = object:: File :: parse ( & * file)
89
110
. map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
90
111
let version_info = version:: read_dylib_info ( & obj) ?;
112
+ if version_info. version_string != crate :: RUSTC_VERSION_STRING {
113
+ return Err ( LoadProcMacroDylibError :: AbiMismatch ( version_info. version_string ) ) ;
114
+ }
115
+
91
116
let symbol_name =
92
117
find_registrar_symbol ( & obj) . map_err ( invalid_data_err) ?. ok_or_else ( || {
93
118
invalid_data_err ( format ! ( "Cannot find registrar symbol in file {path}" ) )
94
119
} ) ?;
95
120
96
- let lib = load_library ( path) . map_err ( invalid_data_err) ?;
97
- let proc_macros = unsafe {
98
- // SAFETY: We extend the lifetime here to avoid referential borrow problems
99
- // We never reveal proc_macros to the outside and drop it before _lib
100
- std:: mem:: transmute :: < & ProcMacros , & ' static ProcMacros > ( ProcMacros :: from_lib (
101
- & lib,
102
- symbol_name,
103
- & version_info. version_string ,
104
- ) ?)
105
- } ;
106
- Ok ( ProcMacroLibrary { _lib : lib, proc_macros } )
121
+ // SAFETY: We have verified the validity of the dylib as a proc-macro library
122
+ let lib = unsafe { load_library ( path) } . map_err ( invalid_data_err) ?;
123
+ // SAFETY: We have verified the validity of the dylib as a proc-macro library
124
+ // The 'static lifetime is a lie, it's actually the lifetime of the library but unavoidable
125
+ // due to self-referentiality
126
+ // But we make sure that we do not drop it before the symbol is dropped
127
+ let proc_macros =
128
+ unsafe { lib. get :: < & ' static & ' static ProcMacros > ( symbol_name. as_bytes ( ) ) } ;
129
+ match proc_macros {
130
+ Ok ( proc_macros) => Ok ( ProcMacroLibrary { proc_macros : * proc_macros, _lib : lib } ) ,
131
+ Err ( e) => Err ( e. into ( ) ) ,
132
+ }
107
133
}
108
134
}
109
135
0 commit comments