EigenStore reads bypass trace/replay and silently use changed live data under strict replay
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 5/5
- 预计耗时
- 一周以上
- 新手友好度
- 48/100
- Issue 类型
- 缺陷
- 描述清晰度
- 基本清楚
- 活跃度
- 活跃
调研方向
Start in src/ext_store.c at builtin_store_open and builtin_store_get, then read docs/TRACE.md and policy precedent #148. Run the provided Python reproduction from the checkout root and inspect replay coverage around store_open and store_get. Done means the chosen store replay boundary prevents changed or newly created live data, preserves persistence, documents the boundary in docs/TRACE.md, and adds regression coverage.
由索引模型根据 Issue 内容生成。
描述
EigenStore reads are neither recorded nor refused during replay. The same program prints a different stored value after the database changes, even with EIGS_REPLAY_STRICT=1, and exits successfully without a warning.
Severity: major correctness issue for deterministic debugging. This is separate from the existing trace threading/ownership issues: the reproduction is single-threaded, uses one database handle, and needs no malformed input.
Reproduction
Confirmed from a fresh default make build of b91768e23c5a874a64e76e4af9ab291e6aa49983. Run this from that checkout's root; all database/tape files are created in a unique temporary directory:
python3 - <<'PY'
import json, os, pathlib, subprocess, tempfile
binary = str(pathlib.Path('src/eigenscript').resolve())
scratch = pathlib.Path(tempfile.mkdtemp(prefix='eigs-store-replay-'))
db = json.dumps(str(scratch / 'probe.db'))
tape = str(scratch / 'run.tape')
base = {k:v for k,v in os.environ.items() if not k.startswith('EIGS_')}
def run(source, **extra):
p = subprocess.run([binary, '-e', source], env=base | extra,
text=True, capture_output=True, timeout=10)
print(p.returncode, repr(p.stdout), repr(p.stderr))
run(f'db is store_open of {db}\nstore_put of [db, "config", {{"_id":"answer","value":10}}]\nstore_close of db\n')
reader = f'db is store_open of {db}\nr is store_get of [db, "config", "answer"]\nprint of r.value\nstore_close of db\n'
run(reader, EIGS_TRACE=tape)
run(f'db is store_open of {db}\nstore_update of [db, "config", "answer", {{"_id":"answer","value":20}}]\nstore_close of db\n')
run(reader, EIGS_REPLAY=tape, EIGS_REPLAY_STRICT='1')
print('N records:', sum(line.startswith('N ') for line in pathlib.Path(tape).read_text().splitlines()))
PY
Actual:
0 '' ''
0 '10\n' ''
0 '' ''
0 '20\n' ''
N records: 0
Expected: replay returns the recorded observation (10), or the store operation raises a clear non-replayable-boundary error before accessing live storage. Silently substituting 20 is neither outcome.
Cause and scope
src/ext_store.c opens the real database in builtin_store_open and reads its current contents in builtin_store_get; it has no trace-record/take hooks or replay refusal. docs/TRACE.md promises replayed nondeterministic inputs and explicitly refuses unsupported subprocess/channel operations, but gives EigenStore no such boundary.
EIGS_REPLAY_STRICT currently checks names on consumed N records. Here there are no N records, so enabling it cannot detect the gap. This report does not claim that strict mode promises a general program-equivalence check.
Define the store's replay boundary as a family: either support logical recorded results and handle lifetime without relying on a live database, or reject unsupported store operations during replay. Simply taping a live handle ID is not sufficient. The minimal confirmed case is store_open + store_get; adjacent queries and writes should be audited when choosing that boundary.
Regression acceptance
- Record a read, change the stored value, then replay the same program. Require recorded output or the explicit refusal, never the changed live value with exit 0.
- Cover a missing database at replay time and confirm the chosen boundary cannot silently create/use a new database.
- Preserve ordinary store persistence behavior and existing replay behavior outside the store.
- Document the boundary in
docs/TRACE.mdand add the real store case to replay coverage.
Related policy precedent: #148. No implementation change is included in this report.
- 主要语言
- C
- 星标
- 3
- 派生
- 7
- 平均合并
- 4 小时 15 分钟
- 30 天内合并 PR
- 106
环境准备
在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。
- 提供 Dockerfile 或 Docker Compose 文件
- 有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
InauguralSystems/EigenScript 的其他 Issue
-
area:lint-tooling bug
难度 2/5 1-3 小时 新手友好度 88/100
InauguralSystems/EigenScript#1340 ·
维护者通常 1 天内回复
-
area:stdlib found-by:code-review kind:silent-wrong
难度 2/5 1-3 小时 新手友好度 88/100
InauguralSystems/EigenScript#1338 ·
维护者通常 1 天内回复
-
area:lint-tooling found-by:critic kind:docs-drift
难度 2/5 1-3 小时 新手友好度 76/100
InauguralSystems/EigenScript#1335 ·
维护者通常 1 天内回复
-
area:ci found-by:critic kind:gate-defect
难度 2/5 1-3 小时 新手友好度 86/100
InauguralSystems/EigenScript#1311 ·
维护者通常 1 天内回复
-
enrolment: decide test_gc_runner_controls.py (exempt vs enrol) and whether floors need a ratchet未关闭area:gates found-by:critic kind:decision
难度 2/5 1-3 小时 新手友好度 65/100
InauguralSystems/EigenScript#1280 · 1 条评论 ·
维护者通常 1 天内回复
查看 InauguralSystems/EigenScript 的全部 Issue
相似的 Issue
-
bug needs triage
难度 2/5 1-3 小时 新手友好度 78/100
netdata/netdata#24062 · 1 条评论 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
-
难度 2/5 1-3 小时 新手友好度 88/100
riscv-software-src/riscv-isa-sim#2448 ·
维护者通常 2 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
-
难度 1/5 1 小时以内 新手友好度 75/100
NabuCasa/silabs-firmware-builder#231 · 1 条评论 ·