Stapelzertrümmerung erkannt

Lesezeit: 15 Minuten

Benutzeravatar von Biswajyoti Das
Biswajyoti Das

Ich führe meine a.out-Datei aus. Nach der Ausführung läuft das Programm einige Zeit und beendet sich dann mit der Meldung:

**** stack smashing detected ***: ./a.out terminated*
*======= Backtrace: =========*
*/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)Aborted*

Was könnten die möglichen Gründe dafür sein und wie kann ich das beheben?

  • Könnten Sie vielleicht identifizieren, welche Teile Ihres Codes das Zerschlagen des Stapels verursachen, und es posten? Dann können wir wahrscheinlich genau aufzeigen, warum es passiert und wie es behoben werden kann.

    – Bjarke Freund-Hansen

    30. August 2009 um 8:45 Uhr

  • Ich denke, es ist ein Synonym für Überlauffehler. Wenn Sie beispielsweise ein Array mit 5 Elementen initialisieren, wird dieser Fehler angezeigt, wenn Sie versuchen, das 6. Element oder ein beliebiges Element außerhalb der Grenzen des Arrays zu schreiben.

    – Dorin Popescu

    12. September 2018 um 20:09 Uhr

Benutzeravatar von sud03r
sud03r

Stack Smashing hier wird tatsächlich durch einen Schutzmechanismus verursacht, der von gcc verwendet wird, um Pufferüberlauffehler zu erkennen. Zum Beispiel im folgenden Ausschnitt:

#include <stdio.h>

void func()
{
    char array[10];
    gets(array);
}

int main(int argc, char **argv)
{
    func();
}

Der Compiler (in diesem Fall gcc) fügt Schutzvariablen (genannt Canaries) hinzu, die bekannte Werte haben. Eine Eingabezeichenfolge mit einer Größe von mehr als 10 verursacht eine Beschädigung dieser Variablen, was dazu führt, dass SIGABRT das Programm beendet.

Um einen Einblick zu erhalten, können Sie versuchen, diesen Schutz von gcc mit der Option zu deaktivieren -fno-stack-protector beim Kompilieren. In diesem Fall erhalten Sie einen anderen Fehler, höchstwahrscheinlich einen Segmentierungsfehler, da Sie versuchen, auf einen illegalen Speicherort zuzugreifen. Beachten Sie, dass -fstack-protector sollte für Release-Builds immer aktiviert sein, da es sich um eine Sicherheitsfunktion handelt.

Sie können einige Informationen über den Überlaufpunkt erhalten, indem Sie das Programm mit einem Debugger ausführen. Valgrind funktioniert nicht gut mit Stack-bezogenen Fehlern, aber wie ein Debugger kann es Ihnen helfen, den Ort und den Grund für den Absturz zu lokalisieren.

  • danke für diese antwort! Ich stellte fest, dass ich in meinem Fall die Variable, in die ich schreiben wollte, nicht initialisiert hatte

    – Ted Pennings

    13. Juni 2012 um 0:16 Uhr

  • Valgrind funktioniert nicht gut bei Stack-bezogenen Fehlern, da es dort keine roten Zonen hinzufügen kann

    – geröstete_Flocken

    7. Januar 2014 um 10:35 Uhr

  • Diese Antwort ist falsch und enthält gefährliche Ratschläge. Zunächst einmal ist das Entfernen des Stack-Schutzes nicht die richtige Lösung – wenn Sie einen Stack-Smashing-Fehler erhalten, haben Sie wahrscheinlich eine ernsthafte Sicherheitslücke in Ihrem Code. Die richtige Antwort ist zu Korrigieren Sie den fehlerhaften Code. Zweitens, wie grasGendarme betont, wird die Empfehlung, Valgrind auszuprobieren, nicht wirksam sein. Valgrind funktioniert normalerweise nicht, um illegale Speicherzugriffe auf stapelzugeordnete Daten zu erkennen.

    – DW

    9. Februar 2014 um 2:16 Uhr


  • Das OP fragt nach möglichen Gründen für dieses Verhalten, meine Antwort enthält ein Beispiel und wie es sich auf einen hinreichend bekannten Fehler bezieht. Außerdem ist das Entfernen des Stapelschutzes keine Lösung, sondern eine Art Experiment, das man durchführen könnte, um mehr Einblicke in das Problem zu erhalten. Der Rat ist eigentlich, den Fehler irgendwie zu beheben, danke für den Hinweis auf Valgrind, ich werde meine Antwort bearbeiten, um dies widerzuspiegeln.

    – sud03r

    9. Februar 2014 um 9:14 Uhr


  • @DW Der Stapelschutz sollte in einer Release-Version deaktiviert werden, da zunächst – die Stapelzertrümmerung erkannt Nachricht ist nur eine Hilfe für Entwickler; zweitens — eine Anwendung könnte noch Überlebenschancen haben; und drittens – dies ist eine winzige Optimierung.

    – Hallo Engel

    4. Juni 2014 um 12:44 Uhr


