Skip to content

Commit

Permalink
pythongh-127257: Add hex code to ssl "unknown error" message (pythonG…
Browse files Browse the repository at this point in the history
…H-127360)

* ssl: Add hex error code to "unknown error" messages

To make it easier to vary the individual parts of the message,
replace the if-ladder with constant format strings by building
the string piece-wise with PyUnicodeWriter.

Use "unknown error (0x%x)" rather than just "unknown error" if we
can't get a better error message. (Hex makes sense as the error
includes two packed parts.)
  • Loading branch information
encukou authored Jan 10, 2025
1 parent 688f3a0 commit 802556a
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
When a descriptive error message cannot be provided for an
:exc:`ssl.SSLError`, the "unknown error" message now shows the internal
error code (as retrieved by ``ERR_get_error`` and similar OpenSSL
functions).
63 changes: 47 additions & 16 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL;
PyObject *verify_obj = NULL, *verify_code_obj = NULL;
PyObject *init_value, *msg, *key;
PyUnicodeWriter *writer = NULL;

if (errcode != 0) {
int lib, reason;
Expand All @@ -495,11 +496,10 @@ fill_and_set_sslerror(_sslmodulestate *state,
if (lib_obj == NULL && PyErr_Occurred()) {
goto fail;
}
if (errstr == NULL)
if (errstr == NULL) {
errstr = ERR_reason_error_string(errcode);
}
}
if (errstr == NULL)
errstr = "unknown error";

/* verify code for cert validation error */
if ((sslsock != NULL) && (type == state->PySSLCertVerificationErrorObject)) {
Expand Down Expand Up @@ -539,20 +539,50 @@ fill_and_set_sslerror(_sslmodulestate *state,
}
}

if (verify_obj && reason_obj && lib_obj)
msg = PyUnicode_FromFormat("[%S: %S] %s: %S (_ssl.c:%d)",
lib_obj, reason_obj, errstr, verify_obj,
lineno);
else if (reason_obj && lib_obj)
msg = PyUnicode_FromFormat("[%S: %S] %s (_ssl.c:%d)",
lib_obj, reason_obj, errstr, lineno);
else if (lib_obj)
msg = PyUnicode_FromFormat("[%S] %s (_ssl.c:%d)",
lib_obj, errstr, lineno);
else
msg = PyUnicode_FromFormat("%s (_ssl.c:%d)", errstr, lineno);
if (msg == NULL)
// Format message roughly as:
// [lib_obj: reason_obj] errstr: verify_obj (_ssl.c:lineno)
// with parts missing/replaced if unavailable
writer = PyUnicodeWriter_Create(64);
if (!writer) {
goto fail;
}
if (lib_obj) {
if (PyUnicodeWriter_Format(writer, "[%S", lib_obj) < 0) {
goto fail;
}
if (reason_obj) {
if (PyUnicodeWriter_Format(writer, ": %S", reason_obj) < 0) {
goto fail;
}
}
if (PyUnicodeWriter_WriteUTF8(writer, "] ", 2) < 0) {
goto fail;
}
}
if (errstr) {
if (PyUnicodeWriter_Format(writer, "%s", errstr) < 0) {
goto fail;
}
}
else {
if (PyUnicodeWriter_Format(
writer, "unknown error (0x%x)", errcode) < 0) {
goto fail;
}
}
if (verify_obj) {
if (PyUnicodeWriter_Format(writer, ": %S", verify_obj) < 0) {
goto fail;
}
}
if (PyUnicodeWriter_Format(writer, " (_ssl.c:%d)", lineno) < 0) {
goto fail;
}
msg = PyUnicodeWriter_Finish(writer);
writer = NULL;
if (!msg) {
goto fail;
}

init_value = Py_BuildValue("iN", ERR_GET_REASON(ssl_errno), msg);
if (init_value == NULL)
Expand Down Expand Up @@ -587,6 +617,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
Py_XDECREF(err_value);
Py_XDECREF(verify_code_obj);
Py_XDECREF(verify_obj);
PyUnicodeWriter_Discard(writer);
}

static int
Expand Down

0 comments on commit 802556a

Please sign in to comment.