Skip to content

Commit ef1c148

Browse files
committed
Use negative lookahead in option regex to prevent backtracking
1 parent 85407ee commit ef1c148

File tree

1 file changed

+6
-22
lines changed

1 file changed

+6
-22
lines changed

Lib/configparser.py

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -613,15 +613,19 @@ class RawConfigParser(MutableMapping):
613613
\] # ]
614614
"""
615615
_OPT_TMPL = r"""
616-
(?P<option>.*?) # very permissive!
616+
(?P<option> # very permissive!
617+
(?:(?!{delim})\S)* # non-delimiter non-whitespace
618+
(?:\s+(?:(?!{delim})\S)+)*) # optionally more words
617619
\s*(?P<vi>{delim})\s* # any number of space/tab,
618620
# followed by any of the
619621
# allowed delimiters,
620622
# followed by any space/tab
621623
(?P<value>.*)$ # everything up to eol
622624
"""
623625
_OPT_NV_TMPL = r"""
624-
(?P<option>.*?) # very permissive!
626+
(?P<option> # very permissive!
627+
(?:(?!{delim})\S)* # non-delimiter non-whitespace
628+
(?:\s+(?:(?!{delim})\S)+)*) # optionally more words
625629
\s*(?: # any number of space/tab,
626630
(?P<vi>{delim})\s* # optionally followed by
627631
# any of the allowed
@@ -1145,26 +1149,6 @@ def _handle_option(self, st, line, fpname):
11451149
# an option line?
11461150
st.indent_level = st.cur_indent_level
11471151

1148-
# Fast path: if no delimiter is present, skip the regex to avoid
1149-
# quadratic backtracking (gh-146333). When allow_no_value is True,
1150-
# treat the whole line as an option name with no value.
1151-
if not any(d in line.clean for d in self._delimiters):
1152-
if self._allow_no_value:
1153-
st.optname = self.optionxform(line.clean.strip())
1154-
if not st.optname:
1155-
st.errors.append(ParsingError(fpname, st.lineno, line))
1156-
return
1157-
if (self._strict and
1158-
(st.sectname, st.optname) in st.elements_added):
1159-
raise DuplicateOptionError(st.sectname, st.optname,
1160-
fpname, st.lineno)
1161-
st.elements_added.add((st.sectname, st.optname))
1162-
st.cursect[st.optname] = None
1163-
return
1164-
else:
1165-
st.errors.append(ParsingError(fpname, st.lineno, line))
1166-
return
1167-
11681152
mo = self._optcre.match(line.clean)
11691153
if not mo:
11701154
# a non-fatal parsing error occurred. set up the

0 commit comments

Comments
 (0)