PI-ITBA / 2024_01

9 stars 0 forks source link

jokesADT #379

Closed sratto0 closed 1 week ago

sratto0 commented 1 week ago

Buen dia, queria saber si me podian ayudar a ver el problema en mi codigo, me tira error en la funcion categories el sanitize, especificamente cuando hago el strcpy y reservo memoria para cada lugar del vector. Perdon las molestias y muchas gracias

El codigo:

#define BLOCK 10

typedef struct jok{
    char *jokee;
    int len;
}jok;

typedef struct category{
    char *name;
    jok*jokes;
    size_t cant_jokes;
    struct category *tail;
}category;

typedef category*TCat;

typedef struct jokesCDT{
    TCat first;
    size_t cant_cat;
}jokesCDT;

jokesADT newJokes(){
    return calloc(1, sizeof(jokesCDT));
}

static char *copy(const char *c){
    char *ans=NULL;
    int i;
    for( i=0;c[i];i++){
        if(i%BLOCK==0)
            ans=realloc(ans, (i+BLOCK)*sizeof(char));
        ans[i]=c[i];
    }
    if(ans!=NULL)
        ans=realloc(ans, (i+1)*sizeof(char));
    return ans;
}

static TCat addRec(TCat first, const char *cat, int *flag){
    if(first==NULL || strcmp(first->name, cat)>0){
        *flag=1;
        TCat aux=malloc(sizeof(*aux));
        aux->name=malloc(strlen(cat)+1);
        strcpy(aux->name,cat);
        aux->tail=first;
        aux->cant_jokes=0;
        aux->jokes=NULL;
        return aux;
    }
    if(strcmp(first->name, cat)==0){
        return first;
    }
    first->tail=addRec(first->tail, cat, flag);
    return first;
}

void addCategory(jokesADT jokes, const char * category){
    int flag=0;
    jokes->first=addRec(jokes->first, category, &flag);
    jokes->cant_cat+=flag;
}

void addJoke(jokesADT jokes, const char * category, const char * joke){
    int flag=0;
    while(jokes->first!=NULL && !flag){
        if(strcmp(jokes->first->name, category)==0){
            jokes->first->jokes=realloc(jokes->first->jokes,jokes->first->cant_jokes*sizeof(jok) );
            jokes->first->jokes[jokes->first->cant_jokes].len=strlen(joke);
            jokes->first->jokes[jokes->first->cant_jokes].jokee=malloc(jokes->first->jokes[jokes->first->cant_jokes].len*sizeof(char));
            jokes->first->jokes[jokes->first->cant_jokes].jokee=copy(joke);
            jokes->first->cant_jokes++;
            return ;
        }
        if(strcmp(jokes->first->name, category)<0)
            flag=1;
        jokes->first=jokes->first->tail;
    }
}

char * joke(jokesADT jokes, const char * category){
    char *ans=NULL;
    int flag=0;
    while(jokes->first!=NULL && !flag){
        if(strcmp(jokes->first->name, category)==0 && jokes->first->cant_jokes!=0){
            int chiste=randInt(0, jokes->first->cant_jokes-1);
            ans=realloc(ans, jokes->first->jokes[chiste].len*sizeof(char));
            ans=copy(jokes->first->jokes[chiste].jokee);
        }
        if(strcmp(jokes->first->name, category)<0)
            flag=1;
        jokes->first=jokes->first->tail;
    }
    return ans;
}

long unsigned int categoriesCount(const jokesADT jokes){
    return jokes->cant_cat;
}

char ** categories(const jokesADT jokes){
    char **vec=NULL;
    if(categoriesCount(jokes)==0)
        return vec;
    size_t cant=categoriesCount(jokes);
    for(int i=0;i<cant;i++){
        if(i==0)
            vec=realloc(vec, cant*sizeof(char*));
        vec[i]=malloc(strlen(jokes->first[i].name)*sizeof(char));
        strcpy(vec[i],jokes->first[i].name);
        printf("%s\n", vec[i]);
    }
    return vec;
}

