BFS: Propagate errors from CachedNode::InternalSetTo properly.

Otherwise, SetTo() might return B_OK when fNode is really NULL,
leading to crashes later when something tries to use the block.

Fixes #14762.
This commit is contained in:
Augustin Cavalier
2026-02-24 21:05:21 -05:00
parent 6084727f52
commit a2443366d9
2 changed files with 22 additions and 10 deletions
@@ -314,7 +314,11 @@ CachedNode::SetTo(off_t offset, const bplustree_node** _node, bool check)
RETURN_ERROR(B_BAD_VALUE);
}
if (InternalSetTo(NULL, offset) != NULL && check) {
status_t status = InternalSetTo(NULL, offset);
if (status != B_OK)
return status;
if (check) {
// sanity checks (links, all_key_count)
if (!fTree->fHeader.CheckNode(fNode)) {
FATAL(("invalid node [%p] read from offset %" B_PRIdOFF " (block %"
@@ -349,7 +353,10 @@ CachedNode::SetToWritable(Transaction& transaction, off_t offset, bool check)
return NULL;
}
if (InternalSetTo(&transaction, offset) != NULL && check) {
if (InternalSetTo(&transaction, offset) != B_OK)
return NULL;
if (check) {
// sanity checks (links, all_key_count)
if (!fTree->fHeader.CheckNode(fNode)) {
FATAL(("invalid node [%p] read from offset %" B_PRIdOFF " (block %"
@@ -420,15 +427,20 @@ CachedNode::SetToWritableHeader(Transaction& transaction)
#endif // !_BOOT_MODE
bplustree_node*
status_t
CachedNode::InternalSetTo(Transaction* transaction, off_t offset)
{
if (offset >= fTree->fStream->Size()) {
Unset();
RETURN_ERROR(B_BAD_VALUE);
}
off_t fileOffset;
block_run run;
if (offset >= fTree->fStream->Size()
|| fTree->fStream->FindBlockRun(offset, run, fileOffset) != B_OK) {
status_t status = fTree->fStream->FindBlockRun(offset, run, fileOffset);
if (status != B_OK) {
Unset();
return NULL;
return status;
}
#if !_BOOT_MODE
@@ -461,7 +473,7 @@ CachedNode::InternalSetTo(Transaction* transaction, off_t offset)
if (fBlock == NULL) {
fBlock = (uint8*)malloc(volume->BlockSize());
if (fBlock == NULL)
return NULL;
RETURN_ERROR(B_NO_MEMORY);
}
if (read_pos(volume->Device(), newBlockNumber << volume->BlockShift(),
@@ -483,10 +495,10 @@ CachedNode::InternalSetTo(Transaction* transaction, off_t offset)
- (fileOffset + (blockOffset << volume->BlockShift())));
} else {
fNode = NULL;
REPORT_ERROR(B_IO_ERROR);
RETURN_ERROR(B_IO_ERROR);
}
return fNode;
return B_OK;
}
@@ -230,7 +230,7 @@ public:
bplustree_node* Node() const { return fNode; }
protected:
bplustree_node* InternalSetTo(Transaction* transaction,
status_t InternalSetTo(Transaction* transaction,
off_t offset);
BPlusTree* fTree;