DE102022204717A1 - Verfahren zum Testen eines Computerprogramms - Google Patents

Verfahren zum Testen eines Computerprogramms Download PDF

Info

Publication number
DE102022204717A1
DE102022204717A1 DE102022204717.6A DE102022204717A DE102022204717A1 DE 102022204717 A1 DE102022204717 A1 DE 102022204717A1 DE 102022204717 A DE102022204717 A DE 102022204717A DE 102022204717 A1 DE102022204717 A1 DE 102022204717A1
Authority
DE
Germany
Prior art keywords
computer program
determined
program
fuzzing
test
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Pending
Application number
DE102022204717.6A
Other languages
English (en)
Inventor
Max Camillo Eisele
Christopher Huth
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Robert Bosch GmbH
Original Assignee
Robert Bosch GmbH
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Robert Bosch GmbH filed Critical Robert Bosch GmbH
Priority to DE102022204717.6A priority Critical patent/DE102022204717A1/de
Priority to CN202310538453.9A priority patent/CN117056200A/zh
Publication of DE102022204717A1 publication Critical patent/DE102022204717A1/de
Pending legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software
    • G06F11/3668Software testing
    • G06F11/3672Test management
    • G06F11/3676Test management for coverage analysis
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software
    • G06F11/3668Software testing
    • G06F11/3672Test management
    • G06F11/3688Test management for test execution, e.g. scheduling of test suites
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F11/00Error detection; Error correction; Monitoring
    • G06F11/36Preventing errors by testing or debugging software
    • G06F11/3668Software testing
    • G06F11/3672Test management
    • G06F11/3684Test management for test design, e.g. generating new test cases

Abstract

Gemäß verschiedenen Ausführungsformen wird ein Verfahren zum Testen eines Computerprogramms beschrieben, aufweisend Ermitteln eines Computerprogrammteils des Computerprogramms, der intensiv getestet werden soll, Durchführen mehrerer Testdurchläufe für das Computerprogramm mit unterschiedlichen Eingaben für das Computerprogramm, und, bei jedem Testdurchlauf für das Computerprogramm, wenn der ermittelte Computerprogrammteil erreicht wurde: Durchführen mehrerer Testdurchläufe für den ermittelten Computerprogrammteil, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Computerprogrammteils in dem Testdurchlauf für das Computerprogramm hat, mit unterschiedlichen Eingaben für den ermittelten Computerprogrammteil.

