#include "libcgc.h" #include "cgc_libc.h" #include "cgc_operation.h" list_t *cgc_haiku_list = NULL; uint32_t next_haiku_id = INIT_HAIKU_ID; uint32_t cgc_recv_uint32() { uint32_t num[1] = { 0 }; RECV(num, sizeof(uint32_t)); return num[0]; } uint32_t cgc_recv_uint16() { uint16_t num[1] = { 0 }; RECV(num, sizeof(uint16_t)); return num[0]; } uint8_t cgc_haiku_list_exists() { if (NULL == cgc_haiku_list) { return FALSE; } else { return TRUE; } } uint8_t cgc_is_haiku_list_empty() { if (0 == cgc_haiku_list->count) { return TRUE; } else { return FALSE; } } void cgc_init_haiku_list() { uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (FALSE == tlv1) { cgc_haiku_list = cgc_list_create(); } } int cgc_get_count() { uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { return cgc_haiku_list->count; } else { return ERR_LIST_NOT_EXIST; } } uint32_t cgc_get_id_from_haiku(node_t * haiku) { if (NULL != haiku->data) { struct haiku* h; h = ( struct haiku * ) haiku -> data; return h->id; } else { return ERR_EMPTY_NODE; } } uint32_t cgc_get_next_haiku_id() { next_haiku_id++; return next_haiku_id - 1; } int cgc_get_random_idx(uint32_t * idx) { uint32_t random_idx; random_idx = 0; int ret; ret = 0; { char* tlv2; tlv2 = ( char * ) & random_idx; cgc_size_t tlv1; tlv1 = 4; ret = cgc_rand(tlv2,tlv1); } int32_t count; count = cgc_get_count ( ); if (ERR_LIST_NOT_EXIST == count) { return count; } else { if (0 == count) { return ERR_LIST_EMPTY; } else { if (0 != ret) { return ERR_RAND_FAILED; } else { *idx = random_idx % (uint32_t) count; return SUCCESS; } } } } int cgc_populate_array_with_haiku_ids(uint32_t id_arr[], uint32_t count) { node_t* haiku_ptr; haiku_ptr = NULL; struct haiku* h; h = NULL; uint32_t id; id = 0; uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { haiku_ptr = cgc_haiku_list->tail; } else { return ERR_LIST_NOT_EXIST; } if ((0 == count) || (NULL == haiku_ptr)) { return ERR_LIST_EMPTY; } while ((0 < count) && (NULL != haiku_ptr)) { h = (struct haiku *) haiku_ptr->data; id_arr[count - 1] = h->id; count--; haiku_ptr = haiku_ptr->prev; } return SUCCESS; } int cgc_find_haiku_with_id(struct haiku **h, uint32_t id) { node_t* haiku_ptr; haiku_ptr = NULL; struct haiku* tmp; tmp = NULL; int count; count = 0; bool_t found; found = FALSE; count = cgc_get_count(); if (0 < count) { haiku_ptr = cgc_haiku_list->head; } else { if (0 == count) { return ERR_LIST_EMPTY; } else { return ERR_LIST_NOT_EXIST; } } while (NULL != haiku_ptr) { tmp = (struct haiku *) haiku_ptr->data; if (id == tmp->id) { *h = tmp; found = TRUE; break; } haiku_ptr = haiku_ptr->next; } if (TRUE == found) { return SUCCESS; } else { return ERR_INVALID_ID; } } void cgc_send_haiku(struct haiku *h) { uint32_t id; id = h -> id; char* content; content = h -> content; uint16_t length; length = h -> length; { const char* tlv2 = ( char * ) & id; cgc_size_t tlv1; tlv1 = sizeof ( uint32_t ); cgc_send(tlv2,tlv1); } { const char* tlv4 = ( char * ) & length; cgc_size_t tlv3; tlv3 = sizeof ( uint16_t ); cgc_send(tlv4,tlv3); } { const char* tlv6 = content; cgc_size_t tlv5; tlv5 = length; cgc_send(tlv6,tlv5); } } void cgc_send_easter_egg_haiku() { uint32_t id; id = EGG_ID; char* content; content = EGG_HAIKU; uint16_t length; { const char* tlv7 = content; length = cgc_strlen(tlv7); } { const char* tlv2 = ( char * ) & id; cgc_size_t tlv1; tlv1 = sizeof ( uint32_t ); cgc_send(tlv2,tlv1); } { const char* tlv4 = ( char * ) & length; cgc_size_t tlv3; tlv3 = sizeof ( uint16_t ); cgc_send(tlv4,tlv3); } { const char* tlv6 = content; cgc_size_t tlv5; tlv5 = length; cgc_send(tlv6,tlv5); } } void cgc_send_haiku_id(uint32_t id) { SENDUI(id); } int cgc_add_haiku_to_list(struct haiku *h) { node_t* nd; { void* tlv1; tlv1 = ( void * ) h; nd = cgc_node_create(tlv1); } return cgc_list_push(cgc_haiku_list, nd); } int cgc_recv_haiku_line(char *haiku_content_ptr, int16_t bytes_remaining) { char temp_line_buf[MAX_HAIKU_LINE_LEN] = { 0 }; int16_t bytes_received; bytes_received = 0; int16_t bytes_written; bytes_written = 0; // bytes_received includes line termination char, // but line term char is not written to temp_line_buf, a null is in its place. { int tlv3; tlv3 = STDIN; char* tlv2; tlv2 = temp_line_buf; cgc_size_t tlv1; tlv1 = MAX_HAIKU_LINE_LEN; bytes_received = cgc_recvline(tlv3,tlv2,tlv1); } // this will make the creation of POV input harder to create // since it will need line termination chars at set intervals. if (0 > bytes_received) { return ERR_INVALID_HAIKU; } // VULN HERE // - if bytes_remaining goes neg, MAX_HAIKU_LINE_LEN chars can be written // to haiku_content_ptr for each line of input. // +1 for trailing null bytes_written = cgc_snprintf(haiku_content_ptr, bytes_remaining + 1, "~c\x07", temp_line_buf); return bytes_written; } struct haiku *cgc_recv_haiku(uint16_t total_bytes) { struct haiku* h; h = NULL; char* haiku_content_ptr; haiku_content_ptr = NULL; int16_t bytes_remaining; bytes_remaining = 0; int16_t bytes_written; bytes_written = 0; bytes_remaining = (int16_t) total_bytes; ALLOC(sizeof(struct haiku) + total_bytes + 1, &h); ; // +1 for trailing null haiku_content_ptr = h->content; // VULN HERE - if something causes bytes_remaining to go negative, this loop will not stop. while (0 != bytes_remaining) { { char* tlv2; tlv2 = haiku_content_ptr; int16_t tlv1; tlv1 = bytes_remaining; bytes_written = cgc_recv_haiku_line(tlv2,tlv1); } if (0 > bytes_written) { // ERR_INVALID_HAIKU return NULL; } haiku_content_ptr += bytes_written; bytes_remaining -= bytes_written; } h->id = cgc_get_next_haiku_id(); h->length = total_bytes; return h; } uint16_t cgc_recv_haiku_size() { return cgc_recv_uint16(); } // Operation functions int cgc_add_haiku() { int ret; ret = SUCCESS; uint16_t total_bytes; total_bytes = 0; ; // number of bytes in haiku, including line termination chars. struct haiku* h; h = NULL; uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (FALSE == tlv1) { cgc_init_haiku_list(); } total_bytes = cgc_recv_haiku_size(); if ((0 < total_bytes) && (MAX_HAIKU_LEN > total_bytes)) { { uint16_t tlv2; tlv2 = total_bytes; h = cgc_recv_haiku(tlv2); } if (NULL == h) { ret = ERR_INVALID_HAIKU; } else { { struct haiku* tlv4; tlv4 = h; ret = cgc_add_haiku_to_list(tlv4); } { uint32_t tlv3; tlv3 = h -> id; cgc_send_haiku_id(tlv3); } } } else { ret = ERR_INVALID_HAIKU_LEN; } return ret; } int cgc_get_haiku_by_id() { struct haiku* h; h = NULL; uint32_t id; id = 0; int res; res = 0; uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { id = cgc_recv_uint32(); if (EGG_ID == id) { cgc_send_easter_egg_haiku(); } else { { struct haiku** tlv3; tlv3 = & h; uint32_t tlv2; tlv2 = id; res = cgc_find_haiku_with_id(tlv3,tlv2); } if (SUCCESS == res) { cgc_send_haiku(h); } } } else { res = ERR_LIST_NOT_EXIST; } return res; } int cgc_get_haiku_cgc_random() { uint32_t random_idx; random_idx = 0; uint32_t count; count = 0; uint32_t* id_arr; id_arr = NULL; struct haiku* rand_haiku; rand_haiku = NULL; int res; res = SUCCESS; uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { count = cgc_get_count(); if (0 == count) { return ERR_LIST_EMPTY; } ALLOC(count * sizeof(uint32_t), &id_arr); // these functions should not return error due to haiku_list existance or count <= 0. { uint32_t** tlv3; tlv3 = id_arr; uint32_t tlv2; tlv2 = count; res = cgc_populate_array_with_haiku_ids(tlv3,tlv2); } { uint32_t* tlv4; tlv4 = & random_idx; res = cgc_get_random_idx(tlv4); } if (ERR_RAND_FAILED != res) { { struct haiku** tlv6; tlv6 = & rand_haiku; uint32_t tlv5; tlv5 = id_arr [ random_idx ]; res = cgc_find_haiku_with_id(tlv6,tlv5); } } DEALLOC(id_arr, count * sizeof(uint32_t)); if (SUCCESS == res) { cgc_send_haiku(rand_haiku); } } else { res = ERR_LIST_NOT_EXIST; } return res; } int cgc_get_haiku_count() { uint32_t count; count = 0; uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { count = cgc_get_count(); SENDUI(count); return SUCCESS; } else { return ERR_LIST_NOT_EXIST; } } int cgc_get_haiku_ids() { uint8_t tlv1; tlv1 = cgc_haiku_list_exists ( ); if (TRUE == tlv1) { uint32_t count; count = ( uint32_t ) cgc_get_count ( ); SENDUI(count); node_t* hl_ptr; hl_ptr = cgc_haiku_list -> head; while (NULL != hl_ptr) { uint32_t id; { node_t* tlv2; tlv2 = hl_ptr; id = cgc_get_id_from_haiku(tlv2); } SENDUI(id); hl_ptr = hl_ptr->next; } } else { return ERR_LIST_NOT_EXIST; } return SUCCESS; }