Aller au contenu

[C]Scanf + Regexp et le dépassement de tampon


Don_Angelo

Messages recommandés

Bonjour à tous,

Je me trouve face à un épineux problème que je pense du à un dépassement de buffer.

Je fais un scanf avec une regexp:

retour = scanf(" %1[a-hA-H]%1[1-8] - %1[a-hA-H]%1[1-8]",lettreDepart,chiffreDepart,lettreArrivee,chiffreArrivee);

Cette ligne fait partie d'une fonction dont voici le prototype:

void saisie_coup (char* lettreDepart, char* chiffreDepart, char* lettreArrivee, char* chiffreArrivee)

Problème si les variables lettreDepart,chiffreDepart,lettreArrivee,chiffreArrivee sont de type char* ça ne marche pas les variables lettre et chiffre départ reçoivent le caractère de fin de chaine. Or il me semble que le masque que je donne à scanf appelle justement à ce que mes variables soient de type char.

En revanche si je m'amuse à typer mes variables en int* short* ou long* l'affectation fonctionne parfaitement. Sauf que sous windows le programme plante à la toute fin du main.

Pas sous Linux celà dit.

Je suis pourtant sûr que scanf formate mes variables comme des char* car si je veux les afficher je dois utiliser un printf avec un masque de type char. Et ceux malgré la drôle de cuisine interne qui se produit avec des casts implicites.

Mon idée c'est que le tampon utilisé par scanf n'est pas suffisamment grand et qu'il y a un buffer-overflow. Sauf que si je comprends bien scanf est justement censée calculer la taille du buffer en fonction du masque qu'elle reçoit en premier argument, or la d'après ce que je vois c'est pas le cas.

A signaler quand même que si je fais le test sur deux variables de type char* aucun problème. C'est le seul point qui démonte ma théorie.

Quelqu'un à t'il une idée sur la raison de ce bug étrange?

D'avance Merci.

Lien à poster

alors à ma connaissance, scanf ne fait pas d'expression regulieres.

donc cela ne m'etonne pas que ca plante. La premiere expression reconnue par scanf est un %l qui correspond à un entier. Donc si tu lui met un pointeur char * cela ne peut marcher.

en gros scanf marche ainsi

char lettre_depart

int chiffre_depart

char lettre_arrive

int chiffre_arrive

retour = scanf("%c%d - %c%d, &lettre_depart, &chiffre_depart, &lettre_arrive, &chiffre_arrive);

en supposant que tu souhaite parser des lignes du style :

a2 - b23

a45 - g12

...

Lien à poster

rjds, justement si je crois bien, pour preuve quand je met un des int* partout et que je tape quelque chose qui ne correspond pas au masque la valeur retournée par scanf change et la saisie est reconnue comme non conforme au masque.

L'interêt de faire ce que j'essaye de faire c'est justement de pouvoir contrôler directement la saisie par scanf et pas à avoir à programmer une fonction qui réalise mes test ensuite. En plus ce que tu écrit n'est pas déjà une expression rationnelle en soit?

Je sais que ça parait dingue, même mon prof de C à la fac a pas saisi ce qui se passe à ce moment la.

Je me demande si en fait scanf ne rajoute pas de '0' à la fin de chaque char qu'elle récupère au clavier, si c'est le cas ça me parait un peu fort qu'avec sa cuisine interne de cast le compilateur arrive à mettre les bonnes valeurs là ou il faut quand la saisie est conforme au masque alors qu'en toute logique il ne devrait pas.

Lien à poster

non je suis catégorique, scanf ne fais pas d'expression. Elle est en revanche capable de detecter des mots et des nombres (pas des groupes de mots).

donc avec scanf tu peux detecter :

%c des char

%d des nombres entier signé

%s des mots

scanf est une fonction rigoureuse et dangereuse. Qui ne marchera pas si ce qu'il y a n'est pas bien formaté.

je te renvoi au man de scanf qui est fort bien documenté.

Lien à poster

D'accord ce ne sont pas des expressions rationnelles comme on en a l'habitude de le voir en Perl par exemple mais le principe y est, et je me demande si au fond on pourrait pas dire que cette implémentation n'est pas un ancêtre de ces fameuses reg. Je serais d'ailleurs pas surpris que leurs implémentations en Perl ou PHP ne soit pas codés de cette façon.

Après m'être arraché les cheveux j'ai fini par comprendre que scanf mettait effectivement un caractère de fin de chaine à la fin de chacun de mes char.

Mon code est à présent fonctionnel.

Après recherche sur google je suis même tombé sur un article qui explique comment faire ce que je voulais (c'est con j'avais pas les bons mots clés)

http://xrenault.developpez.com/tutoriels/c/scanf/

Maintenant que je le vois je me souviens que j'avais déjà lu un truc similaire dans un bouquin de C.

Je suis d'accord sur le fait que c'est pas un usage courant mais au fond je pense qu'on peut faire confiance à développez.com

En plus si je lis le manuel de scanf sur linux-france c'est inscrit:

http://www.linux-france.org/article/man-fr/man3/scanf-3.html

Lien à poster
×
×
  • Créer...