GCC zu erkennen, wie stack-überlauf
Da gibt es eine option -fstack-protector-strong
im gcc zu erkennen, stack-smashing. Allerdings kann es nicht immer erkennen, dass stack-überlauf. Für die erste Funktion func, wenn ich Eingangs ein 10 char mehr Schnur, wird das Programm nicht immer abstürzt. Meine Frage ist, wo gibt es eine Möglichkeit zu erkennen, stack-überlauf.
void func()
{
char array[10];
gets(array);
}
void func2()
{
char buffer[10];
int n = sprintf(buffer, "%s", "abcdefghpapeas");
printf("aaaa [%d], [%s]\n", n, buffer);
}
int main ()
{
func();
func2();
}
- Warum Sie Kennzeichnen die Frage C++, und dann code schreiben, wie das?
- wäre es nicht logischer, um zu vermeiden, dass in den ersten Platz? Zum Beispiel mit
snprintf(buffer, sizeof(buffer), "%s", ...)
- Es ist dort zu erkennen, ob der stack ist zerschlagen, um nicht zu erkennen, wenn Sie überlaufen des Puffers. Verwenden Sie mehr Zeichen.
- da kommt es in einem legacy-code, um zu minimieren die Auswirkungen von code-änderungen, es ist besser, lassen das Programm Abstürzen, wenn überlauf Auftritt
- Glaubst du, es gibt eine undokumentierte
-fstack-protector-strong-but-i-mean-for-real-now
option oder so? - Der stack und buffer sind zwei komplett verschiedenen Dinge.
- nicht ganz, weil der Puffer auf dem Stapel reserviert.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Overflows auf dem stack sind entweder schwer zu finden oder sehr teuer zu erkennen - wählen Sie Ihr Gift.
In einer nussschale, wenn Sie diese:
dann ist das technisch legal: Es wird Speicherplatz auf dem stack, der gehört zu der Funktion. Es ist einfach sehr gefährlich.
Also die Lösung könnte sein, fügen Sie eine Lücke zwischen
a
undb
und füllen Sie diese mit einem Muster. Aber naja, manche Leute tatsächlich den code schreiben, wie oben. Also, dein compiler braucht, um zu erkennen, dass.Alternativ können wir erstellen ein bit-map aller bytes, dass Ihr code hat wirklich zugewiesen und dann instrument alle der code, der prüft, gegen diese Karte. Sehr sicher, ziemlich langsam, bläht sich der Speicherverbrauch. Auf der positiven Seite, es gibt tools, die helfen, mit diesem (wie Valgrind).
Sehen, wohin ich gehe?
Fazit: In C gibt es keinen guten Weg, um automatisch viele Probleme mit dem Speicher, weil die Sprache und die API ist oft zu schlampig. Die Lösung ist, sich zu bewegen-code in helper-Funktionen, überprüfen Sie Ihre Parameter konsequent, immer auf die richtige und gute unit test-Abdeckung.
Verwenden Sie immer
snprintf()
Versionen von Funktionen wenn Sie die Wahl haben. Wenn der alte code verwendet die unsichere Versionen ändern.Können Sie ein tool namens Valgrind
http://valgrind.org/
stack overflow in thread #1: cant't grow stack...
vielleicht brauchen Sie debugging-Informationen.Weil Sie GCC verwenden, können Sie FORTIFY_SOURCES.
FORTIFY_SOURCE verwendet die "sicherere" Variante von high-risk-Funktionen wie
memcpy
,strcpy
undgets
. Der compiler verwendet die sicherere Variante, wenn es ableiten kann, die Ziel-Puffer-Größe. Wenn die Kopie überschreiten würde, die Ziel-Puffer-Größe), dann ruft das Programmabort()
. Wenn der compiler nicht ableiten, das Ziel-Puffer-Größe, dann die "sicherere" Variante (N) werden nicht verwendet.Deaktivieren FORTIFY_SOURCE für die Prüfung, sollten Sie das Programm kompilieren mit
-U_FORTIFY_SOURCE
oder-D_FORTIFY_SOURCE=0
.C-Standard ist "sicherer" - Funktionen über ISO/IEC TR 24731-1 Bounds-Checking Interfaces. Auf konforme Plattformen, können Sie einfach anrufen
gets_s
undsprintf_s
. Sie bieten ein konsistentes Verhalten (wie immer dafür ein string istNULL
beendet) und die konsequente Rückkehr-Werte (wie 0 bei Erfolg oder einerrno_t
).Leider, gcc und glibc nicht konform zum C-Standard. Ulrich Drepper (einer der glibc-maintainer) genannt bounds-checking interfaces "schrecklich ineffizient BSD Mist", und Sie wurden nie Hinzugefügt. Hoffentlich wird es in der Zukunft ändern.
Zunächst Nicht Verwenden gets.By nun fast jeder kennt die alle Sicherheits-und Zuverlässigkeits-Problemen, die auftreten können, mit bekommt. Aber es ist hier aus historischen Gründen als auch, weil es ist ein sehr gutes Beispiel für schlechte Programmierung.
Schauen wir uns alle die Probleme mit dem code:
Da bekommt nicht bounds checking eine Zeichenfolge, die länger als 100 Zeichen überschreiben von Speicher. Wenn Sie Glück haben, wird das Programm einfach Abstürzen, Oder es ist möglicherweise ungewöhnliches Verhalten.
Bekommt die Funktion ist so schlecht, dass die GNU-gcc-linker gibt eine Warnung aus, Wann immer es verwendet wird.
Schützen array-Zugriffe mit assert
C/C++ nicht gebunden überprüfen.
Beispiel:
Verwenden Sie Assert-Funktion für obigen code
Array overflows sind einer der häufigsten Fehler in der Programmierung und sind extrem frustrierend zu versuchen und zu lokalisieren. Diese Codes nicht beseitigen, aber es verursacht buggy code zum frühen abort in einer Weise, die das problem macht enorm leichter zu finden.
Und Verwenden Snprintf(buffer,sizeof(buffer),"%s","abcdefghpapeas") und einige tools wie valgrind,GDB.
Hoffe das hilft Euch..