From e95eb2d275f0a27c3e087926881bf3d915520b35 Mon Sep 17 00:00:00 2001 From: Mysaa Date: Mon, 15 Nov 2021 20:07:47 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20la=20fiche=20MEMCHECK=C2=A0et=20co?= =?UTF-8?q?rrection=20(pour=20l'exercice=205)=20de=20la=20fiche=20C12.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- C12.1.c | 27 +++++++++--- MEMCHECK.3.c | 42 +++++++++++++++++++ MEMCHECK.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 MEMCHECK.3.c create mode 100644 MEMCHECK.md diff --git a/C12.1.c b/C12.1.c index fa906d3..4e93dc7 100644 --- a/C12.1.c +++ b/C12.1.c @@ -40,30 +40,45 @@ int scanfs(char* dest, int length){ return 0; } +void nextLine(){ + int c; + while ((c = getchar()) != '\n' && c != EOF) { }; +} + void demander(personne* p){ int age; - char* initiales = malloc(IntLength*sizeof(char)); + char* initiales = calloc(IntLength,sizeof(char)); if(initiales==NULL)return; - char* num = malloc(NumLength*sizeof(char)); + char* num = calloc(NumLength,sizeof(char)); if(num==NULL){free(initiales);return;} printf("Création d'une nouvelle personne : \n"); do{ printf("Initiales : "); } while(scanfs(initiales,IntLength)); + printf("Âge : "); - scanf("%d", &age); - getchar(); + if(scanf("%d", &age)!=1){ + printf("Ce n'est pas un nombre, je met 42 dans le doute\n"); + nextLine(); + age = 42; + } else + getchar(); + do { printf("Numéro de téléphone : "); } while(scanfs(num, NumLength)); - p->initiales = initiales; p->age = age; p->num = num; } +void freePerso(personne* perso){ + free(perso->initiales); + free(perso->num); +} + int lesmeme(personne* p1, personne* p2){ return (p1->age==p2->age) && (strcmp(p1->initiales, p2->initiales)==0) && (strcmp(p1->num, p2->num)==0); @@ -89,6 +104,8 @@ int main(){ } } + for(int i=0;i +#include +#include + +int main () +{ + int continuer = 1; + + // message secret protégé par mot de passe + char *texte = (char*) malloc((1000+1) * sizeof(char)); + memset(texte, 'a', 1000); + texte[1000] = '\0'; + + char mdp[100]; + while (continuer) { + + + printf("Récupération du message\nEntrez le mot de passe : "); + scanf("%99s", mdp); + + if (strcmp(mdp, "1234")) { + printf("Mot de passe invalide\nRéessayer (0/1) ? "); + scanf("%d", &continuer); + if (!continuer){ + memset(texte, '\0', 1000); + free(texte); + return EXIT_FAILURE; + } + } else { + printf("Mot de passe correct, le message secret est : %s\n", texte); + printf("Continuer (0/1) ? "); + scanf("%d", &continuer); + if (!continuer) + break; + } + } + + // on efface le message secret de la mémoire + memset(texte, '\0', 1000); + free(texte); + return EXIT_SUCCESS; +} diff --git a/MEMCHECK.md b/MEMCHECK.md new file mode 100644 index 0000000..1953787 --- /dev/null +++ b/MEMCHECK.md @@ -0,0 +1,113 @@ +# MEMCHECK + +### Exercice 1 +1. + +Valgrind est disponible sur les plateformes suivantes : + +- x86/Linux: up to and including SSSE3, but not higher -- no SSE4, AVX, AVX2. This target is in maintenance mode now.. +- AMD64/Linux: up to and including AVX2. This is the primary development target and tends to be well supported. +- PPC32/Linux, PPC64/Linux, PPC64LE/Linux: up to and including Power8. +- S390X/Linux: supported. +- ARM/Linux: supported since ARMv7. +- ARM64/Linux: supported for ARMv8. +- MIPS32/Linux, MIPS64/Linux: supported. +- X86/Solaris, AMD64/Solaris, X86/illumos, AMD64/illumos: supported since Solaris 11. +- X86/Darwin (10.10, 10.11), AMD64/Darwin (10.10, 10.11): supported. +- ARM/Android, ARM64/Android, MIPS32/Android, X86/Android: supported. + + *(ce n'est pas du tout un copier-coller ...)* + +2. + +Voici les erreurs que memcheck peut détecter : + +- Les accès mémoire interdits (dépassement, accès après libération, dépassement de la pile) +- Quelles variables ont des valeurs indéfinies (car pas initialisées ou déduites de variables non initialisées). +- Libération incorrecte du tas (par exemple double-libération ou `malloc` ne correspondant pas aux `free` +- Quand la source et le but interferent en utilisant `memcopy` +- Allocation d'une quantité de mémoire potentiellement incorrecte (négative par exemple) +- Fuites de mémoire + +3. + +Valgrind ralentit l'execution et augmente l'utilisation mémoire de manière drastique. + +Aussi, ce n'est pas un outil magique et passe derrière certaines erreurs. + + +### Exercice 2 + + +Liste des erreurs: + + + Invalid write of size 1 + at 0x1091C2: main (MEMCHECK.2.c:12) + Address 0x4a30428 is 0 bytes after a block of size 1,000 alloc'd + at 0x483877F: malloc (vg_replace_malloc.c:307) + by 0x10919D: main (MEMCHECK.2.c:10) + +Cette erreur trahit une tentative de modifier une case mémoire hors du bloc qui a été alloué à la variable. + +--- + + Invalid read of size 1 + at 0x4838CD4: __strlen_sse2 (vg_replace_strmem.c:462) + by 0x48D79EE: vfprintf (vfprintf.c:1638) + by 0x48DE605: printf (printf.c:33) + by 0x1091F8: main (MEMCHECK.2.c:17) + Address 0x4a4a428 is 0 bytes after a block of size 1,000 alloc'd + at 0x483577F: malloc (vg_replace_malloc.c:299) + by 0x10919D: main (MEMCHECK.2.c:10) + +Cette erreur se déclenche car le programme essaie de lire une valeur hors du bloc alloué à la variable. Ici, ça vient du problème de la variable `texte` qui n'a pas de caractère de fin `'\0'`et `printf` ne sait donc pas quand s'arrêter. + +--- + + Conditional jump or move depends on uninitialised value(s) + at 0x483CB98: strcmp (vg_replace_strmem.c:847) + by 0x1091DC: main (MEMCHECK.2.c:16) + +Le strcmp s'applique une première fois à la variable `mdp` qui n'est au départ pas initialisée. + +--- + + + Invalid free() / delete / delete[] / realloc() + at 0x48369AB: free (vg_replace_malloc.c:530) + by 0x1092C7: main (MEMCHECK.2.c:36) + Address 0x4a4a040 is 0 bytes inside a block of size 1,000 free'd + at 0x48369AB: free (vg_replace_malloc.c:530) + by 0x109234: main (MEMCHECK.2.c:21) + Block was alloc'd at + at 0x483577F: malloc (vg_replace_malloc.c:299) + by 0x10919D: main (MEMCHECK.2.c:10) + +La variable `texte` est libérée deux fois, d'où cette erreur. + +--- + + 1,000 bytes in 1 blocks are definitely lost in loss record 1 of 1 + at 0x483577F: malloc (vg_replace_malloc.c:299) + by 0x10919D: main (MEMCHECK.2.c:10) + +Si on ne réessaie pas avec un mot de passe directement invalide, la mémoire allouée à `texte` par `malloc` n'est jamais libérée. + + +### Exercice 4 + +Ce programme affiche `foo bar\n`. Simplement. + +La troisième ligne du main est intriguante. Elle essaie de modifier le 7e caractère de la chaine foo. On peut imaginer que les chaines de caractère `"foo"` et `"bar"` sont stoquées côte à côte dans la mémoire de cette manière: `foo\0bar\0`. La modification modifierai donc la mémoire en `foo\0barz` plus le reste de la mémoire (comme le caractère z par exemple). +Le problème est que cette mémoire est allouée en statique au démarage du programme. Donc elle ne peut pas être modifiée. Et pourtant, Valgrind ne détecte aucune erreur. Je pense que c'est dû au fait que le noyau C ne renvoie pas d'erreur lorsque cette mémoire en lecture seule demande à être modifiée. Cela n'a aucun effet, mais pas non plus d'erreur. + + + ### Exercice 5 + + J'ai corrigé le premier exo. J'avais seulement deux erreurs: Une due à une mauvaise gestion du `scanf` et l'autre due à un simple oubli de libérer les variables. + + Pour le second exercice, une petite erreur sur le `scanf`, mais je pense que l'erreur n'est pas importante. En effet, Valgrind râle parce que scanf utilise une variable non initialisée (ce qui est normal, puisque c'est cette fonction qui lui donne ça premiere valeur). Remplacer `malloc` par `calloc` corrige ce problème, mais est un peu inutile. + + +