@@ -21,13 +21,32 @@ use crate::{ProcMacroKind, ProcMacroSrvSpan, proc_macros::ProcMacros, server_imp
2121/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
2222///
2323/// 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
2428#[ 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
2631 unsafe { Library :: new ( file) }
2732}
2833
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
2948#[ cfg( unix) ]
30- fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
49+ unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
3150 // not defined by POSIX, different values on mips vs other targets
3251 #[ cfg( target_env = "gnu" ) ]
3352 use libc:: RTLD_DEEPBIND ;
@@ -39,6 +58,7 @@ fn load_library(file: &Utf8Path) -> Result<Library, libloading::Error> {
3958 #[ cfg( not( target_env = "gnu" ) ) ]
4059 const RTLD_DEEPBIND : std:: os:: raw:: c_int = 0x0 ;
4160
61+ // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
4262 unsafe { UnixLibrary :: open ( Some ( file) , RTLD_NOW | RTLD_DEEPBIND ) . map ( |lib| lib. into ( ) ) }
4363}
4464
@@ -84,26 +104,32 @@ struct ProcMacroLibrary {
84104impl ProcMacroLibrary {
85105 fn open ( path : & Utf8Path ) -> Result < Self , LoadProcMacroDylibError > {
86106 let file = fs:: File :: open ( path) ?;
107+ #[ allow( clippy:: undocumented_unsafe_blocks) ] // FIXME
87108 let file = unsafe { memmap2:: Mmap :: map ( & file) } ?;
88109 let obj = object:: File :: parse ( & * file)
89110 . map_err ( |e| io:: Error :: new ( io:: ErrorKind :: InvalidData , e) ) ?;
90111 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+
91116 let symbol_name =
92117 find_registrar_symbol ( & obj) . map_err ( invalid_data_err) ?. ok_or_else ( || {
93118 invalid_data_err ( format ! ( "Cannot find registrar symbol in file {path}" ) )
94119 } ) ?;
95120
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+ }
107133 }
108134}
109135
0 commit comments