Ciro Santilli Benutzeravatar von OurBigBook.com
Ciro Santilli OurBigBook.com

Minimales Reproduktionsbeispiel mit Demontageanalyse

Haupt c

void myfunc(char *const src, int len) {
    int i;
    for (i = 0; i < len; ++i) {
        src[i] = 42;
    }
}

int main(void) {
    char arr[] = {'a', 'b', 'c', 'd'};
    int len = sizeof(arr);
    myfunc(arr, len + 1);
    return 0;
}

GitHub-Upstream.

Kompilieren und ausführen:

gcc -fstack-protector-all -g -O0 -std=c99 main.c
ulimit -c unlimited && rm -f core
./a.out

versagt wie gewünscht:

*** stack smashing detected ***: terminated
Aborted (core dumped)

Getestet auf Ubuntu 20.04, GCC 10.2.0.

Auf Ubuntu 16.04 konnte ich mit GCC 6.4.0 reproduzieren -fstack-protector Anstatt von -fstack-protector-allaber es hörte auf zu explodieren, als ich gemäß Geng Jiawens Kommentar auf GCC 10.2.0 testete. man gcc verdeutlicht, dass, wie der Optionsname andeutet, die -all Version fügt Prüfungen aggressiver hinzu und verursacht daher vermutlich einen größeren Leistungsverlust:

-fstack-protector

Geben Sie zusätzlichen Code aus, um nach Pufferüberläufen zu suchen, wie z. B. Stack-Smashing-Angriffen. Dies geschieht durch Hinzufügen einer Guard-Variable zu Funktionen mit anfälligen Objekten. Dazu gehören Funktionen, die “alloca” aufrufen, und Funktionen mit Puffern, die größer oder gleich 8 Bytes sind. Die Wächter werden initialisiert, wenn eine Funktion eingegeben wird, und dann überprüft, wenn die Funktion beendet wird. Schlägt eine Wächterprüfung fehl, wird eine Fehlermeldung ausgegeben und das Programm beendet. Es werden nur tatsächlich auf dem Stack allokierte Variablen berücksichtigt, wegoptimierte Variablen oder in Registern allokierte Variablen zählen nicht.

-fstack-protector-all

Wie -fstack-protector, außer dass alle Funktionen geschützt sind.

Demontage

Nun schauen wir uns die Demontage an:

objdump -D a.out

was beinhaltet:

