2009-11-15 6 views
7

So habe ich dieses einfache Stück Code, das einen einfachen Pufferüberlauf zeigt:Welches Tool kann Pufferüberläufe in C fangen?

#include <stdio.h> 

int main(void) 
{ 
    char c[4] = { 'A', 'B', 'C', 'D' }; 
    char d[4] = { 'W', 'X', 'Y', 'Z' }; 

    printf("c[0] is '%c'\n", c[0]); 

    d[4] = 'Z'; /* Overflow that overwrites c[0] */ 

    printf("c[0] is '%c'\n", c[0]); 

    return 0; 
} 

Der Ausgang:

$ ./a.out 
c[0] is 'A' 
c[0] is 'Z' 

ich diesen Code mit den folgenden gcc Optionen kompiliert habe versucht, und es bestand mit dem Fliegen Farben:

gcc -Wall -Wextra -Wformat=2 -Wswitch-default -Wcast-align -Wpointer-arith \ 
    -Wbad-function-cast -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ 
    -Wcast-qual -Wshadow -Wwrite-strings -Wconversion -Wunreachable-code \ 
    -Wstrict-aliasing=2 -ffloat-store -fno-common -fstrict-aliasing \ 
    -Wstack-protector -fstack-protector-all -std=c99 -pedantic -O0 -ggdb3 

ich habe auch versucht libefence und valgrind. Ich habe erwartet, dass die Libefence passieren wird, da sie dazu gebracht wird, außerhalb der Grenzen zu lesen/schreibt auf dem Heap, aber ich war überrascht, dass Valgrind bestanden hat.

Dieser Code erzeugt keinen Segfault, da sich c [4] und d [0] zufällig überlappen und ich denke, dass dies dazu führt, dass Werkzeuge es vermissen.

Also, was gibt es da CAN fangen Sie das? Etwas Freies, das unter Linux funktioniert, wäre nett.

+0

Die neueste Version von Schiene versuchen, dies nicht zu fangen, leider. –

+0

Sie haben Recht, das ist bedauerlich, aber 'cppcheck' tut! – SiegeX

+0

Enttäuschend, dass gcc dies nicht bemerkt, wenn man bedenkt, dass ich vor einiger Zeit einen Compiler-Fehler umgehen musste, der fälschlicherweise vor einem End-of-Array-Zeiger warnte, der nicht einmal dereferenziert wurde. Siehe http://stackoverflow.com/questions/1168525/c-gcc4-4-warning-array-subscrip-is-above-array-bounds. Ich denke, gcc * versucht * dies zu diagnostizieren, obwohl es nicht erforderlich ist, also entweder deaktivieren Sie Ihre Optionen, oder Sie haben den umgekehrten Compiler-Fehler gefunden ... –

Antwort

5

Versuchen Sie cppcheck. Es hat für mich funktioniert.

+0

Guten Ruf auf 'cppcheck'. Ich habe noch nie von diesem Quellanalysator gehört, aber * IT * findet den Fehler! – SiegeX

+1

Die neue URL ist: http://cppcheck.sourceforge.net/ –

+0

@AndrewSchools Danke; URL aktualisiert – Teddy

0

Wenn es auf Linux ist, würde ich Valgrind zuerst ausprobieren, ich denke, es wird damit umgehen.

Bearbeiten: Wenn es wie SiegeX sagt Ich denke, Valgrind nicht (was sinnvoll ist, weil es keine Möglichkeit, Wachen auf dem Stapel einfügen, da es nur in der Prozesslaufzeit beteiligt ist). Es ist jedoch ein gutes Werkzeug, das es wert ist, in Ihrer Toolbox zu haben, damit ich die Post behalten werde.

+3

Valgrind * Fängt nicht das so klar in der Frage angegeben . Bitte hören Sie auf, dies zu wählen. – SiegeX

+0

-1 nach der Bearbeitung war nicht wirklich fair imho. – Fredrik

+0

@SiegeX: "Valgrind auch übergeben" sieht aus, wie es es fängt. Ich muss sagen, dass ich ein wenig überrascht war, da ich nicht damit gerechnet hatte, dass es damit umgehen würde, da es Speicher abfangen soll, der Heap zugewiesen wurde. – Vatine

-1

