diff options
author | relan <relan@users.noreply.github.com> | 2015-09-10 17:47:16 +0300 |
---|---|---|
committer | relan <relan@users.noreply.github.com> | 2015-09-24 08:29:09 +0300 |
commit | baa724ad0d4340504ee7d9efd293223c36ccbbe3 (patch) | |
tree | 2529254510169f6d5d494b5db5b29f37c7fcbcb9 | |
parent | 38d5c3a929124fd123675ac576401b7de3570b2f (diff) | |
download | android_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.c | 33 |
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) |