diff --git a/src/commands.c b/src/commands.c index c6df995..f07a439 100644 --- a/src/commands.c +++ b/src/commands.c @@ -641,36 +641,141 @@ int commit(int argc, char** argv) { char timestamp[20]; snprintf(timestamp, sizeof(timestamp), "%ld", time(NULL)); - Author author = { - .name = strdup(config.user.name), - .email = strdup(config.user.email), - .timestamp = strdup(timestamp) - }; + Author* authors = calloc(1, sizeof(Author)); + if (!authors) { + file_info_buffer_free(tree); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } - if (log->len != 0) { - char parent_hash[41]; - snprintf(parent_hash, sizeof(parent_hash), "%s", ((Commit*)log->items + (log->len - 1))->hash); + authors[0].name = strdup(config.user.name); + authors[0].email = strdup(config.user.email); + authors[0].timestamp = strdup(timestamp); + if (!authors[0].name || !authors[0].email || !authors[0].timestamp) { + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + file_info_buffer_free(tree); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; } char commit_hash_content[4096]; int offset = 0; - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "tree %s\n", tree_hash); - if (log->len != 0) { - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "parent %s\n", parent_hash); + size_t remaining = sizeof(commit_hash_content); + + int written = snprintf(commit_hash_content + offset, remaining - offset, "tree %s\n", tree_hash); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; } - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "author %s <%s> %s\n", author.name, author.email, author.timestamp); - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "committer %s <%s> %s\n", author.name, author.email, author.timestamp); - offset += snprintf(commit_hash_content + offset, sizeof(commit_hash_content) - offset, "message %s\n", commit_message); + offset += written; + + if (log->len != 0) { + written = snprintf(commit_hash_content + offset, remaining - offset, "parent %s\n", parent_hash); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + } + + written = snprintf(commit_hash_content + offset, remaining - offset, "author %s <%s> %s\n", authors[0].name, authors[0].email, authors[0].timestamp); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + + written = snprintf(commit_hash_content + offset, remaining - offset, "committer %s <%s> %s\n", authors[0].name, authors[0].email, authors[0].timestamp); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; + + written = snprintf(commit_hash_content + offset, remaining - offset, "message %s\n", commit_message); + if (written < 0 || (size_t)written >= remaining - offset) { + commit_log_free(log); + file_info_buffer_free(tree); + free(authors[0].name); + free(authors[0].email); + free(authors[0].timestamp); + free(authors); + free(commit_message); + list_free(files); + base_file_buffer_free(base_files); + free(branch); + free(root); + free_config(&config); + return 1; + } + offset += written; char commit_hash[41]; object_hash(LogObject, commit_hash_content, commit_hash); Commit commit = { - .hash = commit_hash, + .hash = strdup(commit_hash), .tree_hash = strdup(tree_hash), - .authors = &author, + .authors = authors, .authors_count = 1, - .committer = author, + .committer = authors[0], .message = strdup(commit_message) }; @@ -686,6 +791,7 @@ int commit(int argc, char** argv) { free_config(&config); return 1; } + commit_log_free(log); char ref_path[PATH_MAX]; snprintf(ref_path, sizeof(ref_path), "%s/.merk/refs/branches/%s", root, branch); diff --git a/src/commit.c b/src/commit.c index 25ca833..afbcfde 100644 --- a/src/commit.c +++ b/src/commit.c @@ -19,11 +19,13 @@ void commit_log_free(CommitLog* log) { for (size_t j = 0; j < commit->authors_count; j++) { free(commit->authors[j].name); free(commit->authors[j].email); + free(commit->authors[j].timestamp); } free(commit->authors); } free(commit->committer.name); free(commit->committer.email); + free(commit->committer.timestamp); free(commit->message); } free(log->items);