X-Git-Url: https://git.sven.stormbind.net/?p=sven%2Fexfat-utils.git;a=blobdiff_plain;f=libexfat%2Fnode.c;fp=libexfat%2Fnode.c;h=09208476070813947c045e0e8a29ca07fd3609b7;hp=fa9e572632d545ab564a27224ef84009be405811;hb=dbe4348df2ba88986e13163ef13d09fb7247589d;hpb=4cb393cfd9b0ab69392612521ee3dbe481ec492d diff --git a/libexfat/node.c b/libexfat/node.c index fa9e572..0920847 100644 --- a/libexfat/node.c +++ b/libexfat/node.c @@ -108,6 +108,12 @@ static int fetch_next_entry(struct exfat* ef, const struct exfat_node* parent, /* fetch the next cluster if needed */ if ((it->offset & (CLUSTER_SIZE(*ef->sb) - 1)) == 0) { + if (it->offset >= parent->size) + { + exfat_error("missing EOD entry (0x%"PRIx64", 0x%"PRIx64")", + it->offset, parent->size); + return 1; + } it->cluster = exfat_next_cluster(ef, parent, it->cluster); if (CLUSTER_INVALID(it->cluster)) { @@ -166,6 +172,7 @@ static const struct exfat_entry* get_entry_ptr(const struct exfat* ef, static int readdir(struct exfat* ef, const struct exfat_node* parent, struct exfat_node** node, struct iterator* it) { + int rc = -EIO; const struct exfat_entry* entry; const struct exfat_entry_meta1* meta1; const struct exfat_entry_meta2* meta2; @@ -211,13 +218,16 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, if (continuations < 2) { exfat_error("too few continuations (%hhu)", continuations); - return -EIO; + goto error; } reference_checksum = le16_to_cpu(meta1->checksum); actual_checksum = exfat_start_checksum(meta1); *node = allocate_node(); if (*node == NULL) - return -ENOMEM; + { + rc = -ENOMEM; + goto error; + } /* new node has zero reference counter */ (*node)->entry_cluster = it->cluster; (*node)->entry_offset = it->offset; @@ -290,7 +300,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, { exfat_error("invalid checksum (0x%hx != 0x%hx)", actual_checksum, reference_checksum); - return -EIO; + goto error; } if (fetch_next_entry(ef, parent, it) != 0) goto error; @@ -305,7 +315,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, if (CLUSTER_INVALID(le32_to_cpu(upcase->start_cluster))) { exfat_error("invalid cluster in upcase table"); - return -EIO; + goto error; } if (le64_to_cpu(upcase->size) == 0 || le64_to_cpu(upcase->size) > 0xffff * sizeof(uint16_t) || @@ -313,14 +323,15 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, { exfat_error("bad upcase table size (%"PRIu64" bytes)", le64_to_cpu(upcase->size)); - return -EIO; + goto error; } ef->upcase = malloc(le64_to_cpu(upcase->size)); if (ef->upcase == NULL) { exfat_error("failed to allocate upcase table (%"PRIu64" bytes)", le64_to_cpu(upcase->size)); - return -ENOMEM; + rc = -ENOMEM; + goto error; } ef->upcase_chars = le64_to_cpu(upcase->size) / sizeof(le16_t); @@ -333,7 +344,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, if (CLUSTER_INVALID(le32_to_cpu(bitmap->start_cluster))) { exfat_error("invalid cluster in clusters bitmap"); - return -EIO; + goto error; } ef->cmap.size = le32_to_cpu(ef->sb->cluster_count) - EXFAT_FIRST_DATA_CLUSTER; @@ -342,7 +353,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, exfat_error("invalid clusters bitmap size: %"PRIu64 " (expected at least %u)", le64_to_cpu(bitmap->size), (ef->cmap.size + 7) / 8); - return -EIO; + goto error; } ef->cmap.start_cluster = le32_to_cpu(bitmap->start_cluster); /* FIXME bitmap can be rather big, up to 512 MB */ @@ -352,7 +363,8 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, { exfat_error("failed to allocate clusters bitmap chunk " "(%"PRIu64" bytes)", le64_to_cpu(bitmap->size)); - return -ENOMEM; + rc = -ENOMEM; + goto error; } exfat_read_raw(ef->cmap.chunk, le64_to_cpu(bitmap->size), @@ -364,11 +376,11 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, if (label->length > EXFAT_ENAME_MAX) { exfat_error("too long label (%hhu chars)", label->length); - return -EIO; + goto error; } if (utf16_to_utf8(ef->label, label->name, sizeof(ef->label), EXFAT_ENAME_MAX) != 0) - return -EIO; + goto error; break; default: @@ -388,7 +400,7 @@ static int readdir(struct exfat* ef, const struct exfat_node* parent, error: free(*node); *node = NULL; - return -EIO; + return rc; } int exfat_cache_directory(struct exfat* ef, struct exfat_node* dir)