summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZach Brown <zab@redhat.com>2013-01-17 13:24:35 -0800
committerZach Brown <zab@redhat.com>2013-02-05 16:09:38 -0800
commit968efc6f988623aff2b4c21af8317ec80836a4b9 (patch)
treefb153f57b5134c2255e61911954469b619b1f9f7
parentea0ac9416fd13b7e20899d8c7c130e5375171ea6 (diff)
btrfs-progs: more carefully check eb backrefs
check_owner_ref() could deref a null path node if btrfs_search_slot() fails or simply doesn't find a tree tall enough to get to the parent of the desired block. This was flagged by static analysis warning that btrfs_search_slot()'s return value wasn't being checked. Signed-off-by: Zach Brown <zab@redhat.com> Again: caught by static analysis.
-rw-r--r--btrfsck.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/btrfsck.c b/btrfsck.c
index dd0f18bf..d292540d 100644
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -1970,8 +1970,10 @@ static int check_owner_ref(struct btrfs_root *root,
struct btrfs_root *ref_root;
struct btrfs_key key;
struct btrfs_path path;
+ struct extent_buffer *parent;
int level;
int found = 0;
+ int ret;
list_for_each_entry(node, &rec->backrefs, list) {
if (node->is_data)
@@ -2002,10 +2004,13 @@ static int check_owner_ref(struct btrfs_root *root,
btrfs_init_path(&path);
path.lowest_level = level + 1;
- btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0);
+ ret = btrfs_search_slot(NULL, ref_root, &key, &path, 0, 0);
+ if (ret < 0)
+ return 0;
- if (buf->start == btrfs_node_blockptr(path.nodes[level + 1],
- path.slots[level + 1]))
+ parent = path.nodes[level + 1];
+ if (parent && buf->start == btrfs_node_blockptr(parent,
+ path.slots[level + 1]))
found = 1;
btrfs_release_path(ref_root, &path);