Runaway Reguläre Ausdrücke: Katastrophale Backtracking
Betrachten wir den regulären Ausdruck (x + x +) + y. Bevor Sie schreien entsetzt und sagen dieses erfundene Beispiel als xx + y geschrieben sein sollte genau passen die gleiche ohne diese schrecklich verschachtelten quantifiers: einfach mal davon aus, dass jeder „x“ etwas komplexer darstellt, mit bestimmten Zeichenfolge wird von beide "x" abgestimmt. Ein reales Beispiel finden Sie im Abschnitt HTML unten.
Lassen Sie uns sehen, was passiert, wenn Sie diese Regex auf xxxxxxxxxxy anwenden. Die erste x + wird alle 10 x Zeichen übereinstimmen. Die Sekunde x + schlägt fehl. Die erste x + dann Backtracks zu 9 Übereinstimmungen, und die zweite nimmt die verbleibenden x. Die Gruppe hat jetzt einmal abgestimmt. Die Gruppe wiederholt, aber schlägt bei der ersten x + fehl.Da eine Wiederholung ausreichend war, stimmt die Gruppe überein. y passt y und eine Gesamtübereinstimmung ist gefunden. Der Regex wird als funktionsfähig deklariert, der Code wird an den Kunden gesendet, und sein Computer explodiert. Fast.
Der obige Regex wird unschön, wenn die y in der Betreffzeile fehlt. Wenn y fehlschlägt, die Regex-Engine Backtracks. Die Gruppe hat eine Iteration, in die sie zurückgehen kann. Die Sekunde x + stimmte nur ein x, so dass es nicht zurückverfolgen kann. Aber das erste x + kann ein x aufgeben. Die zweite x + prompt entspricht xx. Die Gruppe hat wieder eine Iteration, schlägt die nächste aus, und die y schlägt fehl. Backtracking wieder, die Sekunde x + hat jetzt eine Backtracking Position, reduziert sich auf x anzupassen. Die Gruppe versucht eine zweite Iteration. Der erste x + Treffer, aber der zweite ist am Ende der Zeichenfolge stecken. Backtracking wieder, die erste x + in die erste Iteration der Gruppe reduziert selbst auf 7 Zeichen. Die zweite x + entspricht xxx. Fehlt y, wird die zweite x + auf xx und dann auf x reduziert. Jetzt kann die Gruppe eine zweite Iteration, , mit einem x für jedes x + abgleichen. Aber diese (7,1), (1,1) Kombination scheitert auch. Also geht es zu (6,4) und dann (6,2) (1,1) und dann (6,1), (2,1) und dann (6,1), (1,2) und dann denke ich, dass du startest um die Drift zu bekommen.
Wenn Sie versuchen, diese Regex auf einem 10-fach-String in RegexBuddy des Debuggers, wird es 2558 Schritte unternehmen, um die endgültige y, um herauszufinden, fehlt. Für einen 11x-String benötigt es 5118 Schritte. Für 12 dauert es10238 Schritte. Natürlich haben wir hier eine exponentielle Komplexität von O (2^n). Bei 21x beugt sich der Debugger bei 2,8 Millionen Schritten, Diagnose eines schweren Falles von katastrophalen Backtracking.
RegexBuddy verzeiht, dass er erkennt es im Kreis und bricht das Spiel Versuch. Andere Regex Motoren (wie .NET) wird weiter für immer, während andere mit einen Stapelüberlauf (wie Perl, vor Version 5.10) abstürzen. Stack-Überläufe sind besonders unangenehm auf Windows, seit neigen sie dazu, Ihre Anwendung verschwinden ohne eine Spur oder Erklärung. Seien Sie sehr vorsichtig, wenn Sie einen Webdienst ausführen, der es Benutzern ermöglicht, ihre eigenen regulären Ausdrücke zu liefern. Menschen mit wenig Regex-Erfahrung haben überraschende Fähigkeit, mit exponentiell komplexen regulären Ausdrücke zu kommen.
Ich nehme an, Sie werden es in Code behandeln müssen. Ich schlage vor, Sie kontaktieren den Autor von Regexbuddy und fragen, was benötigt wird, um dieses Szenario zu erkennen.
Nein, es ist ein bekanntes Problem, dass Benutzer ihre eigenen regulären Ausdrücke eingeben dürfen. : -/ –
Pb.NET? Ist das die französische Version von VB.NET? Entschuldigung, ich lerne immer noch diese beiden Sprachen. : P – Cerebrus
@PierrOz: Ihre Frage scheint irreführend zu sein. Es geht nicht um die Regex. Es geht um den Prozess und wie man es abbricht, wenn es zu lange dauert. Aber alle Antworten, die Sie bekommen, werden Ihnen sagen, wie Sie Ihren Regex optimieren können. Meiner Meinung nach fragen Sie das nicht. – Cerebrus