FAILURE MAP
← Case archive

FA-79366 / Barcode symbology encoding / Open access

EAN-13 encoder accepts non-ASCII digits · case 01

Full-width or Arabic-Indic digits pasted from documents are encoded as if they were ASCII.

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

ROOT CAUSE

Only the length is validated and int() accepts any Unicode decimal digit.

VERIFIED REPAIR

Require each character to be one of the ASCII digits 0-9.

Unsuccessful approach: str.isdigit also accepts Unicode digits.

Case contract

Encode a 13-character string of ASCII digits (the check digit is taken as given, not verified) as the 95-module EAN-13 pattern: start guard 101, six left digits in L or G sets chosen by the parity row of the leading digit, centre guard 01010, six right digits in the R set, end guard 101. R is the bitwise complement of L and G is R reversed. Anything else returns None.

Why this case matters

Retail, logistics, pharmacy and document workflows depend on encoders that produce exactly the module pattern, code-set switches, separators and quiet zones scanners expect; one misplaced module or separator makes a label unreadable or, worse, scan as different data.

1 / The failure

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

N = 1
observations = []
def solve(code):
    if len(code) != 13:
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    R = [''.join('1' if b == '0' else '0' for b in p) for p in L]
    G = [p[::-1] for p in R]
    parity = ['LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG', 'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL']
    pat = parity[int(code[0])]
    left = ''.join((L if pat[i] == 'L' else G)[int(code[1 + i])] for i in range(6))
    right = ''.join(R[int(ch)] for ch in code[7:])
    return '101' + left + '01010' + right + '101'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['4006381333931', None], ['12345678901٣2', None], ['5569719879594', '10101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101'], ['5564657964331', '10101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101'], ['8708854500750', '10101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101'], ['3339552094472', '10101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101'], ['2923603435282', '10100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101'], ['8535822111223', '10101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101']], [['12345678901٣2', None], ['4006381333931', None], ['0777861705172', '10101110110111011011101101101110101111001100101010100010011100101001110110011010001001101100101'], ['6141838617595', '10100110010011101011001100010010111101011011101010101000011001101000100100111011101001001110101'], ['8738417160350', '10101110110100001011011100111010110011011101101010110011010100001110010100001010011101110010101'], ['3766842531699', '10101110110101111000010100010010011101001001101010100111010000101100110101000011101001110100101'], ['5117058572420', '10100110010110011001000100011010110001000100101010100111010001001101100101110011011001110010101'], ['4971457247264', '10100010110010001001100101000110111001001000101010110110010111001000100110110010100001011100101']], [['4006381333931', None], ['12345678901٣2', None], ['3716511088176', '10101110110011001000010101110010110011001100101010111001010010001001000110011010001001010000101'], ['5108124299029', '10100110010100111000100100110010010011001110101010110110011101001110100111001011011001110100101'], ['4275982832382', '10100100110010001011000100010110001001001101101010100100010000101101100100001010010001101100101'], ['1841559138266', '10101101110100011011001101100010111001001011101010110011010000101001000110110010100001010000101'], ['4327150109045', '10101111010011011011101100110010111001010011101010110011011100101110100111001010111001001110101'], ['0130230054804', '10100110010111101000110100100110111101000110101010111001010011101011100100100011100101011100101']], [['12345678901٣2', None], ['4006381333931', None], ['1986892142891', '10100010110110111000010101101110010111001101101010110011010111001101100100100011101001100110101'], ['8116329403942', '10100110010110011010111101000010011011000101101010101110011100101000010111010010111001101100101'], ['6087726577121', '10100011010001001001000100100010010011010111101010100111010001001000100110011011011001100110101'], ['9139450687171', '10100110010100001001011101000110111001000110101010101000010010001000100110011010001001100110101'], ['9147502050346', '10100110010011101001000101100010100111001001101010111001010011101110010100001010111001010000101'], ['1043216289480', '10100011010100011010000100100110110011000010101010110110010010001110100101110010010001110010101']], [['4006381333931', None], ['12345678901٣2', None], ['8746102916553', '10101110110011101010111101100110100111001001101010111010011001101010000100111010011101000010101'], ['9803396505759', '10101101110100111010000101111010010111010111101010100111011100101001110100010010011101110100101'], ['5845180047269', '10101101110011101011100100110010110111010011101010111001010111001000100110110010100001110100101'], ['9648988190302', '10101011110011101000100100010110001001011011101010110011011101001110010100001011100101101100101'], ['2139834231886', '10100110010111101001011100010010111101001110101010110110010000101100110100100010010001010000101'], ['1857493890473', '10101101110110001001000101000110010111010000101010100100011101001110010101110010001001000010101']]]