int main (void){
  400579:       55                      push   %rbp
  40057a:       48 89 e5                mov    %rsp,%rbp

  # Allocate 0x10 of stack space.
  40057d:       48 83 ec 10             sub    $0x10,%rsp

  # Put the 8 byte canary from %fs:0x28 to -0x8(%rbp),
  # which is right at the bottom of the stack.
  400581:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400588:       00 00 
  40058a:       48 89 45 f8             mov    %rax,-0x8(%rbp)

  40058e:       31 c0                   xor    %eax,%eax
    char arr[] = {'a', 'b', 'c', 'd'};
  400590:       c6 45 f4 61             movb   $0x61,-0xc(%rbp)
  400594:       c6 45 f5 62             movb   $0x62,-0xb(%rbp)
  400598:       c6 45 f6 63             movb   $0x63,-0xa(%rbp)
  40059c:       c6 45 f7 64             movb   $0x64,-0x9(%rbp)
    int len = sizeof(arr);
  4005a0:       c7 45 f0 04 00 00 00    movl   $0x4,-0x10(%rbp)
    myfunc(arr, len + 1);
  4005a7:       8b 45 f0                mov    -0x10(%rbp),%eax
  4005aa:       8d 50 01                lea    0x1(%rax),%edx
  4005ad:       48 8d 45 f4             lea    -0xc(%rbp),%rax
  4005b1:       89 d6                   mov    %edx,%esi
  4005b3:       48 89 c7                mov    %rax,%rdi
  4005b6:       e8 8b ff ff ff          callq  400546 <myfunc>
    return 0;
  4005bb:       b8 00 00 00 00          mov    $0x0,%eax
}
  # Check that the canary at -0x8(%rbp) hasn't changed after calling myfunc.
  # If it has, jump to the failure point __stack_chk_fail.
  4005c0:       48 8b 4d f8             mov    -0x8(%rbp),%rcx
  4005c4:       64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
  4005cb:       00 00 
  4005cd:       74 05                   je     4005d4 <main+0x5b>
  4005cf:       e8 4c fe ff ff          callq  400420 <__stack_chk_fail@plt>

  # Otherwise, exit normally.
  4005d4:       c9                      leaveq 
  4005d5:       c3                      retq   
  4005d6:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4005dd:       00 00 00 

Beachten Sie die praktischen Kommentare, die automatisch von hinzugefügt werden objdump‘s Modul für künstliche Intelligenz.

Wenn Sie dieses Programm mehrmals über GDB ausführen, werden Sie Folgendes sehen:

  • Der Kanarienvogel erhält jedes Mal einen anderen zufälligen Wert
  • die letzte Schleife von myfunc ist genau das, was die Adresse des Kanarienvogels ändert

Der Kanarienvogel wird randomisiert, indem er mit gesetzt wird %fs:0x28die einen zufälligen Wert enthält, wie erklärt unter:

Debug-Versuche

Von nun an ändern wir den Code:

    myfunc(arr, len + 1);

stattdessen sein:

    myfunc(arr, len);
    myfunc(arr, len + 1); /* line 12 */
    myfunc(arr, len);

interessanter zu sein.

Wir werden dann versuchen zu sehen, ob wir den Übeltäter ausfindig machen können + 1 Aufruf mit einer Methode, die automatisierter ist als nur das Lesen und Verstehen des gesamten Quellcodes.

gcc -fsanitize=address um den Address Sanitizer (ASan) von Google zu aktivieren

Wenn Sie mit diesem Flag neu kompilieren und das Programm ausführen, wird Folgendes ausgegeben:

#0 0x4008bf in myfunc /home/ciro/test/main.c:4
#1 0x40099b in main /home/ciro/test/main.c:12
#2 0x7fcd2e13d82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#3 0x400798 in _start (/home/ciro/test/a.out+0x40079

gefolgt von etwas mehr farbiger Ausgabe.

Dies zeigt deutlich die problematische Linie 12.

Der Quellcode dafür ist unter: https://github.com/google/sanitizers aber wie wir aus dem Beispiel gesehen haben, ist es bereits in GCC vorgelagert.

ASan kann auch andere Speicherprobleme wie Speicherlecks erkennen: Wie findet man Speicherlecks in einem C++-Code/Projekt?

Valgrind SGCheck

Wie von anderen erwähnt, ist Valgrind nicht gut darin, diese Art von Problem zu lösen.

Es hat ein experimentelles Werkzeug namens SGCheck:

SGCheck ist ein Tool zum Auffinden von Überläufen von Stapeln und globalen Arrays. Es arbeitet mit einem heuristischen Ansatz, der aus einer Beobachtung über die wahrscheinlichen Formen von Stapel- und globalen Array-Zugriffen abgeleitet wurde.

Daher war ich nicht sehr überrascht, als der Fehler nicht gefunden wurde:

valgrind --tool=exp-sgcheck ./a.out

Die Fehlermeldung sollte anscheinend so aussehen: Valgrind missing error

GDB

Eine wichtige Beobachtung ist, dass, wenn Sie das Programm über GDB ausführen oder die core Datei nachträglich:

gdb -nh -q a.out core

dann sollte GDB Sie, wie wir in der Assembly gesehen haben, auf das Ende der Funktion verweisen, die die Canary-Prüfung durchgeführt hat:

