GHSA-m9qr-4rcq-3jhc json
Data race and double free via unsound `Send`/`Sync` in `reblessive`
published 2026-11-03 5 d ago modified 2026-11-06 2 d ago also RUSTSEC-2026-0454
- cvss
- 7.8
- version 3.1, OSV
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
`dbs::Executor` drives every SurrealQL statement through `reblessive::tree::TreeStack`. In `reblessive 0.4.3` the runtime types unconditionally assert `Send`/`Sync` (`unsafe impl Send/Sync for Stack`, `TreeStack` and `Runner`), while the public entry points accept any future without a `Send` bound and store it type-erased in a bump allocator.
Two safe-code consequences follow. First, `Runner::step_async`/`finish_async` return driver futures tied to the stack borrow rather than to `&mut self`, so a driver future can be duplicated; because `Stack` is `Sync` those futures are `Send`, and polling two copies on different threads runs `drive_top_task` concurrently — racy `Cell`/`UnsafeCell` access, double `pop_task()`/`pop_dealloc()` (double drop / double free) and a non-atomic `Option::take`. Second, `TreeStack: Send` lets safe code move a driver whose type-erased future captures `!Send` state (`Rc`, `RefCell`) to another thread while the creating thread keeps an alias of that state.
No `unsafe` is needed at the call site. `surrealdb-core`'s own query futures are `Send` only because of the unsound `unsafe impl Send for TreeStack`, while the captured `&mut tree::Stk` is deliberately `!Send`.
The unsound dependency was removed in 4.0.0 and the parser now uses plain recursion (commit `75407c4bcc`).
Patch / fix
CVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| OSV | 3.1 | 7.8 | CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| crates.io | surrealdb-core | >=0.0.0-0, <4.0.0 |
4.0.0 |
References
Sources
Fencer Vulns keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.