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:
Rob Gill
2019-02-15 08:20:09 +00:00
committed by Stephan Aßmus
parent b6adef8501
commit efac84e790
@@ -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;