labels = ["regression: digit character validation", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), solve(args), expected)
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
regression: digit character validation 010100011010100111010111101111010001001011001101010100001010000101000010111010010000101100110101NoneFailed
repair trap 110100100110111101001110101100010000101001000101010100100011101001110010110011010000101101100101NoneFailed
combined fault 21010110001000010100101110111011001100100101110101010010001000100111010010011101110100101110010110101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101Passed
control 31010110001000010100111010101111011000100100010101011101001010000101110010000101000010110011010110101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101Passed
control 41010111011010011101101110001001011100101000110101010011101110010111001010001001001110111001010110101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101Passed
boundary 51010111101011110100101110111001011100100100110101011100101110100101110010111001000100110110010110101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101Passed
boundary 61010001011001001101000010000101000110101000010101010111001000010100111011011001001000110110010110100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101Passed
control 71010110001010000101100010001001001101100100110101011001101100110110011011011001101100100001010110101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101Passed

SHA-256 / cb376a95b0b743c78c3a166d7a5c1f5e716f51d5df5fd042dab9d75bd5b228df

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(code):
    if len(code) != 13 or not code.isdigit():
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    R = [''.join('1' if b == '0' else '0' for b in p) for p in L]
    G = [p[::-1] for p in R]
    parity = ['LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG', 'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL']
    pat = parity[int(code[0])]
    left = ''.join((L if pat[i] == 'L' else G)[int(code[1 + i])] for i in range(6))
    right = ''.join(R[int(ch)] for ch in code[7:])
    return '101' + left + '01010' + right + '101'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['4006381333931', None], ['12345678901٣2', None], ['5569719879594', '10101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101'], ['5564657964331', '10101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101'], ['8708854500750', '10101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101'], ['3339552094472', '10101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101'], ['2923603435282', '10100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101'], ['8535822111223', '10101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101']], [['12345678901٣2', None], ['4006381333931', None], ['0777861705172', '10101110110111011011101101101110101111001100101010100010011100101001110110011010001001101100101'], ['6141838617595', '10100110010011101011001100010010111101011011101010101000011001101000100100111011101001001110101'], ['8738417160350', '10101110110100001011011100111010110011011101101010110011010100001110010100001010011101110010101'], ['3766842531699', '10101110110101111000010100010010011101001001101010100111010000101100110101000011101001110100101'], ['5117058572420', '10100110010110011001000100011010110001000100101010100111010001001101100101110011011001110010101'], ['4971457247264', '10100010110010001001100101000110111001001000101010110110010111001000100110110010100001011100101']], [['4006381333931', None], ['12345678901٣2', None], ['3716511088176', '10101110110011001000010101110010110011001100101010111001010010001001000110011010001001010000101'], ['5108124299029', '10100110010100111000100100110010010011001110101010110110011101001110100111001011011001110100101'], ['4275982832382', '10100100110010001011000100010110001001001101101010100100010000101101100100001010010001101100101'], ['1841559138266', '10101101110100011011001101100010111001001011101010110011010000101001000110110010100001010000101'], ['4327150109045', '10101111010011011011101100110010111001010011101010110011011100101110100111001010111001001110101'], ['0130230054804', '10100110010111101000110100100110111101000110101010111001010011101011100100100011100101011100101']], [['12345678901٣2', None], ['4006381333931', None], ['1986892142891', '10100010110110111000010101101110010111001101101010110011010111001101100100100011101001100110101'], ['8116329403942', '10100110010110011010111101000010011011000101101010101110011100101000010111010010111001101100101'], ['6087726577121', '10100011010001001001000100100010010011010111101010100111010001001000100110011011011001100110101'], ['9139450687171', '10100110010100001001011101000110111001000110101010101000010010001000100110011010001001100110101'], ['9147502050346', '10100110010011101001000101100010100111001001101010111001010011101110010100001010111001010000101'], ['1043216289480', '10100011010100011010000100100110110011000010101010110110010010001110100101110010010001110010101']], [['4006381333931', None], ['12345678901٣2', None], ['8746102916553', '10101110110011101010111101100110100111001001101010111010011001101010000100111010011101000010101'], ['9803396505759', '10101101110100111010000101111010010111010111101010100111011100101001110100010010011101110100101'], ['5845180047269', '10101101110011101011100100110010110111010011101010111001010111001000100110110010100001110100101'], ['9648988190302', '10101011110011101000100100010110001001011011101010110011011101001110010100001011100101101100101'], ['2139834231886', '10100110010111101001011100010010111101001110101010110110010000101100110100100010010001010000101'], ['1857493890473', '10101101110110001001000101000110010111010000101010100100011101001110010101110010001001000010101']]]
