summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author= <jakob@memeware.net>2017-05-13 14:54:43 -0400
committer= <jakob@memeware.net>2017-05-13 14:54:43 -0400
commit1ec0be0143717f9d7af883269f7707dd0161f6ec (patch)
tree21f4cd4901e2b237cd067b45cc62b4ebdf0f0d52
parent986a9e120d79f625cbd7b4c59ccfd479a6a149ec (diff)
Bounds checking when the table is written to disk to prevent serious memory leaks.
-rw-r--r--src/main.c14
-rw-r--r--src/table.c51
-rw-r--r--src/table.h3
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, &timestamp, 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