FA-92331 / PLC ladder logic scan cycles / Open access
Overflow trap clearing rung is evaluated before the math rung · case 01
An overflow in the same scan as the clearing rung still halts the processor.
ROOT CAUSE
The trap clear is applied at the top of the scan instead of after the math instruction.
VERIFIED REPAIR
Clear the trap after the math instruction, matching the later rung position.
Unsuccessful approach: Skipping the clear when the current op overflowed still halts on a handled overflow.
Case contract
16-bit INT math rung followed by a later fault-clearing rung, one op per scan; ops is a list of [a, b, ADD|SUB|MUL, clear]. A result outside -32768..32767 sets the overflow bit V for that instruction and the overflow trap; the stored result is saturated to 32767/-32768 when clamp is set or wrapped as 16-bit two's complement otherwise. V is recomputed per instruction. The later rung clears the trap when clear is true; a trap still set at end of scan halts the processor. Return [result, V, trap] per scan, then "halted" and stop if faulted.
Why this case matters
Ladder programs are executed as repeated scans; each defect here changes what a rung, timer, counter or data-table instruction reports on a particular scan, which is how commissioning and field faults are actually observed.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(clamp, ops):
trap = False
out = []
for a, b, op, clear in ops:
if clear:
trap = False
if op == 'ADD':
r = a + b
elif op == 'SUB':
r = a - b
else:
r = a * b
v = not (-32768 <= r <= 32767)
if v:
trap = True
if clamp:
r = 32767 if r > 0 else -32768
else:
r = (r + 32768) % 65536 - 32768
out.append([r, v, trap])
if trap:
out.append('halted')
break
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 1',
[False,
[[-32768, -20192, 'SUB', True],
[12968, -30310, 'ADD', False],
[-31305, 2, 'SUB', False],
[11091, 200, 'MUL', True],
[10310, 200, 'SUB', False]]],
[[-12576, False, False],
[-17342, False, False],
[-31307, False, False],
[-10024, True, False],
[10110, False, False]]],
['control: scenario 2',
[True,
[[27834, -6307, 'SUB', False],
[30000, -15473, 'SUB', False],
[-1, 1, 'MUL', False],
[-30000, -4507, 'SUB', True],
[-21177, 21481, 'MUL', False],
[31159, 1, 'SUB', False]]],
[[32767, True, True], 'halted']],
['control: scenario 3',
[False,
[[18788, 200, 'SUB', True],
[20369, -23104, 'MUL', False],
[-32768, 10449, 'ADD', False],
[-17550, 18799, 'ADD', False],
[1, 32767, 'MUL', False]]],
[[18588, False, False], [8640, True, True], 'halted']],
['regression: scenario 4',
[False,
[[30000, 1, 'ADD', True],
[-20338, 30000, 'ADD', True],
[18879, 1, 'SUB', True],
[27305, -32768, 'MUL', True],
[16107, -9800, 'MUL', False],
[3999, -32768, 'SUB', False],
[1, -21623, 'ADD', False]]],
[[30001, False, False],
[9662, False, False],
[18878, False, False],
[-32768, True, False],
[27624, True, True],
'halted']]],
[['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[-15041, -14459, 'SUB', False],
[13071, -30000, 'ADD', True],
[-17526, -1, 'MUL', True],
[-30000, 200, 'MUL', False]]],
[[-582, False, False], [-16929, False, False], [17526, False, False], [29312, True, True], 'halted']],
['regression: scenario 2',
[True,
[[-1048, 30000, 'ADD', False],
[2, -13120, 'SUB', False],
[29306, -32768, 'SUB', True],
[-9919, -24931, 'MUL', True]]],
[[28952, False, False], [13122, False, False], [32767, True, False], [32767, True, False]]],
['regression: scenario 3',
[False,
[[-10436, -32034, 'MUL', True],
[2, 22108, 'SUB', False],
[7659, 2, 'MUL', False],
[5339, 1, 'MUL', False]]],
[[7688, True, False], [-22106, False, False], [15318, False, False], [5339, False, False]]],
['regression: scenario 4',
[False,
[[200, -21485, 'MUL', True],
[-200, -32768, 'SUB', True],
[15677, 32607, 'ADD', True],
[-10557, 26430, 'SUB', False],
[-200, 30000, 'SUB', True],
[-30000, 200, 'ADD', True],
[26687, -20358, 'ADD', False]]],
[[28376, True, False], [32568, False, False], [-17252, True, False], [28549, True, True], 'halted']]],
[['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 6',
[True,
[[-22967, 31354, 'ADD', True],
[30000, 2, 'MUL', True],
[-32768, -1, 'MUL', False],
[26774, -19891, 'SUB', False],
[1, -15244, 'ADD', False]]],
[[8387, False, False], [32767, True, False], [32767, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[15094, -24454, 'MUL', False],
[-30000, 24363, 'MUL', True],
[2, -14871, 'MUL', False],
[1, -26550, 'MUL', True],
[-1, -7090, 'SUB', False],
[32767, 1, 'MUL', True],
[-32768, 15967, 'ADD', False],
[21457, -28729, 'SUB', True]]],
[[-9924, True, True], 'halted']],
['control: scenario 2',
[False,
[[-200, -200, 'ADD', True],
[32767, 200, 'MUL', False],
[-9390, 1, 'MUL', False],
[-11169, -28064, 'ADD', True],
[22720, -1, 'ADD', False],
[-200, -1, 'ADD', False],
[-12859, 1, 'ADD', True]]],
[[-400, False, False], [-200, True, True], 'halted']],
['control: scenario 3',
[True,
[[200, 30000, 'ADD', True],
[11009, -200, 'SUB', True],
[-200, 1, 'MUL', False],
[-20841, 21280, 'ADD', True]]],
[[30200, False, False], [11209, False, False], [-200, False, False], [439, False, False]]]],
[['regression: scenario 2',
[False,
[[30000, -32768, 'ADD', True],
[4451, 31437, 'SUB', False],
[-1, 22093, 'MUL', False],
[-30000, -18488, 'SUB', False],
[30000, -28921, 'MUL', True],
[-200, 23349, 'ADD', True],
[-32768, 200, 'SUB', False]]],
[[-2768, False, False],
[-26986, False, False],
[-22093, False, False],
[-11512, False, False],
[1104, True, False],
[23149, False, False],
[32568, True, True],
'halted']],
['regression: scenario 3',
[False,
[[-32768, 19187, 'MUL', True],
[-7301, -200, 'SUB', False],
[-32768, 30000, 'SUB', True],
[-9747, -24186, 'ADD', True],
[-1, -22920, 'SUB', True],
[-259, 22293, 'SUB', False],
[23494, -1, 'MUL', False],
[-32529, 24353, 'SUB', True]]],
[[-32768, True, False],
[-7101, False, False],
[2768, True, False],
[31603, True, False],
[22919, False, False],
[-22552, False, False],
[-23494, False, False],
[8654, True, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[False,
[[-26759, 2, 'SUB', True],
[-30000, -32768, 'SUB', False],
[-3730, -31438, 'ADD', False],
[200, 200, 'SUB', True],
[-24761, 200, 'SUB', True],
[-20747, 200, 'SUB', False],
[200, 19789, 'SUB', True]]],
[[-26761, False, False], [2768, False, False], [30368, True, True], 'halted']],
['control: scenario 4',
[False,
[[18038, 28061, 'MUL', False],
[-200, -3461, 'SUB', True],
[-32768, -11546, 'SUB', False],
[-28255, 22972, 'ADD', False]]],
[[29790, True, True], 'halted']]],
[['regression: scenario 4',
[False,
[[19188, -11432, 'MUL', True],
[-32768, 7005, 'SUB', True],
[-200, 1, 'ADD', True],
[32767, -4687, 'MUL', False],
[7857, 5828, 'ADD', True],
[-11826, -1129, 'MUL', False],
[-1, 1, 'MUL', False],
[-24957, -5100, 'ADD', True]]],
[[-8224, True, False], [25763, True, False], [-199, False, False], [-28081, True, True], 'halted']],
['regression: scenario 11',
[False,
[[200, -200, 'SUB', False],
[-200, -200, 'SUB', False],
[-200, 30000, 'MUL', True],
[-14430, -32768, 'ADD', False]]],
[[400, False, False], [0, False, False], [29312, True, False], [18338, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[True,
[[160, 2, 'SUB', True], [200, 200, 'SUB', True], [222, 200, 'SUB', False], [200, -32768, 'ADD', True]]],
[[158, False, False], [0, False, False], [22, False, False], [-32568, False, False]]],
['regression: scenario 2',
[True,
[[30000, 1574, 'SUB', True],
[-783, -29319, 'SUB', True],
[2, 1803, 'SUB', False],
[200, 2, 'ADD', True],
[9942, 32767, 'MUL', True],
[-30000, -19084, 'MUL', True],
[-10106, -30460, 'ADD', False],
[2, 32767, 'ADD', True]]],
[[28426, False, False],
[28536, False, False],
[-1801, False, False],
[202, False, False],
[32767, True, False],
[32767, True, False],
[-32768, True, True],
'halted']]]]
for label, args, expected in fixtures[N-1]:
check(label, 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: wrap with cleared traps | [[-30536, True, True], 'halted'] | [[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted'] | Failed |
| regression: saturation both signs | [[32767, True, True], 'halted'] | [[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]] | Failed |
| control: exact limits | [[-32768, False, False], [32767, False, False], [12, False, False]] | [[-32768, False, False], [32767, False, False], [12, False, False]] | Passed |
| regression: overflow then clean ops | [[32767, True, True], 'halted'] | [[32767, True, False], [10, False, False], [0, False, False]] | Failed |
| regression: scenario 1 | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, True], 'halted'] | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, False], [10110, False, False]] | Failed |
| control: scenario 2 | [[32767, True, True], 'halted'] | [[32767, True, True], 'halted'] | Passed |
| control: scenario 3 | [[18588, False, False], [8640, True, True], 'halted'] | [[18588, False, False], [8640, True, True], 'halted'] | Passed |
| regression: scenario 4 | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, True], 'halted'] | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, False], [27624, True, True], 'halted'] | Failed |
SHA-256 / f38a67beead870253f16c8cee7403eb8bf868026e1569d1bd67fe48e0b366cfc
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(clamp, ops):
trap = False
out = []
for a, b, op, clear in ops:
if op == 'ADD':
r = a + b
elif op == 'SUB':
r = a - b
else:
r = a * b
v = not (-32768 <= r <= 32767)
if v:
trap = True
if clamp:
r = 32767 if r > 0 else -32768
else:
r = (r + 32768) % 65536 - 32768
if clear and not v:
trap = False
out.append([r, v, trap])
if trap:
out.append('halted')
break
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 1',
[False,
[[-32768, -20192, 'SUB', True],
[12968, -30310, 'ADD', False],
[-31305, 2, 'SUB', False],
[11091, 200, 'MUL', True],
[10310, 200, 'SUB', False]]],
[[-12576, False, False],
[-17342, False, False],
[-31307, False, False],
[-10024, True, False],
[10110, False, False]]],
['control: scenario 2',
[True,
[[27834, -6307, 'SUB', False],
[30000, -15473, 'SUB', False],
[-1, 1, 'MUL', False],
[-30000, -4507, 'SUB', True],
[-21177, 21481, 'MUL', False],
[31159, 1, 'SUB', False]]],
[[32767, True, True], 'halted']],
['control: scenario 3',
[False,
[[18788, 200, 'SUB', True],
[20369, -23104, 'MUL', False],
[-32768, 10449, 'ADD', False],
[-17550, 18799, 'ADD', False],
[1, 32767, 'MUL', False]]],
[[18588, False, False], [8640, True, True], 'halted']],
['regression: scenario 4',
[False,
[[30000, 1, 'ADD', True],
[-20338, 30000, 'ADD', True],
[18879, 1, 'SUB', True],
[27305, -32768, 'MUL', True],
[16107, -9800, 'MUL', False],
[3999, -32768, 'SUB', False],
[1, -21623, 'ADD', False]]],
[[30001, False, False],
[9662, False, False],
[18878, False, False],
[-32768, True, False],
[27624, True, True],
'halted']]],
[['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[-15041, -14459, 'SUB', False],
[13071, -30000, 'ADD', True],
[-17526, -1, 'MUL', True],
[-30000, 200, 'MUL', False]]],
[[-582, False, False], [-16929, False, False], [17526, False, False], [29312, True, True], 'halted']],
['regression: scenario 2',
[True,
[[-1048, 30000, 'ADD', False],
[2, -13120, 'SUB', False],
[29306, -32768, 'SUB', True],
[-9919, -24931, 'MUL', True]]],
[[28952, False, False], [13122, False, False], [32767, True, False], [32767, True, False]]],
['regression: scenario 3',
[False,
[[-10436, -32034, 'MUL', True],
[2, 22108, 'SUB', False],
[7659, 2, 'MUL', False],
[5339, 1, 'MUL', False]]],
[[7688, True, False], [-22106, False, False], [15318, False, False], [5339, False, False]]],
['regression: scenario 4',
[False,
[[200, -21485, 'MUL', True],
[-200, -32768, 'SUB', True],
[15677, 32607, 'ADD', True],
[-10557, 26430, 'SUB', False],
[-200, 30000, 'SUB', True],
[-30000, 200, 'ADD', True],
[26687, -20358, 'ADD', False]]],
[[28376, True, False], [32568, False, False], [-17252, True, False], [28549, True, True], 'halted']]],
[['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 6',
[True,
[[-22967, 31354, 'ADD', True],
[30000, 2, 'MUL', True],
[-32768, -1, 'MUL', False],
[26774, -19891, 'SUB', False],
[1, -15244, 'ADD', False]]],
[[8387, False, False], [32767, True, False], [32767, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[15094, -24454, 'MUL', False],
[-30000, 24363, 'MUL', True],
[2, -14871, 'MUL', False],
[1, -26550, 'MUL', True],
[-1, -7090, 'SUB', False],
[32767, 1, 'MUL', True],
[-32768, 15967, 'ADD', False],
[21457, -28729, 'SUB', True]]],
[[-9924, True, True], 'halted']],
['control: scenario 2',
[False,
[[-200, -200, 'ADD', True],
[32767, 200, 'MUL', False],
[-9390, 1, 'MUL', False],
[-11169, -28064, 'ADD', True],
[22720, -1, 'ADD', False],
[-200, -1, 'ADD', False],
[-12859, 1, 'ADD', True]]],
[[-400, False, False], [-200, True, True], 'halted']],
['control: scenario 3',
[True,
[[200, 30000, 'ADD', True],
[11009, -200, 'SUB', True],
[-200, 1, 'MUL', False],
[-20841, 21280, 'ADD', True]]],
[[30200, False, False], [11209, False, False], [-200, False, False], [439, False, False]]]],
[['regression: scenario 2',
[False,
[[30000, -32768, 'ADD', True],
[4451, 31437, 'SUB', False],
[-1, 22093, 'MUL', False],
[-30000, -18488, 'SUB', False],
[30000, -28921, 'MUL', True],
[-200, 23349, 'ADD', True],
[-32768, 200, 'SUB', False]]],
[[-2768, False, False],
[-26986, False, False],
[-22093, False, False],
[-11512, False, False],
[1104, True, False],
[23149, False, False],
[32568, True, True],
'halted']],
['regression: scenario 3',
[False,
[[-32768, 19187, 'MUL', True],
[-7301, -200, 'SUB', False],
[-32768, 30000, 'SUB', True],
[-9747, -24186, 'ADD', True],
[-1, -22920, 'SUB', True],
[-259, 22293, 'SUB', False],
[23494, -1, 'MUL', False],
[-32529, 24353, 'SUB', True]]],
[[-32768, True, False],
[-7101, False, False],
[2768, True, False],
[31603, True, False],
[22919, False, False],
[-22552, False, False],
[-23494, False, False],
[8654, True, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[False,
[[-26759, 2, 'SUB', True],
[-30000, -32768, 'SUB', False],
[-3730, -31438, 'ADD', False],
[200, 200, 'SUB', True],
[-24761, 200, 'SUB', True],
[-20747, 200, 'SUB', False],
[200, 19789, 'SUB', True]]],
[[-26761, False, False], [2768, False, False], [30368, True, True], 'halted']],
['control: scenario 4',
[False,
[[18038, 28061, 'MUL', False],
[-200, -3461, 'SUB', True],
[-32768, -11546, 'SUB', False],
[-28255, 22972, 'ADD', False]]],
[[29790, True, True], 'halted']]],
[['regression: scenario 4',
[False,
[[19188, -11432, 'MUL', True],
[-32768, 7005, 'SUB', True],
[-200, 1, 'ADD', True],
[32767, -4687, 'MUL', False],
[7857, 5828, 'ADD', True],
[-11826, -1129, 'MUL', False],
[-1, 1, 'MUL', False],
[-24957, -5100, 'ADD', True]]],
[[-8224, True, False], [25763, True, False], [-199, False, False], [-28081, True, True], 'halted']],
['regression: scenario 11',
[False,
[[200, -200, 'SUB', False],
[-200, -200, 'SUB', False],
[-200, 30000, 'MUL', True],
[-14430, -32768, 'ADD', False]]],
[[400, False, False], [0, False, False], [29312, True, False], [18338, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[True,
[[160, 2, 'SUB', True], [200, 200, 'SUB', True], [222, 200, 'SUB', False], [200, -32768, 'ADD', True]]],
[[158, False, False], [0, False, False], [22, False, False], [-32568, False, False]]],
['regression: scenario 2',
[True,
[[30000, 1574, 'SUB', True],
[-783, -29319, 'SUB', True],
[2, 1803, 'SUB', False],
[200, 2, 'ADD', True],
[9942, 32767, 'MUL', True],
[-30000, -19084, 'MUL', True],
[-10106, -30460, 'ADD', False],
[2, 32767, 'ADD', True]]],
[[28426, False, False],
[28536, False, False],
[-1801, False, False],
[202, False, False],
[32767, True, False],
[32767, True, False],
[-32768, True, True],
'halted']]]]
for label, args, expected in fixtures[N-1]:
check(label, 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: wrap with cleared traps | [[-30536, True, True], 'halted'] | [[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted'] | Failed |
| regression: saturation both signs | [[32767, True, True], 'halted'] | [[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]] | Failed |
| control: exact limits | [[-32768, False, False], [32767, False, False], [12, False, False]] | [[-32768, False, False], [32767, False, False], [12, False, False]] | Passed |
| regression: overflow then clean ops | [[32767, True, True], 'halted'] | [[32767, True, False], [10, False, False], [0, False, False]] | Failed |
| regression: scenario 1 | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, True], 'halted'] | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, False], [10110, False, False]] | Failed |
| control: scenario 2 | [[32767, True, True], 'halted'] | [[32767, True, True], 'halted'] | Passed |
| control: scenario 3 | [[18588, False, False], [8640, True, True], 'halted'] | [[18588, False, False], [8640, True, True], 'halted'] | Passed |
| regression: scenario 4 | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, True], 'halted'] | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, False], [27624, True, True], 'halted'] | Failed |
SHA-256 / a5479c524f59f013d35176f5b528ad3f50906ae1e02bb06c3f4b9d78a7d3ef24
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(clamp, ops):
trap = False
out = []
for a, b, op, clear in ops:
if op == 'ADD':
r = a + b
elif op == 'SUB':
r = a - b
else:
r = a * b
v = not (-32768 <= r <= 32767)
if v:
trap = True
if clamp:
r = 32767 if r > 0 else -32768
else:
r = (r + 32768) % 65536 - 32768
if clear:
trap = False
out.append([r, v, trap])
if trap:
out.append('halted')
break
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 1',
[False,
[[-32768, -20192, 'SUB', True],
[12968, -30310, 'ADD', False],
[-31305, 2, 'SUB', False],
[11091, 200, 'MUL', True],
[10310, 200, 'SUB', False]]],
[[-12576, False, False],
[-17342, False, False],
[-31307, False, False],
[-10024, True, False],
[10110, False, False]]],
['control: scenario 2',
[True,
[[27834, -6307, 'SUB', False],
[30000, -15473, 'SUB', False],
[-1, 1, 'MUL', False],
[-30000, -4507, 'SUB', True],
[-21177, 21481, 'MUL', False],
[31159, 1, 'SUB', False]]],
[[32767, True, True], 'halted']],
['control: scenario 3',
[False,
[[18788, 200, 'SUB', True],
[20369, -23104, 'MUL', False],
[-32768, 10449, 'ADD', False],
[-17550, 18799, 'ADD', False],
[1, 32767, 'MUL', False]]],
[[18588, False, False], [8640, True, True], 'halted']],
['regression: scenario 4',
[False,
[[30000, 1, 'ADD', True],
[-20338, 30000, 'ADD', True],
[18879, 1, 'SUB', True],
[27305, -32768, 'MUL', True],
[16107, -9800, 'MUL', False],
[3999, -32768, 'SUB', False],
[1, -21623, 'ADD', False]]],
[[30001, False, False],
[9662, False, False],
[18878, False, False],
[-32768, True, False],
[27624, True, True],
'halted']]],
[['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[-15041, -14459, 'SUB', False],
[13071, -30000, 'ADD', True],
[-17526, -1, 'MUL', True],
[-30000, 200, 'MUL', False]]],
[[-582, False, False], [-16929, False, False], [17526, False, False], [29312, True, True], 'halted']],
['regression: scenario 2',
[True,
[[-1048, 30000, 'ADD', False],
[2, -13120, 'SUB', False],
[29306, -32768, 'SUB', True],
[-9919, -24931, 'MUL', True]]],
[[28952, False, False], [13122, False, False], [32767, True, False], [32767, True, False]]],
['regression: scenario 3',
[False,
[[-10436, -32034, 'MUL', True],
[2, 22108, 'SUB', False],
[7659, 2, 'MUL', False],
[5339, 1, 'MUL', False]]],
[[7688, True, False], [-22106, False, False], [15318, False, False], [5339, False, False]]],
['regression: scenario 4',
[False,
[[200, -21485, 'MUL', True],
[-200, -32768, 'SUB', True],
[15677, 32607, 'ADD', True],
[-10557, 26430, 'SUB', False],
[-200, 30000, 'SUB', True],
[-30000, 200, 'ADD', True],
[26687, -20358, 'ADD', False]]],
[[28376, True, False], [32568, False, False], [-17252, True, False], [28549, True, True], 'halted']]],
[['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['regression: scenario 6',
[True,
[[-22967, 31354, 'ADD', True],
[30000, 2, 'MUL', True],
[-32768, -1, 'MUL', False],
[26774, -19891, 'SUB', False],
[1, -15244, 'ADD', False]]],
[[8387, False, False], [32767, True, False], [32767, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['control: scenario 1',
[False,
[[15094, -24454, 'MUL', False],
[-30000, 24363, 'MUL', True],
[2, -14871, 'MUL', False],
[1, -26550, 'MUL', True],
[-1, -7090, 'SUB', False],
[32767, 1, 'MUL', True],
[-32768, 15967, 'ADD', False],
[21457, -28729, 'SUB', True]]],
[[-9924, True, True], 'halted']],
['control: scenario 2',
[False,
[[-200, -200, 'ADD', True],
[32767, 200, 'MUL', False],
[-9390, 1, 'MUL', False],
[-11169, -28064, 'ADD', True],
[22720, -1, 'ADD', False],
[-200, -1, 'ADD', False],
[-12859, 1, 'ADD', True]]],
[[-400, False, False], [-200, True, True], 'halted']],
['control: scenario 3',
[True,
[[200, 30000, 'ADD', True],
[11009, -200, 'SUB', True],
[-200, 1, 'MUL', False],
[-20841, 21280, 'ADD', True]]],
[[30200, False, False], [11209, False, False], [-200, False, False], [439, False, False]]]],
[['regression: scenario 2',
[False,
[[30000, -32768, 'ADD', True],
[4451, 31437, 'SUB', False],
[-1, 22093, 'MUL', False],
[-30000, -18488, 'SUB', False],
[30000, -28921, 'MUL', True],
[-200, 23349, 'ADD', True],
[-32768, 200, 'SUB', False]]],
[[-2768, False, False],
[-26986, False, False],
[-22093, False, False],
[-11512, False, False],
[1104, True, False],
[23149, False, False],
[32568, True, True],
'halted']],
['regression: scenario 3',
[False,
[[-32768, 19187, 'MUL', True],
[-7301, -200, 'SUB', False],
[-32768, 30000, 'SUB', True],
[-9747, -24186, 'ADD', True],
[-1, -22920, 'SUB', True],
[-259, 22293, 'SUB', False],
[23494, -1, 'MUL', False],
[-32529, 24353, 'SUB', True]]],
[[-32768, True, False],
[-7101, False, False],
[2768, True, False],
[31603, True, False],
[22919, False, False],
[-22552, False, False],
[-23494, False, False],
[8654, True, False]]],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[False,
[[-26759, 2, 'SUB', True],
[-30000, -32768, 'SUB', False],
[-3730, -31438, 'ADD', False],
[200, 200, 'SUB', True],
[-24761, 200, 'SUB', True],
[-20747, 200, 'SUB', False],
[200, 19789, 'SUB', True]]],
[[-26761, False, False], [2768, False, False], [30368, True, True], 'halted']],
['control: scenario 4',
[False,
[[18038, 28061, 'MUL', False],
[-200, -3461, 'SUB', True],
[-32768, -11546, 'SUB', False],
[-28255, 22972, 'ADD', False]]],
[[29790, True, True], 'halted']]],
[['regression: scenario 4',
[False,
[[19188, -11432, 'MUL', True],
[-32768, 7005, 'SUB', True],
[-200, 1, 'ADD', True],
[32767, -4687, 'MUL', False],
[7857, 5828, 'ADD', True],
[-11826, -1129, 'MUL', False],
[-1, 1, 'MUL', False],
[-24957, -5100, 'ADD', True]]],
[[-8224, True, False], [25763, True, False], [-199, False, False], [-28081, True, True], 'halted']],
['regression: scenario 11',
[False,
[[200, -200, 'SUB', False],
[-200, -200, 'SUB', False],
[-200, 30000, 'MUL', True],
[-14430, -32768, 'ADD', False]]],
[[400, False, False], [0, False, False], [29312, True, False], [18338, True, True], 'halted']],
['regression: wrap with cleared traps',
[False,
[[30000, 5000, 'ADD', True],
[-30000, 5000, 'SUB', True],
[200, 200, 'MUL', False],
[1, 1, 'ADD', False]]],
[[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted']],
['regression: saturation both signs',
[True,
[[-2, -20000, 'MUL', True],
[-20000, 20000, 'SUB', True],
[32767, 0, 'ADD', False],
[1, 1, 'ADD', False]]],
[[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]]],
['control: exact limits',
[False, [[-32767, 1, 'SUB', False], [32766, 1, 'ADD', False], [3, 4, 'MUL', False]]],
[[-32768, False, False], [32767, False, False], [12, False, False]]],
['regression: overflow then clean ops',
[True, [[32767, 1, 'ADD', True], [5, 5, 'ADD', False], [7, 7, 'SUB', False]]],
[[32767, True, False], [10, False, False], [0, False, False]]],
['control: scenario 1',
[True,
[[160, 2, 'SUB', True], [200, 200, 'SUB', True], [222, 200, 'SUB', False], [200, -32768, 'ADD', True]]],
[[158, False, False], [0, False, False], [22, False, False], [-32568, False, False]]],
['regression: scenario 2',
[True,
[[30000, 1574, 'SUB', True],
[-783, -29319, 'SUB', True],
[2, 1803, 'SUB', False],
[200, 2, 'ADD', True],
[9942, 32767, 'MUL', True],
[-30000, -19084, 'MUL', True],
[-10106, -30460, 'ADD', False],
[2, 32767, 'ADD', True]]],
[[28426, False, False],
[28536, False, False],
[-1801, False, False],
[202, False, False],
[32767, True, False],
[32767, True, False],
[-32768, True, True],
'halted']]]]
for label, args, expected in fixtures[N-1]:
check(label, 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: wrap with cleared traps | [[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted'] | [[-30536, True, False], [30536, True, False], [-25536, True, True], 'halted'] | Passed |
| regression: saturation both signs | [[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]] | [[32767, True, False], [-32768, True, False], [32767, False, False], [2, False, False]] | Passed |
| control: exact limits | [[-32768, False, False], [32767, False, False], [12, False, False]] | [[-32768, False, False], [32767, False, False], [12, False, False]] | Passed |
| regression: overflow then clean ops | [[32767, True, False], [10, False, False], [0, False, False]] | [[32767, True, False], [10, False, False], [0, False, False]] | Passed |
| regression: scenario 1 | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, False], [10110, False, False]] | [[-12576, False, False], [-17342, False, False], [-31307, False, False], [-10024, True, False], [10110, False, False]] | Passed |
| control: scenario 2 | [[32767, True, True], 'halted'] | [[32767, True, True], 'halted'] | Passed |
| control: scenario 3 | [[18588, False, False], [8640, True, True], 'halted'] | [[18588, False, False], [8640, True, True], 'halted'] | Passed |
| regression: scenario 4 | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, False], [27624, True, True], 'halted'] | [[30001, False, False], [9662, False, False], [18878, False, False], [-32768, True, False], [27624, True, True], 'halted'] | Passed |
SHA-256 / 9b7945e81ad3449362cc252c18d72236739207005ef333446f5a7f8f4d6ffa13
Verification & scope
A deterministic bounded teaching model of one PLC instruction or rung pattern evaluated scan by scan. The stated contract is a stipulated toy convention, not a claim of conformance to any vendor controller or IEC 61131-3 runtime. 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:51:44.598923+00:00.
Case digest / 969e49191ee19530408ad1c460b445e42f690602bab510a4158349e111f4204a