aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrelan <relan@users.noreply.github.com>2015-09-10 17:47:16 +0300
committerrelan <relan@users.noreply.github.com>2015-09-24 08:29:09 +0300
commitbaa724ad0d4340504ee7d9efd293223c36ccbbe3 (patch)
tree2529254510169f6d5d494b5db5b29f37c7fcbcb9
parent38d5c3a929124fd123675ac576401b7de3570b2f (diff)
downloadandroid_external_exfat-baa724ad0d4340504ee7d9efd293223c36ccbbe3.tar.gz
android_external_exfat-baa724ad0d4340504ee7d9efd293223c36ccbbe3.tar.bz2
android_external_exfat-baa724ad0d4340504ee7d9efd293223c36ccbbe3.zip
Detect infinite loop in rootdir_size().
Otherwise malformed FS can cause hang on mount.
-rw-r--r--libexfat/mount.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/libexfat/mount.c b/libexfat/mount.c
index f25d71d..f1fb01a 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)