(
vm: &VirtualMachine,
err: ErrorStack,
)
| 3742 | |
| 3743 | #[track_caller] |
| 3744 | pub(crate) fn convert_openssl_error( |
| 3745 | vm: &VirtualMachine, |
| 3746 | err: ErrorStack, |
| 3747 | ) -> PyBaseExceptionRef { |
| 3748 | match err.errors().last() { |
| 3749 | Some(e) => { |
| 3750 | // Check if this is a system library error (errno-based) |
| 3751 | let lib = sys::ERR_GET_LIB(e.code()); |
| 3752 | |
| 3753 | if lib == sys::ERR_LIB_SYS { |
| 3754 | // A system error is being reported; reason is set to errno |
| 3755 | let reason = sys::ERR_GET_REASON(e.code()); |
| 3756 | |
| 3757 | // errno 2 = ENOENT = FileNotFoundError |
| 3758 | let exc_type = if reason == 2 { |
| 3759 | vm.ctx.exceptions.file_not_found_error.to_owned() |
| 3760 | } else { |
| 3761 | vm.ctx.exceptions.os_error.to_owned() |
| 3762 | }; |
| 3763 | return vm.new_os_subtype_error(exc_type, Some(reason), "").upcast(); |
| 3764 | } |
| 3765 | |
| 3766 | let caller = std::panic::Location::caller(); |
| 3767 | let (file, line) = (caller.file(), caller.line()); |
| 3768 | let file = file |
| 3769 | .rsplit_once(&['/', '\\'][..]) |
| 3770 | .map_or(file, |(_, basename)| basename); |
| 3771 | |
| 3772 | // Get error codes - same approach as CPython |
| 3773 | let lib = sys::ERR_GET_LIB(e.code()); |
| 3774 | let reason = sys::ERR_GET_REASON(e.code()); |
| 3775 | |
| 3776 | // Look up error mnemonic from our static tables |
| 3777 | // CPython uses dict lookup: err_codes_to_names[(lib, reason)] |
| 3778 | let key = super::ssl_data::encode_error_key(lib, reason); |
| 3779 | let errstr = super::ssl_data::ERROR_CODES |
| 3780 | .get(&key) |
| 3781 | .copied() |
| 3782 | .or_else(|| { |
| 3783 | // Fallback: use OpenSSL's error string |
| 3784 | e.reason() |
| 3785 | }) |
| 3786 | .unwrap_or("unknown error"); |
| 3787 | |
| 3788 | // Check if this is a certificate verification error |
| 3789 | // ERR_LIB_SSL = 20 (from _ssl_data_300.h) |
| 3790 | // SSL_R_CERTIFICATE_VERIFY_FAILED = 134 (from _ssl_data_300.h) |
| 3791 | let is_cert_verify_error = lib == 20 && reason == 134; |
| 3792 | |
| 3793 | // Look up library name from our static table |
| 3794 | // CPython uses: lib_codes_to_names[lib] |
| 3795 | let lib_name = super::ssl_data::LIBRARY_CODES.get(&(lib as u32)).copied(); |
| 3796 | |
| 3797 | // Use SSLCertVerificationError for certificate verification failures |
| 3798 | let cls = if is_cert_verify_error { |
| 3799 | PySSLCertVerificationError::class(&vm.ctx).to_owned() |
| 3800 | } else { |
| 3801 | PySSLError::class(&vm.ctx).to_owned() |
no test coverage detected