On Thu, Aug 08, 2019 at 11:55:37PM +0000, WenRuo Qu wrote:
>
>
> On 2019/8/8 下午10:54, David Sterba wrote:
> > On Wed, Aug 07, 2019 at 10:08:41PM +0800, Qu Wenruo wrote:
> >> +
> >> +static int check_extent_item(struct extent_buffer *leaf,
> >> + struct btrfs_key *key, int slot)
> >> +{
> >> + struct btrfs_fs_info *fs_info = leaf->fs_info;
> >> + struct btrfs_extent_item *ei;
> >> + bool is_tree_block = false;
> >> + u64 ptr; /* Current pointer inside inline refs */
> >
> > While u64 is wide enough, I suggest to use unsigned long as the
> > intermediate type for pointer conversions.
>
> In fact, we only need u32 for pointer.
> (u16 is enough for 0~64k-1 but I'm not sure if we would use 64K as offset)
>
> So regular unsigned int should be enough?
No, ther's pointer arithmetic done, u32 is not guaranteed to contain a
pointer:
+ ptr = (u64)(struct btrfs_extent_item *)(ei + 1);
here
+
+ /* Check the special case of btrfs_tree_block_info */
+ if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) {
+ struct btrfs_tree_block_info *info;
+
+ info = (struct btrfs_tree_block_info *)ptr;
and here
+ if (btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL) {
+ extent_err(leaf, slot,
+ "invalid tree block info level, have %u expect [0, %u]",
+ btrfs_tree_block_level(leaf, info),
+ BTRFS_MAX_LEVEL - 1);
+ return -EUCLEAN;
+ }
+ ptr = (u64)(struct btrfs_tree_block_info *)(info + 1);
etc
+ }