Normalement, fsize s'en charge car le fichier n'est pas lu avant l'appel de calculerHash, mais j'essaierai.Citation:
Envoyé par Trap D
Je fais du C, sur Linux 2.6.9
Version imprimable
Normalement, fsize s'en charge car le fichier n'est pas lu avant l'appel de calculerHash, mais j'essaierai.Citation:
Envoyé par Trap D
Je fais du C, sur Linux 2.6.9
C'était effectivement celà que j'évoquais. Il faudrait voir le code en entier, tu dois avoir une erreur avant.Citation:
Envoyé par Strab
Je ne comprends rien à ce qui se passe.
Apparemment, le seg fault ne vient pas d'une lecture de src, mais dans f. En effet, d'après gdb, le seg fault survient à une adresse a, et f = a+1 (alors que src est plus "loin"). C'est louche.
Voulant contourner le problème, je décide de passer par read au lieu de fread. Il y a alors encore un seg fault, mais au moment de l'ouverture cette fois, lorsque je fais :
f est le nom du fichier, issu de la ligne de commande. Que ce soit directement argv[i] ou une copie, le segfault est là...Code:
1
2 int fd = open(f, O_RDONLY);
Le C m'étonnera toujours par ses erreurs incompréhensibles :(
Comme jte dis, c'est un depassement mémoire, et j'ai remarqué que les allocations qui suivent plantent.
Il se peut que le open fasse un malloc qui plante.
Faut voir ce qu'il ya avant
Voici le code se déroulant avant le open problématique :
main.c
valid.cCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 #include <stdio.h> #include <stdlib.h> #include <string.h> #include "valid.h" #include "keygen.h" #include "config.h" #include "crypt.h" /* Donne la valeur d'une option, NULL si elle est absente * str1 est la version courte de l'argument, str2 est la version longue */ char * valArg(char * str1, char * str2, int argc, char ** argv) { int i; char * result; for(i=1; i<argc; i++){ if( !strcmp(str1, argv[i]) || !strcmp(str2, argv[i]) ){ if(i<argc-1){ result = malloc(strlen(argv[i+1]) + 1); strcpy(result, argv[i+1]); return result; } else { fprintf(stderr, "Erreur : la valeur de l'option n'a pas été précisée\n"); return NULL; } } } return NULL; } /* Indique si un argument est présent */ int estPresent(char * str1, char * str2, int argc, char ** argv) { int i; for(i=1; i<argc; i++){ if( !strcmp(str1, argv[i]) || !strcmp(str2, argv[i]) ){ return 1; } } return 0; } int main(int argc, char ** argv) { char * progName = valArg("-f", "--fich", argc, argv); char * privFile = valArg("-p", "--priv", argc, argv); char * pubFile = valArg("-P", "--pub", argc, argv); char * user = valArg("-u", "--user", argc, argv); int added = estPresent("-a", "--ajout", argc, argv); int deleted = estPresent("-s", "--suppr", argc, argv); int crypted = estPresent("-c", "--crypt", argc, argv); if(progName && privFile){ //Validation d'un programme cle * c; FILE * cle = fopen(privFile, "r"); if(!cle){ fprintf(stderr, "Erreur : " "le fichier %s n'a pu être ouvert en lecture.\n", privFile); exit(1); } if(crypted){ int s = fsize(cle); char * msg = malloc(sizeof(char) * (s+1)); fgets(msg, s+1, cle); *c = decrypter(msg, demanderPass()); //free(msg); le free provoque un segfault (?!?) } else { c = file2cle(cle); if(!c){ fprintf(stderr, "Erreur : la clé n'a pu être lue dans %s\n", privFile); exit(1); } } if(valider(progName, *c)){ fprintf(stderr, "Erreur lors de la validation de %s.\n", progName); exit(1); } fclose(cle); exit(0); } ... //Autres options }
Merci à ceux qui auront le courage de lireCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 long size(int fd) { long savepos, size; savepos = lseek(fd, 0, SEEK_CUR); /* sauvegarder la position */ size = lseek(fd, 0, SEEK_END); /* aller en fin */ lseek(fd, savepos, SEEK_SET); /* rétablir la position */ return size; } hash calculerHash(int fd) { hash h = malloc(sizeof(char)*17); if(!h){ return NULL; } //long s = fsize(f); long s = size(fd); char * str = malloc(sizeof(char) * (s+1)); if(!str){ return NULL; } //int lu = fread(str, sizeof(char), s, f); int lu = read(fd, str, s); if(lu != s){ fprintf(stderr, "Erreur lors de la lecture du programme.\n"); return NULL; } str[s] = '\0'; hasher(str, h); free(str); return h; } /** * Calcule la signature d'un fichier et la concatène à la fin du fichier. * @param f - fichier à signer * @param p - clé privée */ int valider(char * f, cle p) { hash h; signature s; FILE * stream; int fd = open(f, O_RDONLY); if(fd==-1){ fprintf(stderr, "Erreur : impossible d'ouvrir %s en lecture.\n", f); return -1; } h = calculerHash(fd); ... //la suite }
Il faut arréter de programmer au hasard.Citation:
Envoyé par jamalmoundir
"engage your brain"...
C'est pas ca qu'on appelle la programmation genetique ? :lol:Citation:
Envoyé par Emmanuel Delahaye
Code incomplet impossible à compiler. Poste le code réduit au minimum qui montre le défaut.Citation:
Envoyé par Strab
Je commence à avoir une lueur d'espoir (c'est pas mal au bout de 10h...).
On dirait que le programme arrête de faire des seg faults à des moments arbitraires lorsque je retire l'appel à cette fonction :
Une idée ?Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 char * demanderPass() { char * pass1 = malloc(sizeof(char) * 32); char pass2[32]; printf("Veuillez entrez votre mot de passe (8-31 caractères).\n"); do{ printf("Password : "); fgets(pass1, 32, stdin); while(strlen(pass1) < 9){ printf("Entre 8 et 31 carcactères svp...\n"); printf("Password : "); fgets(pass1, 32, stdin); } printf("Confirm : "); fgets(pass2, 32, stdin); }while(strcmp(pass1, pass2)); pass1[9] = '\0'; //Je n'ai besoin que des 8 premiers pour l'instant return pass1; }
Surement une coïncidence :mrgreen:Citation:
Envoyé par Strab
Si le free plantait c'est peut être que le défaut est dans decrypter()Citation:
Code:
1
2
3 fgets(msg, s+1, cle); *c = decrypter(msg, demanderPass()); //free(msg); le free provoque un segfault (?!?)
Je ne trouve toujours pas l'erreur, et je suis de moins en moins sûr que celà de vienne de demanderPass() ou decrypter(). Voici en pièce jointe un code compilable (sous linux), qui seg fault à l'instruction de retour et qui se termine sans problème si je retire l'appel à demanderPass() (sur ma machine de test tout du moins).
Pour compiler :
Pour exécuter :Code:gcc (-g) -o valider main.c -lcrypt
où hello est un hello world compilé, et priv.txt un fichier contenant le cryptage DES de la chaine "341&29&0" avec la clé "azertyui" (c'est donc le mot de passe à rentrer lorsqu'il est demander). Je mets aussi le fichier en pièce jointe, car il contient peut-être des caractères non imprimables.Code:./valider -c -f hello -p priv.txt
Je remercie d'avance les bonnes volontés.
Pièce jointe 1195
Pièce jointe 1196
J'ai compilé, il manquait
Bon, chuis en train d'installer gdb :mrgreen:Code:#include <unistd.h>
Moi ça plante là, si je met pas le mot de passe que tu as donné
Sinon, si je mets le bon mot de passe ça plante iciCode:86 *(np++) = *(str++);
Code:205 return res;
J'ai trouvé 8-)
c'était plus évident que je pensais (mais j'ai pas trouvé desuite cela dit)
Ca plantait sur le return du decrypter() par ce qu'il essayait d'ecrire dans *c, alors que c pointe dans l'espace intersidéral.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 int main(int argc, char ** argv) { char * progName = valArg("-f", "--fich", argc, argv); char * privFile = valArg("-p", "--priv", argc, argv); int crypted = estPresent("-c", "--crypt", argc, argv); if(progName && privFile){ //Validation d'un programme cle * c; FILE * cle = fopen(privFile, "r"); if(!cle){ fprintf(stderr, "Erreur : " "le fichier %s n'a pu être ouvert en lecture.\n", privFile); exit(1); } if(crypted){ int s = fsize(cle); char * msg = malloc(sizeof(char) * (s+1)); fgets(msg, s+1, cle); *c = decrypter(msg, demanderPass()); free(msg); } if(valider(progName, *c)){ fprintf(stderr, "Erreur lors de la validation de %s.\n", progName); exit(1); } fclose(cle); exit(0); } else { //Options incohérentes fprintf(stderr, "Erreur, les arguments sont incohérents\n"); fprintf(stderr, USAGE, argv[0], argv[0], argv[0]); } return 0; }
AAAAAAAARRRGGHHHHHHHH:sm::mur:
une journée entière pour une erreur aussi stupide !
Merci beaucoup Gruik, grâce à toi ce 24h-debug s'est transformé en relais-debug :mouarf:.
C'est décidé, je hais le C. J'ai beau avoir acquis pas mal de réflexes, je retombe toujours sur des erreurs incompréhensibles à cause de ces pointeurs à la noix. Oh j'arrête de me plaindre et je retourne coder, ou dormir plutôt, c'est que je passe le toeic demain :roll:.
Encore merci gruik, et tous ceux qui m'ont donné un peu de leur temps.
Strab
Si tu n'aimes pas les pointeurs, ne fait pas de C.Citation:
Envoyé par Strab
Il y a quand même des regles de bon sens, comme donner tout de suite une valeur cohérente à un pointeur :
mais jamaisCode:
1
2
3 T *p = NULL; T *p = malloc(...) T *p = f(...)
tout seul comme ça. C'est la porte ouvert à la catastrophe... Mais bon quand on fait du C, on jongle avec ça. Sinon, on fait autre chose...Code:T *p;
Pas de quoi 'hair le C'. C'est pas un instrument de débutant. On est d'accord. C'est un outil tranchant...
Hola, je ne voulais pas blesser les adeptes du C, je plaisantais.
Si je haissais le C, je ne me serais pas lancé dans ce projet où la plus grande partie consiste en des modifications du noyau...
Les règles de bon sens que tu donnes ne s'appliquent pas lorsque c'est le pointeur ou son contenu qui sont initialisés suivant les cas (cela ne se voit pas ici car j'ai retiré beaucoup de code pour le poster), surtout lorsqu'on ces différents cas ont été implentés à des intervalles de temps assez espacés.
Et oui, C est un outil puissant mais tranchant, mais les langages qui font presque autant de chose à un niveau beaucoup plus haut (cf ma signature ;) )sont tellement pratiques qu'on en perd certaines habitudes... :roll: