Commit 57f31f058c29edfd7d6d810fcd4a964875e9d463

Edward Thomson 2013-08-08T11:05:00

Fixes to safely reading the index Avoid wrapping around extension size when reading, avoid walking off the end of the buffer when reading names.

diff --git a/src/index.c b/src/index.c
index cbdd43b..5f53f1e 100644
--- a/src/index.c
+++ b/src/index.c
@@ -1371,7 +1371,7 @@ static int read_reuc(git_index *index, const char *buffer, size_t size)
 	while (size) {
 		git_index_reuc_entry *lost;
 
-		len = strlen(buffer) + 1;
+		len = p_strnlen(buffer, size) + 1;
 		if (size <= len)
 			return index_error_invalid("reading reuc entries");
 
@@ -1444,7 +1444,7 @@ static int read_conflict_names(git_index *index, const char *buffer, size_t size
 		return -1;
 
 #define read_conflict_name(ptr) \
-	len = strlen(buffer) + 1; \
+	len = p_strnlen(buffer, size) + 1; \
 	if (size < len) \
 		return index_error_invalid("reading conflict name entries"); \
 	\
@@ -1571,7 +1571,8 @@ static size_t read_extension(git_index *index, const char *buffer, size_t buffer
 
 	total_size = dest.extension_size + sizeof(struct index_extension);
 
-	if (buffer_size < total_size ||
+	if (dest.extension_size > total_size ||
+		buffer_size < total_size ||
 		buffer_size - total_size < INDEX_FOOTER_SIZE)
 		return 0;
 
diff --git a/src/posix.h b/src/posix.h
index 40bcc1a..ea97a13 100644
--- a/src/posix.h
+++ b/src/posix.h
@@ -93,6 +93,10 @@ extern int p_gettimeofday(struct timeval *tv, struct timezone *tz);
 #	include "unix/posix.h"
 #endif
 
+#ifndef __MINGW32__
+# define p_strnlen strnlen
+#endif
+
 #ifdef NO_READDIR_R
 #	include <dirent.h>
 GIT_INLINE(int) p_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h
index 7b97b48..97b1cb7 100644
--- a/src/win32/mingw-compat.h
+++ b/src/win32/mingw-compat.h
@@ -19,6 +19,11 @@
 # define S_IFLNK _S_IFLNK
 # define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK)
 
+GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) {
+	const char *end = memchr(s, 0, maxlen);
+	return end ? (end - s) : maxlen;
+}
+
 #endif
 
 #endif /* INCLUDE_mingw_compat__ */