Débordement de cours scanf(“%8”, string)?
Je sais que c'est possible de débordement du code ordinaire:
char string[9];
scanf("%s", string).
Mais est-il possible de débordement scanf("%8", string)? 8 est juste un exemple.
Je sais "%8" fonctionne comme un délimiter, mais je remarque aussi quand j'ai de la chaîne d'entrée de plus de 8 caractères, le programme prendra fin en raison:
* stack smashing détecté *: ./un.hors mis fin
======= Backtrace: =========
...
Évidemment il y a un drapeau qui détecte écrasement de la pile activée par GCC par défaut. Puisque c'est un écrasement de la pile, puis je pense qu'il est encore possible de débordement et d'exécuter du code arbitraire.
Contraire à la normale débordement de mangles l'appelant de scanf("%s"), si scanf("%8") peuvent déborder, elle déborde à l'intérieur de fonction scanf, de sorte que lorsque scanf essayez de retour, le contrôle est acquis.
Mais scanf est un syscall qui nécessite de commutation de mode (passage du mode utilisateur en mode noyau), et à l'intérieur il va appeler des trucs comme lecture de l'entrée standard stdin etc. Si vous ne savez pas si nous pouvons débordement en mode noyau ou quelque chose..
Commentaires sont les bienvenus!!
Mise à JOUR >>
char string[9] est supposé dans l'exemple ci-dessus. char chaine[8] dans la suite du code réel.
La question est vraiment à propos de l'apparente contradictoires histoire entre sûre scanf("%8") et GCC l'avortement suite à l'écrasement de la pile.
Simplifié code:
void foo(pass some pointer) {
char input[8];
int input_number = 0;
while (1) { //looping console
printf some info;
scanf("%8s", input);
input_number = atoi(input);
if ((strlen(input) == 1) && (strncmp(input, "q", 1) == 0)) {
input_number = -1;
}
switch (input_number) {
case -1: to quit the console if input = 'q';
default: to print info that pointer refers to;
...
}
}
}
Remarque:
- foo est appelé par quelqu'un d'autre.
- Si la chaîne est de 8 octets dans la vraie
code avec "%8", je ne pense pas que ce
conduire à des smashing.
comme l'a noté à plusieurs reprises dans les réponses, un octet nul est ajouté, de sorte que vous avez besoin d'un 9 tampon de caractère pour accepter jusqu'à 8 caractères de l'entrée.
Comme beaucoup de gens l'ont souligné, votre hypothèse à la Note 2." est faux. Cet exemple permet à un seul octet de dépassement de, qui est ce que gcc est la détection.
vous les gars sont à droite. Je l'ai testé avec un programme plus simple mais c'est en quelque sorte de ne pas planter la dernière fois que j'ai essayé. Maintenant quand je rentre "12345678" pour la chaîne[8] et scanf(%8s) il se bloque en raison de l'écrasement de la pile! Voici donc la leçon apprise. Smashing ne signifie pas nécessairement qu'il y a un débordement de la pile d'attaque.
Même si la mémoire tampon se trouve être sur la pile dans ce cas, le bug de programmation est un débordement de la mémoire tampon pas de un débordement de pile. J'ai utilisé la question en conséquence.
OriginalL'auteur Figo | 2009-11-24
Vous devez vous connecter pour publier un commentaire.
Voir http://www.opengroup.org/onlinepubs/009695399/functions/scanf.html:
De sorte qu'il ne déborde pas un 9-chaîne d'octets de la mémoire tampon.
parce que vous avez fait une erreur. Afficher votre code!
code posté.
en quelque sorte, vous n'êtes pas à la compréhension. "%8" va stocker jusqu'à 9 octets, de sorte que vous avez besoin d'un neuf tableau de caractères.
OriginalL'auteur ysth
Ne pas jamais utilisation
scanf
(oufscanf
que ce soit), si vous voulez que votre entrée pour être robuste.Vous devriez être en utilisant
fgets
(ou même "protégés de débordement de la mémoire tampon" variante) puis utilisersscanf
.Le principal problème avec
scanf
etfscanf
est que votre pointeur de fichier peuvent se retrouver dans un poste de durée indéterminée si la ligne n'est pas le format attendu (c'est à dire, si lescanf
échoue). Avec lefgets/sscanf
méthode, il est beaucoup plus facile de garantir que vous êtes sur une ligne frontière, sans avoir à utiliserftell
etfseek
pour se déplacer dans le fichier.Concernant votre requête spécifique quant à savoir si le tampon débordement, la norme C a ceci à dire:
Ainsi, pour un
"%8s"
format, vous avez besoin d'un 9-tableau de caractères.Je soupçonne que vous avez un autre problème dans votre code. Avec un programme de test:
J'obtiens:
Quand je change le même programme à utiliser
"%8s"
, je reçois (pour exactement la même entrée):Décrire "robuste"? Donner quelques exemples?
Obtenez votre entrée sous forme de lignes. (2) s'Assurer que vous obtenez l'ensemble des lignes (\n char à la fin), l'erreur, sinon avec la "ligne trop longue". (3) Utiliser sscanf en ligne - vous pouvez le faire autant de fois que vous voulez sur la ligne sans se soucier le fichier sous-jacent.
J'ai aussi tester un semblable simplié code comme vous l'avez fait et GCC ne vais pas me plaindre d'écrasement de la pile.. j'ai posté orig code et le truc, c'est au moment de l'exécution, il y aura GCC se plaindre quand je saisie 12345678 (Remarque dans le code réel, chaîne de char[8]).
vous avez besoin d'un 9-tableau de caractères pour stocker une chaîne de 8 caractères. Parce que, pour une chaîne de 8 caractères composé de 8 caractères (évidemment) et un terminateur null caractère (pas si évident). Si vous changer de char string[9], vous ne devriez pas avoir de problèmes.
OriginalL'auteur paxdiablo
si la chaîne est allouée pour les moins de 8 chartes elle va certainement remplacer le tampon aussi scanf ne sera pas ajouter un terminateur null. Mais aussi longtemps que vous avez suffisamment d'espace dans la chaîne de valeur, vous ne devriez pas obtenir un overwright.
En fait, je pense que scanf va mettre un '\0' à la fin. C standard dit "un caractère de fin null, qui seront ajoutés automatiquement.", également cité par paxdiablo
Je voulais dire si vous n'avez pas également un espace pour les nuls.
Si vous ne disposez pas d'un espace pour les nuls, il l'a mis là, peu importe (en écrasant une autre partie de la pile si nécessaire).
char chaine[9] devrait être bon.
OriginalL'auteur rerun
Comme ysth souligné, le tableau devrait être en mesure de contenir la chaîne de et la fin null-personnage, donc à l'aide d'un 8-tableau d'octets (surtout si c'est allouée sur la pile, comme il est dans votre code) est très probablement le désordre.
OriginalL'auteur Tal Pressman