Oft arbeiten Teams mit Code-Basen, die die Einhaltung eines Programmierstandards wie MISRA oder AUTOSAR verlangen, aber nicht von bereits bestehenden Verletzungen bereinigt wurden. Das passiert gerne, wenn eine neue Entwicklung auf bestehendem Code basiert, wenn ein Projekt auf einem Prototyp aufsetzt, der nicht im Hinblick auf Konformität entwickelt wurde, oder durch die Übernahme von Drittanbieter-Code.
Als typisches Szenario in vielen Unternehmen wollen Entwicklerteams sicherstellen, dass sie die Compliance-Schuld nicht erhöhen, und der von ihnen neu programmierte Code mit dem Programmierstandard übereinstimmt. Bereits bestehende Verstöße werden irgendwann korrigiert, aber vorerst wollen sich die Teams auf den neuen Code konzentrieren.
Bereits bestehende Verstöße behindern die Produktivität der Entwickler. Denn die Teammitglieder, die an der neuen Funktion arbeiten oder bestehenden Code modifizieren, müssen unterscheiden, welche Ergebnisse der statischen Code-Analyse neu und für ihre Änderungen relevant sind und welche sie vorläufig ignorieren können. Es gibt keine gute manuelle Strategie zur Unterscheidung neuer Probleme von den bereits vorhandenen. Zur Fehlerbehebung modifizierte oder zur Implementierung neuer Funktionen erweiterte Dateien können zu einer Quelle neuer Verstöße werden.
Im Rahmen der Parasoft-Studie wurden die statischen Analyseverfahren um eine Ergebnis-Normal-Funktion erweitert: Der Prototyp nutzt einen Referenz- oder Normal-Bericht zur statischen Code-Analyse, der den anerkannten Zustand des Projekts darstellt. Ein Ergebnis-Normal lässt sich für jeden ausgewählten Zustand des Projekts erstellen, beispielsweise identifiziert durch die Source Control Commit ID. Der typische Anwendungsfall ist das Erstellen eines Ergebnis-Normals für die neue Funktionsverzweigung. Wird die statische Code-Analyse auf der geänderten Code-Basis erneut ausgeführt, erfolgt ein Vergleich der neuen Ergebnisse mit dem Normal-Bericht. Alle bereits vorhandenen Probleme werden herausgefiltert, sodass sich die Entwickler auf die Probleme konzentrieren können, die für ihre Code-Änderungen relevant sind. Der Prozess ist in Bild 2 dargestellt.
Das kritische Element der Funktion ist die Art des Vergleichs der Berichte. Derselbe Verstoß gegen die statische Code-Analyse kann in beiden Berichten mit einer anderen Zeilennummer gemeldet werden, da Code-Änderungen den Verstoß möglicherweise verlagert haben. Um brauchbare Vergleiche zu erstellen, wurde für die Studie mit verschiedenen Kombinationen von Verletzungsattributen experimentiert. Gute Ergebnisse erzielten die IDs des Static Analysis Checkers und der Verletzungsmeldung. Zur Vermeidung der unerwünschten Klassifizierung einer neuen Verletzung als eine bereits Vorhandene, wurde der Vergleichsalgorithmus so eingestellt, dass er Verstöße im Zweifelsfall als neu ausweist.
Die Rückmeldungen während der internen Tests des Prototyps sowie der externen Validierung mit Kunden waren sehr positiv. Die Möglichkeit, sich auf die neuen Probleme zu konzentrieren, die mit den jüngsten Code-Änderungen verbunden sind, verbesserte die Produktivität der Entwickler sichtbar, reduzierte die Frustration im Zusammenhang mit dem obligatorischen Prozess der Programmierrichtlinien und erhöhte die Akzeptanz der Technik.
Es gibt zwei Arten von Situationen, in denen Entwickler Ergebnisse der statischen Code-Analyse ausblenden möchten, ohne das Problem zu beheben: Im ersten Fall stellt ein gemeldeter Fehler eine falsche Diagnose des Tools dar. Im zweiten Fall handelt es sich um ein echtes Problem, das von den Entwicklern jedoch als etwas erkannt wird, das sicher ignoriert werden kann. In beiden Situationen soll das vorhandene Problem aus den zukünftigen Berichten eliminiert werden, sodass es keine Zeit für die Analyse verbraucht.
Entscheidend ist, dass der Prozess der Entfernung unerwünschter Befunde der statischen Code-Analyse dokumentiert wird, insbesondere bei sicherheitskritischen Projekten, die das Einhalten von Programmierrichtlinien verlangen. Der Vorgang des Eliminierens unerwünschter Befunde aus zukünftigen Berichten wird als Unterdrückung bezeichnet, ebenso wie die zu diesem Zweck erstellten Datensätze.
Der MISRA-Programmierstandard beschreibt diesen Prozess in der Norm MISRA Compliance 2020 [2] genau. Unerwünschte Verstöße gegen die Programmierrichtlinie, wenn nicht eine Fehlmeldung des Tools, werden als »Abweichung« behandelt und verlangen das Erstellen und Speichern einer zusätzlichen Dokumentation für die Code-Compliance-Audits. Deren Erstellung bedeutet einen Verwaltungsaufwand für den Entwicklungsprozess. Noch problematischer ist es, diese Informationen effektiv an alle relevanten Zweige im Quellcode weiterzugeben, um doppelten Aufwand der Entwickler für die Erstellung der Unterdrückungs-(Abweichungs-)Dokumentation zu vermeiden.
Für die Speicherung und Anwendung von Unterdrückungen gibt es verschiedene Strategien:
Ausgangspunkt ist, dass die Verletzung durch eine Reihe von Eigenschaften eindeutig identifiziert wird, z.B. Quelldateipfad, Funktionsname, Prüf-ID der statischen Code-Analyse und Verletzungsmeldung. Mit diesen Eigenschaften wird eine Kennung erstellt und in der externen Datenbank zusammen mit zusätzlichen Informationen über den Unterdrückungsgrund gespeichert. Die Datenbank wird bei den nachfolgenden Code-Scans abgefragt und bereits unterdrückte Befunde nicht mehr gemeldet. Einige der Lösungen unterstützen die automatische Weitergabe der Befunde an alle relevanten Zweige im SCM-System (Source Code Management).
Als Vorteil trennt diese Strategie die Unterdrückungsinformationen vom Quellcode, wodurch werkzeugspezifische Kommentare im Code nicht mehr benötigt werden. Der größte Nachteil ist die eingeschränkte Sichtbarkeit der Unterdrückungsinformationen, was Quellcode-Audits erschwert und es nicht ermöglicht, Compliance-Anforderungen »as the Code« einzuhalten. Außerdem verlangt der Prozess der automatischen Anwendung von Unterdrückungen auf andere Zweige eine zusätzliche manuelle Überprüfung.
Durch das Hinzufügen von Kommentaren zu den Zeilen mit den Ergebnissen der statischen Analyse entfällt die Notwendigkeit, den Ort des Ergebnisses mithilfe zusätzlicher Ergebnisattribute zu identifizieren (Bild 3). Wird die statische Analyse auf dem Code ausgeführt, der Unterdrückungsanmerkungen enthält, extrahiert das Tool Unterdrückungsinformationen aus dem Code und wendet sie auf identifizierte Probleme an.
der Überprüfung des Codes sind alle relevanten Informationen direkt im Kontext des Quellcodes sichtbar, auf den sie zutreffen. Außerdem ist der Vorgang des Abgleichs von Unterdrückungsdaten mit bestimmten Verstößen vereinfacht und weniger fehleranfällig, da der Kommentar eng an die Stelle im Code gebunden ist, an der das Problem auftaucht.
Der Nachteil ist, dass der Quellcode mit den Kommentaren »verschmutzt« werden muss, die nicht mit der Funktion des Quellcodes zusammenhängen. In streng regulierten Projekten, die z B. dem DO-178C-Standard folgen, kann das Bearbeiten der Datei zum Hinzufügen von Unterdrückungskommentaren höchst unerwünscht sein, da durch die Code-Änderung die Zertifizierung ungültig wird und eine erneute Prüfung erfolgen muss.
Beide Methoden zur Eliminierung unerwünschter Ergebnisse der statischen Analyse haben Vor- und Nachteile. Abhängig von der Situation kann jede Methode für die Entwicklungsteams schwierig zu implementieren sein. In der Studie hat Parasoft einen dritten Ansatz zur Verwaltung von Unterdrückungen prototypisch entwickelt, der die Vorteile beider Methoden kombiniert.
Ausgangslage ist hier, dass die unerwünschten Verstöße mit einem Unterdrückungssatz unterbunden werden, welcher der mit dem Source Code gespeicherten Textdatei hinzugefügt wird (Bild 4). Es kann verschiedene Strategien für die Gruppierung von Unterdrückungseinträgen geben, beispielsweise eine Unterdrückungsdatei pro Projekt oder eine Datei pro Projektordner oder eine Datei für den Quellcode – je nach den Präferenzen des Teams. Im Prototyp nutzte Parasoft eine Unterdrückungsdatei pro Verzeichnis, die Unterdrückungssätze für alle Quelldateien in diesem Verzeichnis enthielt.
Jeder Unterdrückungsdatensatz in der Unterdrückungsdatei enthält eine Sammlung von zu unterbindenden Attributen, wie z.B. den Pfad der Quelldatei, die ID des Prüfers für statische Analysen, die Meldung der Verletzung, die Zeile usw., die zum Identifizieren von Ergebnissen der statischen Code-Analyse verwendet werden. Unterdrückungsdateien werden automatisch in den Code-Scan-Prozess einbezogen, die darin enthaltenen Informationen interpretiert und auf die Menge der Verstöße angewendet. Die Attribute der Unterdrückungsdateien werden mit den Attributen der Verletzungen abgeglichen. Stimmen sie überein, wird die Verletzung unterdrückt.
Die Strategie, Unterdrückungsdatensätze in Klartextdateien zu speichern, ähnelt der unter Punkt 1 besprochenen Strategie, jedoch wird die Speicherung in der Datenbank durch Klartextdateien ersetzt. Als Nachteil dieser Methode ist der zusätzliche Aufwand für die Pflege der Unterdrückungsdateien zu nennen. Dennoch bietet sie viele Vorteile, durch die sie sich sehr gut für die modernen Entwicklungsabläufe eignet:
In der Studie wurden ausgewählte Aspekte des Einsatzes statischer Code-Analysen analysiert und Strategien und Funktionen getestet, die den Verwaltungsaufwand in Bezug auf die statischen Analyse-Tools und den Prozess zur Einhaltung von Standards reduzieren.
Hierbei wurde mit Funktionen experimentiert, die die Dauer der lokalen Analysesitzungen verkürzen und die Reaktionsfähigkeit der Analyse-Engine erhöhen. Geprüft wurde auch, wie bereits vorhandene Ergebnisse der statischen Analyse eliminiert werden können, und wie ein vereinfachter Prozess zur Einführung von Unterdrückungen die Produktivität der Softwareentwickler verbessert.
Erste Anwender des prototypisch realisierten Prozesses bewerteten alle vorgeschlagenen Ansätze und Funktionen positiv. Als wichtigste Pluspunkte nannten die Testanwender die enge Integration mit dem Quellcode, das Fehlen externer Speicher und die vollständige Transparenz des Prozesses. In einem nächsten Projekt sollen quantitative Daten über die Effektivität der vorgeschlagenen Methode gesammelt werden, um weiter an der Optimierung der Dauer von Code-Scans zu arbeiten.
Literatur
[1] MISRA C: 2012 Guidelines for the use of the C language
in critical systems. MISRA, ISBN 978-1-906400-10-1 (Papier),
ISBN 978-1-906400-11-8 (PDF), März 2013.
[2] MISRA Compliance 2020: Achieving compliance with MISRA Coding Guidelines. MISRA, ISBN 978-906400-26-2 (PDF), Februar 2020.
Der Autor
Mirosław Zielinski
ist bei Parasoft als Product Manger für C/C++test verantwortlich. Zu seinen Spezialgebieten zählen C, C++, Java-Sprachen, Echtzeitbetriebssysteme, statische Code-Analyse, Unit-Testing, Softwarequalität für sicherheitskritische Anwendungen und Softwarekonformität mit Sicherheitsstandards wie DO178B, ISO26262, IEC61508, IEC62304 und EN50126.
miroslaw.zielinski@parasoft.com