Reject by-id transaction access from an environment that does not own the transaction
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 42/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- cpp, node.js, typescript
Research direction
Start with Store.getTxnId() in src/store.ts:1206 and the ownership/state handling in transaction_handle.cpp and transaction.cpp. Trace the by-id entry points listed in database.cpp, db_iterator.cpp, and transaction_log_handle.cpp, then compare with test/abandon-writes.test.ts. Done means cross-environment transaction access is covered by tests and is rejected consistently without weakening same-environment behavior.
Written by the indexing model from the issue text.
Description
A transaction created in one worker_threads environment can be reached from another environment by its id, and nothing orders that access against the owning environment or the commit lane. A RocksDB Transaction is not thread-safe, so a concurrent write through it is undefined behavior: heap corruption, or an acknowledged write that never lands.
Found while fixing the writesAbandoned data race in #876. That fix made one field well-defined; #884 rewrote the field's comment to say explicitly that the handle is not synchronized. This issue tracks the rest.
Mechanism
- Transaction ids resolve through the process-global
DBDescriptor(transactionGet(txnId)), shared by every environment that opens the path. Store.getTxnId()(src/store.ts:1206) only checks thattransaction.store.identityPathmatches the database. A{ transaction: { id, store: { identityPath } } }object built in another worker passes it.TransactionHandle::putSync/removeSyncthen read the plainstatefield (transaction_handle.cpp:783,:834). That read has no happens-before edge to the owner'sCommittingstore (transaction.cpp:976) or the commit lane'sCommittedstore (:648), so it can see a stalePending.- The foreign environment then calls
txn->Put/Deleteconcurrently with the lane'stxn->Commit()orresetTransaction(), or with the owner's own staging on its JS thread.
Affected entry points (by-id lookups on main)
| Entry point | Location |
|---|---|
Database::Get |
src/binding/database/database.cpp:1100 |
Database::GetCount |
database.cpp:1412 |
Database::GetSync |
database.cpp:1864 |
Database::PutSync |
database.cpp:2569 |
Database::RemoveSync |
database.cpp:2656 |
| transactional iterator setup | src/binding/iterator/db_iterator.cpp:165 |
TransactionLog.addEntry |
src/binding/transaction_log/transaction_log_handle.cpp:35 |
The writes are the corruption risk. The reads race the same txn against a concurrent commit or reset.
Suggested fix
Enforce the ownership invariant rather than adding atomics field by field: record the owning napi_env on TransactionHandle at creation, and reject a by-id lookup from any other environment at each entry point above (throwing, for example, ERR_TRANSACTION_WRONG_ENV). Doing this per field would still leave txn, the touched-family set and the VT intents unsynchronized.
Open question
Whether any supported caller, Harper in particular, passes transaction ids across workers is unverified. The reviewer who traced this expects not. If none does, rejection is safe. If one does, the fix has to serialize access instead.
Not covered by #876 / #884
test/abandon-writes.test.ts covers same-environment publication only. No test exercises by-id access from another environment.
- Dominant language
- C++
- Stars
- 24
- Forks
- 3
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 49
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from HarperFast/rocksdb-js
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
HarperFast/rocksdb-js#945 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
HarperFast/rocksdb-js#956 ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
HarperFast/rocksdb-js#955 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 45/100
HarperFast/rocksdb-js#952 ·
Maintainers usually reply within 1 day
-
Difficulty 4/5 1-2 days Newbie friendliness 45/100
HarperFast/rocksdb-js#946 ·
Maintainers usually reply within 1 day
All issues in HarperFast/rocksdb-js
Similar issues
-
Remove source files from packaging for deb, zip, etcPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
OpenSpace/OpenSpace#4353 · 1 comment ·
Maintainers usually reply within 5 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
justcallmekoko/ESP32Marauder#1656 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Decompiler: convertCharRef() in xml.y overflows its int4 accumulator on long character referencesPossibly taken @kaayzouee claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
NationalSecurityAgency/ghidra#10009 ·
Maintainers usually reply within 2 days