From 3f73d5625cf32f607941027b8c384dcfe6fd5a6f Mon Sep 17 00:00:00 2001 From: Hy Che Date: Tue, 14 Mar 2017 00:08:48 +0700 Subject: [PATCH] Fix crash when mounting btrfs volumes Found item has data offset higher than block size. Move the stream to get the data. If the data does not fit in the block, fetch it directly from the device. Signed-off-by: Adrien Destugues Fixes #12788. --- .../kernel/file_systems/btrfs/BPlusTree.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/file_systems/btrfs/BPlusTree.cpp b/src/add-ons/kernel/file_systems/btrfs/BPlusTree.cpp index 0f1bf0115d..b4d2dd6101 100644 --- a/src/add-ons/kernel/file_systems/btrfs/BPlusTree.cpp +++ b/src/add-ons/kernel/file_systems/btrfs/BPlusTree.cpp @@ -168,10 +168,22 @@ BPlusTree::_Find(struct btrfs_key &key, void** _value, size_t* _size, stream->entries[i].Offset(), stream->entries[i].Size()); if (_value != NULL) { *_value = malloc(stream->entries[i].Size()); - memcpy(*_value, ((uint8 *)&stream->entries[0] - + stream->entries[i].Offset()), - stream->entries[i].Size()); + uint32 totalOffset = stream->entries[i].Offset() + sizeof(btrfs_header); key.SetOffset(stream->entries[i].key.Offset()); + + if ((fVolume->BlockSize() - totalOffset % fVolume->BlockSize()) + >= stream->entries[i].Size()) { + //If there is enough space for *_value + stream = (btrfs_stream*)cached.SetTo(physical + + totalOffset / fVolume->BlockSize()); + memcpy(*_value, ((uint8 *)&stream->header + + totalOffset % fVolume->BlockSize()), + stream->entries[i].Size()); + } else { + read_pos(fVolume->Device(), physical + * fVolume->BlockSize() + totalOffset, + *_value, stream->entries[i].Size()); + } if (_size != NULL) *_size = stream->entries[i].Size(); }