Commit ff97778a7a01eb3661418d4dcc1465dc4519fda3

Jacques Germishuys 2014-09-25T13:07:36

The raw index buffer content is not guaranteed to be aligned * Ensure alignment by copying the content into a structure on the stack

diff --git a/src/index.c b/src/index.c
index b63a0be..8b757f2 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1767,35 +1767,42 @@ static size_t read_entry(
 	git_index_entry **out, const void *buffer, size_t buffer_size)
 {
 	size_t path_length, entry_size;
-	uint16_t flags_raw;
 	const char *path_ptr;
-	const struct entry_short *source = buffer;
+	struct entry_short source;
 	git_index_entry entry = {{0}};
 
 	if (INDEX_FOOTER_SIZE + minimal_entry_size > buffer_size)
 		return 0;
 
-	entry.ctime.seconds = (git_time_t)ntohl(source->ctime.seconds);
-	entry.ctime.nanoseconds = ntohl(source->ctime.nanoseconds);
-	entry.mtime.seconds = (git_time_t)ntohl(source->mtime.seconds);
-	entry.mtime.nanoseconds = ntohl(source->mtime.nanoseconds);
-	entry.dev = ntohl(source->dev);
-	entry.ino = ntohl(source->ino);
-	entry.mode = ntohl(source->mode);
-	entry.uid = ntohl(source->uid);
-	entry.gid = ntohl(source->gid);
-	entry.file_size = ntohl(source->file_size);
-	git_oid_cpy(&entry.id, &source->oid);
-	entry.flags = ntohs(source->flags);
+	/* buffer is not guaranteed to be aligned */
+	memcpy(&source, buffer, sizeof(struct entry_short));
+
+	entry.ctime.seconds = (git_time_t)ntohl(source.ctime.seconds);
+	entry.ctime.nanoseconds = ntohl(source.ctime.nanoseconds);
+	entry.mtime.seconds = (git_time_t)ntohl(source.mtime.seconds);
+	entry.mtime.nanoseconds = ntohl(source.mtime.nanoseconds);
+	entry.dev = ntohl(source.dev);
+	entry.ino = ntohl(source.ino);
+	entry.mode = ntohl(source.mode);
+	entry.uid = ntohl(source.uid);
+	entry.gid = ntohl(source.gid);
+	entry.file_size = ntohl(source.file_size);
+	git_oid_cpy(&entry.id, &source.oid);
+	entry.flags = ntohs(source.flags);
 
 	if (entry.flags & GIT_IDXENTRY_EXTENDED) {
-		const struct entry_long *source_l = (const struct entry_long *)source;
-		path_ptr = source_l->path;
+		uint16_t flags_raw;
+		size_t flags_offset;
 
-		flags_raw = ntohs(source_l->flags_extended);
-		memcpy(&entry.flags_extended, &flags_raw, 2);
+		flags_offset = offsetof(struct entry_long, flags_extended);
+		memcpy(&flags_raw, (const char *) buffer + flags_offset,
+			sizeof(flags_raw));
+		flags_raw = ntohs(flags_raw);
+
+		memcpy(&entry.flags_extended, &flags_raw, sizeof(flags_raw));
+		path_ptr = (const char *) buffer + offsetof(struct entry_long, path);
 	} else
-		path_ptr = source->path;
+		path_ptr = (const char *) buffer + offsetof(struct entry_short, path);
 
 	path_length = entry.flags & GIT_IDXENTRY_NAMEMASK;
 
@@ -1846,14 +1853,12 @@ static int read_header(struct index_header *dest, const void *buffer)
 
 static size_t read_extension(git_index *index, const char *buffer, size_t buffer_size)
 {
-	const struct index_extension *source;
 	struct index_extension dest;
 	size_t total_size;
 
-	source = (const struct index_extension *)(buffer);
-
-	memcpy(dest.signature, source->signature, 4);
-	dest.extension_size = ntohl(source->extension_size);
+	/* buffer is not guaranteed to be aligned */
+	memcpy(&dest, buffer, sizeof(struct index_extension));
+	dest.extension_size = ntohl(dest.extension_size);
 
 	total_size = dest.extension_size + sizeof(struct index_extension);