jaraco / jaraco/cssutils

CSS file of 320 bytes takes 10+ seconds to parse

オープン
#18 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る
help wanted
主要言語
Python
スター
92
フォーク
30
PR マージ指標
30日以内にマージされた PR はありません

説明

I've encountered CSS file which `cssutils` library takes lots of seconds to parse (in fact, almost infinite).
After some investigation I've minified problematic sample (as possible) and prepared reproducible code example.
On my laptop (core i7-8550U) it takes **14 seconds** to parse file with just one line and 320 bytes of text.

Original file has 20kBytes of text and parser does not finish it in several hours.

Code:
https://gist.github.com/vdmit/ef9007170fa1c616cf5aba1fcebfce87
I'm using:
- latest stable `cssutils` release 2.3.0 from pypi repo
- python 3.8.10
- Ubuntu 20.04 linux distribution.

Notes:
- original CSS file was malformed and even contained non-printable characters. My minified example is still not valid CSS file, but it is a plain ANSI file.
- Adding line break in any place fixes problem;
- Removing of last style expression (`.s11...` reduces execution time from 14 seconds to 3 seconds).
- Adding of one more style expression increases execution time from 14 seconds to 50, 2 more styles yields ~260 seconds.

So, there is a **exponential** complexity somewhere, which is strange.

Traceback of interrupted script is following:

```python3 cssutils_infinite_loop_bug_example.py
Traceback (most recent call last):
File "cssutils_infinite_loop_bug_example.py", line 10, in
sheet = css_parser.parseString(cssText=css_text)
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/parse.py", line 147, in parseString
sheet._setCssTextWithEncodingOverride(
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/css/cssstylesheet.py", line 408, in _setCssTextWithEncodingOverride
self.cssText = cssText
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/css/cssstylesheet.py", line 331, in _setCssText
wellformed, expected = self._parse(
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/util.py", line 484, in _parse
expected = p(expected, seq, token, tokenizer)
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/css/cssstylesheet.py", line 313, in ruleset
rule.cssText = self._tokensupto2(tokenizer, token)
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/util.py", line 343, in _tokensupto2
for token in tokenizer:
File "/home/vdmit/.local/lib/python3.8/site-packages/cssutils/tokenize2.py", line 172, in tokenize
match = matcher(text, pos) # if no match try next production
KeyboardInterrupt
```

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

調査の方向性

リンクされた再現可能な例から始め、cssutils/parse.py、cssutils/css/cssstylesheet.py、util.py、tokenize2.py を通る報告されたパスを追跡します。改行とスタイル式を変化させながらサンプルのベンチマークを実行し、入力のパース時間が指数関数的にならなくなったことを示す回帰テストを追加します。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
performance
issue の種類
バグ
難易度
4/5
見積もり時間
3〜5日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
42/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。