labels = ["regression: digit character validation", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), solve(args), expected)
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
regression: digit character validation 010100011010100111010111101111010001001011001101010100001010000101000010111010010000101100110101NoneFailed
repair trap 110100100110111101001110101100010000101001000101010100100011101001110010110011010000101101100101NoneFailed
combined fault 21010110001000010100101110111011001100100101110101010010001000100111010010011101110100101110010110101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101Passed
control 31010110001000010100111010101111011000100100010101011101001010000101110010000101000010110011010110101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101Passed
control 41010111011010011101101110001001011100101000110101010011101110010111001010001001001110111001010110101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101Passed
boundary 51010111101011110100101110111001011100100100110101011100101110100101110010111001000100110110010110101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101Passed
boundary 61010001011001001101000010000101000110101000010101010111001000010100111011011001001000110110010110100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101Passed
control 71010110001010000101100010001001001101100100110101011001101100110110011011011001101100100001010110101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101Passed

SHA-256 / 3c5d09022ab515e535ba9d4d74944a61ce39ea485b0da052b4f7779827e53f27

3 / The verified repair

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

N = 1
observations = []
def solve(code):
    if len(code) != 13 or not all(ch in '0123456789' for ch in code):
        return None
    L = ['0001101', '0011001', '0010011', '0111101', '0100011', '0110001', '0101111', '0111011', '0110111', '0001011']
    R = [''.join('1' if b == '0' else '0' for b in p) for p in L]
    G = [p[::-1] for p in R]
    parity = ['LLLLLL', 'LLGLGG', 'LLGGLG', 'LLGGGL', 'LGLLGG', 'LGGLLG', 'LGGGLL', 'LGLGLG', 'LGLGGL', 'LGGLGL']
    pat = parity[int(code[0])]
    left = ''.join((L if pat[i] == 'L' else G)[int(code[1 + i])] for i in range(6))
    right = ''.join(R[int(ch)] for ch in code[7:])
    return '101' + left + '01010' + right + '101'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['4006381333931', None], ['12345678901٣2', None], ['5569719879594', '10101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101'], ['5564657964331', '10101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101'], ['8708854500750', '10101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101'], ['3339552094472', '10101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101'], ['2923603435282', '10100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101'], ['8535822111223', '10101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101']], [['12345678901٣2', None], ['4006381333931', None], ['0777861705172', '10101110110111011011101101101110101111001100101010100010011100101001110110011010001001101100101'], ['6141838617595', '10100110010011101011001100010010111101011011101010101000011001101000100100111011101001001110101'], ['8738417160350', '10101110110100001011011100111010110011011101101010110011010100001110010100001010011101110010101'], ['3766842531699', '10101110110101111000010100010010011101001001101010100111010000101100110101000011101001110100101'], ['5117058572420', '10100110010110011001000100011010110001000100101010100111010001001101100101110011011001110010101'], ['4971457247264', '10100010110010001001100101000110111001001000101010110110010111001000100110110010100001011100101']], [['4006381333931', None], ['12345678901٣2', None], ['3716511088176', '10101110110011001000010101110010110011001100101010111001010010001001000110011010001001010000101'], ['5108124299029', '10100110010100111000100100110010010011001110101010110110011101001110100111001011011001110100101'], ['4275982832382', '10100100110010001011000100010110001001001101101010100100010000101101100100001010010001101100101'], ['1841559138266', '10101101110100011011001101100010111001001011101010110011010000101001000110110010100001010000101'], ['4327150109045', '10101111010011011011101100110010111001010011101010110011011100101110100111001010111001001110101'], ['0130230054804', '10100110010111101000110100100110111101000110101010111001010011101011100100100011100101011100101']], [['12345678901٣2', None], ['4006381333931', None], ['1986892142891', '10100010110110111000010101101110010111001101101010110011010111001101100100100011101001100110101'], ['8116329403942', '10100110010110011010111101000010011011000101101010101110011100101000010111010010111001101100101'], ['6087726577121', '10100011010001001001000100100010010011010111101010100111010001001000100110011011011001100110101'], ['9139450687171', '10100110010100001001011101000110111001000110101010101000010010001000100110011010001001100110101'], ['9147502050346', '10100110010011101001000101100010100111001001101010111001010011101110010100001010111001010000101'], ['1043216289480', '10100011010100011010000100100110110011000010101010110110010010001110100101110010010001110010101']], [['4006381333931', None], ['12345678901٣2', None], ['8746102916553', '10101110110011101010111101100110100111001001101010111010011001101010000100111010011101000010101'], ['9803396505759', '10101101110100111010000101111010010111010111101010100111011100101001110100010010011101110100101'], ['5845180047269', '10101101110011101011100100110010110111010011101010111001010111001000100110110010100001110100101'], ['9648988190302', '10101011110011101000100100010110001001011011101010110011011101001110010100001011100101101100101'], ['2139834231886', '10100110010111101001011100010010111101001110101010110110010000101100110100100010010001010000101'], ['1857493890473', '10101101110110001001000101000110010111010000101010100100011101001110010101110010001001000010101']]]
labels = ["regression: digit character validation", "repair trap", "combined fault", "control", "control", "boundary", "boundary", "control"]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("%s %d" % (labels[i % len(labels)], i), solve(args), expected)
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
regression: digit character validation 0NoneNonePassed
repair trap 1NoneNonePassed
combined fault 21010110001000010100101110111011001100100101110101010010001000100111010010011101110100101110010110101100010000101001011101110110011001001011101010100100010001001110100100111011101001011100101Passed
control 31010110001000010100111010101111011000100100010101011101001010000101110010000101000010110011010110101100010000101001110101011110110001001000101010111010010100001011100100001010000101100110101Passed
control 41010111011010011101101110001001011100101000110101010011101110010111001010001001001110111001010110101110110100111011011100010010111001010001101010100111011100101110010100010010011101110010101Passed
boundary 51010111101011110100101110111001011100100100110101011100101110100101110010111001000100110110010110101111010111101001011101110010111001001001101010111001011101001011100101110010001001101100101Passed
boundary 61010001011001001101000010000101000110101000010101010111001000010100111011011001001000110110010110100010110010011010000100001010001101010000101010101110010000101001110110110010010001101100101Passed
control 71010110001010000101100010001001001101100100110101011001101100110110011011011001101100100001010110101100010100001011000100010010011011001001101010110011011001101100110110110011011001000010101Passed

SHA-256 / 48e1b6dd44a49752c4ec06f6c919d1245e9f2028d695bbddb3dbf428e3a29c69

Verification & scope

A deterministic bounded teaching model with a stipulated contract; it makes no claim of conformance to any published specification. 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:49:43.824747+00:00.

Case digest / b64aa5061839c2f6dc27a3d7d6b5a4f0f8de4e634ecc1cb2339267fd0b2ed573