Home / LinuxUser / 2012 / 11 / Splint und Co: Tools zur statischen Code-Analyse

Newsletter abonnieren

Lies uns auf...

Folge LinuxCommunity auf Twitter

Top-Beiträge

Eingedost
(161 Punkte bei 4 Stimmen)
Aufteiler
(161 Punkte bei 4 Stimmen)

Heftarchiv

LinuxUser Heftarchiv

EasyLinux Heftarchiv

Ubuntu User Heftarchiv

Ubuntu User Heftarchiv

Partner-Links:

Das B2B Portal www.Linx.de informiert über Produkte und Dienstleistungen.

AA_kehrmaschine_123rf-14573229_digifuture.jpg

© digifuture, 123RF

Kehraus

Splint und Co: Tools zur statischen Code-Analyse

18.10.2012 Zwar finden Compiler Syntaxfehler in Programmen, aber auch syntaktisch korrekter Code kann Ungenauigkeiten, logische Fehler oder veraltete Funktionen beinhalten. Solche Probleme spüren Sie mit Quellcode-Analyzern auf.

Compiler und Interpreter beanstanden zwar ungültigen Programmcode, in vielen Programmiersprachen sind aber selbst sehr ungewöhnliche Codezeilen noch gültig. Man kann Code auch absichtlich verwirrend gestalten – es gibt sogar diverse Obfuscated Coding Contests ([1],[2]), also Wettbewerbe, die zum Ziel haben, ein Programm absichtlich möglichst unleserlich zu gestalten. Viel öfter allerdings geschieht das unabsichtlich, insbesondere wenn (wie in vielen Open-Source-Projekten) mehrere Entwickler gemeinsam an einem Programm arbeiten. Nicht immer bemerkt der Compiler die daraus resultierenden Schnitzer.

Glücklicherweise gibt es Tools, die hier ansetzen und solche ungewöhnlichen Codekonstruktionen aufspüren. Damit helfen sie, mögliche Fehlerquellen zu beseitigen, und sorgen so für bessere Codequalität. Im Folgenden stellen wir einige ausgewählte Vertreter dieser Gattung vor, wobei unsere Aufstellung keinen AAnspruchauf Vollständigkeit erhebt: Ähnliche Open- und Closed-Source-Werkzeuge gibt es für praktisch jede Programmiersprache.

Splint – Codeprüfung für C

Das erste Werkzeug zur statischen Quellcodeprüfung, Lint, kam bereits 1979 mit Unix zur Auslieferung. Das Programm wurde schnell so populär, dass es den Programmierer-Jargon um den Ausdruck "linten" für statische Codeprüfungen bereicherte. In der Folge diente es dann als Namensgeber für viele ähnliche Tools. Zu diesen gehört das Open-Source-Programm Splint ("Secure Programming Lint", [3]), das wie sein Vorbild mögliche Problemquellen in C-Code aufspürt.

Als Beispiel sehen wir uns das kurze C-Programm aus Listing 1 (Zeile 2 bis 10) dienen, das melden soll, wenn zehn Argumente auf der Kommandozeile übergeben werden. Dies prüft es, indem es argc auswertet: Diese Variable enthält bekanntlich immer die Anzahl der übergebenen Argumente plus Eins, weil es den Programmnamen als erstes Argument mitzählt.

Listing 1

$ cat main.c
#include <stdio.h>
int main(int argc, char * argv[])
{
  if (argc = 10+1) {
    printf("10 Argumente!\n");
  }
  return 0;
  printf("Programm beendet.\n");
}
$ gcc main.c
$ gcc -Wall main.c
main.c: In function 'main':
main.c:4:2: warning: suggest parentheses around assignment used as truth value [-Wparentheses]

Der Compiler GCC meldet beim Übersetzen des Quellcodes normalerweise gar nichts (Zeile 11). Erst wenn Sie mittels der Option -Wall alle Warnungen einschalten (Zeile 12) wirft er eine kurze kryptische Meldung aus, weil der Code anstatt eines Vergleichs (==) eine Zuweisung (=) verwendet (Zeile 5).

Sehen Sie sich zum Vergleich die Ausgabe von Splint in Listing 2 an: Das Tool findet nicht weniger als vier mögliche Fehler in main.c. Außerdem beschreibt es ausführlich die Art der Probleme und die möglichen Ursachen. Daneben liefert es Hinweise, mit welchen Änderungen am Code oder den Parametern Sie die vermuteten Fehler korrigieren oder die Ausgabe unterdrücken können.

Listing 2

$ splint main.c
Splint 3.1.2 --- 29 Oct 2011
main.c: (in function main)
main.c:4:6: Test expression for if is assignment expression: argc = 10 + 1
  The condition test is an assignment expression. Probably, you mean to use ==
  instead of =. If an assignment is intended, add an extra parentheses nesting
  (e.g., if ((a = b)) ...) to suppress this message. (Use -predassign to
  inhibit warning)
