From 2eeaa2171fba4ebec5ec0946cac47179b61d063d Mon Sep 17 00:00:00 2001 From: olemorud Date: Mon, 24 Apr 2023 23:44:17 +0200 Subject: [PATCH] Fix all memory leaks --- include/json_value.h | 8 +++++--- src/json_value.c | 48 ++++++++++++++++++++++++++++++++++---------- src/main.c | 8 ++++++-- src/parse.c | 25 +++++++++++++++++++---- 4 files changed, 69 insertions(+), 20 deletions(-) diff --git a/include/json_value.h b/include/json_value.h index 2ae5dd1..ea49205 100644 --- a/include/json_value.h +++ b/include/json_value.h @@ -4,7 +4,7 @@ #include // bool -#define OBJ_SIZE 64 +#define OBJ_SIZE 32 typedef struct obj_entry { char const* key; @@ -25,7 +25,7 @@ struct json_value { enum json_type type; union { obj_t* object; - struct json_value** array; + struct json_value** array; // we need an array of pointers to allow null termination char* string; bool boolean; double number; @@ -34,8 +34,10 @@ struct json_value { void* obj_at(obj_t m, char* const key); bool obj_insert(obj_t m, char* const key, struct json_value* value); -void obj_delete(obj_t m); +void obj_delete(obj_t* m); void print_json(struct json_value val, int indent); +void json_value_delete(struct json_value val); + #endif diff --git a/src/json_value.c b/src/json_value.c index fab0796..abff305 100644 --- a/src/json_value.c +++ b/src/json_value.c @@ -10,11 +10,12 @@ bool obj_insert(obj_t m, char* const key, struct json_value* value); size_t obj_hash(char const* str); -void obj_delete(obj_t m); +void obj_delete(obj_t* m); +void* obj_at(obj_t m, char* const key); + void print_array(struct json_value** arr, int cur_indent, int indent_amount); void print_json_value(struct json_value val, int cur_indent, int indent_amount); void print_object(obj_t obj, int cur_indent, int indent_amount); -void* obj_at(obj_t m, char* const key); /* djb2 string hash @@ -104,7 +105,7 @@ bool obj_insert(obj_t m, char* const key, struct json_value* value) /* populate new entry */ cur = malloc_or_die(sizeof(struct obj_entry)); - cur->key = strdup(key); + cur->key = key; cur->val = value; cur->next = m[i]; @@ -114,27 +115,52 @@ bool obj_insert(obj_t m, char* const key, struct json_value* value) return true; } +void json_value_delete(struct json_value val) +{ + switch (val.type) { + case array: + for (size_t i = 0; val.array[i] != NULL; i++) { + json_value_delete(*(val.array[i])); + free(val.array[i]); + } + + free(val.array); + break; + + case object: + obj_delete(val.object); + break; + + case string: + free(val.string); + break; + + default: + break; + } +} + /* - Free memory allocated for obj + Free memory allocated for obj TODO: recurively delete children objects */ -void obj_delete(obj_t m) +void obj_delete(obj_t* m) { for (size_t i = 0; i < OBJ_SIZE; i++) { - if (m[i] == NULL) - continue; - - struct obj_entry *e = m[i], *tmp; + struct obj_entry *e = (*m)[i], *tmp; while (e != NULL) { - tmp = e; + json_value_delete(*(e->val)); free((char*)e->key); free(e->val); + + tmp = e; e = e->next; free(tmp); } } + free(m); } void add_indent(int n) @@ -181,7 +207,7 @@ void print_array(struct json_value** arr, int cur_indent, int indent_amount) return; } - for (size_t i = 0; arr[i+1] != NULL; i++) { + for (size_t i = 0; arr[i + 1] != NULL; i++) { putchar('\n'); add_indent(cur_indent); print_json_value(*arr[i], cur_indent + indent_amount, indent_amount); diff --git a/src/main.c b/src/main.c index 4e72d66..5ce3108 100644 --- a/src/main.c +++ b/src/main.c @@ -16,9 +16,13 @@ int main(int argc, char* argv[]) FILE* fp = fopen(argv[1], "r"); - volatile struct json_value x = parse_json_value(fp); + struct json_value x = parse_json_value(fp); - print_json(x, 1); + // print_json(x, 1); + + json_value_delete(x); + + fclose(fp); return EXIT_SUCCESS; } diff --git a/src/parse.c b/src/parse.c index 6ea29e1..b98de26 100644 --- a/src/parse.c +++ b/src/parse.c @@ -113,7 +113,7 @@ struct json_value parse_json_value(FILE* fp) char* read_string(FILE* fp) { int c; - size_t i = 0, result_size = 16 * sizeof(char); + size_t i = 0, result_size = 16; char* result = malloc_or_die(result_size); bool escaped = false; @@ -141,6 +141,7 @@ char* read_string(FILE* fp) return realloc_or_die(result, i); case EOF: + free(result); err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__); default: @@ -170,9 +171,11 @@ obj_t* read_object(FILE* fp) switch (fgetc(fp)) { case EOF: + free(result); err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__); default: + free(result); err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected \"", __func__); case '"': @@ -191,9 +194,11 @@ obj_t* read_object(FILE* fp) break; case EOF: + free(result); err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__); default: + free(result); err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected ':'", __func__); } @@ -204,14 +209,19 @@ obj_t* read_object(FILE* fp) *val = parse_json_value(fp); /* insert key-value pair to obj */ - if (!obj_insert(*result, key, val)) + if (!obj_insert(*result, key, val)) { + free(result); + free(val); errx(EXIT_FAILURE, "failed to insert pair (%s, %p)", key, (void*)val); + } /* read separator or end of object */ discard_whitespace(fp); switch (fgetc(fp)) { case EOF: + free(val); + free(result); err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__); case ',': @@ -221,6 +231,8 @@ obj_t* read_object(FILE* fp) return result; default: + free(val); + free(result); err_ctx(UNEXPECTED_CHAR, fp, "(%s) expected ',' or '}'", __func__); } } @@ -252,6 +264,11 @@ struct json_value** read_array(FILE* fp) switch (c) { case EOF: + free(output); + + for (size_t j = 0; j < i; j++) + free(output[j]); + err_ctx(EARLY_EOF, fp, "(%s) unexpected EOF", __func__); break; @@ -281,7 +298,7 @@ struct json_value** read_array(FILE* fp) void read_null(FILE* fp) { static const char ok[] = { 'n', 'u', 'l', 'l' }; - char buf[sizeof(ok)]; + static char buf[sizeof(ok)]; size_t n_read = fread(buf, sizeof(char), sizeof(ok), fp); @@ -304,7 +321,7 @@ bool read_boolean(FILE* fp) static const char t[] = { 't', 'r', 'u', 'e' }; static const char f[] = { 'f', 'a', 'l', 's', 'e' }; - char buf[sizeof(f)] = { 0 }; + static char buf[sizeof(f)] = { 0 }; size_t n_read = fread(buf, sizeof(char), sizeof(f), fp);