void freeJokes(jokesADT jokes){
    while(jokes->first!=NULL){
        for(int i=0;i<jokes->first->cant_jokes;i++){
            free(jokes->first->jokes[i].jokee);
        }
        free(jokes->first->jokes);
        free(jokes->first->tail);
        jokes->first=jokes->first->tail;
    }
    free(jokes->first);
    free(jokes);
}

int main(void) {
    randomize();
    jokesADT jokes = newJokes();

    assert(categories(jokes)==NULL);
    assert(categoriesCount(jokes)==0);
    addCategory(jokes, "tontos");

    addCategory(jokes, "racistas");

    addCategory(jokes, "tontos");   // no la agrega
    assert(categoriesCount(jokes)==2);

    char ** cat = categories(jokes);
    assert(strcmp("racistas", cat[0])==0);
    assert(strcmp("tontos", cat[1])==0);
    free(cat[0]);
    free(cat[1]);
    free(cat);

    addJoke(jokes, "tontos", "Que hacen las hormigas cuando salen del jardin? Van a la escuela primaria");
    addJoke(jokes, "tontos", "Como pasa Superman por la multitud? Con supermiso.");

    // Este no lo agrega porque no esta la categoria
    addJoke(jokes, "politica", "Van dos politicos en un helicoptero....");

    char * silly = joke(jokes, "suegras");
    assert(silly==NULL);

    // Tiene que ser alguno de los dos chistes tontos
    for(int i=0; i < 10; i++) {
        silly = joke(jokes, "tontos");
        assert(strncmp(silly, "Como", 4)==0 || strncmp(silly, "Que ", 4)==0);
        free(silly);
    }

    freeJokes(jokes);
    puts("OK!");
    return 0;
}

El error:


=================================================================
==428859==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000000098 at pc 0x7fee2ecbe4bf bp 0x7ffe17c2c7f0 sp 0x7ffe17c2bf98
WRITE of size 9 at 0x602000000098 thread T0
    #0 0x7fee2ecbe4be in __interceptor_strcpy ../../../../src/libsanitizer/asan/asan_interceptors.cpp:440
    #1 0x563544278500 in categories /home/sofi/PI/R2/jokesADT/ej.c:116
    #2 0x5635442788c1 in main /home/sofi/PI/R2/jokesADT/ej.c:148
    #3 0x7fee2e983d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
    #4 0x7fee2e983e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
    #5 0x5635442773a4 in _start (/home/sofi/PI/R2/jokesADT/ej+0x23a4)

0x602000000098 is located 0 bytes to the right of 8-byte region [0x602000000090,0x602000000098)
allocated by thread T0 here:
    #0 0x7fee2ed1e887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145
    #1 0x563544278461 in categories /home/sofi/PI/R2/jokesADT/ej.c:115
    #2 0x5635442788c1 in main /home/sofi/PI/R2/jokesADT/ej.c:148
    #3 0x7fee2e983d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)

SUMMARY: AddressSanitizer: heap-buffer-overflow ../../../../src/libsanitizer/asan/asan_interceptors.cpp:440 in __interceptor_strcpy
Shadow bytes around the buggy address:
  0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c047fff8000: fa fa 00 00 fa fa 07 fa fa fa 00 01 fa fa 00 00
=>0x0c047fff8010: fa fa 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c047fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==428859==ABORTING
marcelogarberoglio commented 1 week ago

Compará este malloc y strcpy que funciona (que asumom hiciste vos) aux->name=malloc(strlen(cat)+1); strcpy(aux->name,cat);

con este que falla, ¿no notás algo diferente? Además de multiplicar por sizeof(char) que no es necesario vec[i]=malloc(strlen(jokes->first[i].name)*sizeof(char)); strcpy(vec[i],jokes->first[i].name);