Ma fonction "détruit" ma variable !

Ma fonction "détruit" ma variable ! - C - Programmation

Marsh Posté le 02-05-2005 à 20:19:52    

Code :
  1. [...]
  2.                         printf("%s",chemin);
  3.   Cree_subi(chemin,subi,(patient.DernierExam)-1);
  4.   printf("\n\n\tExamens : \n" );
  5.   printf("%s",chemin);
  6.   AfficherExamens(chemin,subi);
  7.  }
  8. }
  9. printf("\n\nAppuyez sur une touche pour retourner au menu ... " );
  10. getch();
  11. }
  12. void Cree_subi(char *chemin,SUBI_EXAMENS *subi,int ligne)
  13. {
  14. char fichier[20];
  15. FILE *fp;
  16. strcpy(fichier,chemin);
  17. strcat(fichier,"_subi.dat" );
  18. fp=fopen(fichier,"rb" );
  19. while(ligne!=-1)
  20. {
  21.  fseek(fp,sizeof(*subi)*ligne,SEEK_SET);
  22.  fread(subi,sizeof(*subi),1,fp);
  23.  ligne=subi->pointeur;
  24.  subi++;
  25. }
  26. fclose(fp);
  27. }


 
Le premier printf("%s",chemin); se passe sans problème mais le deuxième, mon programme plante ( erreur windows ) , on dirait que la variable chemin s'est "détruite" lors de l'exécution de Creer_subi
Or je ne l'utilise que dans un strcpy , comme deuxième argument, il ne devrait donc subir aucune modif et encore moins devenir "inutilisable"
Quelqu'un à une idée ?
 
PS : J'utilise Visual C++ 6.0
 
Merci d'avance , parce que sur ce coup-là ,je bloque


Message édité par Slay le 02-05-2005 à 20:23:29
Reply

Marsh Posté le 02-05-2005 à 20:19:52   

Reply

Marsh Posté le 02-05-2005 à 20:25:04    

Elle est déclarée comment ta variable *chemin ?
 
Et l'erreur quand ça plante, c'est quoi ?


Message édité par Elmoricq le 02-05-2005 à 20:27:32
Reply

Marsh Posté le 02-05-2005 à 20:29:13    

Elmoricq a écrit :

Elle est déclarée comment ta variable *chemin ?
 
Et l'erreur quand ça plante, c'est quoi ? (bien que j'aie mon idée là-dessus)


char [25]
 
et j'ai une erreur "normal" de windows, "Windows a rencontrer un problème avec le programme ... "
rien de plus
 
 
( le pire c'est que je fais des strcpy de cette meme variable à plein d'autres endroits, et jamais eu aucun problème ! )

Reply

Marsh Posté le 02-05-2005 à 20:33:47    

C'est quoi ton type SUBI_EXAMENS ?

Reply

Marsh Posté le 02-05-2005 à 20:34:02    

Slay a écrit :

char [25]
 
et j'ai une erreur "normal" de windows, "Windows a rencontrer un problème avec le programme ... "
rien de plus
 
 
( le pire c'est que je fais des strcpy de cette meme variable à plein d'autres endroits, et jamais eu aucun problème ! )


je viens de me rendre compte en fesant le debug que ce sont TOUTES mes variables qui s'éfface juste APRES la fin de la fonction  :ouch:  
 
=>
 
+ chemin 0xcccccccc ""
+ index 0xcccccccc
+ fp 0xcccccc00
+ fichier 0x0012fae0 "ÌÌNÌ"
+ patient {...}
+ subi 0x0012f890
 j -858993460
 i -858993460
 ind_pat -858993460

Reply

Marsh Posté le 02-05-2005 à 20:35:10    

Elmoricq a écrit :

C'est quoi ton type SUBI_EXAMENS ?


Code :
  1. struct _subi_examens{
  2. int indice;
  3. int Nomenclature;
  4. char NumSis[11];
  5. DATE Date;
  6. char Facture;
  7. int pointeur;
  8. };


 
mais comme j'ai dis plus haut, toutes mes variables sont affectées ( je m'en étais pas rendu compte au début )

Reply

Marsh Posté le 02-05-2005 à 20:36:47    

Clair qu'il y a un problème dans ta boucle.
 
Déjà j'aime pas ta condition d'arrêt.
 
Ensuite, tu es sûr de ton "subi++" ?!
 
 
Enfin, ta variable "pointeur" qui peut être égale à -1, elle symbolise quoi ?


Message édité par Elmoricq le 02-05-2005 à 20:38:00
Reply

Marsh Posté le 02-05-2005 à 20:40:54    

