Kozea / tinycss

tinycss is a complete yet simple CSS parser for Python.
https://tinycss.readthedocs.io/
Other
88 stars 20 forks source link

parse_stylesheet(['', 'b']) hangs indefinitely #14

Open berleant opened 7 years ago

berleant commented 7 years ago
Python 3.5.1 |Continuum Analytics, Inc.| (default, Dec  7 2015, 11:16:01) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import tinycss
>>> parser = tinycss.make_parser()
>>> parser.parse_stylesheet(['a', 'b'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ubuntu/anaconda3/envs/python3/lib/python3.5/site-packages/tinycss/css21.py", line 395, in parse_stylesheet
    tokens = tokenize_grouped(css_unicode)
  File "/home/ubuntu/anaconda3/envs/python3/lib/python3.5/site-packages/tinycss/tokenizer.py", line 202, in tokenize_grouped
    return regroup(tokenize_flat(css_source, ignore_comments))
  File "tinycss/speedups.pyx", line 108, in tinycss.speedups.tokenize_flat (tinycss/speedups.c:2819)
TypeError: expected string or bytes-like object
>>> parser.parse_stylesheet('')
<Stylesheet 0 rules 0 errors>
>>> parser.parse_stylesheet(['', 'b'])
^C^C^C^C^C
SimonSapin commented 7 years ago

parse_stylesheet expects a string. Some of the things it does with it is getting its length with len(css_source) and indexing it to get a character with char = css_source[pos] where pos is an integer. These happen to work on a list, but that’s an accident. With a string char is a character represented as a string whose length is always 1. In some cases like this one, pos is incremented by len(char) which is normally 1. But with a list containing an empty string, pos is incremented by 0 and the next iteration of the loop does the same thing again. And you get an infinite loop.

Maybe we can tweak the code so that this situation raises an exception instead of looping infinitely. But calling parse_stylesheet with a list rather than a string is always an error in the first place.

berleant commented 7 years ago

Looping indefinitely seems like non-ideal behavior to me, but you're right, it's not technically a bug.