Found by a local-strict-review pass while working #2386 on feature/auto-2386. It predates that branch, which leaves SUMMARY unchanged.
SUMMARY in scripts/pr_review.py, <summary(?:\s+[A-Za-z][^>]*)?>(.*?)</summary> with re.DOTALL, has two arms that scan to the end of the text when nothing closes them. The attribute tail [^>]* crosses lines and stops only at a >, and the lazy (.*?) stops only at a </summary>. So a body of unclosed <summary openers costs quadratic time in unrecognized_in, which calls SUMMARY.findall over the body.
A constructed body of "<summary x\n" * n measured about 0.40s at 3000 lines, 1.60s at 6000, and 6.39s at 12000 (132000 characters) per call. A body of "<summary>\n" * n measured 0.41s at 3000 and 1.77s at 6000. GitHub caps a body at 65536 characters.
Done looks like: both arms are bounded so the scan is linear, for example the attribute tail stopping at < as #2386 did for DETAILS_TAG's opener, and the content arm stopping at the next <summary, with a timing test built from constructed text under the test file's shared BACKTRACK_BOUND, and the existing summary tests still passing.
Found by a
local-strict-reviewpass while working #2386 onfeature/auto-2386. It predates that branch, which leavesSUMMARYunchanged.SUMMARYinscripts/pr_review.py,<summary(?:\s+[A-Za-z][^>]*)?>(.*?)</summary>withre.DOTALL, has two arms that scan to the end of the text when nothing closes them. The attribute tail[^>]*crosses lines and stops only at a>, and the lazy(.*?)stops only at a</summary>. So a body of unclosed<summaryopeners costs quadratic time inunrecognized_in, which callsSUMMARY.findallover the body.A constructed body of
"<summary x\n" * nmeasured about 0.40s at 3000 lines, 1.60s at 6000, and 6.39s at 12000 (132000 characters) per call. A body of"<summary>\n" * nmeasured 0.41s at 3000 and 1.77s at 6000. GitHub caps a body at 65536 characters.Done looks like: both arms are bounded so the scan is linear, for example the attribute tail stopping at
<as #2386 did forDETAILS_TAG's opener, and the content arm stopping at the next<summary, with a timing test built from constructed text under the test file's sharedBACKTRACK_BOUND, and the existing summary tests still passing.