Skip to content

Commit 11ee17c

Browse files
committed
use PyOS_snprintf instead of PyUnicode_FromFormat
1 parent ba1bf20 commit 11ee17c

File tree

1 file changed

+49
-14
lines changed

1 file changed

+49
-14
lines changed

Modules/_ssl.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ format_ssl_error_message(PyObject *lib, PyObject *reason, PyObject *verify,
516516
const char *Py_UNUSED(filename), int lineno)
517517
{
518518
assert(errstr != NULL);
519+
519520
#define CHECK_OBJECT(x) \
520521
do { \
521522
assert(x == NULL || PyUnicode_CheckExact(x)); \
@@ -525,28 +526,62 @@ format_ssl_error_message(PyObject *lib, PyObject *reason, PyObject *verify,
525526
CHECK_OBJECT(reason);
526527
CHECK_OBJECT(verify);
527528
#undef CHECK_OBJECT
529+
528530
#define OPTIONAL_UTF8(x) ((x) == NULL ? NULL : PyUnicode_AsUTF8((x)))
529531
const char *libstr = OPTIONAL_UTF8(lib);
530532
const char *reastr = OPTIONAL_UTF8(reason);
531533
const char *verstr = OPTIONAL_UTF8(verify);
532534
#undef OPTIONAL_UTF8
535+
536+
const size_t errstr_len = strlen(errstr);
537+
const size_t libstr_len = libstr == NULL ? 0 : strlen(libstr);
538+
const size_t reastr_len = reastr == NULL ? 0 : strlen(reastr);
539+
const size_t verstr_len = verstr == NULL ? 0 : strlen(verstr);
540+
const size_t filename_len = 6; /* strlen("_ssl.c") == strlen(__FILE__) */
541+
/* upper bound on the number of characters taken by the line number */
542+
const size_t lineno_len = ceil(log10(abs(lineno) + 1));
543+
const size_t base_alloc = (
544+
libstr_len + reastr_len + verstr_len
545+
+ errstr_len + filename_len + lineno_len
546+
);
547+
548+
int rc;
549+
char *buf;
550+
533551
if (lib && reason && verify) {
534-
// - [LIB: REASON] ERROR: VERIFY (FILENAME:LINENO)
535-
return PyUnicode_FromFormat("[%s: %s] %s: %s (" __FILE__ ":%d)",
536-
libstr, reastr, errstr, verstr, lineno);
537-
}
538-
if (lib && reason) {
539-
// - [LIB: REASON] ERROR (FILENAME:LINENO)
540-
return PyUnicode_FromFormat("[%s: %s] %s (" __FILE__ ":%d)",
541-
libstr, reastr, errstr, lineno);
542-
}
543-
if (lib) {
552+
/* [LIB: REASON] ERROR: VERIFY (FILENAME:LINENO) */
553+
const size_t alloc = base_alloc + (4 + 3 + 4);
554+
buf = (char *)PyMem_RawMalloc(alloc);
555+
rc = PyOS_snprintf(buf, alloc, "[%s: %s] %s: %s (" __FILE__ ":%d)",
556+
libstr, reastr, errstr, verstr, lineno);
557+
}
558+
else if (lib && reason) {
559+
/* [LIB: REASON] ERROR (FILENAME:LINENO) */
560+
const size_t alloc = base_alloc + (3 + 2 + 4);
561+
buf = (char *)PyMem_RawMalloc(alloc);
562+
rc = PyOS_snprintf(buf, alloc, "[%s: %s] %s (" __FILE__ ":%d)",
563+
libstr, reastr, errstr, lineno);
564+
}
565+
else if (lib) {
544566
/* [LIB] ERROR (FILENAME:LINENO) */
545-
return PyUnicode_FromFormat("[%s] %s (" __FILE__ ":%d)",
546-
libstr, errstr, lineno);
567+
const size_t alloc = base_alloc + (2 + 1 + 4);
568+
buf = (char *)PyMem_RawMalloc(alloc);
569+
rc = PyOS_snprintf(buf, alloc, "[%s] %s (" __FILE__ ":%d)",
570+
libstr, errstr, lineno);
571+
}
572+
else {
573+
/* ERROR (FILENAME:LINENO) */
574+
const size_t alloc = base_alloc + (1 + 1 + 2);
575+
buf = (char *)PyMem_RawMalloc(alloc);
576+
rc = PyOS_snprintf(buf, alloc, "%s (" __FILE__ ":%d)",
577+
errstr, lineno);
547578
}
548-
/* ERROR (FILENAME:LINENO) */
549-
return PyUnicode_FromFormat("%s (" __FILE__ ":%d)", errstr, lineno);
579+
580+
PyObject *res = rc < 0
581+
? PyUnicode_FromFormat("%s (" __FILE__ ":%d)", errstr, lineno)
582+
: PyUnicode_FromString(buf) /* uses the ASCII fast path */;
583+
PyMem_RawFree(buf);
584+
return res;
550585
}
551586

552587
/*

0 commit comments

Comments
 (0)