Skip to content

Commit 1e91d8e

Browse files
committed
Make _strptime escape regex syntax in format string to prevent use in internal regex.
1 parent 482c5f7 commit 1e91d8e

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

Lib/_strptime.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,17 @@ def sorter(a, b):
373373
return '%s)' % regex
374374

375375
def pattern(self, format):
376-
"""Return re pattern for the format string."""
376+
"""Return re pattern for the format string.
377+
378+
Need to make sure that any characters that might be interpreted as
379+
regex syntax is escaped.
380+
381+
"""
377382
processed_format = ''
383+
# The sub() call escapes all characters that might be misconstrued
384+
# as regex syntax.
385+
regex_chars = re_compile(r"([\\.^$*+?{}\[\]|])")
386+
format = regex_chars.sub(r"\\\1", format)
378387
whitespace_replacement = re_compile('\s+')
379388
format = whitespace_replacement.sub('\s*', format)
380389
while format.find('%') != -1:

Lib/test/test_strptime.py

+14
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,14 @@ def test_pattern(self):
168168
"did not find 'd' directive pattern string '%s'" %
169169
pattern_string)
170170

171+
def test_pattern_escaping(self):
172+
# Make sure any characters in the format string that might be taken as
173+
# regex syntax is escaped.
174+
pattern_string = self.time_re.pattern("\d+")
175+
self.failUnless(r"\\d\+" in pattern_string,
176+
"%s does not have re characters escaped properly" %
177+
pattern_string)
178+
171179
def test_compile(self):
172180
# Check that compiled regex is correct
173181
found = self.time_re.compile(r"%A").match(self.locale_time.f_weekday[6])
@@ -201,6 +209,12 @@ def test_blankpattern(self):
201209
self.failUnless(_strptime.TimeRE(test_locale).pattern("%Z") == '',
202210
"with timezone == ('',''), TimeRE().pattern('%Z') != ''")
203211

212+
def test_matching_with_escapes(self):
213+
# Make sure a format that requires escaping of characters works
214+
compiled_re = self.time_re.compile("\w+ %m")
215+
found = compiled_re.match("\w+ 10")
216+
self.failUnless(found, "Escaping failed of format '\w+ 10'")
217+
204218
class StrptimeTests(unittest.TestCase):
205219
"""Tests for _strptime.strptime."""
206220

0 commit comments

Comments
 (0)