#     char fichier[20];
#     FILE *fp;
#     strcpy(fichier,chemin);
#     strcat(fichier,"_subi.dat" );
 
Quel est le nombre maximal de caractères que peut contenir "chemin" sans qu'il n' y ait un comportement indéfini ?


Message édité par ++fab le 02-05-2005 à 20:41:44
Reply

Marsh Posté le 02-05-2005 à 20:42:02    

Elmoricq a écrit :

Clair qu'il y a un problème dans ta boucle.
 
Déjà j'aime pas ta condition d'arrêt.
 
Ensuite, tu es sûr de ton "subi++" ?!
 
 
Enfin, ta variable "pointeur" qui peut être égale à -1, elle symbolise quoi ?


le pointeur c'est l'enregistrement suivant , s'il n'en existe pas ,c'est égale à -1
 
Subi est initialisé dans la fonction précédente et est un vecteur de structure
donc si ligne = -1 ( qui est en réalité que le pointeur vers la structure suivante) cela signifie que l'on est a la fin du chainage

Reply

Marsh Posté le 02-05-2005 à 20:44:14    

++fab a écrit :

#     char fichier[20];
#     FILE *fp;
#     strcpy(fichier,chemin);
#     strcat(fichier,"_subi.dat" );
 
Quel est le nombre maximal de caractères que peut contenir "chemin" sans qu'il n' y ait un comportement indéfini ?


 
 :cry: 20 également , je viens de tester à 25 et ca fonctionne :o
je comprend pas pcq dans mes teste mon " chemin " était formé de 11 caractères , je pensais pas que le problème pouvait venir de là, honte à moi  :cry:  
 
N'empeche c'est bizzare comment ca bouzillait toutes les variables  :ouch:  :ouch:
 
 
Merci bien , comme quoi des fois c'est vraiment un truc débile  :wahoo:


Message édité par Slay le 02-05-2005 à 20:45:43
Reply

Marsh Posté le 02-05-2005 à 20:44:14   

Reply

Marsh Posté le 02-05-2005 à 20:49:42    

prend un chemin de 20 caracteres par exemple, et ça ne fonctionnera plus à nouveau. Pourquoi ? refléchit un peu à ça :
#     strcpy(fichier,chemin);
#     strcat(fichier,"_subi.dat" ); *
demande toi combien de caractères a "fichier" à chaque instruction.


Message édité par ++fab le 02-05-2005 à 20:50:15
Reply

Marsh Posté le 02-05-2005 à 20:52:06    

++fab a écrit :

prend un chemin de 20 caracteres par exemple, et ça ne fonctionnera plus à nouveau. Pourquoi ? refléchit un peu à ça :
#     strcpy(fichier,chemin);
#     strcat(fichier,"_subi.dat" ); *
demande toi combien de caractères a "fichier" à chaque instruction.


oui exact ;)
je viens de penser que le faite que les variables "plantaient" , vu que je dépassais la taille prévue j'allais écrire sur les autres variables dans la mémoire :)
 
 
ps : comme quoi l'assembleur ca permet de comprendre certaines choses [:aloy]  

Reply

Marsh Posté le 02-05-2005 à 20:55:15    

bravo, c'est ce qui provoquait ce comportement indéfini.
Maintenant, à toi de jouer pour trouver la parade :)

Reply

Marsh Posté le 02-05-2005 à 21:03:02    

Slay a écrit :


N'empeche c'est bizzare comment ca bouzillait toutes les variables  :ouch:  :ouch:


 
que voila un magnifique buffer overflow
 

Code :
  1. void Cree_subi(char *chemin,SUBI_EXAMENS *subi,int ligne)
  2. {
  3. char fichier[20];
  4. strcpy(fichier,chemin);
  5. }


 
tu as l'âme d'un cracker ? :d
 
lors de l'appel de la fonction, les parametres, ..., les variables locales sont empilés par adresse decroissantes, ce qui fais qu'un overflow sur le tableau fichier corrompt ta pile en ecrivant vers les parametres.
 
l'article sur wikipedia
http://fr.wikipedia.org/wiki/D%C3% [...] _de_tampon

Reply

Marsh Posté le 02-05-2005 à 21:04:48    

skelter a écrit :

que voila un magnifique buffer overflow
 

Code :
  1. void Cree_subi(char *chemin,SUBI_EXAMENS *subi,int ligne)
  2. {
  3. char fichier[20];
  4. strcpy(fichier,chemin);
  5. }


 
tu as l'âme d'un cracker ? :d
 
