From d8bc76e48bc56735485e542a4bb5d1d04817d741 Mon Sep 17 00:00:00 2001 From: Will_Zhu MacBook Pro <will_zyq@qq.com> Date: Mon, 30 Sep 2019 22:44:13 +1000 Subject: [PATCH] wait for testing --- src/vuln-1/passbook.c | 543 ++++++++++++++++++------------------------ 1 file changed, 226 insertions(+), 317 deletions(-) diff --git a/src/vuln-1/passbook.c b/src/vuln-1/passbook.c index 98007a9..8d72064 100644 --- a/src/vuln-1/passbook.c +++ b/src/vuln-1/passbook.c @@ -38,212 +38,149 @@ typedef struct { typedef struct node { char * url; cred_t cred; - // struct node *left; - // struct node *right; + struct node *left; + struct node *right; } node_t; -#define MAP_NODE_NUM 50 - -static const node_t * lookup(const node_t *map, const char *url){ - // while (p != NULL){ - // int ret = strcmp(url,p->url); - // if (ret == 0){ - // return p; - // }else if (ret < 0){ - // p = p->left; - // }else{ - // p = p->right; - // } - // } - // return p; // not found - if (map == NULL) { - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); - } - for (int i = 0; i < MAP_NODE_NUM; i++) { - if ((map + i)->url == NULL) { - continue; - } - if (strcmp((map + i)->url,url) == 0) { - return (map + i); +static const node_t * lookup(const node_t *p, const char *url){ + while (p != NULL){ + int ret = strcmp(url,p->url); + if (ret == 0){ + return p; + }else if (ret < 0){ + p = p->left; + }else{ + p = p->right; } } - return NULL; + return p; // not found } - - static void node_print(const node_t *p){ printf("URL: %s, Username: %s, Password: %s\n",p->url,p->cred.username,p->cred.password); } -// /* construct a new node */ -// static node_t *node_new(const char *url, const cred_t cred){ -// node_t *new = malloc(sizeof(node_t)); -// assert(new != NULL && "new: malloc failed"); -// new->url = strdup(url); -// assert(new->url != NULL && "new: strdup url failed"); -// new->cred.username = strdup(cred.username); -// assert(new->cred.username != NULL && "new: strdup username failed"); -// new->cred.password = strdup(cred.password); -// assert(new->cred.password != NULL && "new: strdup password failed"); -// // new->left = NULL; -// // new->right = NULL; -// return new; -// } - -// /* updates a node's credential in place: -// replaces p's credential with that from q and frees q */ -// static void node_edit_cred(node_t * p, node_t *q){ -// free(p->cred.username); -// free(p->cred.password); - -// p->cred.username = q->cred.username; -// p->cred.password = q->cred.password; -// free(q->url); -// free(q); -// } - -// static void node_free(node_t *p){ -// free(p->url); -// free(p->cred.username); -// free(p->cred.password); -// free(p); -// } +/* construct a new node */ +static node_t *node_new(const char *url, const cred_t cred){ + node_t *new = malloc(sizeof(node_t)); + assert(new != NULL && "new: malloc failed"); + new->url = strdup(url); + assert(new->url != NULL && "new: strdup url failed"); + new->cred.username = strdup(cred.username); + assert(new->cred.username != NULL && "new: strdup username failed"); + new->cred.password = strdup(cred.password); + assert(new->cred.password != NULL && "new: strdup password failed"); + new->left = NULL; + new->right = NULL; + return new; +} + +/* updates a node's credential in place: + replaces p's credential with that from q and frees q */ +static void node_edit_cred(node_t * p, node_t *q){ + free(p->cred.username); + free(p->cred.password); + + p->cred.username = q->cred.username; + p->cred.password = q->cred.password; + free(q->url); + free(q); +} + +static void node_free(node_t *p){ + free(p->url); + free(p->cred.username); + free(p->cred.password); + free(p); +} /* insert q into p we assume that if q has children then it cannot already be present in p. Otherwise, if q has no children and we find its url in p, then we edit the found entry in place while preserving its children */ -// static node_t * node_insert(node_t *map, node_t *q){ - // if (p == NULL){ - // return q; - // } - // if (q == NULL){ - // return p; - // } - // /* we store a pointer to a node pointer that remembers where in the - // tree the new node needs to be added */ - // node_t ** new = NULL; - // node_t * const start = p; - // while (new == NULL) { - // int ret = strcmp(q->url,p->url); - // if (ret == 0){ - // assert (q->left == NULL && q->right == NULL && "illegal insertion"); - // /* edit the node in place */ - // node_edit_cred(p,q); - // /* q is now freed so cannot be used anymore */ - // return start; - // }else if (ret < 0){ - // if (p->left == NULL){ - // new = &(p->left); - // }else{ - // p = p->left; - // } - // }else{ - // if (p->right == NULL){ - // new = &(p->right); - // }else{ - // p = p->right; - // } - // } - // } - // *new = q; - // return start; -// } - -/* returns a pointer to the tree with the node added or with the existing - node updated if it was already present */ -static node_t * put(node_t *map, const char *url, const cred_t cred){ - if (map == NULL) { - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); +static node_t * node_insert(node_t *p, node_t *q){ + if (p == NULL){ + return q; } - for (int i = 0; i < MAP_NODE_NUM; i++) { - if ((map + i)->url != NULL && strcmp((map + i)->url, url) == 0) { - free((map + i)->cred.password); - free((map + i)->cred.username); - (map + i)->cred.password = strdup(cred.password); - (map + i)->cred.username = strdup(cred.username); - return map; - } + if (q == NULL){ + return p; } - int i = 0; - while (1) { - if ((map + i)->url == NULL) - { - (map + i)->cred.password = strdup(cred.password); - (map + i)->cred.username = strdup(cred.username); - (map + i)->url = strdup(url); - return map; + /* we store a pointer to a node pointer that remembers where in the + tree the new node needs to be added */ + node_t ** new = NULL; + node_t * const start = p; + while (new == NULL) { + int ret = strcmp(q->url,p->url); + if (ret == 0){ + assert (q->left == NULL && q->right == NULL && "illegal insertion"); + /* edit the node in place */ + node_edit_cred(p,q); + /* q is now freed so cannot be used anymore */ + return start; + }else if (ret < 0){ + if (p->left == NULL){ + new = &(p->left); + }else{ + p = p->left; + } + }else{ + if (p->right == NULL){ + new = &(p->right); + }else{ + p = p->right; + } } - i++; } - return map; + *new = q; + return start; +} + +/* returns a pointer to the tree with the node added or with the existing + node updated if it was already present */ +static node_t * put(node_t *p, const char *url, const cred_t cred){ + return node_insert(p,node_new(url,cred)); } /* destroy tree rooted at p */ -static void destroy(node_t *map){ - if(map == NULL) { - return; +static void destroy(node_t *p){ + while (p != NULL){ + node_t * left = p->left; + node_t * const right = p->right; + left = node_insert(left,right); + node_free(p); + p = left; } - for(int i = 0; i < MAP_NODE_NUM; i++) { - if ((map + i)->url != NULL) { - free((map + i)->url); - free((map + i)->cred.password); - free((map + i)->cred.username); - } - } - free(map); - map = NULL; } /* returns a pointer to the tree with the node removed (if it was present) */ -static node_t * rem(node_t *map, const char *url){ - // node_t * const start = p; - // /* remember where the pointer to p was stored */ - // node_t ** pptr = NULL; - // while (p != NULL){ - // int ret = strcmp(url,p->url); - // if (ret == 0){ - // node_t * left = p->left; - // node_t * const right = p->right; - // left = node_insert(left,right); - // node_free(p); - // if (pptr != NULL){ - // *pptr = left; - // return start; - // }else{ - // /* p was the only node in the tree */ - // assert(p == start); - // return left; - // } - // }else if (ret < 0){ - // pptr = &(p->left); - // p = p->left; - // }else{ - // pptr = &(p->right); - // p = p->right; - // } - // } - // return start; // not found - if (map == NULL) { - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); - } - for (int i = 0; i < MAP_NODE_NUM; i++) { - if ((map + i)->url == NULL) { - continue; - } - if (strcmp((map + i)->url, url) == 0) { - free((map + i)->url); - (map + i)->url = NULL; - free((map + i)->cred.password); - free((map + i)->cred.username); - break; +static node_t * rem(node_t *p, const char *url){ + node_t * const start = p; + /* remember where the pointer to p was stored */ + node_t ** pptr = NULL; + while (p != NULL){ + int ret = strcmp(url,p->url); + if (ret == 0){ + node_t * left = p->left; + node_t * const right = p->right; + left = node_insert(left,right); + node_free(p); + if (pptr != NULL){ + *pptr = left; + return start; + }else{ + /* p was the only node in the tree */ + assert(p == start); + return left; + } + }else if (ret < 0){ + pptr = &(p->left); + p = p->left; + }else{ + pptr = &(p->right); + p = p->right; } } - return map; + return start; // not found } const char WHITESPACE[] = " \t\r\n"; @@ -294,112 +231,103 @@ node_t * map = NULL; tree traversal algorithms without using recursion (to avoid stack overflow for very large trees). Stack overflow is a trivial form of memory-safety vulnerability. */ -// typedef struct nodeptr_list_elem { -// const node_t *p; -// struct nodeptr_list_elem *next; -// struct nodeptr_list_elem *prev; -// } nodeptr_list_elem_t; - -// typedef struct nodeptr_list { -// nodeptr_list_elem_t *head; -// nodeptr_list_elem_t *last; -// } nodeptr_list_t; - - -// /* push an element p onto the front of a nodeptr list lst */ -// nodeptr_list_t list_push(nodeptr_list_t lst, const node_t *p){ -// nodeptr_list_elem_t *n = malloc(sizeof(nodeptr_list_elem_t)); -// assert(n != NULL && "push: malloc failed"); -// n->p = p; -// n->next = lst.head; -// n->prev = NULL; -// if (lst.head != NULL){ -// assert(lst.last != NULL); -// lst.head->prev = n; -// }else{ -// assert(lst.last == NULL); -// lst.last = n; -// } -// lst.head = n; +typedef struct nodeptr_list_elem { + const node_t *p; + struct nodeptr_list_elem *next; + struct nodeptr_list_elem *prev; +} nodeptr_list_elem_t; + +typedef struct nodeptr_list { + nodeptr_list_elem_t *head; + nodeptr_list_elem_t *last; +} nodeptr_list_t; + + +/* push an element p onto the front of a nodeptr list lst */ +nodeptr_list_t list_push(nodeptr_list_t lst, const node_t *p){ + nodeptr_list_elem_t *n = malloc(sizeof(nodeptr_list_elem_t)); + assert(n != NULL && "push: malloc failed"); + n->p = p; + n->next = lst.head; + n->prev = NULL; + if (lst.head != NULL){ + assert(lst.last != NULL); + lst.head->prev = n; + }else{ + assert(lst.last == NULL); + lst.last = n; + } + lst.head = n; -// return lst; -// } - -// /* when out is non-NULL we place a pointer to the first node into it. -// assumption: lst.head and lst.last are non-NULL */ -// nodeptr_list_t list_pop(nodeptr_list_t lst, const node_t **out){ -// assert(lst.head != NULL && lst.last != NULL); -// if (out != NULL){ -// *out = lst.head->p; -// } -// if (lst.last == lst.head){ -// free(lst.head); -// lst.head = NULL; -// lst.last = NULL; -// }else{ -// nodeptr_list_elem_t *ret = lst.head->next; -// free(lst.head); -// lst.head = ret; -// } -// return lst; -// } - -// /* when out is non-NULL we place a pointer to the last node into it. -// assumption: lst.head and lst.last are non-NULL */ -// nodeptr_list_t list_dequeue(nodeptr_list_t lst, const node_t **out){ -// assert(lst.head != NULL && lst.last != NULL); -// if (out != NULL){ -// *out = lst.last->p; -// } - -// if (lst.last == lst.head){ -// free(lst.head); -// lst.head = NULL; -// lst.last = NULL; -// }else{ -// nodeptr_list_elem_t *ret = lst.last->prev; -// free(lst.last); -// lst.last = ret; -// } -// return lst; -// } + return lst; +} + +/* when out is non-NULL we place a pointer to the first node into it. + assumption: lst.head and lst.last are non-NULL */ +nodeptr_list_t list_pop(nodeptr_list_t lst, const node_t **out){ + assert(lst.head != NULL && lst.last != NULL); + if (out != NULL){ + *out = lst.head->p; + } + if (lst.last == lst.head){ + free(lst.head); + lst.head = NULL; + lst.last = NULL; + }else{ + nodeptr_list_elem_t *ret = lst.head->next; + free(lst.head); + lst.head = ret; + } + return lst; +} + +/* when out is non-NULL we place a pointer to the last node into it. + assumption: lst.head and lst.last are non-NULL */ +nodeptr_list_t list_dequeue(nodeptr_list_t lst, const node_t **out){ + assert(lst.head != NULL && lst.last != NULL); + if (out != NULL){ + *out = lst.last->p; + } + + if (lst.last == lst.head){ + free(lst.head); + lst.head = NULL; + lst.last = NULL; + }else{ + nodeptr_list_elem_t *ret = lst.last->prev; + free(lst.last); + lst.last = ret; + } + return lst; +} /* in order traversal to print out nodes in sorted order. Is used to implement listing of all entries in the passbook */ -void print_inorder( ){ - // nodeptr_list_t lst = {.head = NULL, .last = NULL}; - // if (p != NULL){ - // lst = list_push(lst,p); - - // while(lst.head != NULL){ - // // keep recursing left until we can go no further - // while (p->left != NULL){ - // lst = list_push(lst,p->left); - // p = p->left; - // } +void print_inorder(const node_t *p){ + nodeptr_list_t lst = {.head = NULL, .last = NULL}; + if (p != NULL){ + lst = list_push(lst,p); + + while(lst.head != NULL){ + // keep recursing left until we can go no further + while (p->left != NULL){ + lst = list_push(lst,p->left); + p = p->left; + } - // // pop from the stack to simulate the return - // const node_t *q; - // lst = list_pop(lst,&q); - - // // print the node following the return - // node_print(q); - - // // simulate right recursive call - // if (q->right != NULL){ - // lst = list_push(lst,q->right); - // p = q->right; - // } - // } - // } - if (map == NULL) { - return; - } - for (int i = 0; i < MAP_NODE_NUM; i++) { - if((map + i)->url == NULL) { - continue; + // pop from the stack to simulate the return + const node_t *q; + lst = list_pop(lst,&q); + + // print the node following the return + node_print(q); + + // simulate right recursive call + if (q->right != NULL){ + lst = list_push(lst,q->right); + p = q->right; + } } - node_print((map + i)); } } @@ -432,7 +360,7 @@ void masterpw_save(const char *pw, FILE *f){ that the resulting tree has the same structure as the original one. This is how we save the passbook to a file. Returns 0 on success; nonzero on failure */ -int save_levelorder(const node_t *map, const char *masterpw, +int save_levelorder(const node_t *p, const char *masterpw, const char * filename){ #ifdef PASSBOOK_FUZZ // ignore the file name when fuzzing etc. to avoid DoS on the server @@ -445,30 +373,20 @@ int save_levelorder(const node_t *map, const char *masterpw, return -1; } masterpw_save(masterpw,f); - // nodeptr_list_t lst = {.head = NULL, .last = NULL}; - // if (p != NULL){ - // lst = list_push(lst,p); - - // while(lst.last != NULL){ - // lst = list_dequeue(lst,&p); - // node_save(p,f); - // if (p->left != NULL){ - // lst = list_push(lst,p->left); - // } - // if (p->right != NULL){ - // lst = list_push(lst,p->right); - // } - // } - // } - if (map == NULL) { - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); - } - for(int i = 0; i < MAP_NODE_NUM; i++) { - if ((map + i)->url == NULL) { - continue; + nodeptr_list_t lst = {.head = NULL, .last = NULL}; + if (p != NULL){ + lst = list_push(lst,p); + + while(lst.last != NULL){ + lst = list_dequeue(lst,&p); + node_save(p,f); + if (p->left != NULL){ + lst = list_push(lst,p->left); + } + if (p->right != NULL){ + lst = list_push(lst,p->right); + } } - node_save((map + i), f); } fclose(f); return 0; @@ -497,9 +415,7 @@ static int execute(void){ printf("Not found.\n"); } destroy(map); - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); - + map = NULL; } else if (strcmp(toks[0],INSTRUCTION_REM) == 0){ if (numToks != 2){ debug_printf("Expected 1 argument to %s instruction but instead found %u\n",INSTRUCTION_REM,numToks-1); @@ -507,9 +423,7 @@ static int execute(void){ } debug_printf("Removing: %s\n",toks[1]); map = rem(map,toks[1]); - destroy(map); - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); + } else if (strcmp(toks[0],INSTRUCTION_PUT) == 0){ if (numToks != 4){ debug_printf("Expected 3 arguments to %s instruction but instead found %u\n",INSTRUCTION_PUT,numToks-1); @@ -530,9 +444,7 @@ static int execute(void){ debug_printf("Error saving to file %s\n",toks[2]); return -1; } - destroy(map); - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); + } else if (strcmp(toks[0],INSTRUCTION_MASTERPW) == 0){ if (numToks != 2){ debug_printf("Expected 1 argument to %s instruction but instead found %u\n",INSTRUCTION_MASTERPW,numToks-1); return -1; @@ -547,15 +459,14 @@ static int execute(void){ #else return -1; #endif + } else if (strcmp(toks[0],INSTRUCTION_LIST) == 0){ if (numToks != 1){ debug_printf("Expected 0 arguments to %s instruction but instead found %u\n",INSTRUCTION_LIST,numToks-1); return -1; } - print_inorder(); - destroy(map); - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); + print_inorder(map); + }else{ debug_printf("Unrecognised instruction %s\n",toks[0]); return -1; @@ -665,8 +576,6 @@ int main(const int argc, const char * argv[]){ exit(1); } } - map = (node_t *)calloc(MAP_NODE_NUM, sizeof(node_t)); - assert(map != NULL); int ans = run(f); if (ans < 0){ fprintf(stderr,"Error\n"); -- GitLab