[3.12] gh-143927: Normalize all line endings (CR, CRLF, and LF) in configparser (GH-143929) (#152005)
Yhg1s <[email protected]> Tue, 04 Aug 2026 05:27:52 -0400 (EDT)
| Newsgroups | gmane.comp.python.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://github.com/python/cpython/commit/db4a157c790479710a1a840d7937c5c815a6f8b6 commit: db4a157c790479710a1a840d7937c5c815a6f8b6 branch: 3.12 author: Miss Islington (bot) <[email protected]> committer: Yhg1s <[email protected]> date: 2026-08-04T11:27:20+02:00 summary: [3.12] gh-143927: Normalize all line endings (CR, CRLF, and LF) in configparser (GH-143929) (#152005) gh-143927: Normalize all line endings (CR, CRLF, and LF) in configparser (GH-143929) (cherry picked from commit 5858e42c539dac8394636a6e9b30472b8994851f) Co-authored-by: Seth Larson <[email protected]> files: A Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst M Lib/configparser.py M Lib/test/test_configparser.py diff --git a/Lib/configparser.py b/Lib/configparser.py index f96704eb455b90..8ae35a0a1893b4 100644 --- a/Lib/configparser.py +++ b/Lib/configparser.py @@ -907,7 +907,9 @@ def _write_section(self, fp, section_name, section_items, delimiter): value = self._interpolation.before_write(self, section_name, key, value) if value is not None or not self._allow_no_value: - value = delimiter + str(value).replace('\n', '\n\t') + # Convert all possible line-endings into '\n\t' + value = (delimiter + str(value).replace('\r\n', '\n') + .replace('\r', '\n').replace('\n', '\n\t')) else: value = "" fp.write("{}{}\n".format(key, value)) diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py index b7e68d7a3e7332..389aa15e67009a 100644 --- a/Lib/test/test_configparser.py +++ b/Lib/test/test_configparser.py @@ -527,6 +527,17 @@ def test_default_case_sensitivity(self): cf.get(self.default_section, "Foo"), "Bar", "could not locate option, expecting case-insensitive defaults") + def test_crlf_normalization(self): + cf = self.newconfig({"key1": "a\nb","key2": "a\rb", "key3": "a\r\nb", "key4": "a\r\nb"}) + buf = io.StringIO() + cf.write(buf) + cf_str = buf.getvalue() + self.assertNotIn("\r", cf_str) + self.assertNotIn("\r\n", cf_str) + self.assertEqual(cf_str.count("\n"), 10) + self.assertEqual(cf_str.count("\n\t"), 4) + self.assertTrue(cf_str.endswith("\n\n")) + def test_parse_errors(self): cf = self.newconfig() self.parse_error(cf, configparser.ParsingError, diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst new file mode 100644 index 00000000000000..ca554997e5c396 --- /dev/null +++ b/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst @@ -0,0 +1,2 @@ +Normalize all line endings (CR, CRLF, and LF) to LF+TAB when writing +multi-line configparser values. _______________________________________________ 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]