lors de l'appel de la fonction, les parametres, ..., les variables locales sont empilés par adresse decroissantes, ce qui fais qu'un overflow sur le tableau fichier corrompt ta pile en ecrivant vers les parametres.
 
l'article sur wikipedia
http://fr.wikipedia.org/wiki/D%C3% [...] _de_tampon


 
le pire c'est que je le savais bien  [:totoz] mais je n'y avais pas pensé  [:jkley]
 
Edit : je savais pas que cela se fesait aussi facilement en C, en ASM en 2 lignes c'est fait mais je croyais que le C protégait un peu plus :)


Message édité par Slay le 02-05-2005 à 21:05:48
Reply

Marsh Posté le 02-05-2005 à 21:06:26    


Je n'ai pas bien compris ce que tu voulais faire, mais déjà je travaillerais un peu plus dans la sécurité :


#include <stdlib.h>
#include <stdio.h>
#include <string.h>
 
typedef struct
{
   int indice;
   int Nomenclature;
   char NumSis[11];
   char Facture;
   int pointeur;
}
SUBI_EXAMENS;
 
void Cree_subi (char const *chemin, SUBI_EXAMENS * subi)
{
#define F "_subi.dat"
   char fichier[20];
 
   if (strlen (chemin) + sizeof F <= sizeof fichier)
   {
      strcpy (fichier, chemin);
      strcat (fichier, F);
 
      printf ("Ouverture de '%s'\n", fichier);
 
      FILE *fp = fopen (fichier, "rb" );
 
      if (fp != NULL)
      {
         do
         {
            fread (subi, sizeof *subi, 1, fp);
         }
         while (subi->pointeur != -1);
 
         fclose (fp);
      }
      else
      {
         perror (fichier);
      }
   }
   else
   {
      fprintf (stderr, "ERR : chemin trop long\n" );
   }
}
 
void AfficherExamens (char *chemin, SUBI_EXAMENS * subi)
{
#define PRT_I(f) \
   printf ("%-10s = %d\n", #f, subi->f)
 
#define PRT_S(f) \
   printf ("%-10s = %s\n", #f, subi->f)
 
   PRT_I (indice);
   PRT_I (Nomenclature);
   PRT_S (NumSis);
   PRT_I (Facture);
   PRT_I (pointeur);
 
}
 
int main (void)
{
   char chemin[25] = "../";
   SUBI_EXAMENS subi_;
   SUBI_EXAMENS *subi = &subi_;
 
   struct patient
   {
      int DernierExam;
   }
   patient =
   {
      1
   };
 
   Cree_subi (chemin, subi);
   printf ("\n\n\tExamens : \n" );
   AfficherExamens (chemin, subi);
 
   return 0;
}


Modifie ce code pour être conforme à ce que tu fais et fourni un moyen de créer le fichier de données...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 02-05-2005 à 21:08:14    

Slay a écrit :


Edit : je savais pas que cela se fesait aussi facilement en C, en ASM en 2 lignes c'est fait mais je croyais que le C protégait un peu plus :)


 
ben la puissance et la flexibilité du C se paye par aucun controles de bord
 
edit: le C c'est juste un asm de haut niveau
edit2: et portable


Message édité par skelter le 02-05-2005 à 21:09:28
Reply

Marsh Posté le 02-05-2005 à 21:11:05    

skelter a écrit :

ben la puissance et la flexibilité du C se paye par aucun controles de bord
 
edit: le C c'est juste un asm de haut niveau
edit2: et portable


enfin bon , en gros j'aurai pu faire planté la machine si mon overflow était beaucoup plus important :p ( sauf si windows, lui, protège les endroits "critiques" de la mémoire )

Reply

Marsh Posté le 02-05-2005 à 21:17:54    

Un processus dispose de son propre espace d'adressage [:adodonicoco]  (pas de tout temps, mais aujourd'hui oui :) )
Donc pour répondre à ta question : non

Reply

Marsh Posté le 02-05-2005 à 21:18:35    

Slay a écrit :

je savais pas que cela se fesait aussi facilement en C, en ASM en 2 lignes c'est fait mais je croyais que le C protégait un peu plus :)


Non. En C, rien ne te protège d'un comportement indéfini. Il peut arriver n'importe quoi.


Message édité par Emmanuel Delahaye le 02-05-2005 à 21:19:43

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 02-05-2005 à 21:26:21    

Emmanuel Delahaye a écrit :

Non. En C, rien ne te protège d'un comportement indéfini. Il peut arriver n'importe quoi.


Si, une vieille barbe de 68ard  [:petrus75]  :D  

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed