From cb1a999dced311d534f3167667ea1721fa5a71f8 Mon Sep 17 00:00:00 2001 From: relan Date: Fri, 17 Mar 2017 08:31:43 +0300 Subject: [PATCH] Improve upper bound check in CLUSTER_INVALID() macro. Check that cluster value does not exceed actual number of clusters. Note that clusters numbering starts with 2. --- dump/main.c | 2 +- fsck/main.c | 2 +- libexfat/cluster.c | 19 ++++++++++--------- libexfat/exfat.h | 4 ++-- libexfat/io.c | 8 ++++---- libexfat/mount.c | 2 +- libexfat/node.c | 6 +++--- 7 files changed, 22 insertions(+), 21 deletions(-) diff --git a/dump/main.c b/dump/main.c index 420a951..4a764a8 100644 --- a/dump/main.c +++ b/dump/main.c @@ -168,7 +168,7 @@ static int dump_file_fragments(const char* spec, const char* path) { off_t lsize; - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef.sb, cluster)) { exfat_error("'%s' has invalid cluster %#x", path, cluster); rc = 1; diff --git a/fsck/main.c b/fsck/main.c index b413c58..b7222f0 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -39,7 +39,7 @@ static int nodeck(struct exfat* ef, struct exfat_node* node) while (clusters--) { - if (CLUSTER_INVALID(c)) + if (CLUSTER_INVALID(*ef->sb, c)) { char name[EXFAT_UTF8_NAME_BUFFER_MAX]; diff --git a/libexfat/cluster.c b/libexfat/cluster.c index 1d39233..19b7d0d 100644 --- a/libexfat/cluster.c +++ b/libexfat/cluster.c @@ -103,7 +103,7 @@ cluster_t exfat_advance_cluster(const struct exfat* ef, for (i = node->fptr_index; i < count; i++) { node->fptr_cluster = exfat_next_cluster(ef, node, node->fptr_cluster); - if (CLUSTER_INVALID(node->fptr_cluster)) + if (CLUSTER_INVALID(*ef->sb, node->fptr_cluster)) break; /* the caller should handle this and print appropriate error message */ } @@ -214,7 +214,7 @@ static cluster_t allocate_cluster(struct exfat* ef, cluster_t hint) static void free_cluster(struct exfat* ef, cluster_t cluster) { - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) exfat_bug("freeing invalid cluster 0x%x", cluster); if (cluster - EXFAT_FIRST_DATA_CLUSTER >= ef->cmap.size) exfat_bug("freeing non-existing cluster 0x%x (0x%x)", cluster, @@ -252,7 +252,7 @@ static int grow_file(struct exfat* ef, struct exfat_node* node, { /* get the last cluster of the file */ previous = exfat_advance_cluster(ef, node, current - 1); - if (CLUSTER_INVALID(previous)) + if (CLUSTER_INVALID(*ef->sb, previous)) { exfat_error("invalid cluster 0x%x while growing", previous); return -EIO; @@ -265,7 +265,7 @@ static int grow_file(struct exfat* ef, struct exfat_node* node, /* file does not have clusters (i.e. is empty), allocate the first one for it */ previous = allocate_cluster(ef, 0); - if (CLUSTER_INVALID(previous)) + if (CLUSTER_INVALID(*ef->sb, previous)) return -ENOSPC; node->fptr_cluster = node->start_cluster = previous; allocated = 1; @@ -276,7 +276,7 @@ static int grow_file(struct exfat* ef, struct exfat_node* node, while (allocated < difference) { next = allocate_cluster(ef, previous + 1); - if (CLUSTER_INVALID(next)) + if (CLUSTER_INVALID(*ef->sb, next)) { if (allocated != 0) shrink_file(ef, node, current + allocated, allocated); @@ -321,7 +321,7 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node, { cluster_t last = exfat_advance_cluster(ef, node, current - difference - 1); - if (CLUSTER_INVALID(last)) + if (CLUSTER_INVALID(*ef->sb, last)) { exfat_error("invalid cluster 0x%x while shrinking", last); return -EIO; @@ -343,12 +343,13 @@ static int shrink_file(struct exfat* ef, struct exfat_node* node, /* free remaining clusters */ while (difference--) { - if (CLUSTER_INVALID(previous)) + if (CLUSTER_INVALID(*ef->sb, previous)) { exfat_error("invalid cluster 0x%x while freeing after shrink", previous); return -EIO; } + next = exfat_next_cluster(ef, node, previous); if (!set_next_cluster(ef, node->is_contiguous, previous, EXFAT_CLUSTER_FREE)) @@ -381,7 +382,7 @@ static int erase_range(struct exfat* ef, struct exfat_node* node, cluster_boundary = (begin | (CLUSTER_SIZE(*ef->sb) - 1)) + 1; cluster = exfat_advance_cluster(ef, node, begin / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while erasing", cluster); return -EIO; @@ -395,7 +396,7 @@ static int erase_range(struct exfat* ef, struct exfat_node* node, { cluster = exfat_next_cluster(ef, node, cluster); /* the cluster cannot be invalid because we have just allocated it */ - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) exfat_bug("invalid cluster 0x%x after allocation", cluster); if (!erase_raw(ef, CLUSTER_SIZE(*ef->sb), exfat_c2o(ef, cluster))) return -EIO; diff --git a/libexfat/exfat.h b/libexfat/exfat.h index 21b760e..5a60499 100644 --- a/libexfat/exfat.h +++ b/libexfat/exfat.h @@ -43,8 +43,8 @@ #define SECTOR_SIZE(sb) (1 << (sb).sector_bits) #define CLUSTER_SIZE(sb) (SECTOR_SIZE(sb) << (sb).spc_bits) -#define CLUSTER_INVALID(c) \ - ((c) < EXFAT_FIRST_DATA_CLUSTER || (c) > EXFAT_LAST_DATA_CLUSTER) +#define CLUSTER_INVALID(sb, c) ((c) < EXFAT_FIRST_DATA_CLUSTER || \ + (c) - EXFAT_FIRST_DATA_CLUSTER >= le32_to_cpu((sb).cluster_count)) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) diff --git a/libexfat/io.c b/libexfat/io.c index 514383c..8cbcfa1 100644 --- a/libexfat/io.c +++ b/libexfat/io.c @@ -289,7 +289,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, return 0; cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while reading", cluster); return -EIO; @@ -299,7 +299,7 @@ ssize_t exfat_generic_pread(const struct exfat* ef, struct exfat_node* node, remainder = MIN(size, node->size - offset); while (remainder > 0) { - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while reading", cluster); return -EIO; @@ -345,7 +345,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, return 0; cluster = exfat_advance_cluster(ef, node, offset / CLUSTER_SIZE(*ef->sb)); - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while writing", cluster); return -EIO; @@ -355,7 +355,7 @@ ssize_t exfat_generic_pwrite(struct exfat* ef, struct exfat_node* node, remainder = size; while (remainder > 0) { - if (CLUSTER_INVALID(cluster)) + if (CLUSTER_INVALID(*ef->sb, cluster)) { exfat_error("invalid cluster 0x%x while writing", cluster); return -EIO; diff --git a/libexfat/mount.c b/libexfat/mount.c index f907f29..4910b51 100644 --- a/libexfat/mount.c +++ b/libexfat/mount.c @@ -44,7 +44,7 @@ static uint64_t rootdir_size(const struct exfat* ef) clusters); return 0; } - if (CLUSTER_INVALID(rootdir_cluster)) + if (CLUSTER_INVALID(*ef->sb, rootdir_cluster)) { exfat_error("bad cluster %#x while reading root directory", rootdir_cluster); diff --git a/libexfat/node.c b/libexfat/node.c index bccf9a1..e50bb69 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -252,7 +252,7 @@ static bool check_node(const struct exfat* ef, struct exfat_node* node, node->start_cluster); ret = false; } - if (node->size > 0 && CLUSTER_INVALID(node->start_cluster)) + if (node->size > 0 && CLUSTER_INVALID(*ef->sb, node->start_cluster)) { exfat_get_name(node, buffer); exfat_error("'%s' points to invalid cluster %#x", buffer, @@ -401,7 +401,7 @@ static int readdir(struct exfat* ef, struct exfat_node* parent, if (ef->upcase != NULL) break; upcase = (const struct exfat_entry_upcase*) &entry; - if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster))) + if (CLUSTER_INVALID(*ef->sb, le32_to_cpu(upcase->start_cluster))) { exfat_error("invalid cluster 0x%x in upcase table", le32_to_cpu(upcase->start_cluster)); @@ -452,7 +452,7 @@ static int readdir(struct exfat* ef, struct exfat_node* parent, case EXFAT_ENTRY_BITMAP: bitmap = (const struct exfat_entry_bitmap*) &entry; ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster); - if (CLUSTER_INVALID(ef->cmap.start_cluster)) + if (CLUSTER_INVALID(*ef->sb, ef->cmap.start_cluster)) { exfat_error("invalid cluster 0x%x in clusters bitmap", ef->cmap.start_cluster); -- 2.11.0