https://github.com/python/cpython/commit/2662db0c45aa16232136628457a53681b6683c25
commit: 2662db0c45aa16232136628457a53681b6683c25
branch: main
author: Bénédikt Tran <[email protected]>
committer: picnixz <[email protected]>
date: 2026-04-14T00:32:54+02:00
summary:
gh-148370: prevent quadratic behavior in `configparser.ParsingError.combine`
(#148452)
files:
A Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst
M Lib/configparser.py
M Lib/test/test_configparser.py
diff --git a/Lib/configparser.py b/Lib/configparser.py
index e76647d339e913..a53ac87276445a 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -315,12 +315,15 @@ def __init__(self, source, *args):
def append(self, lineno, line):
self.errors.append((lineno, line))
- self.message += '\n\t[line %2d]: %s' % (lineno, repr(line))
+ self.message += f'\n\t[line {lineno:2d}]: {line!r}'
def combine(self, others):
+ messages = [self.message]
for other in others:
- for error in other.errors:
- self.append(*error)
+ for lineno, line in other.errors:
+ self.errors.append((lineno, line))
+ messages.append(f'\n\t[line {lineno:2d}]: {line!r}')
+ self.message = "".join(messages)
return self
@staticmethod
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index d7c4f19c1a5ef0..8d8dd2a2bf27fb 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -1729,6 +1729,19 @@ def test_error(self):
self.assertEqual(e1.message, e2.message)
self.assertEqual(repr(e1), repr(e2))
+ def test_combine_error_linear_complexity(self):
+ # Ensure that ParsingError.combine() has linear complexity.
+ # See https://github.com/python/cpython/issues/148370.
+ n = 50000
+ s = '[*]\n' + (err_line := '=\n') * n
+ p = configparser.ConfigParser(strict=False)
+ with self.assertRaises(configparser.ParsingError) as cm:
+ p.read_string(s)
+ errlines = cm.exception.message.splitlines()
+ self.assertEqual(len(errlines), n + 1)
+ self.assertStartsWith(errlines[0], "Source contains parsing errors: ")
+ self.assertEqual(errlines[42], f"\t[line {43:2d}]: {err_line!r}")
+
def test_nosectionerror(self):
import pickle
e1 = configparser.NoSectionError('section')
diff --git
a/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst
b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst
new file mode 100644
index 00000000000000..3bb662350796f6
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-04-12-16-40-11.gh-issue-148370.0Li2EK.rst
@@ -0,0 +1,2 @@
+:mod:`configparser`: prevent quadratic behavior when a
:exc:`~configparser.ParsingError`
+is raised after a parser fails to parse multiple lines. Patch by Bénédikt Tran.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]