FA-11581 / Filesystem semantics / Open access
Truncation rewinds an open file position · case 01
Truncation rewinds an open file position.
ROOT CAUSE
Changing file length is incorrectly coupled to changing the descriptor offset.
VERIFIED REPAIR
Resize contents while retaining the descriptor position even beyond new EOF.
Unsuccessful approach: Clamping the position to new EOF still changes a valid beyond-EOF offset.
Case contract
Deterministic in-memory filesystem model. Resize text to nonnegative size, filling growth with null characters, and return [new text, unchanged nonnegative offset].
Why this case matters
An offline semantic experiment for file API clients; it models only the stated operations, not a complete operating system.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(text, offset, size):
return [text[:size]+'\0'*max(0,size-len(text)),0]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shrink below current offset',solve('abcdef',N+6,2),['ab',N+6])
check('truncate to zero retains position',solve('abc',N,0),['',N])
check('growth retains position',solve('a',1,3),['a\0\0',1])
check('same size retains position',solve('abc',2,3),['abc',2])
check('position zero',solve('abc',0,1),['a',0])
check('empty growing file',solve('',N,1),['\0',N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| shrink below current offset | ['ab', 0] | ['ab', 7] | Failed |
| truncate to zero retains position | ['', 0] | ['', 1] | Failed |
| growth retains position | ['a\x00\x00', 0] | ['a\x00\x00', 1] | Failed |
| same size retains position | ['abc', 0] | ['abc', 2] | Failed |
| position zero | ['a', 0] | ['a', 0] | Passed |
| empty growing file | ['\x00', 0] | ['\x00', 1] | Failed |
SHA-256 / e90aaf101be6f410497802bf38597dc703b155b380a23d6b2f22524201c312c2
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(text, offset, size):
return [text[:size]+'\0'*max(0,size-len(text)),min(offset,size)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shrink below current offset',solve('abcdef',N+6,2),['ab',N+6])
check('truncate to zero retains position',solve('abc',N,0),['',N])
check('growth retains position',solve('a',1,3),['a\0\0',1])
check('same size retains position',solve('abc',2,3),['abc',2])
check('position zero',solve('abc',0,1),['a',0])
check('empty growing file',solve('',N,1),['\0',N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| shrink below current offset | ['ab', 2] | ['ab', 7] | Failed |
| truncate to zero retains position | ['', 0] | ['', 1] | Failed |
| growth retains position | ['a\x00\x00', 1] | ['a\x00\x00', 1] | Passed |
| same size retains position | ['abc', 2] | ['abc', 2] | Passed |
| position zero | ['a', 0] | ['a', 0] | Passed |
| empty growing file | ['\x00', 1] | ['\x00', 1] | Passed |
SHA-256 / 154b338e6572d53551defab5fa11e949a0f53e65fae398df96bcc8cab5f45de7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(text, offset, size):
return [text[:size]+'\0'*max(0,size-len(text)),offset]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('shrink below current offset',solve('abcdef',N+6,2),['ab',N+6])
check('truncate to zero retains position',solve('abc',N,0),['',N])
check('growth retains position',solve('a',1,3),['a\0\0',1])
check('same size retains position',solve('abc',2,3),['abc',2])
check('position zero',solve('abc',0,1),['a',0])
check('empty growing file',solve('',N,1),['\0',N])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| shrink below current offset | ['ab', 7] | ['ab', 7] | Passed |
| truncate to zero retains position | ['', 1] | ['', 1] | Passed |
| growth retains position | ['a\x00\x00', 1] | ['a\x00\x00', 1] | Passed |
| same size retains position | ['abc', 2] | ['abc', 2] | Passed |
| position zero | ['a', 0] | ['a', 0] | Passed |
| empty growing file | ['\x00', 1] | ['\x00', 1] | Passed |
SHA-256 / d23109b2abc7dfffe357c30cdea3a6239a078d32ed22019e0603a6550ff06fb9
Verification & scope
This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:38:49.217094+00:00.
Case digest / 2401341bb79e1fd9a6e1d722e4ad862825b90d6831966267bc10c7d87ecbf46a