Software-Tests automatisch erzeugen: Frische Ansätze für Forschung, Praxis und Lehre
Andreas Zeller, CISPA Helmholtz-Zentrum für Informationssicherheit, Saarbrücken
Automatisch erzeugte Softwaretests können mit wenig menschlichem Aufwand viele Fehler finden. In diesem Vortrag stelle ich aktuelle Techniken zur Testerzeugung vor, die für ein gegebenes Programm vollautomatisch dessen Eingabesprache ableiten und aus den so entstehenden Grammatiken große Mengen gültiger Testeingaben ableiten. Unser grammatikbasierter LangFuzz-Testgenerator hat so in den JavaScript-Interpretern von Firefox, Chrome und Edge tausende Fehler gefunden. Die Techniken sind in dem interaktiven Buch “Generating Software Tests” (www.fuzzingbook.org) zusammengefasst. In einer Mischung von Text und Programmcode können Leser im Browser direkt mit den Programmen experimentieren und ihren Code live ergänzen und erweitern.
Andreas Zeller ist Forscher am CISPA Helmholtz-Zentrum für Informationssicherheit und Professor für Softwaretechnik an der Universität des Saarlandes, beide in Saarbrücken. Seine Forschung beschäftigt sich mit der Analyse großer Software-Systeme und ihre Entwicklungsgeschichte. In 2010 wurde Zeller zum Fellow der ACM ernannt für seine Beiträge zur automatischen Fehlersuche und der Analyse von Software-Archiven, für die er 2018 als erster Deutscher den Outstanding Research Award der ACM SIGSOFT erhielt. Seine aktuellen Projekte kombinieren Testerzeugung und Specification Mining, gefördert durch den Europäischen Forschungsrat (ERC).
9. @AndreasZeller
• Annahme: Ich möchte einen Parser testen,
der komplexe Eingaben verarbeitet
• Um am Parser vorbeizukommen, braucht
man syntaktisch gültige Eingaben
Grammatik-basiertes Fuzzing
Parser
10. LangFuzz (2012)
• Fuzzer für JavaScript und andere
Sprachen
• Nutzt Grammatiken, um
Eingaben zu erzeugen
• Nutzt die Grammatik, um
existierende Eingaben zu
verarbeiten
20. @AndreasZeller
JavaScript
Parser
JavaScript-Fuzzing
hase III
est case into
ter, check for
and assertions
1 var haystack = "foo";
2 var re text = "^foo";
3 haystack += "x";
4 re text += "(x)";
5 var re = new RegExp(re text);
6 re. test(haystack);
7 RegExp.input = Number();
8 print(RegExp.$1);
Figure 2: Test case generated by LangFuzz, crashing the
JavaScript interpreter when executing Line 8. The static
access of RegExp is deprecated but valid. Reported asHoller, Herzig, Zeller: "Fuzzing with Code Fragments", USENIX 2012
30 Chromium + Mozilla Security Rewards
53,000 US$ als Bug-Prämien
C. Holler
22. @AndreasZeller
Grammatiken lernen
• Jedes Verhalten eines Programmms kann durch dessen
Eingabe hervorgerufen werden
• Wir sehen die Eingabe als eine Folge von Zeichen
(Buchstaben, Interaktionen, Ereignisse…)
• Eine Sprache beschreibt die erlaubten Zeichenfolgen
• Wir möchten die Eingabesprache eines Programmms lernen
31. @AndreasZeller
Eingaben verfolgen
Wir verfolgen Eingaben durch den Programmlauf:
1. Dynamisches Tainting versieht jedes Zeichen
der Eingabe mit einem Etikett, das mit jeder
Berechnung weitergereicht wird
2. Eingaben wiedererkennen prüft Zeichenketten
im Speicher, ob sie Teil der Eingabe sind
33. @AndreasZeller
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
scheme = 'http'
netloc = 'user:pass@www.google.com:80'
<start> ::= http://user:pass@www.google.com:80/path#ref
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
34. @AndreasZeller
<start> ::= http://<netloc>/path#ref
<netloc> ::= user:pass@www.google.com:80
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
scheme = 'http'
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
35. @AndreasZeller
Grammatiken lernen
fragment = 'ref'
url = '/path'
path = '/path'
<start> ::= <scheme>://<netloc>/path#ref
<netloc> ::= user:pass@www.google.com:80
<scheme> ::= http
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
36. @AndreasZeller
<start> ::= <scheme>://<netloc><path>#ref
<netloc> ::= user:pass@www.google.com:80
<scheme> ::= http
<path> ::= /path
fragment = 'ref'
url = '/path'
Grammatiken lernen
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
37. @AndreasZeller
Grammatiken lernen
url = '/path'
<start> ::= <scheme>://<netloc><path>#<fragment>
<netloc> ::= user:pass@www.google.com:80
<scheme> ::= http
<path> ::= /path
<fragment> ::= ref
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
38. @AndreasZeller
Grammatiken lernen
<start> ::= <scheme>://<netloc><path>#<fragment>
<netloc> ::= user:pass@www.google.com:80
<scheme> ::= http
<path> ::= <url>
<fragment> ::= ref
<url> ::= /path
• Für jede (Variable, Wert) im Programmlauf, wobei
Wert in der Eingabe auftritt:
1. Ersetze alle Auftreten von Wert durch <Variable>
2. Füge eine neue Regel <Variable> ::= Wert hinzu
40. @AndreasZeller
AUTOGRAM
AUTOGRAM ist ein Grammatik-Lerner für Java-Programme
Durch systematische Experimente lernt AUTOGRAM
• Wiederholungen
• Optionale Teile
• Häufige Elemente (Zahlen, Bezeichner…)
Höschele, Zeller: "Mining Input Grammars from Dynamic Taints", ASE 2016
47. @AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
0 ✔
Test-Generator Programm
48. @AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
0 ✔
Test-Generator Programm
51. @AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
false ✔
Test-Generator Programm
52. @AndreasZeller
Lernen ohne Beispiele
– prüft auf Ziffer
– prüft auf "true"/"false"
– prüft auf '"'
– prüft auf '['
– prüft auf '{'
false ✔
Test-Generator Programm
56. @AndreasZeller
Fuzzing ohne Beispiele
PYGMALION Prototyp für Python-Programme
Program
Under Test
Parser-Directed
Test Generator
ComparisonsTests Dynamic Taints
Grammar
Learner
Test Inputs
Inputs +
Equivalence Classes
Grammar
Fuzzer
Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars", ArXiV 2018
Perfekte Abdeckung, beispiellose Effizienz
57. @AndreasZeller
Fuzzing ohne Beispiele
PYGMALION Prototyp für Python-Programme
Program
Under Test
Parser-Directed
Test Generator
ComparisonsTests Dynamic Taints
Grammar
Learner
Test Inputs
Inputs +
Equivalence Classes
Grammar
Fuzzer
Gopinath, Mathis, Höschele, Kampmann, Zeller: "Sample-Free Learning of Input Grammars"
Perfekte Abdeckung, beispiellose Effizienz
61. @AndreasZeller
Eine Quelle für Alles
HTML
Fuzzing: Breaking Things
with Random Inputs
A Chapter of “Generating Software Tests”
Author:
Andreas Zeller,
Rahul Gopinath,
Marcel Böhme,
Gordon Fraser, and
Christian Holler
February 20, 2019
PDF
Code
+ Folien
+ EPUB
+ LaTeX
+ Word
+ TXT …Notebook