@@ -107,11 +107,26 @@ mod dl {
107
107
handle : * mut u8 ,
108
108
symbol : * const libc:: c_char ,
109
109
) -> Result < * mut u8 , String > {
110
+ // HACK(#74469): On some platforms, users observed foreign code
111
+ // (specifically libc) invoking `dlopen`/`dlsym` in parallel with the
112
+ // functions in this module. This is problematic because, according to
113
+ // the POSIX API documentation, `dlerror` must be called to determine
114
+ // whether `dlsym` succeeded. Unlike `dlopen`, a NULL return value may
115
+ // indicate a successfully resolved symbol with an address of zero.
116
+ //
117
+ // Because symbols with address zero shouldn't occur in practice, we
118
+ // treat them as errors on platforms with misbehaving libc
119
+ // implementations.
120
+ const DLSYM_NULL_IS_ERROR : bool = cfg ! ( target_os = "illumos" ) ;
121
+
110
122
let mut dlerror = error:: lock ( ) ;
111
123
112
- // Flush `dlerror` since we need to use it to determine whether the subsequent call to
113
- // `dlsym` is successful.
114
- dlerror. clear ( ) ;
124
+ // No need to flush `dlerror` if we aren't using it to determine whether
125
+ // the subsequent call to `dlsym` succeeded. If an error occurs, any
126
+ // stale value will be overwritten.
127
+ if !DLSYM_NULL_IS_ERROR {
128
+ dlerror. clear ( ) ;
129
+ }
115
130
116
131
let ret = libc:: dlsym ( handle as * mut libc:: c_void , symbol) as * mut u8 ;
117
132
@@ -121,7 +136,12 @@ mod dl {
121
136
return Ok ( ret) ;
122
137
}
123
138
124
- dlerror. get ( ) . map ( |( ) | ret)
139
+ match dlerror. get ( ) {
140
+ Ok ( ( ) ) if DLSYM_NULL_IS_ERROR => Err ( "Unknown error" . to_string ( ) ) ,
141
+ Ok ( ( ) ) => Ok ( ret) ,
142
+
143
+ Err ( msg) => Err ( msg) ,
144
+ }
125
145
}
126
146
127
147
pub ( super ) unsafe fn close ( handle : * mut u8 ) {
0 commit comments