(gdb) bt
#0  0x00007f0f66e20428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
#1  0x00007f0f66e2202a in __GI_abort () at abort.c:89
#2  0x00007f0f66e627ea in __libc_message (do_abort=do_abort@entry=1, fmt=fmt@entry=0x7f0f66f7a49f "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175
#3  0x00007f0f66f0415c in __GI___fortify_fail (msg=<optimized out>, msg@entry=0x7f0f66f7a481 "stack smashing detected") at fortify_fail.c:37
#4  0x00007f0f66f04100 in __stack_chk_fail () at stack_chk_fail.c:28
#5  0x00000000004005f6 in main () at main.c:15
(gdb) f 5
#5  0x00000000004005f6 in main () at main.c:15
15      }
(gdb)

Daher liegt das Problem wahrscheinlich in einem der Aufrufe dieser Funktion.

Als nächstes versuchen wir, den genauen fehlgeschlagenen Anruf zu lokalisieren, indem wir zuerst einzeln nach oben treten, kurz nachdem der Kanarienvogel gesetzt wurde:

  400581:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  400588:       00 00 
  40058a:       48 89 45 f8             mov    %rax,-0x8(%rbp)

und die Adresse beobachten:

(gdb) p $rbp - 0x8
$1 = (void *) 0x7fffffffcf18
(gdb) watch 0x7fffffffcf18
Hardware watchpoint 2: *0x7fffffffcf18
(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffcf18

Old value = 1800814336
New value = 1800814378
myfunc (src=0x7fffffffcf14 "*****?Vk\266", <incomplete sequence \355\216>, len=5) at main.c:3
3           for (i = 0; i < len; ++i) {
(gdb) p len
$2 = 5
(gdb) p i
$3 = 4
(gdb) bt
#0  myfunc (src=0x7fffffffcf14 "*****?Vk\266", <incomplete sequence \355\216>, len=5) at main.c:3
#1  0x00000000004005cc in main () at main.c:12

Nun, das lässt uns bei der richtigen beleidigenden Anweisung zurück: len = 5 und i = 4und in diesem speziellen Fall haben wir uns auf die schuldige Linie 12 verwiesen.

Der Backtrace ist jedoch beschädigt und enthält etwas Müll. Ein korrekter Backtrace würde wie folgt aussehen:

#0  myfunc (src=0x7fffffffcf14 "abcd", len=4) at main.c:3
#1  0x00000000004005b8 in main () at main.c:11

Dies könnte also möglicherweise den Stapel beschädigen und verhindern, dass Sie die Ablaufverfolgung sehen.

Außerdem erfordert diese Methode, dass Sie wissen, was der letzte Aufruf der Canary-Prüffunktion ist, da Sie sonst falsch positive Ergebnisse erhalten, was nicht immer möglich ist, es sei denn, Sie verwenden umgekehrtes Debugging.

  • auf einem höheren gcc wie 10 müssen Sie möglicherweise verwenden -fstack-protector-all. Demo: godbolt.org/z/n1cqPn

    – Geng Jiawen

    19. Februar 2021 um 3:39 Uhr


  • Ergänzung zum obigen Kommentar – -fstack-protector-strong funktioniert auch

    – valano

    8. November 2021 um 14:42 Uhr

Benutzeravatar von wearetherock
tragender Rock

Bitte sehen Sie sich folgende Situation an:

ab@cd-x:$ cat test_overflow.c 
#include <stdio.h>
#include <string.h>

int check_password(char *password){
    int flag = 0;
    char buffer[20];
    strcpy(buffer, password);

    if(strcmp(buffer, "mypass") == 0){
        flag = 1;
    }
    if(strcmp(buffer, "yourpass") == 0){
        flag = 1;
    }
    return flag;
}

int main(int argc, char *argv[]){
    if(argc >= 2){
        if(check_password(argv[1])){
            printf("%s", "Access granted\n");
        }else{
            printf("%s", "Access denied\n");
        }
    }else{
        printf("%s", "Please enter password!\n");
    }
}
ab@cd-x:$ gcc -g -fno-stack-protector test_overflow.c 
ab@cd-x:$ ./a.out mypass
Access granted
ab@cd-x:$ ./a.out yourpass
Access granted
ab@cd-x:$ ./a.out wepass
Access denied
ab@cd-x:$ ./a.out wepassssssssssssssssss
Access granted

ab@cd-x:$ gcc -g -fstack-protector test_overflow.c 
ab@cd-x:$ ./a.out wepass
Access denied
ab@cd-x:$ ./a.out mypass
Access granted
ab@cd-x:$ ./a.out yourpass
Access granted
ab@cd-x:$ ./a.out wepassssssssssssssssss
*** stack smashing detected ***: ./a.out terminated
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x48)[0xce0ed8]
/lib/tls/i686/cmov/libc.so.6(__fortify_fail+0x0)[0xce0e90]
./a.out[0x8048524]
./a.out[0x8048545]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xc16b56]
./a.out[0x8048411]
======= Memory map: ========
007d9000-007f5000 r-xp 00000000 08:06 5776       /lib/libgcc_s.so.1
007f5000-007f6000 r--p 0001b000 08:06 5776       /lib/libgcc_s.so.1
007f6000-007f7000 rw-p 0001c000 08:06 5776       /lib/libgcc_s.so.1
0090a000-0090b000 r-xp 00000000 00:00 0          [vdso]
00c00000-00d3e000 r-xp 00000000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d3e000-00d3f000 ---p 0013e000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d3f000-00d41000 r--p 0013e000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d41000-00d42000 rw-p 00140000 08:06 1183       /lib/tls/i686/cmov/libc-2.10.1.so
00d42000-00d45000 rw-p 00000000 00:00 0 
00e0c000-00e27000 r-xp 00000000 08:06 4213       /lib/ld-2.10.1.so
00e27000-00e28000 r--p 0001a000 08:06 4213       /lib/ld-2.10.1.so
00e28000-00e29000 rw-p 0001b000 08:06 4213       /lib/ld-2.10.1.so
08048000-08049000 r-xp 00000000 08:05 1056811    /dos/hacking/test/a.out
08049000-0804a000 r--p 00000000 08:05 1056811    /dos/hacking/test/a.out
0804a000-0804b000 rw-p 00001000 08:05 1056811    /dos/hacking/test/a.out
08675000-08696000 rw-p 00000000 00:00 0          [heap]
b76fe000-b76ff000 rw-p 00000000 00:00 0 
b7717000-b7719000 rw-p 00000000 00:00 0 
bfc1c000-bfc31000 rw-p 00000000 00:00 0          [stack]
Aborted
ab@cd-x:$ 

