From 3a590dd7c156b1bdf4a119921ee39035b2ec1626 Mon Sep 17 00:00:00 2001 From: dam Date: Sun, 23 Oct 2022 22:53:01 +0000 Subject: Added protection to overflow on malloc argument. Decided not to implement logging. --- main.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 10d5142..733778a 100644 --- a/main.c +++ b/main.c @@ -63,10 +63,14 @@ const char DB_FILE_SIGN[] = DB_FILE_SIGN_STR; const size_t DB_FILE_SIGN_LENGTH = sizeof(DB_FILE_SIGN_STR)-1; const size_t SIZEOF_TASK_ST = sizeof(task_st); const size_t SIZEOF_DATABASE_ST = sizeof(database_st); +const size_t SIZEOF_CHAR = sizeof(char); +const size_t SIZEOF_INT64 = sizeof(int64_t); const int64_t SECONDS_IN_MINUTE = (int64_t)60; const int64_t SECONDS_IN_HOUR = (int64_t)60*SECONDS_IN_MINUTE; const int64_t SECONDS_IN_DAY = (int64_t)24*SECONDS_IN_HOUR; const int64_t SECONDS_IN_YEAR = (int64_t)365*SECONDS_IN_DAY; +const size_t MAX_DATABASE_TASKS = (PTRDIFF_MAX < (SIZE_MAX / SIZEOF_TASK_ST)) ? PTRDIFF_MAX : (SIZE_MAX / SIZEOF_TASK_ST); + database_st database = { .tasks = NULL }; database_st archive = { .tasks = NULL }; @@ -93,7 +97,7 @@ bool is_file_accessible(const char *path) { // Given an UTF8 encoded string, truncate it to length without breaking any UTF8 character. // The string should have capacity for at least length number of items. // The terminating null byte ('\0') is included in length. -// The function returns the amount of items that got discarded counting from length. +// Returns the amount of items discarded. size_t truncate_string_utf8(char *string, size_t length) { // Check for special cases where no truncation is required. @@ -237,12 +241,13 @@ task_st *get_selected_task(database_st *db) { return task; } + // Creates new task returned in the pointer. If necessary, expands database capacity. // Returns success. bool create_task(database_st *db, task_st **task) { assert(db != NULL); - if (db->count == PTRDIFF_MAX) { + if (db->count == MAX_DATABASE_TASKS) { fprintf(stderr, "Database reached maximum capacity.\n"); return false; } @@ -251,7 +256,7 @@ bool create_task(database_st *db, task_st **task) { size_t current_capacity = db->capacity; if((db->count + 1) > current_capacity) { size_t new_capacity = current_capacity == 0 ? 2 : - current_capacity > PTRDIFF_MAX >> 1 ? PTRDIFF_MAX : + current_capacity > MAX_DATABASE_TASKS >> 1 ? MAX_DATABASE_TASKS : current_capacity << 1; task_st *new_tasks = realloc(db->tasks, new_capacity * SIZEOF_TASK_ST); @@ -443,7 +448,7 @@ void update_total_times(database_st *db) { int64_t *d4 = &db->total_times[4]; int64_t *d5 = &db->total_times[5]; int64_t *d6 = &db->total_times[6]; - memset(db->total_times, 0, NUM_WEEK_DAYS * sizeof(int64_t)); + memset(db->total_times, 0, NUM_WEEK_DAYS * SIZEOF_INT64); for (size_t idx = 0; idx < db->count; idx++) { int64_t *times = db->tasks[idx].times; @@ -513,7 +518,7 @@ bool store_database(const database_st *db, const char *path) { return false; } - fwrite(DB_FILE_SIGN, sizeof(char), DB_FILE_SIGN_LENGTH, file); + fwrite(DB_FILE_SIGN, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file); fwrite(db, SIZEOF_DATABASE_ST, 1, file); fwrite(db->tasks, SIZEOF_TASK_ST, db->count, file); @@ -536,7 +541,7 @@ bool load_database(database_st *db, const char *path) { // Validate file signature. char file_signature[DB_FILE_SIGN_LENGTH]; - fread(&file_signature, sizeof(char), DB_FILE_SIGN_LENGTH, file); + fread(&file_signature, SIZEOF_CHAR, DB_FILE_SIGN_LENGTH, file); if (strncmp(file_signature, DB_FILE_SIGN, DB_FILE_SIGN_LENGTH) != 0) { fprintf(stderr, "Invalid file signature.\n"); fclose(file); @@ -547,7 +552,7 @@ bool load_database(database_st *db, const char *path) { fread(db, SIZEOF_DATABASE_ST, 1, file); // Restore database capacity. - db->tasks = calloc(db->capacity, SIZEOF_TASK_ST); + db->tasks = malloc(db->capacity * SIZEOF_TASK_ST); // Read database entries. fread(db->tasks, SIZEOF_TASK_ST, db->count, file); @@ -685,7 +690,7 @@ bool append_to_csv(task_st *task, const char *path) { char last_char; fseek(file, -1, SEEK_END); - fread(&last_char, sizeof(char), 1, file); + fread(&last_char, SIZEOF_CHAR, 1, file); if (last_char != '\n') { fprintf(file, "\n"); } @@ -708,7 +713,6 @@ bool append_to_csv(task_st *task, const char *path) { return true; } - #define INPUT_TIMEOUT_MS 1000 #define INPUT_AWAIT_INF -1 @@ -1139,6 +1143,7 @@ int main(int argc, char *argv[]) { load_database(&database, db_file_path); + flushinp(); ungetch(KEY_RESIZE); for (int key; (key = getch()) != 'q'; ) { @@ -1188,6 +1193,7 @@ int main(int argc, char *argv[]) { db->selected_task = selected_task - db->tasks; // Force rename action. + flushinp(); ungetch(KEY_F(2)); break; } @@ -1526,6 +1532,8 @@ int main(int argc, char *argv[]) { break; } + // TODO Should I change the selected_task directly? + case KEY_HOME: { if (db->count > 0) { db->selected_task = 0; -- cgit v1.2.3