main.c:4:6: Test expression for if not boolean, type int: argc = 10 + 1
  Test expression type is not boolean or int. (Use -predboolint to inhibit
  warning)
main.c:8:2: Unreachable code: printf("Programm...
  This code will never be reached on any possible execution. (Use -unreachable
  to inhibit warning)
main.c:2:27: Parameter argv not used
  A function parameter is not used in the body of the function. If the argument
  is needed for type compatibility or future plans, use /*@unused@*/ in the
  argument declaration. (Use -paramuse to inhibit warning)
Finished checking --- 4 code warnings

Neben der schon von GCC bemerkten fehlerhaften Zuweisung im If-Statement, zu der Splint gleich zwei Anmerkungen liefert, findet der Analyzer auch noch eine unbenutzte Variable (argv) sowie Programmcode, der niemals ausgeführt wird. Beim Kommentar /*@unused@*/, dem Splint in der vierten Warnung vorschlägt, handelt es sich um eine sogenannte Annotation. Ein solcher spezieller Kommentar steuert das Verhalten von Splint, indem er beispielweise gewisse Prüfungen (de-)aktiviert und Splint weitere Hinweise gibt, welche die Prüfungen unterstützen. Der Aufruf splint --help annotations gibt einen Überblick über die Möglichkeiten.

Neben der Hilfe-Funktion, die mittels splint --help einen ersten Überblick über die Themen liefert, kennt Splint noch zahlreiche weitere Kommandozeilenoptionen. Für Einsteiger sind wahrscheinlich die Optionen --weak, --standard, --checks und --strict am interessantesten, die steuern, wie pedantisch sich Splint gibt. Der Aufruf splint --help modes gibt Ihnen einen ersten Überblick über die (de-)aktivierten Optionen in diesen Einstellungen.

Übrigens bemerkt auch GCC durchaus, dass der Befehl printf("Programm beendet\n") nie ausgeführt wird. Er optimiert den Befehl daraufhin schlicht weg, sprich: erzeugt gar nicht erst Code dafür. Das erkennen Sie unschwer, indem Sie sich mit dem Kommando strings die Texte im generierten Executable ansehen. Etwas lesbarer fällt die Variante aus, mit gcc -S main.c die Assembler-Datei main.s zu erzeugen. In jedem Fall unterschlägt der Compiler jedoch hier die Information, dass hier völlig überflüssiger Code vorhanden ist. Klar, er soll ja auch übersetzen und nicht Fehler suchen – zur Verbesserung der Codequalität trägt das aber nicht gerade bei.

Auch andere C-Compiler schlagen sich hier nicht viel besser: Der Open64-Compiler meldet standardmäßig das selbe wie GCC: Nichts. Der Sun/Oracle-Compiler beanstandet zwar das nicht erreichbare Statement, findet aber an der wahrscheinlich fehlerhaften Zuweisung in der If-Abfrage nichts auszusetzen. LLVM/Clang bemerkt zwar die falsche Zuweisung, meldet aber ebenfalls nichts zum nicht ausführbaren Code.

Perl::Critic

Die Programmiersprache Perl tritt explizit mit dem Motto "There is more than one way to do it" an – sie erlaubt also viele Wege, um ein Problem zu lösen. Für möglichst seltsame und unlesbare Wege gibt es sogar einen eigenen Wettbewerb, den Obfuscated Perl Contest [2] . Dazu passend hat der Code-Analyzer Perl::Critic das Motto "Some Ways Are Better Than Others". Perl::Critic hilft wie Splint, mögliche Fehler zu finden und einen einheitlichen Programmierstil durchzusetzen.

Möchten Sie sich Perl::Critic ohne Installation ansehen, können Sie dazu den entsprechenden Webservice [4] nutzen (Abbildung 1). Dort laden Sie Ihren Perl-Code hoch und sehen dann sofort das Ergebnis der Evaluierung. Dabei unterstützt das Analysetool fünf verschiedene "Härtegrade".

Abbildung 1

Abbildung 1: Der Perl::Critic-Webservice liefert nach dem Hochladen des zu prüfenden Codes sofort Ergebnisse.

Auf der Kommandozeile rufen Sie das einmal installierte Werkzeug mit einem schlichten perlcritic auf. Auch hier kennt Perl::Critic die bereits erwähnten fünf Prüfstufen, die von 1 ("brutal") bis 5 ("gentle") reichen. Im Beispiel aus Listing 3 rufen wir den Analyzer mit dem dritten Level ("harsh") auf, damit er bei dem kurzen Programm (Zeilen 2 bis 5) auch etwas zu reklamieren findet.

TIPP

In OpenSuse 12.1 fehlt (im Gegensatz zu anderen gängigen Distributionen) das Executable-Bit bei der Datei /usr/bin/perlcritic. Sie müssen es entweder nachträglich setzen oder das Analyse-Tool explizit mit perl /usr/bin/perlcritic aufrufen, um es zu nutzen.

Listing 3

$ cat test.pl
#!/usr/bin/perl
print `cat test.pl`
print "Return drücken";
my $filename = <STDIN>;
$ perlcritic --severity 3 test.pl
Code before strictures are enabled at line 2, column 1.  See page 429 of PBP.  (Severity: 5)
Code before warnings are enabled at line 2, column 1.  See page 431 of PBP.  (Severity: 4)
Backtick operator used at line 2, column 7.  Use IPC::Open3 instead.  (Severity: 3)
Use "<>" or "<ARGV>" or a prompting module instead of "<STDIN>" at line 4, column 16.  See pages 216,220,221 of PBP.  (Severity: 4)

Tatsächlich macht Perl::Critic auf gleich vier Verbesserungsmöglichkeiten aufmerksam (Zeilen 7 bis 10). Dabei gibt es jeweils eine Beurteilung des Schweregrads und häufig auch eine Referenz auf das Buch "Perl Best Practices" (PBP) von Damian Conway aus. Ähnlich wie Splint können Sie auch Perl::Critic mit speziellen Kommentaren (## no critic) am Ende einer Zeile anweisen, diese nicht zu untersuchen. Daneben verzichtet das Tool darauf, Code zwischen den Marken ## no critic und ## use critic zu prüfen.

Genau wie Splint bietet Perl::Critic daneben auch noch wesentlich mehr Einstellungsmöglichkeiten. Zum einen dürfen Sie vorgeben, welche Prüf-Policies es anwenden soll, zum anderen können Sie dem vorhandenen Fundus auch eigene Policies hinzuzufügen. Der Befehl perlcritic --help liefert eine erste Übersicht, auch eine umfangreiche Manpage (man perlcritic) steht zur Verfügung.

Als Teil der kommerziellen Activestate-Perl-Distribution [5] gibt es auch eine grafische Oberfläche für Perl::Critic (perlcritic-gui, Abbildung 2), mit der Sie sich einen groben Überblick über die vielfältigen Optionen verschaffen können. Active State Perl lässt sich kostenlos herunterladen und nutzen, ist jedoch keine freie Software.

Abbildung 2

Abbildung 2: Active State Perl bringt eine grafische Oberfläche für Perl::Critic mit.

Tip a friend    Druckansicht Bookmark and Share
Kommentare
Weitere interessante Sourcecode-Analyzer.
Wolfgang Dautermann, Sonntag, 14. Juli 2013 10:08:35
Ein/Ausklappen

* http://www.shellcheck.net/ Shellskript-Analyzer
* http://cppcheck.sourceforge.net/ Ein weiterer interessanter C/C++ Checker
* http://www.jslint.com/ Javascript-Checker


Bewertung: Noch keine Bewertung abgegeben!
Den Beitrag bewerten: Gut / Schlecht

2081 Hits
Wertung: 212 Punkte (16 Stimmen)

Schlecht Gut

Infos zur Publikation

Infos zur Publikation

LinuxUser 05/2014

Aktuelle Ausgabe kaufen:

Heft als PDF kaufen

LinuxUser erscheint monatlich und kostet in der Nomedia-Ausgabe EUR 5,95 und mit DVD EUR 8,50. Weitere Informationen zum Heft finden Sie auf der LinuxUser-Homepage.

Im LinuxUser-Probeabo erhalten Sie drei Ausgaben für 3 Euro. Das Jahresabo (ab EUR 60,60) können Sie im Medialinx-Shop bestellen.

Tipp der Woche

Bilder vergleichen mit diffimg
Bilder vergleichen mit diffimg
Tim Schürmann, 01.04.2014 12:40, 1 Kommentare

Das kleine Werkzeug diffimg kann zwei (scheinbar) identische Bilder miteinander vergleichen und die Unterschiede optisch hervorheben. Damit lassen sich nicht nur Rätsel a la „Orignial und Fäls...

Aktuelle Fragen

programm suche
Hans-Joachim Köpke, 13.04.2014 10:43, 8 Antworten
suche noch programme die zu windows gibt, die auch unter linux laufen bzw sich ähneln sozusagen a...
Funknetz (Web-Stick)
Hans-Joachim Köpke, 04.04.2014 07:31, 2 Antworten
Bei Windows7 brauche ich den Stick nur ins USB-Fach schieben dann erkennt Windows7 Automatisch, a...
Ubuntu 13.10 überschreibt immer Windows 8 Bootmanager
Thomas Weiss, 15.03.2014 19:20, 8 Antworten
Hallo Leute, ich hoffe das ich richtig bin. Ich habe einen Dell Insipron 660 Ich möchte gerne Ub...
USB-PTP-Class Kamera wird nicht erkannt (Windows-only)
Wimpy *, 14.03.2014 13:04, 15 Antworten
ich habe meiner Frau eine Digitalkamera, AGFA Optima 103, gekauft und wir sind sehr zufrieden dam...
Treiber
Michael Kristahn, 12.03.2014 08:28, 5 Antworten
Habe mir ein Scanner gebraucht gekauft von Canon CanoScan LiDE 70 kein Treiber wie bekomme ich de...