Skip to content

Commit 1b24013

Browse files
tonghuarootmiss-islington
authored andcommitted
gh-153404: Silently ignore non-decimal digits in robots.txt Crawl-delay and Request-rate (GH-153405)
str.isdigit() returned True for non-decimal Unicode digits such as U+00B2 SUPERSCRIPT TWO, which int() then rejected with ValueError. (cherry picked from commit 597ec2d) Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com>
1 parent 38c3f11 commit 1b24013

3 files changed

Lines changed: 35 additions & 3 deletions

File tree

Lib/test/test_robotparser.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ def test_request_rate(self):
188188
parsed_request_rate.seconds,
189189
self.request_rate.seconds
190190
)
191+
else:
192+
self.assertIsNone(parsed_request_rate)
191193

192194

193195
class EmptyFileTest(BaseRequestRateTest, unittest.TestCase):
@@ -246,6 +248,32 @@ class InvalidCrawlDelayTest(BaseRobotTest, unittest.TestCase):
246248
bad = []
247249

248250

251+
class NonDecimalDigitsTest(BaseRequestRateTest, unittest.TestCase):
252+
# Non-decimal Unicode digits pass str.isdigit() but int() rejects
253+
# them, so the directive must be silently ignored, not raise.
254+
robots_txt = """\
255+
User-Agent: *
256+
Disallow: /tmp/
257+
Crawl-delay: ²
258+
Request-rate: ²/5
259+
"""
260+
good = ['/foo.html']
261+
bad = ['/tmp/']
262+
crawl_delay = None
263+
request_rate = None
264+
265+
266+
class NonDecimalDenominatorTest(BaseRequestRateTest, unittest.TestCase):
267+
robots_txt = """\
268+
User-agent: *
269+
Disallow: /tmp/
270+
Request-rate: 5/²
271+
"""
272+
good = ['/foo.html']
273+
request_rate = None
274+
bad = ['/tmp/']
275+
276+
249277
class AnotherInvalidRequestRateTest(BaseRobotTest, unittest.TestCase):
250278
# also test that Allow and Diasallow works well with each other
251279
robots_txt = """\

Lib/urllib/robotparser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,15 @@ def parse(self, lines):
143143
# before trying to convert to int we need to make
144144
# sure that robots.txt has valid syntax otherwise
145145
# it will crash
146-
if line[1].strip().isdigit():
146+
if line[1].strip().isdecimal():
147147
entry.delay = int(line[1])
148148
state = 2
149149
elif line[0] == "request-rate":
150150
if state != 0:
151151
numbers = line[1].split('/')
152152
# check if all values are sane
153-
if (len(numbers) == 2 and numbers[0].strip().isdigit()
154-
and numbers[1].strip().isdigit()):
153+
if (len(numbers) == 2 and numbers[0].strip().isdecimal()
154+
and numbers[1].strip().isdecimal()):
155155
entry.req_rate = RequestRate(int(numbers[0]), int(numbers[1]))
156156
state = 2
157157
elif line[0] == "sitemap":
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
:class:`urllib.robotparser.RobotFileParser` now silently ignores a
2+
``Crawl-delay`` or ``Request-rate`` value written with non-decimal digits
3+
(such as ``U+00B2 SUPERSCRIPT TWO``) instead of raising :exc:`ValueError`
4+
and aborting the parse of the whole ``robots.txt`` file.

0 commit comments

Comments
 (0)