Ich denke, es gibt ein implizites Nullzeichen in diesem Fall, da Sie eine literale Zeichenfolge verweisen. Daher ist d [4] immer noch in Grenzen (stell dir d als const char * vor ...). Aber ich mag falsch sein.

+1

Wenn ich es als c [5] = "ABCD" deklariert hätte; dann hätte der Compiler das NUL-Byte am Ende geworfen. Da jedoch für das NUL-Byte mit nur 4 Zeichen kein Platz ist, wird es verworfen. Allerdings habe ich den Code geändert, um Zeichen explizit für die Initialisierung zu verwenden, um Verwirrung zu vermeiden. – SiegeX

2

Da valgrind auf binär funktioniert, hat es mit diesem Code nichts falsch gemacht. Überprüfen Sie diese (http://www.thefreecountry.com/programming/debuggers.shtml) statischen Quellcodeanalysatoren, die sie finden sollten. Wenn sie nicht funktionieren, wird PC-Lint (http://www.gimpel.com/html/pcl.htm) damit umgehen ....

+0

+1 für die Empfehlung von statischen Quelle Analysatoren ... Das und/oder Peer-Reviews sind wahrscheinlich am ehesten zu fangen, wenn Dinge wie Valgrind nicht (und darüber nachzudenken, ich weiß, es gibt keinen Weg Valgrind kann es finden, es sei denn es wird in den Kompilierungsprozess einbezogen) – Fredrik

+0

Obwohl Ihr 'debuggers.shtml' Link nicht über 'cppcheck' (akzeptierte Antwort) spricht, ist dies ansonsten ein sehr guter Link. Danke – SiegeX

+0

Ich habe noch nie von cppcheck gehört. Die älteste Veröffentlichung war 2007, also ist es relativ neu. Vor allem im Vergleich zu PC-Lint ... – Malkocoglu

1

Rational Purify funktioniert ziemlich gut mit Erkennung von Pufferüberläufen, Speicherlecks, Beschädigungen usw. Es ist jedoch ziemlich teuer.

Das Mem-Paket erwähnt in this SO answer kann eine andere Option sein.

1

Coverity (ein statisches Analysewerkzeug) wird dies erfassen.

0

Pufferüberläufe sind in C ziemlich schwer zu finden, da sie erst zur Laufzeit auftreten. Um die Wahrscheinlichkeit zu minimieren, einen zu verursachen, sollten Sie die etwas sichereren Standardbibliotheksfunktionen verwenden, die einige Grenzen überprüfen - z. fgets() anstelle von gets().

Wenn Sie viele Arrays manuell manipulieren, sollten Sie wahrscheinlich Komponententests schreiben, um Randfälle in Ihren Algorithmen zu überprüfen. Cmockery ist ein Beispiel für ein Unit-Test-Framework für C.

+0

Dieser spezifische Pufferüberlauf sollte zur Kompilierzeit abfragbar sein, da der Code (statisch) auf * (c + 4) zugreift, mit einer Zuweisung, bei der c + 3 die letzte gültige Adresse ist. – Vatine

0

Valgrind nicht überläuft in automatischen und statischen Speicher. Zumindest nicht standardmäßig. IIRC, um es zum Laufen zu bringen, sollten Sie entweder eine Option aktivieren oder die mitgelieferten "in development" Tools ausführen, nicht den Standard "memcheck".

+0

Ich habe auf das neueste Valgrind 3.5.0 aktualisiert und den Befehl --tool = exp-ptrcheck verwendet, der weiterhin mit null Warnungen und Fehlern bestanden hat. – SiegeX

0

Visual Studio (mit -Zi denke ich, aber ich könnte falsch liegen) fängt diese Art von Zuweisung mit seiner Laufzeit Stack Checker. Es ist nicht die freie Linux-Lösung, die Sie bevorzugen, aber funktioniert gut.

2

Versuchen Sie mit Bugfighter C/C++.

Ich benutze es jeden Tag und es funktioniert gut, auch mit mehrdimensionalen Array wie array[5][5][5].

Die Bugfighter-Webseite ist www.bugfighter-soft.com.

2

valgrind des memcheck wird über den Heap-Speicher

Für den Stapel zu erfassen, können Sie valgrind der SGCheck