FAILURE MAP
← Case archive

FA-53426 / Accessibility interaction semantics / Open access

Negative range starts are measured from zero · case 01

Negative range starts are measured from zero.

Verified by executionVariant 1 · 10 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The negative origin start decision in the text range bridge adapter violates its declared contract.

VERIFIED REPAIR

Apply the exact contract at the negative origin start decision: if start < 0: start += size

Unsuccessful approach: The local repair substitutes if start < -size: start = 0 but still mishandles the regression fixtures.

Case contract

Input [text,start,end,unit] where indices are measured in utf16 or codepoint units. Negative indices count backward from end, clamp to valid extent, and sort reversed endpoints. A boundary inside a surrogate pair expands outward (start down, end up). CRLF is exposed as one LF after slicing. NUL becomes replacement character. Return [exposed_text,normalized_start,normalized_end,source_units]. UTF16 offsets refer to original source, not normalized text.

Why this case matters

Offline accessibility bridge model with explicit policy; useful for testing semantic API adapters independently of browser implementations.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,start,end,unit = data
    widths = [2 if unit == 'utf16' and ord(c) > 65535 else 1 for c in text]
    edges = [0]
    for width in widths: edges.append(edges[-1]+width)
    size = edges[-1]
    if start < 0: start = 0
    if end < 0: end += size
    start = min(size,max(0,start))
    end = min(size,max(0,end))
    if start > end: start,end = end,start
    left = max(i for i,x in enumerate(edges) if x <= start)
    right = min(i for i,x in enumerate(edges) if x >= end)
    snippet = text[left:right].replace('\r\n','\n').replace('\x00','\ufffd')
    return [snippet,edges[left],edges[right],size]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('surrogate interior expands', solve(['A'*N+'😀Z',N+1,N+2,'utf16'],), ['😀',N,N+2,N+3])
check('negative start', solve(['A'*N+'BC',-2,N+2,'codepoint'],), ['BC',N,N+2,N+2])
check('negative end', solve(['A'*N+'BC',N,-1,'codepoint'],), ['B',N,N+1,N+2])
check('clamp both', solve(['AB',-20,40,'utf16'],), ['AB',0,2,2])
check('reverse', solve(['ABCDE',4,1,'codepoint'],), ['BCD',1,4,5])
check('CRLF normalization', solve(['A\r\nB',0,4,'utf16'],), ['A\nB',0,4,4])
check('NUL replacement', solve(['A\x00B',0,3,'utf16'],), ['A�B',0,3,3])
check('codepoint emoji', solve(['😀B',1,2,'codepoint'],), ['B',1,2,2])
check('empty', solve(['',0,0,'utf16'],), ['',0,0,0])
check('surrogate end expands', solve(['A😀Z',0,2,'utf16'],), ['A😀',0,3,4])
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 fixtureActualExpectedOutcome
surrogate interior expands['😀', 1, 3, 4]['😀', 1, 3, 4]Passed
negative start['ABC', 0, 3, 3]['BC', 1, 3, 3]Failed
negative end['B', 1, 2, 3]['B', 1, 2, 3]Passed
clamp both['AB', 0, 2, 2]['AB', 0, 2, 2]Passed
reverse['BCD', 1, 4, 5]['BCD', 1, 4, 5]Passed
CRLF normalization['A\nB', 0, 4, 4]['A\nB', 0, 4, 4]Passed
NUL replacement['A�B', 0, 3, 3]['A�B', 0, 3, 3]Passed
codepoint emoji['B', 1, 2, 2]['B', 1, 2, 2]Passed
empty['', 0, 0, 0]['', 0, 0, 0]Passed
surrogate end expands['A😀', 0, 3, 4]['A😀', 0, 3, 4]Passed

SHA-256 / 2c24eb29778cdda6c6b63c0c3d7d9a5992fc5d990d6293356a232111e6bcb6bd

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,start,end,unit = data
    widths = [2 if unit == 'utf16' and ord(c) > 65535 else 1 for c in text]
    edges = [0]
    for width in widths: edges.append(edges[-1]+width)
    size = edges[-1]
    if start < -size: start = 0
    if end < 0: end += size
    start = min(size,max(0,start))
    end = min(size,max(0,end))
    if start > end: start,end = end,start
    left = max(i for i,x in enumerate(edges) if x <= start)
    right = min(i for i,x in enumerate(edges) if x >= end)
    snippet = text[left:right].replace('\r\n','\n').replace('\x00','\ufffd')
    return [snippet,edges[left],edges[right],size]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('surrogate interior expands', solve(['A'*N+'😀Z',N+1,N+2,'utf16'],), ['😀',N,N+2,N+3])