Als ich den Stack-Smashing-Protector deaktivierte, wurden keine Fehler erkannt, was hätte passieren müssen, wenn ich “./a.out wepasssssssssssssssssss” verwendet habe.

Um Ihre obige Frage zu beantworten, wurde die Meldung “** Stack-Smashing erkannt: xxx” angezeigt, weil Ihr Stack-Smashing-Schutz aktiv war und festgestellt hat, dass in Ihrem Programm ein Stack-Überlauf vorliegt.

Finden Sie einfach heraus, wo das auftritt, und beheben Sie es.

Sie könnten versuchen, das Problem mit zu debuggen Valgrind:

Die Valgrind-Distribution umfasst derzeit sechs Tools in Produktionsqualität: einen Speicherfehlerdetektor, zwei Thread-Fehlerdetektoren, einen Cache- und Verzweigungsvorhersage-Profiler, einen Call-Graph-generierenden Cache-Profiler und einen Heap-Profiler. Es enthält auch zwei experimentelle Tools: a
Heap/Stack/globaler Array-Überlaufdetektor, und einen einfachen SimPoint-Blockvektorgenerator. Es läuft auf den folgenden Plattformen: X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux und X86/Darwin (Mac OS X).

Es bedeutet, dass Sie auf illegale Weise in einige Variablen auf dem Stack geschrieben haben, höchstwahrscheinlich als Ergebnis von a Pufferüberlauf.

  • Stapelüberlauf ist der Stapel, der in etwas anderes zerschmettert wird. Hier ist es umgekehrt: Etwas ist in den Stapel geschmettert.

    – Peter Mortensen

    28. August 2009 um 9:27 Uhr

  • Nicht wirklich. Es ist ein Teil des Stapels, der in einen anderen Teil zerschmettert. Es ist also wirklich ein Pufferüberlauf, nur nicht über den Stack, sondern “nur” in einen anderen Teil des Stacks.

    – Bas Wijnen

    30. November 2012 um 7:48 Uhr

