@@ -107,11 +107,26 @@ mod dl {
107107 handle : * mut u8 ,
108108 symbol : * const libc:: c_char ,
109109 ) -> 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+
110122 let mut dlerror = error:: lock ( ) ;
111123
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+ }
115130
116131 let ret = libc:: dlsym ( handle as * mut libc:: c_void , symbol) as * mut u8 ;
117132
@@ -121,7 +136,12 @@ mod dl {
121136 return Ok ( ret) ;
122137 }
123138
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+ }
125145 }
126146
127147 pub ( super ) unsafe fn close ( handle : * mut u8 ) {
0 commit comments