check('negative start', solve(['A'*N+'BC',-2,N+2,'codepoint'],), ['BC',N,N+2,N+2])
check('negative end', solve(['A'*N+'BC',N,-1,'codepoint'],), ['B',N,N+1,N+2])
check('clamp both', solve(['AB',-20,40,'utf16'],), ['AB',0,2,2])
check('reverse', solve(['ABCDE',4,1,'codepoint'],), ['BCD',1,4,5])
check('CRLF normalization', solve(['A\r\nB',0,4,'utf16'],), ['A\nB',0,4,4])
check('NUL replacement', solve(['A\x00B',0,3,'utf16'],), ['A�B',0,3,3])
check('codepoint emoji', solve(['😀B',1,2,'codepoint'],), ['B',1,2,2])
check('empty', solve(['',0,0,'utf16'],), ['',0,0,0])
check('surrogate end expands', solve(['A😀Z',0,2,'utf16'],), ['A😀',0,3,4])
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 fixtureActualExpectedOutcome
surrogate interior expands['😀', 1, 3, 4]['😀', 1, 3, 4]Passed
negative start['ABC', 0, 3, 3]['BC', 1, 3, 3]Failed
negative end['B', 1, 2, 3]['B', 1, 2, 3]Passed
clamp both['AB', 0, 2, 2]['AB', 0, 2, 2]Passed
reverse['BCD', 1, 4, 5]['BCD', 1, 4, 5]Passed
CRLF normalization['A\nB', 0, 4, 4]['A\nB', 0, 4, 4]Passed
NUL replacement['A�B', 0, 3, 3]['A�B', 0, 3, 3]Passed
codepoint emoji['B', 1, 2, 2]['B', 1, 2, 2]Passed
empty['', 0, 0, 0]['', 0, 0, 0]Passed
surrogate end expands['A😀', 0, 3, 4]['A😀', 0, 3, 4]Passed

SHA-256 / b4d2a71b554ab49f1e39535bef9d38dcaa862623d0314b114cfd6c6405ae6dfb

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,start,end,unit = data
    widths = [2 if unit == 'utf16' and ord(c) > 65535 else 1 for c in text]
    edges = [0]
    for width in widths: edges.append(edges[-1]+width)
    size = edges[-1]
    if start < 0: start += size
    if end < 0: end += size
    start = min(size,max(0,start))
    end = min(size,max(0,end))
    if start > end: start,end = end,start
    left = max(i for i,x in enumerate(edges) if x <= start)
    right = min(i for i,x in enumerate(edges) if x >= end)
    snippet = text[left:right].replace('\r\n','\n').replace('\x00','\ufffd')
    return [snippet,edges[left],edges[right],size]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('surrogate interior expands', solve(['A'*N+'😀Z',N+1,N+2,'utf16'],), ['😀',N,N+2,N+3])
check('negative start', solve(['A'*N+'BC',-2,N+2,'codepoint'],), ['BC',N,N+2,N+2])
check('negative end', solve(['A'*N+'BC',N,-1,'codepoint'],), ['B',N,N+1,N+2])
check('clamp both', solve(['AB',-20,40,'utf16'],), ['AB',0,2,2])
check('reverse', solve(['ABCDE',4,1,'codepoint'],), ['BCD',1,4,5])
check('CRLF normalization', solve(['A\r\nB',0,4,'utf16'],), ['A\nB',0,4,4])
check('NUL replacement', solve(['A\x00B',0,3,'utf16'],), ['A�B',0,3,3])
check('codepoint emoji', solve(['😀B',1,2,'codepoint'],), ['B',1,2,2])
check('empty', solve(['',0,0,'utf16'],), ['',0,0,0])
check('surrogate end expands', solve(['A😀Z',0,2,'utf16'],), ['A😀',0,3,4])
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 fixtureActualExpectedOutcome
surrogate interior expands['😀', 1, 3, 4]['😀', 1, 3, 4]Passed
negative start['BC', 1, 3, 3]['BC', 1, 3, 3]Passed
negative end['B', 1, 2, 3]['B', 1, 2, 3]Passed
clamp both['AB', 0, 2, 2]['AB', 0, 2, 2]Passed
reverse['BCD', 1, 4, 5]['BCD', 1, 4, 5]Passed
CRLF normalization['A\nB', 0, 4, 4]['A\nB', 0, 4, 4]Passed
NUL replacement['A�B', 0, 3, 3]['A�B', 0, 3, 3]Passed
codepoint emoji['B', 1, 2, 2]['B', 1, 2, 2]Passed
empty['', 0, 0, 0]['', 0, 0, 0]Passed
surrogate end expands['A😀', 0, 3, 4]['A😀', 0, 3, 4]Passed

SHA-256 / 7eaa050111be90c437ec742e294457f17a16a44e622078e38a0dd32f96a504e1

Verification & scope

Stipulated finite adapter contract, not a claim of platform accessibility or ARIA 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:45:38.783749+00:00.

Case digest / 60de8c6cff1e7d7beb7e0db7d5c335c8eeea6ba185e4a0074ba97c3969675aac