348 votes

Destruction de la pile détectée

J'exécute mon fichier a.out. Après l'exécution, le programme fonctionne pendant un certain temps puis se termine avec le message suivant :

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

Quelles peuvent en être les raisons et comment y remédier ?

2 votes

Pourriez-vous peut-être identifier les parties de votre code qui provoquent l'effondrement de la pile, et le poster ? Nous serons alors probablement en mesure d'indiquer exactement pourquoi cela se produit et comment le corriger.

0 votes

Je pense que c'est un synonyme d'erreur de dépassement de capacité. Par exemple, si vous initialisez un tableau de 5 éléments, cette erreur apparaîtra lorsque vous essaierez d'écrire le 6ème élément, ou tout élément en dehors des limites du tableau.

455voto

sud03r Points 6093

Le stack smashing ici est en fait causé par un mécanisme de protection utilisé par gcc pour détecter les erreurs de dépassement de tampon. Par exemple, dans l'extrait suivant :

#include <stdio.h>

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

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

Le compilateur, (dans ce cas gcc) ajoute des variables de protection (appelées canaries) qui ont des valeurs connues. Une chaîne d'entrée de taille supérieure à 10 provoque la corruption de cette variable, ce qui entraîne l'arrêt du programme par SIGABRT.

Pour y voir plus clair, vous pouvez essayer de désactiver cette protection de gcc en utilisant l'option -fno-stack-protector lors de la compilation. Dans ce cas, vous obtiendrez une erreur différente, très probablement une erreur de segmentation car vous essayez d'accéder à un emplacement mémoire illégal. Notez que -fstack-protector doit toujours être activée pour les versions publiées car il s'agit d'une fonctionnalité de sécurité.

Vous pouvez obtenir des informations sur le point de débordement en exécutant le programme avec un débogueur. Valgrind ne fonctionne pas bien avec les erreurs liées à la pile, mais comme un débogueur, il peut vous aider à déterminer l'emplacement et la raison du plantage.

6 votes

Merci pour cette réponse ! J'ai découvert que dans mon cas, je n'avais pas initialisé la variable dans laquelle j'essayais d'écrire.

5 votes

Valgrind ne fonctionne pas bien pour les erreurs liées à la pile, car il ne peut pas y ajouter de zones rouges.

9 votes

Cette réponse est incorrecte, et donne un conseil dangereux. Tout d'abord, la suppression du protecteur de pile n'est pas la bonne solution. Si vous obtenez une erreur d'écrasement de pile, vous avez probablement une grave vulnérabilité de sécurité dans votre code. La bonne réponse est de corriger le code bogué . Deuxièmement, comme le souligne grasGendarme, la recommandation d'essayer Valgrind ne sera pas efficace. Valgrind ne fonctionne généralement pas pour détecter les accès mémoire illégaux aux données allouées à la pile.

18voto

bugbug Points 894

Veuillez examiner la situation suivante :

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:$ 

Lorsque j'ai désactivé le protecteur de pile, aucune erreur n'a été détectée, ce qui aurait dû se produire lorsque j'ai utilisé "./a.out wepassssssssssssssss".

Donc, pour répondre à votre question ci-dessus, le message "** stack smashing detected : xxx" a été affiché parce que votre protecteur de stack smashing était actif et a trouvé qu'il y a un débordement de pile dans votre programme.

Il suffit de trouver où cela se produit, et de le réparer.

17voto

Travis Points 101

Votre variable tampon ne permet que 20 caractères, votre argument est de 23, augmentez votre tampon pour soutenir votre argument...

char buffer[20];

8voto

hlovdal Points 11039

Vous pouvez essayer de déboguer le problème en utilisant Valgrind :

La distribution de Valgrind comprend actuellement comprend actuellement six outils de qualité production : un détecteur d'erreurs de mémoire, deux détecteurs détecteurs d'erreurs, un profileur de cache et prédiction de branchement, un profileur de cache générant des graphes d'appels, et un profileur de tas. Il comprend également deux outils expérimentaux : un dépassement de tas/pile/réseau global détecteur et un générateur de vecteurs de blocs de base SimPoint générateur de vecteurs. Il fonctionne sur les plateformes suivantes : X86/Linux, AMD64/Linux, PPC32/Linux, PPC64/Linux, et X86/Darwin (Mac OS X).

2 votes

Oui, mais Valgrind ne fonctionne pas bien pour les débordements de tampons alloués par pile, ce qui est la situation que ce message d'erreur indique.

4 votes

Comment pourrions-nous utiliser cette détecteur de dépassement de tableau de pile ? Pouvez-vous préciser ?

1 votes

@CraigMcQueen J'ai essayé d'utiliser l'heuristique expérimentale SGCheck de Valgrind pour détecter les ruptures de pile sur un exemple minimal : stackoverflow.com/a/51897264/895245 mais ça a échoué.

6voto

starblue Points 29696

Cela signifie que vous avez écrit sur certaines variables de la pile d'une manière illégale, très probablement à la suite d'une erreur d'écriture. Dépassement de tampon .

9 votes

Le débordement de pile est le fait que la pile se fracasse sur quelque chose d'autre. Ici, c'est l'inverse : quelque chose s'est écrasé sur la pile.

6 votes

Pas vraiment. C'est une partie de la pile qui s'écrase sur une autre partie. Il s'agit donc bien d'un débordement de tampon, mais pas sur le sommet de la pile, mais "seulement" sur une autre partie de la pile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X