`Tx.Check` can hang or dereference invalid pages when branch references are corrupt
- Dominant language
- Go
- Stars
- 9.7k
- Forks
- 753
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 18
Description
## Description
I was experimenting with the bbolt source code and intentionally corrupted
database files when I noticed two cases where `Tx.Check` does not handle
corrupt branch-page references safely.
I wrote two test cases that reproduce the problems:
1. A branch page references an already visited page, forming a cycle.
2. A branch page references a page ID equal to the database high-water mark.
Both tests currently fail.
## Cyclic page reference
The reachability check detects that a page has multiple references, but the
page traversal continues descending into it.
For example, a branch page might reference itself:
```text
root page → root page
```
Or several pages might form a longer cycle:
```
A → B → C → A
```
In either case, the checker repeatedly follows the cycle. The goroutine running
Tx.Check never finishes, leaving callers waiting indefinitely while ranging
over the error channel.
## Out-of-bounds branch reference
The recursive traversal dereferences branch page IDs before validating them
against `tx.meta.Pgid()`.
The second test sets a branch reference to the database high-water mark. This
is invalid because valid page IDs must be below that value. Instead of returning
a clear out of bounds error, the checker attempts to load the page and may
report a recovered panic or another validation error.
The page ID should be checked before it is dereferenced, using
`pageID >= hwm` as the invalid boundary condition.
I also found [#877: Check of corrupted file deadlocks](https://github.com/etcd-io/bbolt/issues/877), which looks related because it also reports `Tx.Check` hanging on a corrupted database. However, I’m not sure whether it has the same underlying cause.
I have a proposed fix along with two regression tests. Once it is open, I will link it here. Thanks!
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with Tx.Check and the two regression tests described in the issue. Trace branch-page traversal and verify that already visited pages do not trigger further descent, while page IDs at or above tx.meta.Pgid() are rejected before dereferencing. Done means both tests pass, cyclic references terminate, and the out-of-bounds case reports a clear validation error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100