IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Buffer overflow incomprise


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut Buffer overflow incomprise
    Bonjour,
    alors il semble bien que le code suivant crée un buffer overflow. Cependant, je ne m'en sors pas pour trouver l'origine de ce problème.
    Le programme est censé à terme reproduire la structure d'un répertoire. Pour l'instant, c'est encore en test donc il n'y a que des printf.

    Voici le code (tronqué pour plus de clarté) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <dirent.h>
    #include <sys/stat.h>
     
     
    struct FileList
    {
        int nb;
        char ** list;
    };
     
    void
    process(char *sourcedir, char *outdir)
    {
        struct FileList dlst = {0, NULL};
        listdir(sourcedir, &dlst);	
        char *tmpsrc = NULL;
        char *tmpout = NULL;
     
        for (int i=0; i<dlst.nb; i++)
        {
            tmpsrc = malloc(sizeof(sourcedir) + sizeof(char) + sizeof(dlst.list[i]));
            sprintf(tmpsrc, "%s/%s", sourcedir, dlst.list[i]);
            tmpout = malloc(sizeof(outdir) + sizeof(char) + sizeof(dlst.list[i]));
            sprintf(tmpout, "%s/%s", outdir, dlst.list[i]);
     
            if (isfile(tmpsrc))
            {
                if (isdir(tmpsrc))
                {
                    printf("* %s -> %s\n",tmpsrc, tmpout);
                    if (! isdir(tmpout))
                    {
                        printf("... Creating %s\n", tmpout);
                        mkdir(tmpout, 0777);
                    }
                    process(tmpsrc, tmpout);
                }
                else
                    printf("* %s -> %s\n",tmpsrc, tmpout);
            }
            free(tmpsrc);
            free(tmpout);
        }
     
        freefilelist(dlst);
    }
     
    void
    freefilelist(struct FileList f)
    {
        for (int i=0; i<f.nb; i++)
            free(f.list[i]);
        free(f.list);
    }
     
    int
    countdir(const char *path)
    // return number of files in path
    {
     
        int num = 0;
        struct dirent *ent = NULL;
        DIR *d = opendir(path);
        if (d == NULL)
            perror("Open dir");
     
        while ((ent = readdir(d)) != NULL)
            num++;
        closedir(d);
        return num;
    }
     
    void 
    listdir(const char *path, struct FileList *filelist)
    {
        struct dirent *ent = NULL;
        int i = 0;
     
        DIR *d = opendir(path);
        if (d == NULL)
            perror("Open dir");
     
        // Allocate number of files
        filelist->list = malloc(sizeof(char*) * countdir(path));
     
        // Put file names in dirlist
        rewinddir(d);
        while ((ent = readdir(d)) != NULL)
        {
            //skip . and ..
            if ( (strcmp(ent->d_name, ".") == 0) ||
               (strcmp(ent->d_name, "..") == 0) )
                continue;
            // Allocate enough place for filename
            filelist->list[i] = malloc( sizeof(char) * (strlen(ent->d_name)+1));
                                        //+ sizeof(path) + sizeof(char));
            strcpy(filelist->list[i], ent->d_name);
            i++;
        }
        closedir(d);
     
        filelist->nb = i;
    }
    Et voici le message d'erreur à l'exécution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
     
    * test/index.md -> test.static/index.md
    * test/dir2 -> test.static/dir2
    * test/dir2/index.md -> test.static/dir2/index.md
    * test/dir2/test.md -> test.static/dir2/test.md
    *** glibc detected *** ./cw: free(): invalid pointer: 0x0000000000aa3120 ***
    ======= Backtrace: =========
    /lib/x86_64-linux-gnu/libc.so.6[0x309b076d76]
    /lib/x86_64-linux-gnu/libc.so.6(cfree+0x6c)[0x309b07baac]
    ./cw[0x400c23]
    ./cw[0x400bfb]
    ./cw[0x4010bc]
    /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xfd)[0x309b01eead]
    ./cw[0x400969]
    ======= Memory map: ========
    00400000-00402000 r-xp 00000000 fe:00 22944625                           /home/xavier/hg/cw/cw
    00601000-00602000 rw-p 00001000 fe:00 22944625                           /home/xavier/hg/cw/cw
    00aa3000-00ac4000 rw-p 00000000 00:00 0                                  [heap]
    3099a00000-3099a20000 r-xp 00000000 08:01 5268                           /lib/x86_64-linux-gnu/ld-2.13.so
    3099c1f000-3099c20000 r--p 0001f000 08:01 5268                           /lib/x86_64-linux-gnu/ld-2.13.so
    3099c20000-3099c21000 rw-p 00020000 08:01 5268                           /lib/x86_64-linux-gnu/ld-2.13.so
    3099c21000-3099c22000 rw-p 00000000 00:00 0 
    309b000000-309b180000 r-xp 00000000 08:01 5269                           /lib/x86_64-linux-gnu/libc-2.13.so
    309b180000-309b380000 ---p 00180000 08:01 5269                           /lib/x86_64-linux-gnu/libc-2.13.so
    309b380000-309b384000 r--p 00180000 08:01 5269                           /lib/x86_64-linux-gnu/libc-2.13.so
    309b384000-309b385000 rw-p 00184000 08:01 5269                           /lib/x86_64-linux-gnu/libc-2.13.so
    309b385000-309b38a000 rw-p 00000000 00:00 0 
    30a1000000-30a1015000 r-xp 00000000 08:01 5246                           /lib/x86_64-linux-gnu/libgcc_s.so.1
    30a1015000-30a1215000 ---p 00015000 08:01 5246                           /lib/x86_64-linux-gnu/libgcc_s.so.1
    30a1215000-30a1216000 rw-p 00015000 08:01 5246                           /lib/x86_64-linux-gnu/libgcc_s.so.1
    7fa664000000-7fa664021000 rw-p 00000000 00:00 0 
    7fa664021000-7fa668000000 ---p 00000000 00:00 0 
    7fa66ad7d000-7fa66ad80000 rw-p 00000000 00:00 0 
    7fa66ad9b000-7fa66ad9e000 rw-p 00000000 00:00 0 
    7fff4d2bb000-7fff4d2dc000 rw-p 00000000 00:00 0                          [stack]
    7fff4d3f2000-7fff4d3f3000 r-xp 00000000 00:00 0                          [vdso]
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
    zsh: abort      ./cw test
    Merci d'avance pour votre aide.

  2. #2
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 871
    Par défaut
    Il y a une ENORME incomprehension pour les malloc et surtout les sizeof :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char *s;
    s = malloc(sizeof(*s) * 18);
    snprintf(s, 17, "lalalalaal");
     
    printf("sizeof : %d\nvraie taille : %d\n", sizeof(s), strlen(s));
    Quand t'auras compris ca je pense que ca devrait aller beaucoup mieux.

    Autre chose :

    Ca c'est tres moyen, surtout si list vaut NULL. Fais plutot ceci :


  3. #3
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    Effectivement, et de taille.
    Voici ce que j'avais compris : sizeof donne la taille prise en mémoire, tandis que strlen indique le nombre de "char" dans une chaîne de caractère. C'est pourquoi pour avoir la taille réellement prise en mémoire, je pensais qu'il fallait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sizeof(char) * (strlen(chaine) + 1)
    Qu'en est-il réellement?

    Merci en tout cas, le code fonctionne désormais!

  4. #4
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    871
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 871
    Par défaut
    Voici l'explication du sizeof donnee par wikipedia. Voici la mienne maintenant :

    Ton incomprehension venait sans doute de ton manque de connaissance des pointeurs (ce ne sont que des suppositions). Bref, quand tu envoies un pointeur dans le sizeof, il te renverra la taille du pointeur (soit 4 octets sur 32 bits et 8 sur 64 bits). Ainsi, ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    char *c = malloc(10);
     
    printf("%d\n", sizeof(c));
    Affichera non pas la taille de la chaine de caracteres mais la taille du pointeur. Et ce sera vrai pour tous les types de variable que tu enverras dans sizeof. Autre petite chose que je pointe du doigt. Quand tu alloues de la memoire, refere-toi a cette facon de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void *c;
    int taille_ptr = 10;
     
    c = malloc(taille_ptr); // pas bien !
    c = malloc(sizeof(*c) * taille_ptr); //la c'est bon
    Si c'est un char, rajoute toujours une case de plus a la fin pour pouvoir mettre le '\0'. Je t'explique maintenant rapidement pourquoi on ne doit pas allouer la memoire de la premiere facon. Si c est un int et que tu veux creer un tableau de 3 cases, en realite tu n'auras meme pas une case (un int fait 4 octets donc si tu en alloues seulement 3....). Avec la deuxieme methode, tu auras un tableau de 12 cases, donc la c'est bon.

    Si tu as d'autres questions n'hesite pas a les poser.

  5. #5
    Membre averti
    Inscrit en
    Janvier 2011
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Janvier 2011
    Messages : 20
    Par défaut
    ton manque de connaissance des pointeurs
    Certainement, ce que tu vois là sont mes premiers mallocs

    Merci pour ces explications complémentaires, elles sont les bienvenues!
    J'avoue ne pas encore intégrer le tout de façon spontanée, mais j'espère que ça va venir.

    Apparement, sizeof(char) vaut toujours 1 d'après le lien wikipedia.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c = malloc(sizeof(*c) * taille_ptr); //la c'est bon
    C'est noté, j'essaierais d'utiliser cette méthode à l'avenir.

    Encore merci.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Se protéger contre les buffers overflows
    Par pharaonline dans le forum C
    Réponses: 2
    Dernier message: 11/06/2006, 22h25
  2. Buffer overflow ?
    Par Albator5151 dans le forum Général Java
    Réponses: 6
    Dernier message: 08/02/2006, 01h23
  3. [oracle 9i] ORU-10027: buffer overflow
    Par jejam dans le forum Oracle
    Réponses: 7
    Dernier message: 01/09/2005, 13h05
  4. Erreur ORU-10027 : buffer overflow
    Par valerie90 dans le forum Oracle
    Réponses: 3
    Dernier message: 14/02/2005, 08h40
  5. [Erreur] buffer overflow
    Par cmoulin dans le forum Administration
    Réponses: 8
    Dernier message: 04/08/2004, 14h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo