PI-ITBA / 2024_01

8 stars 0 forks source link

airportADT #324

Closed sratto0 closed 3 months ago

sratto0 commented 3 months ago

Buenas tardes, el codigo para airportADT no me pasa el assert, me da error en el sanitizer en la funcion addRunway en la linea que realloca memoria para el runway, y en la que se fija si esta ocupado ese runway o no. El error: ==355910==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x610000000030 at pc 0x555debee2db7 bp 0x7fffbef495a0 sp 0x7fffbef49590 READ of size 1 at 0x610000000030 thread T0

0 0x555debee2db6 in addRunway /home/sofi/PI/P2/2023_1C/airportADT.c:92

#1 0x555debee3452 in main /home/sofi/PI/P2/2023_1C/main.c:13
#2 0x7efd656f1d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)
#3 0x7efd656f1e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f)
#4 0x555debee2304 in _start (/home/sofi/PI/P2/2023_1C/ej1+0x2304)

0x610000000030 is located 16 bytes to the left of 192-byte region [0x610000000040,0x610000000100) allocated by thread T0 here:

0 0x7efd65a8c887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145

#1 0x555debee2c2a in addRunway /home/sofi/PI/P2/2023_1C/airportADT.c:84
#2 0x555debee340c in main /home/sofi/PI/P2/2023_1C/main.c:12
#3 0x7efd656f1d8f  (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)

SUMMARY: AddressSanitizer: heap-buffer-overflow /home/sofi/PI/P2/2023_1C/airportADT.c:92 in addRunway

El codigo:


#define BLOCK 10

typedef struct node{
    char *matricula;
    struct node *tail;
}TNode;

typedef TNode *TList;

typedef struct runway{
    TList first;
    TList last;
    char occuppied;
    size_t cant;
}TRunway;

typedef struct airportCDT{
    TRunway *runway;
    size_t size; //espacio reservado
    size_t dim;
}airportCDT;

airportADT newAirport(void){
    return calloc(1, sizeof(airportCDT));
}

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

char * takeOff(airportADT airportAdt, long unsigned int runwayId){
    if(airportAdt->runway[runwayId-1].occuppied==0 || airportAdt->runway[runwayId-1].cant==0){
        return NULL;
    }
    char *ans=malloc(sizeof(char));
    strcpy(ans, airportAdt->runway[runwayId-1].first->matricula);
    TList aux=airportAdt->runway[runwayId-1].first->tail;
    free(airportAdt->runway[runwayId-1].first);
    airportAdt->runway[runwayId-1].first=aux;
    if(airportAdt->runway[runwayId-1].first->tail==NULL){
        airportAdt->runway[runwayId-1].last=NULL;
    }
    airportAdt->runway[runwayId-1].cant--;
    return ans;
}

char ** pendingFlights(airportADT airportAdt, long unsigned int runwayId){
    if(airportAdt->runway[runwayId-1].occuppied==0)
        return NULL;
    char **ans=malloc(sizeof(char *));
    int i;
    TList current=airportAdt->runway[runwayId].first;
    for(i=airportAdt->runway[runwayId-1].cant-1;i>0 && current!=NULL;i++){
        if(i%BLOCK==0){
            ans=realloc(ans, (i+BLOCK)*sizeof(char*));
        }
        strcpy(ans[i], airportAdt->runway[runwayId-1].first->matricula);
        current=current->tail;
    }
    ans=realloc(ans, (i+1)*sizeof(char *));
    ans[i]=NULL;
    return ans;
}

int addRunway(airportADT a, long unsigned int runwayId){
    if(a->size<=runwayId){
        a->runway=realloc(a->runway,(1+runwayId)*sizeof(TRunway));

        for(int i=a->size;i<runwayId;i++){
            a->runway[i].occuppied=0;
            a->runway[i].first=NULL;
        }
        a->size=1+runwayId;
    }
    if(a->runway[runwayId-1].occuppied)
        return -1;

    a->runway[runwayId-1].first=NULL;
    a->dim++;
    return a->dim;
}

int addPlaneToRunway(airportADT a, long unsigned int runwayId, const char * registration){
    if(a->runway[runwayId-1].occuppied==0)
        return -1;
    TList aux=malloc(sizeof(TNode));
    aux->matricula=copy(registration);
    aux->tail=NULL;
    if(a->runway[runwayId-1].cant==0){
        a->runway[runwayId-1].first=aux;
        a->runway[runwayId-1].cant++;
        return 1;
    }
    a->runway[runwayId-1].last->matricula=aux->matricula;
    free(a->runway[runwayId-1].last);
    a->runway[runwayId-1].last=aux;
    a->runway[runwayId-1].cant++;
    return 1;
}

static void freeRec(TList l){
    free(l->tail);
    free(l);
}

void freeAirport(airportADT airportAdt){
    for(int i=0;i<airportAdt->dim;i++){
        freeRec(airportAdt->runway[i].first);
    }
    free(airportAdt->runway);
    free(airportAdt);
}
marcelogarberoglio commented 3 months ago

En principio no veo error en el reallod, salvo que le hayas pasado un número negativo o demasiado grande. ¿Podés subir el programa de prueba y el .h?

sratto0 commented 3 months ago

El .h

typedef struct airportCDT * airportADT;
/* Crea un sistema de administración de pistas y despegues de aviones
** de un aeropuerto.
** El sistema inicia sin pistas.
*/
airportADT newAirport(void);
/* Agrega una pista de despegue con el identificador runwayId.
** La pista inicia sin aviones.
** Retorna la cantidad actual de pistas en el sistema o -1 si falla.
** Falla si existe una pista con el identificador runwayId.
*/
int addRunway(airportADT airportAdt, long unsigned int runwayId);
/* Agrega al final de la pista de despegue con el identificador
** runwayId al avión de matrícula registration
** y retorna la cantidad actual de aviones en la pista o -1 si falla.
** Falla si la pista no existe.
*/
int addPlaneToRunway(airportADT airportAdt, long unsigned int runwayId, const char * registration);
/* Elimina al avión que se encuentra al principio de la pista de
** despegue con el identificador runwayId
** y retorna la matrícula del avión eliminado o NULL si falla.
** Falla si la pista no existe.
** Falla si no hay aviones en la pista.
*/
char * takeOff(airportADT airportAdt, long unsigned int runwayId);
/* Retorna un arreglo con las matrículas de los aviones que se
** encuentran en la pista de despegue con el identificador
** runwayId en orden inverso al orden de despegue (el último elemento
** del arreglo debe coincidir con el valor de retorno de una
** invocación a la función takeOff sobre esa pista).
** El arreglo debe ** contar con una cadena vacía "" como marca de fin.
** Si la pista no existe retorna NULL.
*/
char ** pendingFlights(airportADT airportAdt, long unsigned int runwayId);
/* Libera los recursos utilizados por el sistema de administración de
** pistas y despegues de aviones de un aeropuerto.
*/
void freeAirport(airportADT airportAdt);

El codigo de prueba:


int
main(void) {
// Crea un sistema sin pistas
airportADT airportAdt = newAirport();
// Agrega la pista con el id 5
assert(addRunway(airportAdt, 5) == 1);
assert(addRunway(airportAdt, 0) == 2);
// Falla porque ya existe una pista con el id 5
assert(addRunway(airportAdt, 5) == -1);
// Falla porque no es válida la pista cero
assert(addRunway(airportAdt, 0) == -1);
// Agrega al final de la pista de id 5 al avión de matrícula AR01 y será
// el primero en despegar
char aux[20] = "AR01";
assert(addPlaneToRunway(airportAdt, 5, aux) == 1);
// Agrega al final de la pista de id 5 al avión de matrícula AC91 y será
// el segundo en despegar
strcpy(aux, "AC91");
assert(addPlaneToRunway(airportAdt, 5, aux) == 2);
strcpy(aux, "AC92");
assert(addPlaneToRunway(airportAdt, 5, aux) == 3);
// Obtiene los aviones por despegar de la pista de id 5 en orden inverso al
// orden de despegue
char ** aux1 = pendingFlights(airportAdt, 5);
assert(!strcmp(aux1[0], "AC92"));
assert(!strcmp(aux1[1], "AC91"));
assert(!strcmp(aux1[2], "AR01"));
assert(!strcmp(aux1[3], ""));
free(aux1);
// Despega el primer avión de la pista de id 5
assert(!strcmp(takeOff(airportAdt, 5), "AR01"));
assert(!strcmp(takeOff(airportAdt, 5), "AC91"));
assert(!strcmp(takeOff(airportAdt, 5), "AC92"));
// Ya no quedan aviones por despegar en la pista de id 5
assert(takeOff(airportAdt, 5) == NULL);
// No existe la pista 3
assert(takeOff(airportAdt, 3) == NULL);
// No se puede agregar un avión a una pista que no existe
assert(addPlaneToRunway(airportAdt, 3, "FL91") == -1);
// No se puede agregar un avión a una pista que no existe
assert(pendingFlights(airportAdt, 3) == NULL);
freeAirport(airportAdt);
puts("Despegue exitoso!");
return 0;
}
marcelogarberoglio commented 3 months ago

No está coherente addRunway con el ejemplo, por ejemplo aceptando la pista 0, y tampoco está marcando la pista como ocupada o inicializando en NULL el puntero para que pueda hacer luego el reallod, tendría que ser

int addRunway(airportADT a, long unsigned int runwayId){
    if(a->size<=runwayId){
        a->runway=realloc(a->runway,(1+runwayId)*sizeof(TRunway));

        for(int i=a->size;i<=runwayId;i++){
            a->runway[i].occuppied=0;
            a->runway[i].first=NULL;
        }
        a->size=1+runwayId;
    }
    if(a->runway[runwayId].occuppied)
        return -1;

    a->runway[runwayId].occuppied=1;
    a->dim++;
    return a->dim;
}

corregido esta hay errores en la que agrega aviones, fijate de corregirlos, por ejemplo hay que ajustar lo del índice, que no hay que restar -1

marcelogarberoglio commented 3 months ago

Revisando la consigna, en la misma dice que empiezan en 1, así que o bien les hacés caso al test y aceptás 0, o le hacés caso a la consigna y entonces quedaría así

int addRunway(airportADT a, long unsigned int runwayId){
   if ( runwayId==0)
      return -1;
    if(a->size<runwayId){
        a->runway=realloc(a->runway,(runwayId)*sizeof(TRunway));

        for(int i=a->size; i<runwayId;i++){
            a->runway[i].occuppied=0;
            a->runway[i].first=NULL;
        }
        a->size=runwayId;
    }
    if(a->runway[runwayId-1].occuppied)
        return -1;

    a->runway[runwayId-1].occuppied=1;
    a->dim++;
    return a->dim;
}