From 6d3efa68318b33051a7e7a91a6156fba56ec205a Mon Sep 17 00:00:00 2001
From: Sven Hoexter <sven@timegate.de>
Date: Fri, 30 Oct 2015 10:28:18 +0100
Subject: [PATCH] Add the fix for https://github.com/relan/exfat/issues/6 found
 and reported by The Fuzzing Project. Detect infinite loop.

---
 debian/changelog |  2 ++
 libexfat/mount.c | 33 +++++++++++++++++++++------------
 2 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/debian/changelog b/debian/changelog
index 41d33cc..2434953 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,6 +2,8 @@ exfat-utils (1.1.0-2+deb8u1) UNRELEASED; urgency=medium
 
   * Add the fix for https://github.com/relan/exfat/issues/5 found
     and reported by The Fuzzing Project. Check sector and cluster size.
+  * Add the fix for https://github.com/relan/exfat/issues/6 found
+    and reported by The Fuzzing Project. Detect infinite loop. 
 
  --
 
diff --git a/libexfat/mount.c b/libexfat/mount.c
index 2456187..9a29cbe 100644
--- a/libexfat/mount.c
+++ b/libexfat/mount.c
@@ -30,23 +30,32 @@
 
 static uint64_t rootdir_size(const struct exfat* ef)
 {
-	uint64_t clusters = 0;
+	uint32_t clusters = 0;
+	uint32_t clusters_max = le32_to_cpu(ef->sb->cluster_count);
 	cluster_t rootdir_cluster = le32_to_cpu(ef->sb->rootdir_cluster);
 
-	while (!CLUSTER_INVALID(rootdir_cluster))
+	/* Iterate all clusters of the root directory to calculate its size.
+	   It can't be contiguous because there is no flag to indicate this. */
+	do
 	{
-		clusters++;
-		/* root directory cannot be contiguous because there is no flag
-		   to indicate this */
+		if (clusters == clusters_max) /* infinite loop detected */
+		{
+			exfat_error("root directory cannot occupy all %d clusters",
+					clusters);
+			return 0;
+		}
+		if (CLUSTER_INVALID(rootdir_cluster))
+		{
+			exfat_error("bad cluster %#x while reading root directory",
+					rootdir_cluster);
+			return 0;
+		}
 		rootdir_cluster = exfat_next_cluster(ef, ef->root, rootdir_cluster);
+		clusters++;
 	}
-	if (rootdir_cluster != EXFAT_CLUSTER_END)
-	{
-		exfat_error("bad cluster %#x while reading root directory",
-				rootdir_cluster);
-		return 0;
-	}
-	return clusters * CLUSTER_SIZE(*ef->sb);
+	while (rootdir_cluster != EXFAT_CLUSTER_END);
+
+	return (uint64_t) clusters * CLUSTER_SIZE(*ef->sb);
 }
 
 static const char* get_option(const char* options, const char* option_name)
-- 
2.39.5