Skip to content

Commit 802556a

Browse files
authored
gh-127257: Add hex code to ssl "unknown error" message (GH-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.)
1 parent 688f3a0 commit 802556a

File tree

2 files changed

+51
-16
lines changed

2 files changed

+51
-16
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
When a descriptive error message cannot be provided for an
2+
:exc:`ssl.SSLError`, the "unknown error" message now shows the internal
3+
error code (as retrieved by ``ERR_get_error`` and similar OpenSSL
4+
functions).

Modules/_ssl.c

+47-16
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
473473
PyObject *err_value = NULL, *reason_obj = NULL, *lib_obj = NULL;
474474
PyObject *verify_obj = NULL, *verify_code_obj = NULL;
475475
PyObject *init_value, *msg, *key;
476+
PyUnicodeWriter *writer = NULL;
476477

477478
if (errcode != 0) {
478479
int lib, reason;
@@ -495,11 +496,10 @@ fill_and_set_sslerror(_sslmodulestate *state,
495496
if (lib_obj == NULL && PyErr_Occurred()) {
496497
goto fail;
497498
}
498-
if (errstr == NULL)
499+
if (errstr == NULL) {
499500
errstr = ERR_reason_error_string(errcode);
501+
}
500502
}
501-
if (errstr == NULL)
502-
errstr = "unknown error";
503503

504504
/* verify code for cert validation error */
505505
if ((sslsock != NULL) && (type == state->PySSLCertVerificationErrorObject)) {
@@ -539,20 +539,50 @@ fill_and_set_sslerror(_sslmodulestate *state,
539539
}
540540
}
541541

542-
if (verify_obj && reason_obj && lib_obj)
543-
msg = PyUnicode_FromFormat("[%S: %S] %s: %S (_ssl.c:%d)",
544-
lib_obj, reason_obj, errstr, verify_obj,
545-
lineno);
546-
else if (reason_obj && lib_obj)
547-
msg = PyUnicode_FromFormat("[%S: %S] %s (_ssl.c:%d)",
548-
lib_obj, reason_obj, errstr, lineno);
549-
else if (lib_obj)
550-
msg = PyUnicode_FromFormat("[%S] %s (_ssl.c:%d)",
551-
lib_obj, errstr, lineno);
552-
else
553-
msg = PyUnicode_FromFormat("%s (_ssl.c:%d)", errstr, lineno);
554-
if (msg == NULL)
542+
// Format message roughly as:
543+
// [lib_obj: reason_obj] errstr: verify_obj (_ssl.c:lineno)
544+
// with parts missing/replaced if unavailable
545+
writer = PyUnicodeWriter_Create(64);
546+
if (!writer) {
547+
goto fail;
548+
}
549+
if (lib_obj) {
550+
if (PyUnicodeWriter_Format(writer, "[%S", lib_obj) < 0) {
551+
goto fail;
552+
}
553+
if (reason_obj) {
554+
if (PyUnicodeWriter_Format(writer, ": %S", reason_obj) < 0) {
555+
goto fail;
556+
}
557+
}
558+
if (PyUnicodeWriter_WriteUTF8(writer, "] ", 2) < 0) {
559+
goto fail;
560+
}
561+
}
562+
if (errstr) {
563+
if (PyUnicodeWriter_Format(writer, "%s", errstr) < 0) {
564+
goto fail;
565+
}
566+
}
567+
else {
568+
if (PyUnicodeWriter_Format(
569+
writer, "unknown error (0x%x)", errcode) < 0) {
570+
goto fail;
571+
}
572+
}
573+
if (verify_obj) {
574+
if (PyUnicodeWriter_Format(writer, ": %S", verify_obj) < 0) {
575+
goto fail;
576+
}
577+
}
578+
if (PyUnicodeWriter_Format(writer, " (_ssl.c:%d)", lineno) < 0) {
555579
goto fail;
580+
}
581+
msg = PyUnicodeWriter_Finish(writer);
582+
writer = NULL;
583+
if (!msg) {
584+
goto fail;
585+
}
556586

557587
init_value = Py_BuildValue("iN", ERR_GET_REASON(ssl_errno), msg);
558588
if (init_value == NULL)
@@ -587,6 +617,7 @@ fill_and_set_sslerror(_sslmodulestate *state,
587617
Py_XDECREF(err_value);
588618
Py_XDECREF(verify_code_obj);
589619
Py_XDECREF(verify_obj);
620+
PyUnicodeWriter_Discard(writer);
590621
}
591622

592623
static int

0 commit comments

Comments
 (0)