C-Reduce-Techniken, die sich in jeder Sprache verwenden lassen
(bernsteinbear.com)- C-Reduce ist ein Werkzeug zum Verkleinern von Reproduktionscode für C-Compiler-Bugs, lässt sich aber auch auf andere Sprachen anwenden, wenn es eine deterministische Bedingung, eine schnelle Reproduktion und bearbeitbare Quelldateien gibt
- Das Beispiel zeigt den Prozess, einen Bug zu verkleinern, der beim Ausführen von scrapscript in RustPython auftrat;
interesting.shprüft dabei anhand einer bestimmten Fehlermeldung, ob der Fehler reproduziert wurde - Allein mit
creduce --not-c interesting.sh scrapscript.pywurde die Dateigröße schnell reduziert, und schon früh war ein Fortschritt von fast 50 % Reduktion zu sehen --not-cist eine Option, die C-spezifische Reduktions-Pässe vermeidet, und hilft bei Eingaben wie Python, unnötige Laufzeit zu sparen- Wenn sich die Bedingung für die Fehlerreproduktion als kurzes Skript formulieren lässt, können auch Bug-Reports für Nicht-C-Sprachen mit C-Reduce kleiner und leichter handhabbar gemacht werden
Bedingungen für den Einsatz von C-Reduce bei Nicht-C-Eingaben
- C-Reduce ist ein von Regehr und Kollegen entwickeltes Werkzeug zur Minimierung von Reproduktionscode für C-Compiler-Bugs
- Wenn eine 10.000 Zeilen lange C-Datei einen Clang-Bug auslöst, kann es verwendet werden, um die riesige Datei automatisch zu verkleinern, statt sie unverändert einzureichen
- Es wirkt wie ein C-spezifisches Werkzeug, kann aber auch für Eingaben anderer Sprachen verwendet werden, wenn die folgenden Bedingungen erfüllt sind
-
Deterministische Bedingung
- Eine relativ schnelle Reproduktionsmethode, die der Reduktionsgeschwindigkeit zugutekommt
- Eine oder mehrere bearbeitbare Quelldateien, die C-Reduce verkleinern kann
- Deterministische Bedingungen lassen sich mit einem Schleifen-Wrapper auch probabilistisch nachbilden
-
Beispiel: Verkleinerung einer RustPython-Bug-Reproduktion
- Beim Ausführen von scrapscript in RustPython trat ein Bug auf; um ihn zu melden, wurde das Skript
interesting.shgeschrieben - Das Skript führt
scrapscript.pymit dem absoluten Pfad zur RustPython-Binärdatei aus und sucht dann in der Ausgabe einschließlich Standardfehler nach der folgenden Zeichenkettetried to push value onto stack but overflowed max_stackdepth
- Der Ausführungsbefehl lautet wie folgt
creduce --not-c interesting.sh scrapscript.py
- C-Reduce führt den Interestingness-Test parallel aus und verkleinert dabei die Dateigröße schnell
- Beispielhafte Fortschrittswerte werden als 0.5 %, 9.2 %, 18.1 %, 47.5 % usw. angezeigt
- Innerhalb weniger Sekunden wird die Datei um fast 50 % verkleinert
- Zum Zeitpunkt des Schreibens war bereits eine Reduktion von 96.9 % erreicht
- Ohne
--not-cverwendet C-Reduce zahlreiche C-spezifische Pässe- Bei Python-Eingaben können diese Pässe die Laufzeit verlangsamen
- Das eigentliche Ergebnis wird dadurch wahrscheinlich nicht wesentlich verändert
- Verwandte Inhalte wurden später auf die Seite Delta debugging verschoben
1 Kommentare
Hacker-News-Kommentare
Da keine reduzierte Datei geteilt wurde, habe ich es selbst ausprobiert. Ich habe
RustPythongebaut,scrapscript.pygeholt, den Pfad ininteresting.shgeändert und es mitnix run nixpkgs#creduce -- --not-c interesting.sh scrapscript.pyausgeführt. Am Ende blieb es bei ungefähr 96,4 %, 7347 Byte stehen; das Ergebnis steht unter https://gist.github.com/judofyr/47cba8a20cb2cd5798943ef975d0...shrinkrayreduziert es nach etwa 10 Minuten auf 162 Byte: https://gist.github.com/DRMacIver/ee025c90b4867125b382a13aaa...Wenn man es länger laufen lässt, wird es vielleicht noch etwas besser, aber es sah fast so aus, als würde es nicht mehr weiterkommen, also wurde mir langweilig und ich habe abgebrochen
Auch John Regehr, der Autor von C-Reduce, empfiehlt, für diesen Zweck
Shrinkrayauszuprobieren.Shrinkraysei darauf ausgelegt, formatunabhängig zu arbeiten, und passe gut zu Fällen, in denen C-Reduce nicht gut ist: https://mastodon.social/@regehr/113489759789563570Shrinkray? https://github.com/DRMacIver/shrinkraycviseerwähnen: https://github.com/marxin/cviseEine Python-Alternative, die auch mit Nicht-C-Sprachen recht gut funktioniert
Es gibt ein Paper von John Regehr und weiteren Autoren aus dem Jahr 2012, das die Funktionsweise erklärt: https://fsl.cs.illinois.edu/publications/regehr-chen-cuoq-ei...
Soweit ich mich erinnere, sind die meisten domänenunabhängigen Reduktionen in C-Reduce eher schlichtes Brute Force
Ich habe C-Reduce gerade erst entdeckt und bin schon fasziniert. Es fühlt sich ähnlich an wie damals, als ich zum ersten Mal git bisect entdeckt habe
Das sollte ich mir irgendwo im Hinterkopf behalten, damit ich es verwenden kann, wenn irgendwann die passende Situation kommt
Ich überlege, das einzurichten. Da VICE offenbar eine Funktion unterstützt, mit der es in Dateien des Host-Betriebssystems „ausgibt“, könnte man die Tests wohl im Emulator laufen lassen
Delta Debugging ist kein neues Konzept: https://en.wikipedia.org/wiki/Delta_debugging
Meine eigene Delta-Debugging-Implementierung
deltaist über 19 Jahre alt: https://github.com/dsw/deltaDamals, als Microsoft Open Source noch als „Krebsgeschwür“ bezeichnete, schickte Microsoft Research jemanden in mein Büro, um mich zu bitten, es öffentlich freizugeben, also habe ich es als Open Source veröffentlicht. Auch in Latners Einführung zu LLVM wird es als „standardmäßiges Delta-Debugging-Tool“ erwähnt, es ist also ein recht bekanntes Werkzeug: https://aosabook.org/en/v1/llvm.html
Die Schlussfolgerung ist also, dass effektive Programmreduktion mehr erfordert als simples Delta Debugging. Natürlich ist auch C-Reduce inzwischen ein 12 Jahre altes Werkzeug
Gleichzeitig ist das verlinkte LLVM-Tool
BugPointauf LLVM IR beschränkt, während C-Reduce allgemeiner wirkt. Automatische Tools und Techniken zur Minimierung von Test-Cases sind den meisten Entwicklern noch immer unbekannt; daher kann dieser Artikel nützlich sein, auch wenn die Idee in diesem Bereich schon lange bekannt istIch habe einen Artikel mit Vorher-nachher-Beispielen gefunden: https://pramodkumbhar.com/2024/01/c-reduce-systematically-ta...
Trotzdem verstehe ich noch nicht gut, woher es bei jeder Iteration weiß, was entfernt werden soll. Ein gewisses Maß an Tokenisierung muss es geben, aber ich weiß nicht, wie das über mehrere Programmiersprachen hinweg funktioniert
creduceist großartigAls ich ein obskures LLVM-Target-Backend entwickelte, hatte ich ein Testskript, das mit
CSmithstundenlang zufällige Testprogramme generierte. Wenn es zu einem Crash kam, ließ es automatisch C-Reduce laufen und legte eine Datei zum Untersuchen ab; das war wirklich eine enorme HilfeFunktioniert auch gut mit SQL. Ich nutze es in der Praxis und bin über https://github.com/sqlancer/sqlancer?tab=readme-ov-file#redu... darauf gestoßen.
Wenn nicht erklärt wird, warum es auch mit anderen Sprachen als C funktioniert, ist das schwer zu glauben. Ich halte es nicht für gelogen, aber dass das ohne LLM geht, irritiert mich.
Wenn man etwa die Eingabe nach C-Art tokenisiert und dann zufällig Stücke der Länge etwa 1 bis 13 verwirft, funktioniert das bei den meisten C-ähnlichen Sprachen gut, weil sie ähnliche Tokenisierungsregeln haben; so lassen sich unnötige Qualifier oder Attribute gut entfernen. Auch ein Pass, der Einheiten mit ausgeglichenen Klammern
(),{},[]entfernt, ist in fast allen Sprachen nützlich. Das Entfernen von Kommentaren und Whitespace ist ebenfalls effektiv, da viele Sprachen wie C die Stile/* */und//verwenden.Tatsächlich gibt es nicht viele Passes, die sehr spezifisch für C/C++ sind. Nach meiner Erfahrung ist eine der großen Schwächen von
creduce, dass es bei Reduktionsschritten zum Entfernen von Templates – also bei einer Aufgabe, die vergleichsweise leicht zu automatisieren scheint – wirklich schlecht ist.Manche Transformationen sind ziemlich C-spezifisch und nutzen das Clang-Frontend, andere sind recht allgemein und dürften bei Algol-artigen Sprachen im Großen und Ganzen funktionieren. Da es ein modulares Tool ist, kann man bei Bedarf auch Transformationen hinzufügen, die andere Sprachen verstehen.
Gemeint sind hier Dinge wie Algorithmen, nicht unheimliches Machine Learning. Dazu gehört auch so etwas wie Prolog für AI zu verwenden, mit dem kleinen Nachteil, dass es für den Zweck, AI zu bauen, nicht besonders gut funktioniert.
creducedas veränderte Eingabeskript ausführen und meine Dateien löschen oder mein Mittagessen wegfuttern?Wie ist es im Vergleich zu
dustmite? https://dlang.org/blog/2020/04/13/dustmite-the-general-purpo....