btrfs return errors on panic, add memory deleter to ReadAt()
* Additional return BAD_DATA after error conditions encountered when attempting to decompress BTRFS extents. * MemoryDeleter for extent_data added to ReadAt() preventing double-free after error. Change-Id: Ib9f8e9723d3fb6aaff8e69dbb66cd279e86f226b Reviewed-on: https://review.haiku-os.org/c/1045 Reviewed-by: Stephan Aßmus <[email protected]>
This commit is contained in:
@@ -240,27 +240,31 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
|
|||||||
"\n", status);
|
"\n", status);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
MemoryDeleter deleter(extent_data);
|
||||||
|
|
||||||
|
|
||||||
uint8 compression = extent_data->Compression();
|
uint8 compression = extent_data->Compression();
|
||||||
if (FileCache() != NULL
|
if (FileCache() != NULL
|
||||||
&& extent_data->Type() == BTRFS_EXTENT_DATA_REGULAR) {
|
&& extent_data->Type() == BTRFS_EXTENT_DATA_REGULAR) {
|
||||||
TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %" B_PRIdOFF ", length %lu)\n",
|
TRACE("inode %" B_PRIdINO ": ReadAt cache (pos %" B_PRIdOFF ", length %lu)\n",
|
||||||
ID(), pos, length);
|
ID(), pos, length);
|
||||||
free(extent_data);
|
|
||||||
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
||||||
return file_cache_read(FileCache(), NULL, pos, buffer, _length);
|
return file_cache_read(FileCache(), NULL, pos, buffer, _length);
|
||||||
else if (compression == BTRFS_EXTENT_COMPRESS_ZLIB)
|
else if (compression == BTRFS_EXTENT_COMPRESS_ZLIB)
|
||||||
panic("zlib isn't unsupported for regular extent\n");
|
panic("zlib isn't unsupported for regular extent\n");
|
||||||
else
|
else
|
||||||
panic("unknown extent compression; %d\n", compression);
|
panic("unknown extent compression; %d\n", compression);
|
||||||
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Inode::ReadAt(%" B_PRIdINO ") key.Offset() %" B_PRId64 "\n", ID(),
|
TRACE("Inode::ReadAt(%" B_PRIdINO ") key.Offset() %" B_PRId64 "\n", ID(),
|
||||||
search_key.Offset());
|
search_key.Offset());
|
||||||
|
|
||||||
off_t diff = pos - search_key.Offset();
|
off_t diff = pos - search_key.Offset();
|
||||||
if (extent_data->Type() != BTRFS_EXTENT_DATA_INLINE)
|
if (extent_data->Type() != BTRFS_EXTENT_DATA_INLINE) {
|
||||||
panic("unknown extent type; %d\n", extent_data->Type());
|
panic("unknown extent type; %d\n", extent_data->Type());
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
*_length = min_c(extent_data->Size() - diff, *_length);
|
*_length = min_c(extent_data->Size() - diff, *_length);
|
||||||
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
if (compression == BTRFS_EXTENT_COMPRESS_NONE)
|
||||||
@@ -313,7 +317,6 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
|
|||||||
|
|
||||||
status = inflateInit2(&zStream, 15);
|
status = inflateInit2(&zStream, 15);
|
||||||
if (status != Z_OK) {
|
if (status != Z_OK) {
|
||||||
free(extent_data);
|
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -335,14 +338,15 @@ Inode::ReadAt(off_t pos, uint8* buffer, size_t* _length)
|
|||||||
|
|
||||||
if (status != Z_STREAM_END) {
|
if (status != Z_STREAM_END) {
|
||||||
TRACE("Inode::ReadAt() inflating failed: %d!\n", status);
|
TRACE("Inode::ReadAt() inflating failed: %d!\n", status);
|
||||||
free(extent_data);
|
|
||||||
return B_BAD_DATA;
|
return B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
*_length = zStream.total_out;
|
*_length = zStream.total_out;
|
||||||
|
|
||||||
} else
|
} else {
|
||||||
panic("unknown extent compression; %d\n", compression);
|
panic("unknown extent compression; %d\n", compression);
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
free(extent_data);
|
free(extent_data);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user