FA-47481 / Delimited text / Open access
Text after a closing quote is silently discarded · case 01
A structured table violates the declared record or column contract.
ROOT CAUSE
The postquote state ignores forbidden suffix text.
VERIFIED REPAIR
Preserve the named invariant at the faulty decision: else: return None
Unsuccessful approach: Appending suffix text admits a malformed closing boundary.
Case contract
Lex one physical comma record. A quote opens only at field start; doubled quotes decode inside quoted fields; after a closing quote only comma or EOF is legal. CR/LF outside quoted fields reject. Return fields and quote-origin flags; a physical newline inside quoted text remains literal.
Why this case matters
Delimited interchange needs explicit framing, schema and field semantics at ingestion and emission boundaries.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
if value == '@END': return 3 + 4*N
if isinstance(value, str): return value.replace('@', 'cell' * N)
if isinstance(value, list): return [_vary(x) for x in value]
if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
return value
N = 1
observations = []
def solve(data):
result, buf, state, origin = [], [], 'start', False
for ch in data:
if state == 'quoted':
if ch == '"': state = 'closed'
else: buf.append(ch)
elif state == 'closed':
if ch == '"':
buf.append('"')
state = 'quoted'
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
else: pass
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
elif ch == '"':
if state != 'start': return None
state, origin = 'quoted', True
elif ch in '\r\n': return None
else:
buf.append(ch)
state = 'bare'
if state == 'quoted': return None
result.append([''.join(buf), origin])
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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 |
|---|---|---|---|
| quoted flags | [['cell', True], ['a', False]] | [['cell', True], ['a', False]] | Passed |
| doubled | [['a"b', True]] | [['a"b', True]] | Passed |
| triple ending | [['cell"', True]] | [['cell"', True]] | Passed |
| empty quoted | [['', True]] | [['', True]] | Passed |
| empty bare | [['', False]] | [['', False]] | Passed |
| suffix comma | [['cell', True], ['', False]] | [['cell', True], ['', False]] | Passed |
| bare quote | None | None | Passed |
| balanced quote suffix | None | None | Passed |
| junk closing | [['a', True]] | None | Failed |
| space closing | [['a', True]] | None | Failed |
| quoted newlines | [['a\nb', True]] | [['a\nb', True]] | Passed |
| quoted carriage return | [['a\rb', True]] | [['a\rb', True]] | Passed |
| unquoted newline | None | None | Passed |
| two quoted | [['a', True], ['b', True]] | [['a', True], ['b', True]] | Passed |
| unterminated | None | None | Passed |
| plain | [['cell', False], ['z', False]] | [['cell', False], ['z', False]] | Passed |
SHA-256 / 3d9b5b4fda5acb8ed8b80375320d194f072be9c586acf708267b1cf14be85902
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
if value == '@END': return 3 + 4*N
if isinstance(value, str): return value.replace('@', 'cell' * N)
if isinstance(value, list): return [_vary(x) for x in value]
if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
return value
N = 1
observations = []
def solve(data):
result, buf, state, origin = [], [], 'start', False
for ch in data:
if state == 'quoted':
if ch == '"': state = 'closed'
else: buf.append(ch)
elif state == 'closed':
if ch == '"':
buf.append('"')
state = 'quoted'
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
else: buf.append(ch)
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
elif ch == '"':
if state != 'start': return None
state, origin = 'quoted', True
elif ch in '\r\n': return None
else:
buf.append(ch)
state = 'bare'
if state == 'quoted': return None
result.append([''.join(buf), origin])
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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 |
|---|---|---|---|
| quoted flags | [['cell', True], ['a', False]] | [['cell', True], ['a', False]] | Passed |
| doubled | [['a"b', True]] | [['a"b', True]] | Passed |
| triple ending | [['cell"', True]] | [['cell"', True]] | Passed |
| empty quoted | [['', True]] | [['', True]] | Passed |
| empty bare | [['', False]] | [['', False]] | Passed |
| suffix comma | [['cell', True], ['', False]] | [['cell', True], ['', False]] | Passed |
| bare quote | None | None | Passed |
| balanced quote suffix | None | None | Passed |
| junk closing | [['ax', True]] | None | Failed |
| space closing | [['a ', True]] | None | Failed |
| quoted newlines | [['a\nb', True]] | [['a\nb', True]] | Passed |
| quoted carriage return | [['a\rb', True]] | [['a\rb', True]] | Passed |
| unquoted newline | None | None | Passed |
| two quoted | [['a', True], ['b', True]] | [['a', True], ['b', True]] | Passed |
| unterminated | None | None | Passed |
| plain | [['cell', False], ['z', False]] | [['cell', False], ['z', False]] | Passed |
SHA-256 / bc1f9ce89cbf02579843fddca9e4c9216ae92be694ab37ffae06a63863bf3394
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
def _vary(value):
if value == '@END': return 3 + 4*N
if isinstance(value, str): return value.replace('@', 'cell' * N)
if isinstance(value, list): return [_vary(x) for x in value]
if isinstance(value, dict): return {_vary(k): _vary(v) for k,v in value.items()}
return value
N = 1
observations = []
def solve(data):
result, buf, state, origin = [], [], 'start', False
for ch in data:
if state == 'quoted':
if ch == '"': state = 'closed'
else: buf.append(ch)
elif state == 'closed':
if ch == '"':
buf.append('"')
state = 'quoted'
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
else: return None
elif ch == ',':
result.append([''.join(buf), origin])
buf, state, origin = [], 'start', False
elif ch == '"':
if state != 'start': return None
state, origin = 'quoted', True
elif ch in '\r\n': return None
else:
buf.append(ch)
state = 'bare'
if state == 'quoted': return None
result.append([''.join(buf), origin])
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('quoted flags', solve(_vary('"@",a')), _vary([['@', True], ['a', False]]))
check('doubled', solve(_vary('"a""b"')), _vary([['a"b', True]]))
check('triple ending', solve(_vary('"@"""')), _vary([['@"', True]]))
check('empty quoted', solve(_vary('""')), _vary([['', True]]))
check('empty bare', solve(_vary('')), _vary([['', False]]))
check('suffix comma', solve(_vary('"@",')), _vary([['@', True], ['', False]]))
check('bare quote', solve(_vary('a"b')), _vary(None))
check('balanced quote suffix', solve(_vary('a"b"')), _vary(None))
check('junk closing', solve(_vary('"a"x')), _vary(None))
check('space closing', solve(_vary('"a" ')), _vary(None))
check('quoted newlines', solve(_vary('"a\nb"')), _vary([['a\nb', True]]))
check('quoted carriage return', solve(_vary('"a\rb"')), _vary([['a\rb', True]]))
check('unquoted newline', solve(_vary('a\nb')), _vary(None))
check('two quoted', solve(_vary('"a","b"')), _vary([['a', True], ['b', True]]))
check('unterminated', solve(_vary('"a')), _vary(None))
check('plain', solve(_vary('@,z')), _vary([['@', False], ['z', False]]))
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 |
|---|---|---|---|
| quoted flags | [['cell', True], ['a', False]] | [['cell', True], ['a', False]] | Passed |
| doubled | [['a"b', True]] | [['a"b', True]] | Passed |
| triple ending | [['cell"', True]] | [['cell"', True]] | Passed |
| empty quoted | [['', True]] | [['', True]] | Passed |
| empty bare | [['', False]] | [['', False]] | Passed |
| suffix comma | [['cell', True], ['', False]] | [['cell', True], ['', False]] | Passed |
| bare quote | None | None | Passed |
| balanced quote suffix | None | None | Passed |
| junk closing | None | None | Passed |
| space closing | None | None | Passed |
| quoted newlines | [['a\nb', True]] | [['a\nb', True]] | Passed |
| quoted carriage return | [['a\rb', True]] | [['a\rb', True]] | Passed |
| unquoted newline | None | None | Passed |
| two quoted | [['a', True], ['b', True]] | [['a', True], ['b', True]] | Passed |
| unterminated | None | None | Passed |
| plain | [['cell', False], ['z', False]] | [['cell', False], ['z', False]] | Passed |
SHA-256 / bac48864035b7b80055290c2dab4772ec827a8f19a1edf5dceabcc1205a99283
Verification & scope
Deterministic bounded in-memory model. No claim of complete CSV or external format conformance. 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:44:41.839564+00:00.
Case digest / 3abbe04366d9ee9a429f78010473cc012a8a8b5a7ddc3288cdd2395acfce087a