summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--check/main.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/check/main.c b/check/main.c
index c051a862..97baae58 100644
--- a/check/main.c
+++ b/check/main.c
@@ -9054,6 +9054,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
struct btrfs_key found_key;
struct btrfs_extent_item *ei;
struct btrfs_extent_inline_ref *iref;
+ unsigned long item_end;
int slot = path.slots[0];
int type;
u64 flags;
@@ -9082,6 +9083,7 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
flags = btrfs_extent_flags(leaf, ei);
+ item_end = (unsigned long)ei + btrfs_item_size_nr(leaf, slot);
if (found_key.type == BTRFS_EXTENT_ITEM_KEY &&
!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK))
@@ -9099,6 +9101,15 @@ static int build_roots_info_cache(struct btrfs_fs_info *info)
}
/*
+ * It's a valid extent/metadata item that has no inline ref,
+ * but SHARED_BLOCK_REF or other shared references.
+ * So we need to do extra check to avoid reading beyond leaf
+ * boudnary.
+ */
+ if ((unsigned long)iref >= item_end)
+ goto next;
+
+ /*
* For a root extent, it must be of the following type and the
* first (and only one) iref in the item.
*/