Description

  • Stand der Technik
  • Die vorliegende Offenbarung bezieht sich auf Verfahren zum Testen eines Computerprogramms.
  • Ein wesentlicher Bestandteil der Entwicklung von Softwareanwendungen ist das Testen und, wenn Fehler gefunden werden, eine entsprechende Fehlerbereinigung. Insbesondere sollten Fehler, die zum Versagen einer Anwendung führen, identifiziert und korrigiert werden. Da die Frequenz, mit der Software aktualisiert wird, immer mehr zunimmt, sind Testverfahren wünschenswert, die ein effektives Testen in einer Situation ermöglichen, in der sich die zu testende Software schell ändert, und dementsprechend ein schnelles und nichtsdestotrotz zuverlässiges Testen von aktualisierter Software ermöglichen.
  • Offenbarung der Erfindung
  • Gemäß verschiedenen Ausführungsformen wird ein Verfahren zum Testen eines Computerprogramms bereitgestellt, aufweisend Ermitteln eines Computerprogrammteils des Computerprogramms, der intensiv getestet werden soll, Durchführen mehrerer Testdurchläufe für das Computerprogramm mit unterschiedlichen Eingaben für das Computerprogramm, und, bei jedem Testdurchlauf für das Computerprogramm, wenn der ermittelte Computerprogrammteil erreicht wurde: Durchführen mehrerer Testdurchläufe für den ermittelten Computerprogrammteil, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Computerprogrammteils in dem Testdurchlauf für das Computerprogramm hat, mit unterschiedlichen Eingaben für den ermittelten Computerprogrammteil.
  • Das oben beschriebene Verfahren ermöglicht ein schnelles Testen und ist damit zum Testen für Programmcode geeignet, der sich schnell ändert, auch dann, wenn Programmteile nicht unabhängig von dem gesamten Programm getestet werden können, z.B. weil ihr Verhalten vom Ausführungskontext eines Gesamtprogramms (z.B. zur Steuerung in einem Fahrzeug) abhängt, d.h. für kontextabhängigen Programmcode. Testen, bei dem man nur an bestimmten Programmteilen eines Programms interessiert ist (z.B. mittels Fuzzing), kann dadurch erheblich schneller durchgeführt werden.
  • Es sollte beachtet werden, dass bei einem Testdurchlauf für das Computerprogramm die Eingabe für den ermittelten Computerprogrammteil eigentlich fest vorgegeben ist. Gemäß dem oben beschriebenen Verfahren erfolgen für so eine (also dieselbe) Eingabe für das Computerprogramm aber Testläufe für unterschiedliche Eingaben für den ermittelten Computerprogrammteil. Es wird also beispielsweise ein Teil der Eingabe für das Computerprogramm, der die Eingabe für den ermittelten Computerprogrammteil bildet (oder sie definiert, z.B. durch dem ermittelten Computerprogrammteil vorhergehende Verarbeitung in dem Computerprogramm), für die Testdurchläufe für den ermittelten Computerprogrammteil variiert.
  • Auf der Grundlage der Testdurchläufe (für das (Gesamt-)Computerprogramm und den ermittelten Computerprogrammteil) kann ein Testergebnis erzeugt werden. Insbesondere können gefundene Fehler angezeigt werden und ggf. korrigiert werden.
  • Das Ermitteln eines Computerprogrammteils des Computerprogramms, der intensiv getestet werden soll, kann als das Ermitteln eines Computerprogrammteils verstanden werden, der intensiver getestet werden soll als ein oder mehrere andere Computerprogrammteile des Computerprogramms.
  • Die Ermittlung des Computerprogrammteils, der intensiv getestet werden soll, kann entsprechend einer Benutzereingabe erfolgen. Der Zustand der Programmumgebung ist beispielsweise der Zustand eine Datenverarbeitungseinrichtung, auf dem das Computerprogramm zum Testen ausgeführt wird, wobei die Datenverarbeitungseinrichtung allerdings auch emuliert werden kann.
  • Im Folgenden werden verschiedene Ausführungsbeispiele angegeben.
  • Ausführungsbeispiel 1 ist ein Verfahren zum Testen eines Computerprogramms, wie oben beschrieben.
  • Ausführungsbeispiel ist das Verfahren nach Ausführungsbeispiel 1, wobei das Ermitteln des Computerprogrammteils, der intensiv getestet werden soll, dadurch erfolgt, dass ein Computerprogrammteil des Computerprogramms ermittelt wird, der als letztes von mehreren Computerprogrammteilen des Computerprogramms geändert worden ist und dieser Computerprogrammteil als der Computerprogrammteil festgelegt wird, der intensiv getestet werden soll.
  • Besonders zuletzt geänderte Computerprogrammteile haben, da sie kaum oder gar nicht eingesetzt und/oder getestet wurden, ein hohes Fehlerrisiko. Das intensive Testen eines solchen Computerprogrammteils (oder auch mehrerer solcher Computerprogrammteile) kann deshalb im statistischen Mittel (für gegebenen Testaufwand) die meisten Fehler finden, d.h. liefert die höchste Testeffizienz.
  • Ausführungsbeispiel 3 ist das Verfahren nach Ausführungsbeispiel 1 oder 2, wobei das Ermitteln des Computerprogrammteils, der intensiv getestet werden soll, durch Vergleichen von kompilierten Versionen des Computerprogramms erfolgt.
  • In anderen Worten wird beispielsweise anhand der (ausführbaren) Binärdatei eines Computerprogramms in verschiedenen Versionen ermittelt, welche Computerprogrammteile sich geändert haben. Dies ermöglicht den Einsatz der obigen Vorgehensweise auch für den Fall, dass der Source-Code des Computerprogramms nicht zur Verfügung steht.
  • Ausführungsbeispiel 4 ist das Verfahren nach einem der Ausführungsbeispiele 1 bis 3, wobei die Testdurchläufe für das Computerprogramm gemäß Mutations-basiertem Fuzzing durchgeführt werden, wobei Eingaben für das Computerprogramm auf der Grundlage eines ersten Korpus durchgeführt werden, und die Eingaben für die Testdurchläufe für den ermittelten Computerprogrammteil gemäß Mutations-basiertem Fuzzing auf der Grundlage eines zweiten Korpus generiert werden, und wobei Änderungen des zweiten Korpus, die sich aus Ergebnissen der Testdurchläufe für den ermittelten Computerprogrammteil ergeben, in den ersten Korpus übernommen werden und/oder Änderungen des ersten Korpus, die sich aus Ergebnissen der Testdurchläufe für das Computerprogramm ergeben, in den zweiten Korpus übernommen werden.
  • In anderen Worten lernen die Korpi der beiden Fuzzer („Gesamt-Fuzzer“ für das Computerprogramm und „Sub-Fuzzer“ für den ermittelten Computerprogrammteil) voneinander, d.h. sie werden in gewissem Maße synchronisiert. Insbesondere könnten durch das intensive Testen des ermittelten Computerprogrammteils interessante Eingaben für das Computerprogramm gefunden werden. Dies erhöht die Effizienz des Testens, z.B. kann mittels weniger Testdurchläufen eine höhere Testabdeckung erreicht werden. Allgemein kann, wenn für eine Eingabe für den ermittelten Computerprogrammteil, mit dem ein Testdurchlauf für den ermittelten Computerprogrammteil durchgeführt wurde, ein interessantes Ergebnis erzielt wurde (z.B. ein neuer Ausführungspfad in dem ermittelten Computerprogrammteil gefunden wurde oder auch ein Fehler in dem ermittelten Computerprogrammteil gefunden wurde) ein Testdurchlauf des Programms mit einer Eingabe durchgeführt werden, die diese Eingabe enthält. Dadurch kann insbesondere festgestellt werden, ob ein Fehler, der durch die gefundene Eingabe in dem Computerprogrammteil auftritt, auch in dem (gesamten) Computerprogramm auftritt, oder dort abgefangen wird.
  • Ausführungsbeispiel 5 ist das Verfahren nach einem der Ausführungsbeispiele 1 bis 4, aufweisend Ermitteln eines Bestandteils des ermittelten Computerprogrammteils, der intensiver getestet werden soll als ein oder mehrere andere Bestandteile des ermittelten Computerprogrammteils und, bei jedem Testdurchlauf für den ermittelten Computerprogrammteil, Durchführen mehrerer Testdurchläufe für den ermittelten Bestandteil, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Bestandteils in dem Testdurchlauf für den ermittelten Computerprogrammteil hat, mit unterschiedlichen Eingaben für den ermittelten Unterprogrammteil.
  • In anderen Worten kann ein Bestandteil des ermittelten Computerprogrammteils besonders intensiv (intensiver als der Computerprogrammteil selbst) getestet werden. Die Herangehensweise des obigen Verfahrens kann also in mehreren Hierarchiestufen angewendet werden, wobei, je kleiner die Einheit des ermittelten Computerprogramms ist, die getestet werden soll, die Einheit desto intensiver getestet wird (da für jeden übergeordneten Testdurchlauf mehrere Testdurchläufe durchgeführt werden). Beispielsweise kann der Computerprogrammteil eine Programmkomponente und der Bestandteil eine Funktion sein.
  • Ausführungsbeispiel 6 ist das Verfahren nach einem der Ausführungsbeispiele 1 bis 5, wobei das Computerprogramm ein Steuerprogramm für eine Robotervorrichtung ist und die Robotervorrichtung abhängig von einem Ergebnis des Testens des Computerprogramms mit dem Computerprogramm gesteuert wird.
  • In anderen Worten kann ein Verfahren zum Steuern einer Robotervorrichtung bereitgestellt werden, bei dem mittels ein Steuerprogramm getestet wird, wobei ein Computerprogrammteil (z.B. einer, der kürzlich geändert wurde) intensiv getestet wird. Dies erlaubt ein schnelles Testen und damit einen schnellen Einsatz des geänderten Steuerprogramms, insbesondere von Aktualisierungen des Steuerprogramms und erhöht letztlich die Zuverlässigkeit und Sicherheit der Robotervorrichtung.
  • Ausführungsbeispiel 7 ist ein Testsystem, das eingerichtet ist, ein Verfahren nach einem der Ausführungsbeispiele 1 bis 6 durchzuführen.
  • Ausführungsbeispiel 8 ist ein Computerprogramm mit Befehlen, die, wenn sie durch einen Prozessor ausgeführt werden, bewirken, dass der Prozessor ein Verfahren nach einem der Ausführungsbeispiele 1 bis 6 durchführt.
  • Ausführungsbeispiel 9 ist ein Computerlesbares Medium, das Befehle speichert, die, wenn sie durch einen Prozessor ausgeführt werden, bewirken, dass der Prozessor ein Verfahren nach einem der Ausführungsbeispiele 1 bis 6 durchführt.
  • In den Zeichnungen beziehen sich ähnliche Bezugszeichen im Allgemeinen auf dieselben Teile in den ganzen verschiedenen Ansichten. Die Zeichnungen sind nicht notwendigerweise maßstäblich, wobei die Betonung stattdessen im Allgemeinen auf die Darstellung der Prinzipien der Erfindung gelegt wird. In der folgenden Beschreibung werden verschiedene Aspekte mit Bezug auf die folgenden Zeichnungen beschrieben.
    • 1 zeigt einen Computer für die Entwicklung und/oder das Testen von Softwareanwendungen.
    • 2 veranschaulicht ein Fuzzing eines Gesamtprogramms gemäß einem Ausführungsbeispiel.
    • 3 veranschaulicht ein Fuzzing auf verschiedenen Ebenen.
  • Die folgende ausführliche Beschreibung bezieht sich auf die begleitenden Zeichnungen, die zur Erläuterung spezielle Details und Aspekte dieser Offenbarung zeigen, in denen die Erfindung ausgeführt werden kann. Andere Aspekte können verwendet werden und strukturelle, logische und elektrische Änderungen können durchgeführt werden, ohne vom Schutzbereich der Erfindung abzuweichen. Die verschiedenen Aspekte dieser Offenbarung schließen sich nicht notwendigerweise gegenseitig aus, da einige Aspekte dieser Offenbarung mit einem oder mehreren anderen Aspekten dieser Offenbarung kombiniert werden können, um neue Aspekte zu bilden.
  • Im Folgenden werden verschiedene Beispiele genauer beschrieben.
  • 1 zeigt einen Computer 100 für die Entwicklung und/oder das Testen von Softwareanwendungen.
  • Der Computer 100 weist eine CPU (Central Processing Unit) 101 und einen Arbeitsspeicher (RAM) 102 auf. Der Arbeitsspeicher 102 wird zum Laden von Programmcode verwendet, z.B. von einer Festplatte 103, und die CPU 101 führt den Programmcode aus.
  • Im vorliegenden Beispiel wird davon ausgegangen, dass ein Benutzer beabsichtigt, mit dem Computer 100 eine Softwareanwendung zu entwickeln und/oder zu testen.
  • Dazu führt der Benutzer eine Softwareentwicklungsumgebung 104 auf der CPU 101 aus.
  • Die Softwareentwicklungsumgebung 104 ermöglicht es dem Benutzer, eine Anwendung (d.h. ein Computerprogramm, also eine Software) 105 für verschiedene Geräte 106, also ein Ziel-Hardware, wie eingebettete Systeme zum Steuern von Robotervorrichtungen, inklusive Roboterarme und autonome Fahrzeuge, oder auch für mobile (Kommunikations-)Geräte, zu entwickeln und zu testen. Dazu kann die CPU 101 als Teil der Softwareentwicklungsumgebung 104 einen Emulator ausführen, um das Verhalten des jeweiligen Geräts 106 zu simulieren, für das eine Anwendung entwickelt wird oder wurde. Der Computer kann aber auch eine Ausführung der Software 105 auf dem jeweiligen Zielgerät 106 steuern und so die Software 105 Testen. Wird sie nur zum Testen einer Software aus anderer Quelle eingesetzt, kann die Softwareentwicklungsumgebung 104 auch als Softwaretestumgebung angesehen werden bzw. ausgestaltet sein.
  • Der Benutzer kann die fertige Anwendung über ein Kommunikationsnetzwerk 107 an entsprechende Geräte 106 verteilen. Statt über ein Kommunikationsnetzwerk 107 kann dies auch auf andere Weise erfolgen, beispielsweise mittels eines USB-Sticks.
  • Bevor dies geschieht, sollte der Benutzer jedoch die Anwendung 105 testen und Fehler bereinigen (d.h. die Anwendung 105, d.h. das Programm, ggf. anpassen), um zu vermeiden, dass eine nicht ordnungsgemäß funktionierende Anwendung an die Geräte 106 verteilt wird. Dies kann auch der Fall sein, wenn der Benutzer die Anwendung 105 nicht selbst auf dem Computer 100 geschrieben hat.
  • Ein Testverfahren ist das sogenannte Fuzzing. Fuzzing oder Fuzz-Testing ist ein automatisiertes Software-Testverfahren, bei dem einem zu testenden Computerprogramm ungültige, unerwartete oder zufällige Daten als Eingaben zugeführt werden. Das Programm wird dann auf Ausnahmen wie Abstürze, fehlende fehlgeschlagene integrierte Code-Assertions oder potenzielle Speicherlecks hin überwacht.
  • Typischerweise werden Fuzzer (d.h. Testprogramme, die Fuzzing verwenden) zum Testen von Programmen verwendet, die strukturierte Eingaben verarbeiten. Diese Struktur ist z. B. in einem Dateiformat oder einem Dateiformat oder Protokoll spezifiziert und unterscheidet zwischen gültigen und ungültigen Eingaben. Ein effektiver Fuzzer erzeugt halb-gültige Eingaben die „gültig genug“ sind, um nicht direkt vom Eingabeparser des zu testenden Programms zurückgewiesen zu werden, aber „ungültig genug“ sind, um unerwartete Verhaltensweisen und Grenzfälle aufzudecken, die im zu testenden Programm nicht richtig behandelt werden.
  • Im Folgenden wird im Zusammenhang mit Fuzzing verwendete Terminologie beschrieben:
    • • Fuzzing oder Fuzz-Testing ist der automatisierte Test-Prozess, zufällig generierte Eingaben an ein Zielprogramm (zu testendes Programm) zu senden und seine Reaktion zu beobachten.
    • • Ein Fuzzer oder eine Fuzzing-Engine ist ein Programm, das automatisch Eingaben generiert. Sie ist also nicht mit der zu testenden Software verknüpft, und es wird auch keine Instrumentierung durchgeführt. Es hat jedoch die Fähigkeit, Code zu instrumentieren, Testfälle zu erzeugen und zu testende Programme auszuführen. Bekannte Beispiele sind AFL und Libfuzzer.
    • • Ein Fuzz-Target ist ein Softwareprogramm oder eine Funktion, die durch Fuzzing getestet werden soll. Ein Hauptmerkmal eines Fuzz-Targets sollte sein, dass es potenziell nicht vertrauenswürdige Eingaben annimmt, die vom Fuzzer während des während des Fuzzing-Prozesses erzeugt wird.
    • • Ein Fuzz-Test ist die kombinierte Version eines Fuzzers und eines Fuzz-Targets. Ein Fuzz-Target kann dann instrumentierter Code sein, bei dem ein Fuzzer mit seinen Eingaben verknüpft ist (d.h. diese liefert). Ein Fuzz-Test ist ausführbar. Ein Fuzzer kann auch mehrere Fuzz-Tests starten, beobachten und stoppen (normalerweise Hunderte oder Tausende pro Sekunde), jeder mit einer etwas anderen Eingabe, die vom Fuzzer erzeugt wird.
    • • Ein Testfall ist eine bestimmte Eingabe und ein bestimmter Testdurchlauf aus einem Fuzz-Test. Normalerweise werden für die Reproduzierbarkeit interessante Läufe (Finden von neuen Codepfaden oder Abstürzen) gespeichert. Auf diese Weise kann ein bestimmter Testfall mit der entsprechenden Eingabe auch auf einem Fuzz-Target ausgeführt werden, das nicht mit einem Fuzzer verbunden ist, z.B. die Release-Version eines Programms.
    • • Abdeckungsgesteuertes Fuzzing (engl. coverage-guided fuzzing) verwendet Code-Abdeckungsinformationen als Feedback während des Fuzzings, um zu erkennen, ob eine Eingabe die Ausführung neuer CodePfade oder Blöcke verursacht hat.
    • • Generator-basiertes Fuzzing (engl. generation-based fuzzing) verwendet vorheriges Wissen über das Zielprogramm (Fuzz-Target), um Testeingaben zu erstellen. Ein Beispiel für ein solches Vorwissen ist eine Grammatik, die der Eingabespezifikation des Fuzz-Targets entspricht, d.h. die Eingabe-Grammatik des Fuzz-Targets (d.h. des zu testenden Programms).
    • • Statische Instrumentierung ist das Einfügen von Anweisungen in ein (zu testendes) Programm, um Feedback über die Ausführung zu erhalten. Sie wird meist durch den Compiler realisiert und kann zum Beispiel die erreichten Codeblöcke während der Ausführung angeben.
    • • Dynamische Instrumentierung ist die Steuerung der Ausführung eines (zu testenden) Programms während der Laufzeit, um Feedback aus der Ausführung zu generieren. Sie wird meist durch Betriebssystem-Systemfunktionalitäten oder durch die Verwendung von Emulatoren realisiert.
    • • Mutations-basiertes Fuzzing ist das Erzeugen von neuen Eingaben unter Verwendung einer Menge (Korpus) von bekannten Eingaben durch zufällige Anwendungen von Mutationen darauf.
  • Beispielsweise bieten die Fuzzer AFL, Honggfuzz oder Libfuzzer mutationsbasiertes, abdeckungsgesteuertes Fuzzing zum Testen von Software mit geringem Aufwand. Dabei wird in jeder Runde (d.h. für jeden Testfall bzw. Testdurchlauf) eine Eingabe aus dem Eingabekorpus ausgewählt, zufällig mutiert und an das Zielprogramm gesendet. Wenn die neu generierte Eingabe ein zuvor nicht gesehenes Verhalten auslöst (z.B. neue ausgeführte Codepfade), wird sie dem Eingabekorpus hinzugefügt. Auf diese Weise kann der Eingaberaum eines Programms 105 mit wenig bis gar keiner Kenntnis des Eingabeformats des Programms erforscht werden.
  • Software wird in immer schnelleren Zyklen entwickelt. DevOps (Entwicklung und Betrieb) ist eine der neuen Ansätze, die schnelle Codeänderungen und Softwareeinsatz in den Mittelpunkt stellt. DevOps ist besonders geeignet für Cloud-basierte Microservices, kann aber auch für traditionellere Software-Entwicklung eingesetzt werden, wie z.B. Software für eingebettete Kfz-Steuergeräte.
  • Eine der größten Herausforderungen bei DevOps oder auch in DevSecOps, wo die Sicherheit hervorgehoben wird, ist die Anwendung von automatisierten Testwerkzeugen. DAST (Dynamic Application Security Testing) ist eine dieser Gruppen von Testwerkzeugen, die nicht direkt angewendet werden können. Normalerweise nimmt DAST nämlich eine längere Zeit in Anspruch, z. B. zwischen Stunden bis Tagen, während die komplette Erstellung und Verteilung von Software schneller abgeschlossen ist, z. B. im Zeitraum von in Minuten bis Stunden. Da DevOps schnelle Codeänderungen (oder schnelle Releases) anstrebt, ist DAST zu langsam, um mit den Rest der CI/CD-Pipeline (Continuous Integration/Continuous Delivery)-Pipeline mitzuhalten und bildet somit einen Engpass. Fuzzing ist eine dieser DAST-Methoden, die sehr gut darin ist, Fehler in Software zu finden. Allerdings ist Fuzzing eine der zeitaufwändigsten DAST-Methoden.
  • Unabhängige Software-Komponenten, wie z. B. Bibliotheken, können separat gefuzzt (d.h. mittels Fuzzing getestet) werden, um einen hohen Test-Durchsatz zu erreichen. Allerdings kann Programmcode, der vom Kontext eines Systems abhängt, wie er z.B. häufig in der Automobil-Software zu finden sind, nicht separat von dem System (z.B. einer Steuereinrichtung in einem Fahrzeug) ausgeführt werden. In so einem Fall muss das gesamte Programm getestet werden, um den kontextabhängigen Code zu testen. Solche Systemtests können aber zu einer Verlangsamung um mehrere Größenordnungen im Vergleich zu Unit-Tests führen.
  • Gemäß verschiedenen Ausführungsformen wird ein auf Fuzzing basierendes Testen eingesetzt, wobei es so ausgestaltet ist, dass es effektiv in einer sich schnell ändernden Quellcode-Umgebung angewendet werden kann, wie z.B. DevOps oder CI/CD (Continuous Integration/Continuous Development), und ein effektives Testen ermöglicht, wenn Programmteile nicht unabhängig von dem gesamten Programm getestet werden können. Dies wird erreicht, indem zusätzliche Fuzzer an gewünschten Stellen in einem Programm innerhalb eines Fuzzing-Testsetups für das (Gesamt-)Programms eingeführt werden. Diese zusätzlichen Fuzzer fokussieren sich beispielsweise auf Programmteile (z.B. Teile des Codes) des Programms, die kürzlich geändert wurden. Mittels eines Snapshot-Mechanismus wird der Ausführungskontext, wie er ist, wenn ein solcher Programmteil begonnen wird (z.B. bei einem Funktionsaufruf, mit dem der Programmteil beginnt) aufbewahrt, sodass ausgehend von diesem Kontext (d.h. diesem Systemzustand) mehrere Testläufe (in diesem Beispiel Fuzzing-Testläufe) ausgeführt werden können. Das System kann hierbei emuliert werden (z.B. von einem Emulator der Softwareentwicklungsumgebung 104) oder das Programm kann auf einem Gerät 106 getestet werden, auf dem es auch eingesetzt werden soll, sodass der Systemzustand der Zustand des Geräts 106 ist. Der Systemzustand beinhaltet Registerinhalte und Speicherinhalte (die das Programm betreffen, also von Speicherbereichen, auf die das Programm zugreift).
  • Wenn bei einem Fuzzing-Testdurchlauf des Gesamtprogramms der jeweilige Codeteil erreicht wird, wird für diesen ein (Sub-)Fuzzing-Prozess gestartet, der sich auf die Eingaben (z.B. Parameterwerte) dieses Programmteils (z.B. eine Funktion), also „lokale“ Parameter, konzentriert.
  • 2 veranschaulicht ein Fuzzing eines Gesamtprogramms gemäß einem Ausführungsbeispiel.
  • In diesem Beispiel besteht das Gesamtprogramm aus einem ersten Programmteil 201, einem zweiten Programmteil 202 und einem dritten Programmteil 203 in dieser Reihenfolge.
  • Für das Gesamtprogramm ist ein (Gesamt-Fuzzing-)Korpus 204 vorgesehen, für den ersten Programmteil ein erster Programmteil-Fuzzing-Korpus 205, für den zweiten Programmteil ein zweiter Codeteil-Fuzzing-Korpus 206 und für den dritten Programmteil ein dritter Codeteil-Fuzzing-Korpus 207.
  • Es wird nun angenommen, dass sich der zweite Codeteil in einen geänderten Programmteil 208 geändert hat. Für diesen wird dann ein vierter Programmteil-Fuzzing-Korpus 209 vorgesehen (dieser kann auf dem zweiten Programmteil-Fuzzing-Korpus 206 basieren, kann aber im gegenüber auch Änderungen enthalten).
  • Da das Programm nun den geänderten Programmteil 208 enthält, wird beim Testen (in diesem Beispiel Fuzzing) der geänderte Programmteil 208 ausführlicher (intensiver) getestet als der Rest des Programms (d.h. als der erste Programmteil 201 und der dritte Programmteil 203).
  • Dazu werden von einem (Gesamtprogramm-)Fuzzer mehrere Testdurchläufe des Gesamtprogramms durchgeführt. Für jeden dieser Testdurchläufe erzeugt der (Gesamtprogramm-)Fuzzer eine Eingabe für das Gesamtprogramm (z.B. eine Datei, die das Gesamtprogramm verarbeitet) auf der Grundlage des Gesamt-Fuzzing-Korpus 204 (z.B. durch Sampeln einer Eingabe aus dem Gesamt-Fuzzing-Korpus 204 und Mutieren desselben).
  • Wird nun bei einem Testdurchlauf der geänderte Programmteil 208 erreicht 208 (z.B. ein jeweiliger Funktionsaufruf oder anderer Eintritt in den geänderten Programmteil 208), so werden ausgehend von dem Zustand des Systems, das das Programm ausführt, den es zu diesem Punkt hat (z.B. bei dem Funktionsaufruf) von einem Sub-Fuzzer mehrere Testdurchläufe für den geänderten Codeblock 208 ausgeführt, wobei der Sub-Fuzzer für jeden solcher Sub-Testdurchläufe eine Eingabe auf Grundlage des vierten Programmteil-Fuzzing-Korpus erzeugt. Der Sub-Fuzzer und der Gesamtprogramm-Fuzzer können vom gleichen Typ sein (d.h. das gleiche Fuzzing-Programm), werden aber auf unterschiedliche Programme (nämlich Gesamtprogramm und Programmteil) angewendet. Hat der Sub-Fuzzer die mehreren Sub-Testdurchläufe durchgeführt (d.h. ist der Sub-Fuzzer fertig mit dem Sub-Fuzzing), stellt der Gesamtprogramm-Fuzzer den aktuellen Testdurchlauf des Gesamtprogramms fertig (indem das Programm auch noch den dritten Programmteil 203 durchläuft) und der Gesamtprogramm-Fuzzer startet den nächsten Testdurchlauf für das Gesamtprogramm (der wiederum mehrere Sub-Testdurchläufe für den geänderten Programmteil 208 enthält).
  • Der Sub-Fuzzer kann z.B. mit dem Sub-Fuzzing fertig sein, d.h. das Sub-Fuzzing beenden, wenn eine Metrik (z.B. Abdeckung) eine bestimmte Schwelle erreicht hat. Es kann auch ein Synchronisationssignal geben, auf dessen Grundlage der Sub-Fuzzer das Sub-Fuzzing beendet (z.B. nach einer bestimmten Anzahl von Synchronisations-Pulsen).
  • Es wird somit ein Gesamtprogramm-Fuzzing-Prozess durchgeführt, wobei bei der Ausführung von geändertem Code 208 ein Snapshot des Systemzustands erstellt wird und ausgehend von diesem System-Snapshot ein Sub-Fuzzing durchgeführt wird. Der Gesamtprogramm-Fuzzing-Prozess arbeitet normal (und ist langsam), aber mit wenigen falschen Positiven. Das Sub-Fuzzing wird z.B. nur für einen geänderten Programmteil (z.B. eine geänderte Funktion) ausgeführt, wodurch der geänderte Programmteil schnell getestet werden kann.
  • In einer konkreten Implementierung kann das Sub-Fuzzing auf jeder Abstraktionsebene stattfinden, d.h. der Programmteil 208, für den ein Sub-Fuzzing durchgeführt wird, kann eine Code-Einheit, eine Code-Komponente, eine Funktion, etc. sein. In so einem Fall können die Korpi für verschiedene Ebenen voneinander lernen. Im Beispiel von 2 könnte, wenn beim Sub-Fuzzing des geänderten Programmteils 208 der Sub-Fuzzer eine interessante Eingabe für den Programmteil 208 findet, eine Eingabe für das Gesamtprogramm dem (Gesamt-Fuzzing-)Korpus 204 hinzugefügt werden, die diese Eingabe für den Programmteil 208 enthält (oder zu dieser führt). Beispielsweise verarbeitet der Programmteil 208 einen Teil einer Datei, die von dem Gesamtprogramm verarbeitet wird. Dann kann dem (Gesamt-Fuzzing-)Korpus 204 eine Version der Dateien hinzugefügt werden, die für diesen Teil der Datei Inhalte enthält, die sich beim Sub-Fuzzing als interessant herausgestellt haben (z.B. durch neue Pfade des geänderten Programmteils 208 erreicht wurden).
  • 3 veranschaulicht ein Fuzzing auf verschiedenen Ebenen.
  • Das Gesamtprogramm 301 wird mittels eines Gesamt-Fuzzing-Korpus 302 getestet, Komponenten 303 mittels jeweiliger Komponenten-Fuzzing-Korpi 304 und Funktionen (oder Units) 305 mittels jeweiliger Funktionen(oder Unit)-Fuzzing-Korpi 306. Es kann auch mehrere Fuzztests auf Systemebene, d.h. für das Gesamtprogramm geben.
  • Wie oben erläutert können die Fuzzing-Korpi 304, 305, 306 voneinander lernen oder, in anderen Worten, synchronisiert werden. Optional werden für das gegenseitige Lernen die Testfälle übersetzt. Zum Beispiel können die Komponenten-Fuzzing-Korpi 304 von den Funktionen(oder Unit)-Fuzzing-Korpi 306 und umgekehrt und der Gesamt-Fuzzing-Korpus 302 kann von den Komponenten-Fuzzing-Korpi 304 lernen und umgekehrt.
  • Für das Sub-Fuzzing von Units oder Funktionen sind das Komponenten-Fuzzing und das Gesamtprogramm-Fuzzing übergeordnetes Fuzzing. Für das Sub-Fuzzing von Komponenten ist das Gesamtprogramm-Fuzzing das übergeordnete Fuzzing.
  • Abdeckungs-basiertes Fuzzing und Sub-Fuzzing kann mittels Feedback durch Source-Code-Instrumentation oder Feedback aus einem Emulator (je nach Art des Testens) erfolgen. Die Implementierung des Snapshot-Mechanismus hängt von dem verwendeten Feedback-Mechanismus ab. Wenn Source-Code-Instrumentation verwendet wird, wird der Snapshot-Mechanismus beispielsweise auch in das zu testende Programm kompiliert. Dies kann unter Verwendung eines Forkserver-Mechanismus erfolgen. Wenn mittels eines Emulators getestet wird und dieser entsprechend das Feedback liefert, kann der Snapshot in den Emulator eingebaut werden. Er kann auch in diesem Fall mittels eines Forkserver-Mechanismus realisiert werden.
  • Der Sub-Fuzzer arbeitet auf dem Snapshot und fuzzt lokale Parameter (d.h. Eingaben für den geänderten Programmteil 208), wie z.B. Funktionsargumente, sodass der geänderte Programmteil 208 gründlich getestet wird.
  • Die oben beschriebene Herangehensweise ist besonders geeignet zum Testen eines Programms, wenn sich bei einer Aktualisierung des Programms nur ein kleiner Programmteil ändert, der nur in einer kleinen Änderung des kompilierten Binärprogramms resultiert („sparse recompilation“). Solche eine Rekompilierung ist besonders nützlichen, wenn eine Bibliothek verwendet wird, z.B. mit getrennten Quellcode-Dateien oder Auswahl von Code auf der Grundlage von Präprozessor-Makros. Beim Linken (z.B. wenn C/C++ Code kompiliert wird) kommen nur die gebrauchten (ggf. geänderten Funktionen) in das Binärprogramm.
  • Eine andere Möglichkeit, um Änderungen zwischen Versionen eines Binärprogramms zu identifizieren ist es, die Dateien, z.B. die ELF (Executable and Linkable Format)-Dateien der Versionen zu vergleichen (z.B. mittels eines diff-Befehls). Auf diese Weise können die geänderten Programmteile (wie der geänderte Programmteil 208 im Beispiel von 2) leicht entdeckt werden, auch wenn der Source-Code nicht zur Verfügung steht.
  • Zusammengefasst wird gemäß verschiedenen Ausführungsformen ein Verfahren bereitgestellt, wie in 4 dargestellt.
  • 4 zeigt ein Ablaufdiagramm, das ein Verfahren zum Testen eines Computerprogramms gemäß einer Ausführungsform darstellt.
  • In 401 wird ein Computerprogrammteil des Computerprogramms ermittelt, der intensiv getestet werden soll.
  • In 402 werden mehrere Testdurchläufe für das Computerprogramm mit unterschiedlichen Eingaben für das Computerprogramm durchgeführt (wobei jede dieser Eingaben auch eine Eingabe für den ermittelten Computerprogrammteil enthält bzw. definiert (z.B. durch Verarbeitung ein oder mehrerer Computerprogrammteile, die dem ermittelten Computerprogrammteil vorhergehen).
  • Dabei werden, bei jedem Testdurchlauf für das Computerprogramm, wenn der ermittelte Computerprogrammteil erreicht wurde in 403 mehrere Testdurchläufe für den ermittelten Computerprogrammteil durchgeführt, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Computerprogrammteils in dem Testdurchlauf für das Computerprogramm hat. Diese Testdurchläufe für den ermittelten Computerprogrammteil werden mit unterschiedlichen Eingaben für den ermittelten Computerprogrammteil durchgeführt.
  • Das Verfahren von 4 kann durch einen oder mehrere Computer mit einer oder mehreren Datenverarbeitungseinheiten durchgeführt werden. Der Begriff „Datenverarbeitungseinheit“ kann als irgendein Typ von Entität verstanden werden, die die Verarbeitung von Daten oder Signalen ermöglicht. Die Daten oder Signale können beispielsweise gemäß mindestens einer (d.h. einer oder mehr als einer) speziellen Funktion behandelt werden, die durch die Datenverarbeitungseinheit durchgeführt wird. Eine Datenverarbeitungseinheit kann eine analoge Schaltung, eine digitale Schaltung, eine Logikschaltung, einen Mikroprozessor, einen Mikrocontroller, eine Zentraleinheit (CPU), eine Graphikverarbeitungseinheit (GPU), einen Digitalsignalprozessor (DSP), eine integrierte Schaltung einer programmierbaren Gatteranordnung (FPGA) oder irgendeine Kombination davon umfassen oder aus dieser ausgebildet sein. Irgendeine andere Weise zum Implementieren der jeweiligen Funktionen, die hierin genauer beschrieben werden, kann auch als Datenverarbeitungseinheit oder Logikschaltungsanordnung verstanden werden. Es können ein oder mehrere der im Einzelnen hier beschriebenen Verfahrensschritte durch eine Datenverarbeitungseinheit durch eine oder mehrere spezielle Funktionen ausgeführt (z. B. implementiert) werden, die durch die Datenverarbeitungseinheit durchgeführt werden.
  • Die Herangehensweise von 4 wird beispielsweise auf ein Steuerprogramm für eine Robotervorrichtung angewendet, das bei seiner Ausführung ein Steuersignal für die Robotervorrichtung erzeugt. Der Begriff „Robotervorrichtung“ kann als sich auf irgendein technisches System (mit einem mechanischen Teil, dessen Bewegung gesteuert wird) beziehend verstanden werden, wie z. B. eine computergesteuerte Maschine, ein Fahrzeug, ein Haushaltsgerät, ein Elektrowerkzeug, eine Fertigungsmaschine, einen persönlichen Assistenten oder ein Zugangssteuersystem.
  • Obwohl spezielle Ausführungsformen hier dargestellt und beschrieben wurden, wird vom Fachmann auf dem Gebiet erkannt, dass die speziellen Ausführungsformen, die gezeigt und beschrieben sind, gegen eine Vielfalt von alternativen und/oder äquivalenten Implementierungen ausgetauscht werden können, ohne vom Schutzbereich der vorliegenden Erfindung abzuweichen. Diese Anmeldung soll irgendwelche Anpassungen oder Variationen der speziellen Ausführungsformen abdecken, die hier erörtert sind. Daher ist beabsichtigt, dass diese Erfindung nur durch die Ansprüche und die Äquivalente davon begrenzt ist.

Claims (9)

  1. Verfahren zum Testen eines Computerprogramms, aufweisend: Ermitteln eines Computerprogrammteils des Computerprogramms, der intensiv getestet werden soll; Durchführen mehrerer Testdurchläufe für das Computerprogramm mit unterschiedlichen Eingaben für das Computerprogramm; Bei jedem Testdurchlauf für das Computerprogramm, wenn der ermittelte Computerprogrammteil erreicht wurde; Durchführen mehrerer Testdurchläufe für den ermittelten Computerprogrammteil, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Computerprogrammteils in dem Testdurchlauf für das Computerprogramm hat, mit unterschiedlichen Eingaben für den ermittelten Computerprogrammteil.
  2. Verfahren nach Anspruch 1, wobei das Ermitteln des Computerprogrammteils, der intensiv getestet werden soll, dadurch erfolgt, dass ein Computerprogrammteil des Computerprogramms ermittelt wird, der als letztes von mehreren Computerprogrammteilen des Computerprogramms geändert worden ist und dieser Computerprogrammteil als der Computerprogrammteil festgelegt wird, der intensiv getestet werden soll.
  3. Verfahren nach Anspruch 1 oder 2, wobei das Ermitteln des Computerprogrammteils, der intensiv getestet werden soll, durch Vergleichen von kompilierten Versionen des Computerprogramms erfolgt.
  4. Verfahren nach einem der Ansprüche 1 bis 3, wobei die Testdurchläufe für das Computerprogramm gemäß Mutations-basiertem Fuzzing durchgeführt werden, wobei Eingaben für das Computerprogramm auf der Grundlage eines ersten Korpus durchgeführt werden, und die Eingaben für die Testdurchläufe für den ermittelten Computerprogrammteil gemäß Mutations-basiertem Fuzzing auf der Grundlage eines zweiten Korpus generiert werden, und wobei Änderungen des zweiten Korpus, die sich aus Ergebnissen der Testdurchläufe für den ermittelten Computerprogrammteil ergeben, in den ersten Korpus übernommen werden und/oder Änderungen des ersten Korpus, die sich aus Ergebnissen der Testdurchläufe für das Computerprogramm ergeben, in den zweiten Korpus übernommen werden.
  5. Verfahren nach einem der Ansprüche 1 bis 4, aufweisend Ermitteln eines Bestandteils des ermittelten Computerprogrammteils, der intensiver getestet werden soll als ein oder mehrere andere Bestandteile des ermittelten Computerprogrammteils; und Bei jedem Testdurchlauf für den ermittelten Computerprogrammteil, Durchführen mehrerer Testdurchläufe für den ermittelten Bestandteil, jeweils ausgehend von einem Systemzustand, den eine Programmumgebung, in der das Computerprogramm ausgeführt wird, bei Erreichen des ermittelten Bestandteils in dem Testdurchlauf für den ermittelten Computerprogrammteil hat, mit unterschiedlichen Eingaben für den ermittelten Unterprogrammteil.
  6. Verfahren nach einem der Ansprüche 1 bis 5, wobei das Computerprogramm ein Steuerprogramm für eine Robotervorrichtung ist und die Robotervorrichtung abhängig von einem Ergebnis des Testens des Computerprogramms mit dem Computerprogramm gesteuert wird.
  7. Testsystem, das eingerichtet ist, ein Verfahren nach einem der Ansprüche 1 bis 6 durchzuführen.
  8. Computerprogramm mit Befehlen, die, wenn sie durch einen Prozessor ausgeführt werden, bewirken, dass der Prozessor ein Verfahren nach einem der Ansprüche 1 bis 6 durchführt.
  9. Computerlesbares Medium, das Befehle speichert, die, wenn sie durch einen Prozessor ausgeführt werden, bewirken, dass der Prozessor ein Verfahren nach einem der Ansprüche 1 bis 6 durchführt.
DE102022204717.6A 2022-05-13 2022-05-13 Verfahren zum Testen eines Computerprogramms Pending DE102022204717A1 (de)

Priority Applications (2)

Application Number Priority Date Filing Date Title
DE102022204717.6A DE102022204717A1 (de) 2022-05-13 2022-05-13 Verfahren zum Testen eines Computerprogramms
CN202310538453.9A CN117056200A (zh) 2022-05-13 2023-05-12 用于测试计算机程序的方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
DE102022204717.6A DE102022204717A1 (de) 2022-05-13 2022-05-13 Verfahren zum Testen eines Computerprogramms

Publications (1)

Publication Number Publication Date
DE102022204717A1 true DE102022204717A1 (de) 2023-11-16

Family

ID=88510322

Family Applications (1)

Application Number Title Priority Date Filing Date
DE102022204717.6A Pending DE102022204717A1 (de) 2022-05-13 2022-05-13 Verfahren zum Testen eines Computerprogramms

Country Status (2)

Country Link
CN (1) CN117056200A (de)
DE (1) DE102022204717A1 (de)

Also Published As

Publication number Publication date
CN117056200A (zh) 2023-11-14

Similar Documents

Publication Publication Date Title
DE69831732T2 (de) Verfahren und gerät zum korrigieren von fehlern in einem rechnersystem
EP3001313A1 (de) Verfahren zur Simulation eines Anwendungsprogramms eines elektronischen Steuergeräts auf einem Computer
EP1794680A1 (de) Verfahren zur abarbeitung eines computerprogramms auf einem computersystem
DE102014102551A1 (de) Maschine und Verfahren zum Evaluieren von fehlschlagenden Softwareprogrammen
DE112014002960T5 (de) Ableitung verallgemeinerter Testfälle
DE102009050161A1 (de) Verfahren und Vorrichtung zum Testen eines Systems mit zumindest einer Mehrzahl von parallel ausführbaren Softwareeinheiten
EP3306295A1 (de) Verfahren und vorrichtung zum testen elektronischer steuerungen, insbesondere zum testen von automobilsteuerungen
DE10324594A1 (de) Verfahren zum Bereitstellen einer verbesserten Simulationsfähigkeit eines dynamischen Systems außerhalb der ursprünglichen Modellierungsumgebung
DE112018002316T5 (de) Codeabdeckungsverfolgung für ein mikrocontroller-programm
DE102022204717A1 (de) Verfahren zum Testen eines Computerprogramms
DE102020213809A1 (de) Verfahren zum Betreiben eines Steuergeräts beim Testen einer Software des Steuergeräts und Verfahren zum Betreiben eines Testcomputers beim Testen einer Software eines Steuergeräts
DE102022206900A1 (de) Verfahren zum Testen eines Computerprogramms in mehreren Zusammensetzungen aus Computerprogramm-Modulen
DE102022202338A1 (de) Verfahren zum Testen eines Computerprogramms
WO2021170316A1 (de) Analyse einer container-instanz eines betriebssystems
EP2329374A1 (de) Testmodul und verfahren zum testen einer o/r-abbildungs-middleware
DE102022202339A1 (de) Verfahren zum Software-Fehlerbereinigung
DE102022202542A1 (de) Verfahren zum Testen eines Computerprogramms
DE102022202541A1 (de) Verfahren zum Testen eines Computerprogramms
DE102022202697A1 (de) Verfahren zum Bereitstellen einer Blockchain
DE102020115820B3 (de) Testvorrichtung sowie Verfahren und Speichermedium zum Betreiben eines Prozessorsystems
DE102021212596A1 (de) Fuzzing mit softwareabdeckungsfeedback durch dynamische instrumentierung
DE102022200412A1 (de) Fuzzing von applikationssoftwares von recheneinheiten von fahrzeugen via basissoftwareadapter auf externem computer-system
DE102010014720A1 (de) Verfahren zum Verifizieren eines aus einem Quellmodell generierten Zielprogramms
DE102022112141A1 (de) Verfahren zur Erstellung eines vereinfachten virtuellen Steuergeräts
DE102021130822A1 (de) Automatisches erstellen und ausführen eines testsystems für arbeitsabläufe