From 1ec0be0143717f9d7af883269f7707dd0161f6ec Mon Sep 17 00:00:00 2001 From: = Date: Sat, 13 May 2017 14:54:43 -0400 Subject: Bounds checking when the table is written to disk to prevent serious memory leaks. --- src/main.c | 14 +++++--------- src/table.c | 51 +++++++++++++++++++++++++++------------------------ src/table.h | 3 ++- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/main.c b/src/main.c index a3d8622..bc167b6 100644 --- a/src/main.c +++ b/src/main.c @@ -33,7 +33,7 @@ #define EXIT_FAILURE 1 #define EXIT_SUCCESS 0 -#define VERSION_STR "2.0.0" +#define VERSION_STR "2.1.0b1" /* Writes usage information to stderr. */ @@ -71,7 +71,7 @@ static void print_help(void) { /* Inflates the table according to information in the header. */ static struct stream *load_table(struct stream *s) { - uint8_t compressed; + uint8_t compressed; uint64_t len, decompressed_len; stream_read(&compressed, s, sizeof(uint8_t)); stream_read(&len, s, sizeof(uint64_t)); @@ -210,17 +210,13 @@ static void create_archive(char **paths, int argc, struct params p) { struct header *h = create_header(); struct table_entry *root = calloc(sizeof(struct table_entry), 1), *cur; struct stream *table = stream_new(1); + uint64_t table_size; dump_header(fp, h); for (int i = 1; i < argc - p.vararg_index; i++) { cur = add_file(root, paths[i]); } - dump_table(table, root); - /* FIXME: table->len steps the bounds of the table and leaks memory - which can potentially be a huge security risk. Either fix the - functionality that expands the stream in memory, or get a table - size. */ - stream_seek(table, 0, SEEK_SET); - stream_dump(fp, table, table->len); + table_size = dump_table(table, root); + stream_dump(fp, table, table_size); } diff --git a/src/table.c b/src/table.c index 0582467..7bf6c2a 100644 --- a/src/table.c +++ b/src/table.c @@ -203,33 +203,28 @@ struct table_entry *add_file(struct table_entry *root, char *path) { } -/* Dumps the adlr segment for `key` into the table at `s` and returns - the number of bytes written. */ -static uint64_t dump_adlr(struct stream *s, uint32_t key) { +/* Dumps the adlr segment for `key` into the table at `s`. */ +static void dump_adlr(struct stream *s, uint32_t key) { uint32_t magic = ADLR_MAGIC; uint64_t entry_size = sizeof(uint32_t); stream_write(s, &magic, sizeof(uint32_t)); stream_write(s, &entry_size, sizeof(uint64_t)); stream_write(s, &key, sizeof(uint32_t)); - return 16; } -/* Dumps the time segment for `timestamp` into the table at `s` and - returns the number of bytes written. */ -static uint64_t dump_time(struct stream *s, uint64_t timestamp) { +/* Dumps the time segment for `timestamp` into the table at `s`. */ +static void dump_time(struct stream *s, uint64_t timestamp) { uint32_t magic = TIME_MAGIC; uint64_t entry_size = sizeof(uint64_t); stream_write(s, &magic, sizeof(uint32_t)); stream_write(s, &entry_size, sizeof(uint64_t)); stream_write(s, ×tamp, sizeof(uint64_t)); - return 20; } -/* Dumps the segm segment for `cur` into the table at `s` and returns - the number of bytes written. */ -static uint64_t dump_segm(struct stream *s, struct table_entry *cur) { +/* Dumps the segm segment for `cur` into the table at `s`. */ +static void dump_segm(struct stream *s, struct table_entry *cur) { struct segment *segm; uint32_t magic = SEGM_MAGIC; uint64_t entry_size = cur->segment_count * 28; @@ -242,48 +237,56 @@ static uint64_t dump_segm(struct stream *s, struct table_entry *cur) { stream_write(s, &segm->decompressed_size, sizeof(uint64_t)); stream_write(s, &segm->compressed_size, sizeof(uint64_t)); } - return 12 + 28 * cur->segment_count; } -/* Dumps the File entry for `cur` into the table at `s`. */ -static void dump_file(struct stream *s, struct table_entry *cur) { +/* Dumps the File entry for `cur` into the table at `s` and returns the + number of bytes written. */ +static uint64_t dump_file(struct stream *s, struct table_entry *cur) { uint32_t magic = FILE_MAGIC; - uint64_t bytes_written; stream_write(s, &magic, sizeof(uint32_t)); stream_write(s, &bytes_written, sizeof(uint64_t)); - bytes_written = dump_adlr(s, cur->key); - bytes_written += dump_time(s, cur->ctime); - bytes_written += dump_segm(s, cur); + + dump_adlr(s, cur->key); + dump_time(s, cur->ctime); + dump_segm(s, cur); stream_seek(s, -bytes_written, SEEK_CUR); stream_write(s, &bytes_written, sizeof(uint64_t)); stream_seek(s, bytes_written, SEEK_CUR); + return 28 * cur->segment_count + 48; } -/* Dumps the eliF entry for `cur` into the table at `s`. */ -static void dump_elif(struct stream *s, struct table_entry *cur) { +/* Dumps the eliF entry for `cur` into the table at `s` and returns the + number of bytes written. */ +static uint64_t dump_elif(struct stream *s, struct table_entry *cur) { uint32_t magic = ELIF_MAGIC; uint16_t name_len = strlen(cur->filename); uint64_t entry_size = name_len * 2 + 8; char *encoded = malloc(name_len * 2 + 2); utf16le_encode(cur->filename, encoded, name_len); + stream_write(s, &magic, sizeof(uint32_t)); stream_write(s, &entry_size, sizeof(uint64_t)); stream_write(s, &cur->key, sizeof(uint32_t)); stream_write(s, &name_len, sizeof(uint16_t)); stream_write(s, encoded, name_len * 2 + 2); + return 18 + name_len * 2 + 2; } -/* Dumps the XP3 table specified by `root` into `s`. */ -void dump_table(struct stream *s, struct table_entry *root) { +/* Dumps the XP3 table specified by `root` into `s` and returns the + number of bytes written. */ +uint64_t dump_table(struct stream *s, struct table_entry *root) { + uint64_t bytes_written = 0; struct table_entry *cur; for (cur = root->next; cur != NULL; cur = cur->next) { - dump_elif(s, cur); - dump_file(s, cur); + bytes_written += dump_elif(s, cur); + bytes_written += dump_file(s, cur); } + stream_seek(s, 0, SEEK_SET); + return bytes_written; } diff --git a/src/table.h b/src/table.h index dd01fa3..53012f7 100644 --- a/src/table.h +++ b/src/table.h @@ -74,7 +74,8 @@ void entry_append(struct table_entry *root, struct table_entry *e); /* Frees every entry in the linked list specified by `cur`. */ void entry_free(struct table_entry *cur); -/* Dumps the XP3 table specified by `root` into `s`. */ +/* Dumps the XP3 table specified by `root` into `s` and returns the + number of bytes written. */ void dump_table(struct stream *s, struct table_entry *root); /* Inserts the file specified by `path` into the table linked list -- cgit v1.3