1515//! Err(e) => println!("Parsing Error: {:?}", e),
1616//! }
1717//! ```
18- use libc:: { c_char, c_uint} ;
18+ use libc:: { c_char, c_int, c_uint} ;
19+ use openssl_macros:: corresponds;
1920use std:: borrow:: Cow ;
2021use std:: error;
2122use std:: ffi:: CStr ;
@@ -34,7 +35,8 @@ pub struct ErrorStack(Vec<Error>);
3435
3536impl ErrorStack {
3637 /// Pops the contents of the OpenSSL error stack, and returns it.
37- #[ allow( clippy:: must_use_candidate) ]
38+ #[ corresponds( ERR_get_error_line_data ) ]
39+ #[ must_use = "Use ErrorStack::clear() to drop the error stack" ]
3840 pub fn get ( ) -> ErrorStack {
3941 let mut vec = vec ! [ ] ;
4042 while let Some ( err) = Error :: get ( ) {
@@ -44,6 +46,7 @@ impl ErrorStack {
4446 }
4547
4648 /// Pushes the errors back onto the OpenSSL error stack.
49+ #[ corresponds( ERR_put_error ) ]
4750 pub fn put ( & self ) {
4851 for error in self . errors ( ) {
4952 error. put ( ) ;
@@ -55,6 +58,14 @@ impl ErrorStack {
5558 pub ( crate ) fn internal_error ( err : impl error:: Error ) -> Self {
5659 Self ( vec ! [ Error :: new_internal( err. to_string( ) ) ] )
5760 }
61+
62+ /// Empties the current thread's error queue.
63+ #[ corresponds( ERR_clear_error ) ]
64+ pub ( crate ) fn clear ( ) {
65+ unsafe {
66+ ffi:: ERR_clear_error ( ) ;
67+ }
68+ }
5869}
5970
6071impl ErrorStack {
@@ -80,7 +91,9 @@ impl fmt::Display for ErrorStack {
8091 write ! (
8192 fmt,
8293 "[{}]" ,
83- err. reason_internal( ) . unwrap_or( "unknown reason" )
94+ err. reason_internal( )
95+ . or_else( || err. library( ) )
96+ . unwrap_or( "unknown reason" )
8497 ) ?;
8598 }
8699 Ok ( ( ) )
@@ -101,7 +114,7 @@ impl From<ErrorStack> for fmt::Error {
101114 }
102115}
103116
104- /// An error reported from OpenSSL .
117+ /// A detailed error reported as part of an [`ErrorStack`] .
105118#[ derive( Clone ) ]
106119pub struct Error {
107120 code : c_uint ,
@@ -117,7 +130,8 @@ static BORING_INTERNAL: &CStr = c"boring-rust";
117130
118131impl Error {
119132 /// Pops the first error off the OpenSSL error stack.
120- #[ allow( clippy:: must_use_candidate) ]
133+ #[ must_use = "Use ErrorStack::clear() to drop the error stack" ]
134+ #[ corresponds( ERR_get_error_line_data ) ]
121135 pub fn get ( ) -> Option < Error > {
122136 unsafe {
123137 ffi:: init ( ) ;
@@ -150,6 +164,7 @@ impl Error {
150164 }
151165
152166 /// Pushes the error back onto the OpenSSL error stack.
167+ #[ corresponds( ERR_put_error ) ]
153168 pub fn put ( & self ) {
154169 unsafe {
155170 ffi:: ERR_put_error (
@@ -179,7 +194,10 @@ impl Error {
179194 }
180195 }
181196
182- /// Returns the raw OpenSSL error code for this error.
197+ /// Returns a raw OpenSSL **packed** error code for this error, which **can't be reliably compared to any error constant**.
198+ ///
199+ /// Use [`Error::library_code()`] and [`Error::reason_code()`] instead.
200+ /// Packed error codes are different than [SSL error codes](crate::ssl::ErrorCode).
183201 #[ must_use]
184202 pub fn code ( & self ) -> c_uint {
185203 self . code
@@ -201,27 +219,17 @@ impl Error {
201219 }
202220 }
203221
204- /// Returns the raw OpenSSL error constant for the library reporting the
205- /// error.
222+ /// Returns the raw OpenSSL error constant for the library reporting the error (`ERR_LIB_{name}`).
223+ ///
224+ /// Error [reason codes](Error::reason_code) are not globally unique, but scoped to each library.
206225 #[ must_use]
207- pub fn library_code ( & self ) -> libc :: c_int {
226+ pub fn library_code ( & self ) -> c_int {
208227 ffi:: ERR_GET_LIB ( self . code )
209228 }
210229
211- /// Returns the name of the function reporting the error.
212- #[ must_use]
230+ /// Returns `None`. Boring doesn't use function codes.
213231 pub fn function ( & self ) -> Option < & ' static str > {
214- if self . is_internal ( ) {
215- return None ;
216- }
217- unsafe {
218- let cstr = ffi:: ERR_func_error_string ( self . code ) ;
219- if cstr. is_null ( ) {
220- return None ;
221- }
222- let bytes = CStr :: from_ptr ( cstr as * const _ ) . to_bytes ( ) ;
223- str:: from_utf8 ( bytes) . ok ( )
224- }
232+ None
225233 }
226234
227235 /// Returns the reason for the error.
@@ -237,9 +245,14 @@ impl Error {
237245 }
238246 }
239247
240- /// Returns the raw OpenSSL error constant for the reason for the error.
248+ /// Returns [library-specific](Error::library_code) reason code corresponding to some of the `{lib}_R_{reason}` constants.
249+ ///
250+ /// Reason codes are ambiguous, and different libraries reuse the same numeric values for different errors.
251+ ///
252+ /// For `ERR_LIB_SYS` the reason code is `errno`. `ERR_LIB_USER` can use any values.
253+ /// Other libraries may use [`ERR_R_*`](ffi::ERR_R_FATAL) or their own codes.
241254 #[ must_use]
242- pub fn reason_code ( & self ) -> libc :: c_int {
255+ pub fn reason_code ( & self ) -> c_int {
243256 ffi:: ERR_GET_REASON ( self . code )
244257 }
245258
@@ -256,6 +269,8 @@ impl Error {
256269 }
257270
258271 /// Returns the line in the source file which encountered the error.
272+ ///
273+ /// 0 if unknown
259274 #[ allow( clippy:: unnecessary_cast) ]
260275 #[ must_use]
261276 pub fn line ( & self ) -> u32 {
@@ -294,20 +309,19 @@ impl Error {
294309impl fmt:: Debug for Error {
295310 fn fmt ( & self , fmt : & mut fmt:: Formatter ) -> fmt:: Result {
296311 let mut builder = fmt. debug_struct ( "Error" ) ;
297- builder. field ( "code" , & self . code ( ) ) ;
298- if let Some ( library) = self . library ( ) {
299- builder. field ( "library" , & library) ;
300- }
301- builder. field ( "library_code" , & self . library_code ( ) ) ;
302- if let Some ( function) = self . function ( ) {
303- builder. field ( "function" , & function) ;
304- }
305- if let Some ( reason) = self . reason ( ) {
306- builder. field ( "reason" , & reason) ;
312+ builder. field ( "code" , & self . code ) ;
313+ if !self . is_internal ( ) {
314+ if let Some ( library) = self . library ( ) {
315+ builder. field ( "library" , & library) ;
316+ }
317+ builder. field ( "library_code" , & self . library_code ( ) ) ;
318+ if let Some ( reason) = self . reason ( ) {
319+ builder. field ( "reason" , & reason) ;
320+ }
321+ builder. field ( "reason_code" , & self . reason_code ( ) ) ;
322+ builder. field ( "file" , & self . file ( ) ) ;
323+ builder. field ( "line" , & self . line ( ) ) ;
307324 }
308- builder. field ( "reason_code" , & self . reason_code ( ) ) ;
309- builder. field ( "file" , & self . file ( ) ) ;
310- builder. field ( "line" , & self . line ( ) ) ;
311325 if let Some ( data) = self . data ( ) {
312326 builder. field ( "data" , & data) ;
313327 }
@@ -321,7 +335,7 @@ impl fmt::Display for Error {
321335 fmt,
322336 "{}\n \n Code: {:08X}\n Loc: {}:{}" ,
323337 self . reason_internal( ) . unwrap_or( "unknown TLS error" ) ,
324- self . code( ) ,
338+ & self . code,
325339 self . file( ) ,
326340 self . line( )
327341 )
0 commit comments