@@ -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