Benutzeravatar von Michi
Michi

Was könnten die möglichen Gründe dafür sein und wie kann ich das beheben?

Ein Szenario wäre im folgenden Beispiel:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap ( char *a , char *b );
void revSTR ( char *const src );

int main ( void ){
    char arr[] = "A-B-C-D-E";

    revSTR( arr );
    printf("ARR = %s\n", arr );
}

void swap ( char *a , char *b ){
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

void revSTR ( char *const src ){
    char *start = src;
    char *end   = start + ( strlen( src ) - 1 );

    while ( start < end ){
        swap( &( *start ) , &( *end ) );
        start++;
        end--;
    }
}

In diesem Programm können Sie einen String oder einen Teil des Strings umkehren, wenn Sie ihn zum Beispiel aufrufen reverse() mit sowas:

reverse( arr + 2 );

Wenn Sie sich entscheiden, die Länge des Arrays wie folgt zu übergeben:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void swap ( char *a , char *b );
void revSTR ( char *const src, size_t len );

int main ( void ){
    char arr[] = "A-B-C-D-E";
    size_t len = strlen( arr );

    revSTR( arr, len );
    printf("ARR = %s\n", arr );
}

void swap ( char *a , char *b ){
    char tmp = *a;
    *a = *b;
    *b = tmp;
}

void revSTR ( char *const src, size_t len ){
    char *start = src;
    char *end   = start + ( len - 1 );

    while ( start < end ){
        swap( &( *start ) , &( *end ) );
        start++;
        end--;
    }
}

Funktioniert auch gut.

Aber wenn Sie dies tun:

revSTR( arr + 2, len );

Sie bekommen:

==7125== Command: ./program
==7125== 
ARR = A-
*** stack smashing detected ***: ./program terminated
==7125== 
==7125== Process terminating with default action of signal 6 (SIGABRT)
==7125==    at 0x4E6F428: raise (raise.c:54)
==7125==    by 0x4E71029: abort (abort.c:89)
==7125==    by 0x4EB17E9: __libc_message (libc_fatal.c:175)
==7125==    by 0x4F5311B: __fortify_fail (fortify_fail.c:37)
==7125==    by 0x4F530BF: __stack_chk_fail (stack_chk_fail.c:28)
==7125==    by 0x400637: main (program.c:14)

Und das passiert, weil im ersten Code die Länge von arr wird innen überprüft revSTR() das ist in Ordnung, aber im zweiten Code, wo Sie die Länge übergeben:

revSTR( arr + 2, len );

Die Länge ist jetzt länger als die tatsächliche Länge, die Sie übergeben, wenn Sie sagen arr + 2.

Länge von strlen ( arr + 2 ) != strlen ( arr ).

  • Stapelüberlauf ist der Stapel, der in etwas anderes zerschmettert wird. Hier ist es umgekehrt: Etwas ist in den Stapel geschmettert.

    – Peter Mortensen

    28. August 2009 um 9:27 Uhr

  • Nicht wirklich. Es ist ein Teil des Stapels, der in einen anderen Teil zerschmettert. Es ist also wirklich ein Pufferüberlauf, nur nicht über den Stack, sondern “nur” in einen anderen Teil des Stacks.

    – Bas Wijnen

    30. November 2012 um 7:48 Uhr

Benutzeravatar von Calmarius
Calmarius

Stapelbeschädigungen werden normalerweise durch Pufferüberläufe verursacht. Sie können sich dagegen wehren, indem Sie defensiv programmieren.

Immer wenn Sie auf ein Array zugreifen, setzen Sie ein Assert davor, um sicherzustellen, dass der Zugriff nicht außerhalb der Grenzen liegt. Zum Beispiel:

assert(i + 1 < N);
assert(i < N);
a[i + 1] = a[i];

Dies lässt Sie über Array-Grenzen nachdenken und auch darüber nachdenken, Tests hinzuzufügen, um sie auszulösen, wenn möglich. Wenn einige dieser Assertionen während des normalen Gebrauchs fehlschlagen können, machen Sie sie zu einer regulären if.

1427380cookie-checkStapelzertrümmerung erkannt

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy