diff options
| author | Mosder <xmosder12@gmail.com> | 2026-07-23 17:35:04 +0200 |
|---|---|---|
| committer | Mosder <xmosder12@gmail.com> | 2026-07-23 17:35:04 +0200 |
| commit | 8317c3b33b9b1c70e5ae4c87c7efe33d9b9ce09a (patch) | |
| tree | 8a6b5e20196a253c75b44762de223f1ea2b4a067 | |
| parent | 33fcaa8140784ab32cfc8c14a6fc7fdb71435265 (diff) | |
feat: added helper functions for dealing with memory management and refactored the codebase to use them
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | analyzer/parser/fight_results/fight_results.c | 109 | ||||
| -rw-r--r-- | analyzer/parser/fight_results/fight_results.h | 6 | ||||
| -rw-r--r-- | analyzer/parser/parser.c | 16 | ||||
| -rw-r--r-- | analyzer/parser/structs.c | 4 | ||||
| -rw-r--r-- | analyzer/structures/hashmap.c | 12 | ||||
| -rw-r--r-- | analyzer/structures/heap.c | 10 | ||||
| -rw-r--r-- | analyzer/utils/memory.c | 62 | ||||
| -rw-r--r-- | analyzer/utils/memory.h | 42 | ||||
| -rw-r--r-- | analyzer/utils/tcp.c | 46 |
10 files changed, 195 insertions, 113 deletions
@@ -36,6 +36,7 @@ utils: $(CC) $(CFLAGS) -c analyzer/utils/tcp.c $(CC) $(CFLAGS) -c analyzer/utils/tcp_seq_math.c $(CC) $(CFLAGS) -c analyzer/utils/roman.c + $(CC) $(CFLAGS) -c analyzer/utils/memory.c parser: $(CC) $(CFLAGS) -c analyzer/parser/parser.c diff --git a/analyzer/parser/fight_results/fight_results.c b/analyzer/parser/fight_results/fight_results.c index e7c7123..efc4b36 100644 --- a/analyzer/parser/fight_results/fight_results.c +++ b/analyzer/parser/fight_results/fight_results.c @@ -30,6 +30,8 @@ void cleanup_fight_results(void *data) { for (size_t i = 0; i < fight_results->num_enemy; i++) { free(fight_results->enemy_results[i].name); } + free(fight_results->friendly_results); + free(fight_results->enemy_results); } byte_t *find_fight_results(TCPStream *stream, int offset, int *length) { @@ -41,12 +43,6 @@ byte_t *find_fight_results(TCPStream *stream, int offset, int *length) { return start; } -Item *expand_items(Item *items, size_t *items_capacity, size_t to_fit) { - while (*items_capacity < to_fit) - *items_capacity <<= 1; - return realloc(items, *items_capacity * sizeof(Item)); -} - void get_stars(char *buffer, int incr_above_b1) { char star_types[] = {'B', 'S', 'G'}; sprintf(buffer, " (%c%d)", star_types[incr_above_b1 / 3], incr_above_b1 % 3 + 1); @@ -67,10 +63,11 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) if (gears_separator) gears_str = gears_separator + strlen(SEPARATOR_GEAR); - Item item; - + // get gear info for rank, name and stars / syng level GearInfo gear_info = {0}; fill_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields), gear.info, strlen(gear.info), SEPARATOR_GEAR_INFO_FIELD); + + // create the buffer of information about gear char buffer[SINGLE_ITEM_BUFFER_LEN]; char roman[5]; to_roman(roman, gear_info.rank); @@ -91,9 +88,9 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) break; } } - item.data = strdup(buffer); - cleanup_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields)); + // add gear with specific type + Item item = {.data = strdup(buffer)}; switch (gear.type) { case TYPE_SYNG_NORMAL: // atoi should be fine, since syng_tier starts from 1 for syngs @@ -109,26 +106,22 @@ void add_gear(FriendlyResults *results, size_t *items_capacity, char *gears_str) item.type = EPIC; break; } + results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); - // expand if needed - if (results->num_items >= *items_capacity) - results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = item; + cleanup_struct(&gear_info, gear_info_fields, ARR_LEN(gear_info_fields)); // add orb to items if it exists if (strlen(gear.orb)) { - Item item; - char buffer[SINGLE_ITEM_BUFFER_LEN]; Orb orb = {0}; fill_struct(&orb, orb_fields, ARR_LEN(orb_fields), gear.orb, strlen(gear.orb), SEPARATOR_ORB_FIELD); + + char buffer[SINGLE_ITEM_BUFFER_LEN]; sprintf(buffer, "%sorb %s", get_artifact_size_from_id(orb.size), get_orb_name_from_id(orb.id)); - item.data = strdup(buffer); + + Item item = {.data = strdup(buffer), .type = ORB}; + results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); + cleanup_struct(&orb, orb_fields, ARR_LEN(orb_fields)); - item.type = ORB; - // expand if needed - if (results->num_items >= *items_capacity) - results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = item; } cleanup_struct(&gear, gear_fields, ARR_LEN(gear_fields)); @@ -150,16 +143,10 @@ void add_drifs(FriendlyResults *results, size_t *items_capacity, char *drifs_str if (drifs_separator) drifs_str = drifs_separator + strlen(SEPARATOR_DRIF); - Item item; - item.data = strdup(drif.name); - item.type = DRIF; + Item item = {.data = strdup(drif.name), .type = DRIF}; + results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); cleanup_struct(&drif, drif_fields, ARR_LEN(drif_fields)); - - // expand if needed - if (results->num_items >= *items_capacity) - results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = item; } while (drifs_separator); } @@ -180,37 +167,31 @@ void add_items(FriendlyResults *results, size_t *items_capacity, char *items_str if (items_separator) items_str = items_separator + strlen(SEPARATOR_ITEMS); - Item item; - item.data = strdup(buffer); - item.type = NORMAL; - - // expand if needed - if (results->num_items >= *items_capacity) - results->items = expand_items(results->items, items_capacity, results->num_items + 1); - results->items[results->num_items++] = item; + Item item = {.data = strdup(buffer), .type = NORMAL}; + results->items = array_append(results->items, sizeof(Item), &results->num_items, items_capacity, &item); } while (items_separator); } // parse EntityResults to FriendlyResults FriendlyResults parse_to_friendly(EntityResults entity_results) { - FriendlyResults results; - - results.name = strdup(entity_results.name); - results.exp = entity_results.exp; - results.gold = entity_results.gold; - results.level = entity_results.level; - results.psycho = entity_results.psycho; - results.splinters = entity_results.splinters; + FriendlyResults results = { + .name = strdup(entity_results.name), + .exp = entity_results.exp, + .gold = entity_results.gold, + .level = entity_results.level, + .psycho = entity_results.psycho, + .splinters = entity_results.splinters, + .num_items = 0, + .saturation = 0 + }; // create items array and add to it gear, drifs and items - results.num_items = 0; - results.items = malloc(INIT_ITEMS_CAPACITY * sizeof(Item)); + results.items = safe_malloc(INIT_ITEMS_CAPACITY * sizeof(Item)); size_t items_cap = INIT_ITEMS_CAPACITY; add_gear(&results, &items_cap, entity_results.gear); add_drifs(&results, &items_cap, entity_results.drifs); add_items(&results, &items_cap, entity_results.items); - results.saturation = 0; if (strlen(entity_results.saturation) > 0) { int saturation_id; sscanf(entity_results.saturation, "%d,%d", &saturation_id, &results.saturation); @@ -222,25 +203,26 @@ FriendlyResults parse_to_friendly(EntityResults entity_results) { // parse EntityResults to EnemyResults EnemyResults parse_to_enemy(EntityResults entity_results) { - EnemyResults results; - - results.name = strdup(entity_results.name); - results.level = entity_results.level; - + EnemyResults results = {.name = strdup(entity_results.name), .level = entity_results.level}; return results; } ParsedData parse_fight_results(byte_t *data, size_t length) { - ParsedData parsed_data; - parsed_data.data_type = TYPE_FIGHT_RESULTS; + ParsedData parsed_data = {.data_type = TYPE_FIGHT_RESULTS, .data_cleanup = cleanup_fight_results}; // ignore start and end indicators data += strlen(FIGHT_RESULTS_START); length -= strlen(FIGHT_RESULTS_START) + strlen(FIGHT_RESULTS_END); - FightResults *results = malloc(sizeof(FightResults)); + FightResults *results = safe_malloc(sizeof(FightResults)); + + results->friendly_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(FriendlyResults)); results->num_friendly = 0; + size_t friendly_cap = INIT_ENTITIES_PER_SIDE; + + results->enemy_results = safe_malloc(INIT_ENTITIES_PER_SIDE * sizeof(EnemyResults)); results->num_enemy = 0; + size_t enemy_cap = INIT_ENTITIES_PER_SIDE; byte_t *entity_separator; do { @@ -252,12 +234,16 @@ ParsedData parse_fight_results(byte_t *data, size_t length) { // depending on team - parse it into friendly or enemy results switch (entity_results.team) { - case TEAM_FRIEND: - results->friendly_results[results->num_friendly++] = parse_to_friendly(entity_results); + case TEAM_FRIEND: { + FriendlyResults res = parse_to_friendly(entity_results); + results->friendly_results = array_append(results->friendly_results, sizeof(FriendlyResults), &results->num_friendly, &friendly_cap, &res); break; - case TEAM_ENEMY: - results->enemy_results[results->num_enemy++] = parse_to_enemy(entity_results); + } + case TEAM_ENEMY: { + EnemyResults res = parse_to_enemy(entity_results); + results->enemy_results = array_append(results->enemy_results, sizeof(EnemyResults), &results->num_enemy, &enemy_cap, &res); break; + } } cleanup_struct(&entity_results, entity_fields, ARR_LEN(entity_fields)); @@ -270,6 +256,5 @@ ParsedData parse_fight_results(byte_t *data, size_t length) { } while (entity_separator); parsed_data.data = results; - parsed_data.data_cleanup = cleanup_fight_results; return parsed_data; } diff --git a/analyzer/parser/fight_results/fight_results.h b/analyzer/parser/fight_results/fight_results.h index 04add96..ec90394 100644 --- a/analyzer/parser/fight_results/fight_results.h +++ b/analyzer/parser/fight_results/fight_results.h @@ -44,14 +44,14 @@ typedef struct { int level; } EnemyResults; -#define MAX_ENTITIES_PER_SIDE 8 +#define INIT_ENTITIES_PER_SIDE 6 // entire fight resutls typedef struct { size_t num_friendly; - FriendlyResults friendly_results[MAX_ENTITIES_PER_SIDE]; + FriendlyResults *friendly_results; size_t num_enemy; - EnemyResults enemy_results[MAX_ENTITIES_PER_SIDE]; + EnemyResults *enemy_results; } FightResults; extern find_function_t find_fight_results; diff --git a/analyzer/parser/parser.c b/analyzer/parser/parser.c index 87ab4c0..d00cd97 100644 --- a/analyzer/parser/parser.c +++ b/analyzer/parser/parser.c @@ -5,13 +5,6 @@ #include "parser/find_parse_functions.h" #include "utils/memory.h" -// expand parsed data exponentially to fit el_count elements -ParsedData *expand_parsed_data(ParsedData *parsed_data, size_t *capacity, size_t el_count) { - while (*capacity < el_count) - *capacity <<= 1; - return realloc(parsed_data, *capacity * sizeof(ParsedData)); -} - // find earliest data to parse in stream byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_length, parse_function_t **earliest_parse_fun) { byte_t *earliest_data = NULL; @@ -30,7 +23,7 @@ byte_t *find_earliest_data(TCPStream *stream, int stream_offset, int *earliest_l ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed_data) { size_t parsed_data_capacity = INIT_PARSED_DATA_CAPACITY; - ParsedData *parsed_data = malloc(parsed_data_capacity * sizeof(ParsedData)); + ParsedData *parsed_data = safe_malloc(parsed_data_capacity * sizeof(ParsedData)); *n_parsed_data = 0; int stream_offset = 0; @@ -50,11 +43,8 @@ ParsedData *parse_stream(TCPStream *stream, size_t *parsed_len, size_t *n_parsed // if data to parse was found, parse it and update the offset if (earliest_data) { - // if no capacity in parsed data array - expand it - if (*n_parsed_data >= parsed_data_capacity) - parsed_data = expand_parsed_data(parsed_data, &parsed_data_capacity, *n_parsed_data + 1); - - parsed_data[(*n_parsed_data)++] = earliest_parse_fun(earliest_data, earliest_length); + ParsedData new_parsed = earliest_parse_fun(earliest_data, earliest_length); + parsed_data = array_append(parsed_data, sizeof(ParsedData), n_parsed_data, &parsed_data_capacity, &new_parsed); stream_offset = earliest_data - stream->data + earliest_length; } } while (earliest_data); diff --git a/analyzer/parser/structs.c b/analyzer/parser/structs.c index c59fa82..dedf0d1 100644 --- a/analyzer/parser/structs.c +++ b/analyzer/parser/structs.c @@ -4,12 +4,14 @@ #include <stdlib.h> #include <string.h> +#include "utils/memory.h" + void fill_struct(void *obj, const StructField *fields, size_t n_fields, const char *data, size_t data_len, const char *sep) { for (size_t i = 0; i < n_fields; i++) { char *next_sep = memmem(data, data_len, sep, strlen(sep)); size_t len = next_sep ? next_sep - data : data_len; - char *str = malloc(len + 1); + char *str = safe_malloc(len + 1); memcpy(str, data, len); str[len] = '\0'; diff --git a/analyzer/structures/hashmap.c b/analyzer/structures/hashmap.c index 84cc289..5eb27ae 100644 --- a/analyzer/structures/hashmap.c +++ b/analyzer/structures/hashmap.c @@ -3,6 +3,8 @@ #include <stdlib.h> #include <string.h> +#include "utils/memory.h" + HashMap *hashmap_new( size_t key_size, size_t value_size, @@ -11,9 +13,9 @@ HashMap *hashmap_new( void (*key_cleanup)(void *key), void (*value_cleanup)(void *key) ) { - HashMap *map = malloc(sizeof(HashMap)); + HashMap *map = safe_malloc(sizeof(HashMap)); // initialize NULLs - memset(map->table, 0, sizeof(HashMapNode *) * HASHMAP_TABLE_SIZE); + memset(map->table, 0, HASHMAP_TABLE_SIZE * sizeof(HashMapNode *)); map->key_size = key_size; map->value_size = value_size; map->hash = hash; @@ -42,9 +44,9 @@ void hashmap_put(HashMap *map, void *key, void *value) { } // if it doesn't exist - create new node - HashMapNode *new_node = malloc(sizeof(HashMapNode)); - new_node->key = malloc(map->key_size); - new_node->value = malloc(map->value_size); + HashMapNode *new_node = safe_malloc(sizeof(HashMapNode)); + new_node->key = safe_malloc(map->key_size); + new_node->value = safe_malloc(map->value_size); memcpy(new_node->key, key, map->key_size); memcpy(new_node->value, value, map->value_size); diff --git a/analyzer/structures/heap.c b/analyzer/structures/heap.c index 6102940..1267668 100644 --- a/analyzer/structures/heap.c +++ b/analyzer/structures/heap.c @@ -3,9 +3,11 @@ #include <stdlib.h> #include <string.h> +#include "utils/memory.h" + Heap *heap_new(size_t element_size, int (*compare)(void *element1, void *element2), void (*element_cleanup)(void *element)) { - Heap *heap = malloc(sizeof(Heap)); - heap->data = malloc(INIT_HEAP_CAPACITY * sizeof(void *)); + Heap *heap = safe_malloc(sizeof(Heap)); + heap->data = safe_malloc(INIT_HEAP_CAPACITY * sizeof(void *)); heap->n_elements = 0; heap->element_size = element_size; heap->capacity = INIT_HEAP_CAPACITY; @@ -40,7 +42,7 @@ void swap(void **p_el1, void **p_el2) { void expand_heap(Heap *heap, size_t el_count) { while (heap->capacity < el_count) heap->capacity = (heap->capacity << 1) | 1; - heap->data = realloc(heap->data, heap->capacity * sizeof(void *)); + heap->data = safe_realloc(heap->data, heap->capacity * sizeof(void *)); } void heap_insert(Heap *heap, void *element) { @@ -50,7 +52,7 @@ void heap_insert(Heap *heap, void *element) { // insert into the last position size_t i = heap->n_elements; - heap->data[i] = malloc(heap->element_size); + heap->data[i] = safe_malloc(heap->element_size); memcpy(heap->data[i], element, heap->element_size); heap->n_elements++; diff --git a/analyzer/utils/memory.c b/analyzer/utils/memory.c new file mode 100644 index 0000000..0a43bd3 --- /dev/null +++ b/analyzer/utils/memory.c @@ -0,0 +1,62 @@ +#include "memory.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +void *safe_malloc(size_t size) { + for (size_t i = 0; i < MAX_ALLOC_ATTEMPTS; i++) { + void *p = malloc(size); + if (p) + return p; + if (i < MAX_ALLOC_ATTEMPTS - 1) { + printf("Failed malloc. Retrying in 1s...\n"); + sleep(1); + } + } + + printf("ERROR: Failed malloc %d times. Exiting...", MAX_ALLOC_ATTEMPTS); + exit(EXIT_FAILURE); +} + +void *safe_realloc(void *ptr, size_t size) { + if (!ptr) + return safe_malloc(size); + + for (size_t i = 0; i < MAX_ALLOC_ATTEMPTS; i++) { + void *p = realloc(ptr, size); + if (p) + return p; + if (i < MAX_ALLOC_ATTEMPTS - 1) { + printf("Failed realloc. Retrying in 1s...\n"); + sleep(1); + } + } + + printf("ERROR: Failed realloc %d times. Exiting...", MAX_ALLOC_ATTEMPTS); + exit(EXIT_FAILURE); +} + +// expand an array +// returns pointer to the expanded array +void *array_expand(void *arr, size_t el_size, size_t *cap, size_t to_fit) { + while (*cap < to_fit) + *cap *= 2; + return safe_realloc(arr, *cap * el_size); +} + +void *array_append(void *arr, size_t el_size, size_t *len, size_t *cap, void *val) { + if (*len >= *cap) + arr = array_expand(arr, el_size, cap, *len + 1); + memcpy((char *)arr + (*len)++ * el_size, val, el_size); + return arr; +} + +void *array_concat(void *arr1, size_t el_size, size_t *len1, size_t *cap, void *arr2, size_t len2) { + if (*len1 + len2 > *cap) + arr1 = array_expand(arr1, el_size, cap, *len1 + len2); + memcpy((char *)arr1 + *len1 * el_size, arr2, len2 * el_size); + *len1 += len2; + return arr1; +} diff --git a/analyzer/utils/memory.h b/analyzer/utils/memory.h index 1de58b9..0973623 100644 --- a/analyzer/utils/memory.h +++ b/analyzer/utils/memory.h @@ -1,4 +1,46 @@ // utils/memory.h // helper functions for dealing with memory management +#include <stddef.h> + #define ARR_LEN(arr) (sizeof(arr) / sizeof(arr[0])) + +#define MAX_ALLOC_ATTEMPTS 3 + +// tries malloc MAX_ALLOC_ATTEMPTS times, if all fail - exits the program +// params: +// - size - count of bytes to allocate +// returns: +// pointer to the allocated memory +extern void *safe_malloc(size_t size); + +// tries realloc MAX_ALLOC_ATTEMPTS times, if all fail - exits the program +// params: +// - ptr - pointer to the memory to reallocate +// - size - new size of the memory +// returns: +// pointer to the reallocated memory +extern void *safe_realloc(void *ptr, size_t size); + +// append to array, expand if necessary +// params: +// - arr - array to append to +// - el_size - size of an array element +// - len - pointer to the length of the array +// - cap - pointer to the capacity of the array +// - val - pointer to the value to append to the array +// returns: +// new pointer to the array (different if it was realloced) +extern void *array_append(void *arr, size_t el_size, size_t *len, size_t *cap, void *val); + +// concatenate 2 arrays, expand if necessary +// params: +// - arr1 - first array (destination) +// - el_size - size of an array element +// - len1 - pointer to the length of arr1 +// - cap - pointer to the capacity of arr1 +// - arr2 - second array +// - len2 - length of arr2 +// returns: +// new pointer to the array (different if it was realloced) +extern void *array_concat(void *arr1, size_t el_size, size_t *len1, size_t *cap, void *arr2, size_t len2); diff --git a/analyzer/utils/tcp.c b/analyzer/utils/tcp.c index b925ecf..6309e64 100644 --- a/analyzer/utils/tcp.c +++ b/analyzer/utils/tcp.c @@ -6,15 +6,19 @@ #include <stdlib.h> #include <string.h> +#include "utils/memory.h" #include "utils/tcp_seq_math.h" // initalize default TCP segment TCPSegment new_segment() { - TCPSegment segment; - segment.payload = NULL; - segment.len = 0; - segment.seq = 0; - segment.port = 0; + // clang-format off + TCPSegment segment = { + .payload = NULL, + .len = 0, + .seq = 0, + .port = 0 + }; + // clang-format on return segment; } @@ -61,19 +65,22 @@ TCPSegment get_segment_from_packet(const byte_t *packet, const struct pcap_pkthd // get payload int total_header_len = eth_header_len + ip_header_len + tcp_header_len; segment.len = packet_data->caplen - total_header_len; - segment.payload = malloc(segment.len); + segment.payload = safe_malloc(segment.len); memcpy(segment.payload, packet + total_header_len, segment.len); return segment; } TCPStream new_stream() { - TCPStream stream; - stream.data = malloc(INIT_STREAM_CAPACITY); - stream.len = 0; - stream.capacity = INIT_STREAM_CAPACITY; - stream.seq = 0; - stream.port = 0; - stream.pending = NULL; + // clang-format off + TCPStream stream = { + .data = safe_malloc(INIT_STREAM_CAPACITY), + .len = 0, + .capacity = INIT_STREAM_CAPACITY, + .seq = 0, + .port = 0, + .pending = NULL + }; + // clang-format on return stream; } @@ -107,20 +114,9 @@ int in_acceptable_range(TCPStream stream, TCPSegment segment) { return seq_in_range_ei(segment.seq, stream_expected, max_acceptable_seq); } -// expand stream capacity exponentially to fit new_len -void expand_stream_capacity(TCPStream *stream, size_t new_len) { - while (stream->capacity < new_len) - stream->capacity <<= 1; - stream->data = realloc(stream->data, stream->capacity); -} - // add segment directly to stream void add_segment(TCPStream *stream, TCPSegment segment, size_t data_start) { - size_t new_stream_len = stream->len + segment.len - data_start; - if (new_stream_len > stream->capacity) - expand_stream_capacity(stream, new_stream_len); - memcpy(stream->data + stream->len, segment.payload + data_start, segment.len - data_start); - stream->len = new_stream_len; + stream->data = array_concat(stream->data, 1, &stream->len, &stream->capacity, segment.payload + data_start, segment.len - data_start); } // add pending segments to the stream |
