FA-90181 / Bytecode virtual machines / Open access
LEB128 immediates: u32 immediates sign-extended · case 01
Unsigned 32-bit immediates whose last byte has bit 6 set become negative.
ROOT CAUSE
Sign extension is applied to every kind except u64.
THE FAILURE
Sign extension is applied to every kind except u64.
Unsuccessful approach: Restricting extension to s32 leaves negative s64 immediates positive.
Case contract
Decode consecutive LEB128 immediates of kinds u32, s32, u64, s64 from a byte list: 7 payload bits per byte, least significant group first, bit 0x80 means another byte follows; at most ceil(bits/7) bytes (5 for 32-bit, 10 for 64-bit). Signed kinds sign-extend from bit 0x40 of the final byte; u32/s32 values outside their range are errors. Return decoded values followed by the first error, if any: ["unexpected-end", pos], ["too-long", pos] or ["out-of-range", pos].
Why this case matters
Compact bytecode formats encode immediates with LEB128; decoding errors silently change operands.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data, kinds):
pos = 0
out = []
for kind in kinds:
bits = 32 if kind in ('u32', 's32') else 64
maxlen = (bits + 6) // 7
result = 0
shift = 0
n = 0
while True:
if pos >= len(data):
return out + [['unexpected-end', pos]]
byte = data[pos]
pos += 1
n += 1
result |= (byte & 0x7F) << shift
shift += 7
if (byte & 0x80) == 0:
break
if n == maxlen:
return out + [['too-long', pos]]
if kind != 'u64' and byte & 0x40:
result -= 1 << shift
if kind == 's32' and not -(1 << 31) <= result < (1 << 31):
return out + [['out-of-range', pos]]
if kind == 'u32' and result >= (1 << 32):
return out + [['out-of-range', pos]]
out.append(result)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: mixed immediates', ([237, 7, 179, 127, 127], ['u32', 's32', 's64']), [1005, -77, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 1], ['u32']), [268435456]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 1], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([65, 128, 64], ['u32', 'u32']), [65, 8192]),
('negative s64 spanning several bytes', ([255, 255, 255, 255, 255, 95], ['s64']), [-1099511627777]),
('truncated immediate', ([128, 129], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([213, 15, 230, 126, 127], ['u32', 's32', 's64']), [2005, -154, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 2], ['u32']), [536870912]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 2], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([66, 128, 64], ['u32', 'u32']), [66, 8192]),
('negative s64 spanning several bytes', ([254, 255, 255, 255, 255, 95], ['s64']), [-1099511627778]),
('truncated immediate', ([128, 130], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([189, 23, 153, 126, 127], ['u32', 's32', 's64']), [3005, -231, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 3], ['u32']), [805306368]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 3], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([67, 128, 64], ['u32', 'u32']), [67, 8192]),
('negative s64 spanning several bytes', ([253, 255, 255, 255, 255, 95], ['s64']), [-1099511627779]),
('truncated immediate', ([128, 131], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([165, 31, 204, 125, 127], ['u32', 's32', 's64']), [4005, -308, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 4], ['u32']), [1073741824]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 4], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([68, 128, 64], ['u32', 'u32']), [68, 8192]),
('negative s64 spanning several bytes', ([252, 255, 255, 255, 255, 95], ['s64']), [-1099511627780]),
('truncated immediate', ([128, 132], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([141, 39, 255, 124, 127], ['u32', 's32', 's64']), [5005, -385, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 5], ['u32']), [1342177280]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 5], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([69, 128, 64], ['u32', 'u32']), [69, 8192]),
('negative s64 spanning several bytes', ([251, 255, 255, 255, 255, 95], ['s64']), [-1099511627781]),
('truncated immediate', ([128, 133], ['u64']), [['unexpected-end', 2]])]]
for label, args, expected in cases[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: mixed immediates | [1005, -77, -1] | [1005, -77, -1] | Passed |
| single byte 0x7F | [-1, -1] | [127, -1] | Failed |
| five-byte u32 is the maximum length | [268435456] | [268435456] | Passed |
| six-byte u32 is too long | [['too-long', 5]] | [['too-long', 5]] | Passed |
| s32 2^31 out of range, -2^31 in range | [-2147483648, ['out-of-range', 10]] | [-2147483648, ['out-of-range', 10]] | Passed |
| u32 with bit 6 set in last byte stays positive | [-63, -8192] | [65, 8192] | Failed |
| negative s64 spanning several bytes | [-1099511627777] | [-1099511627777] | Passed |
| truncated immediate | [['unexpected-end', 2]] | [['unexpected-end', 2]] | Passed |
SHA-256 / 0303a7008590077883687ce04ddfe2b045aac6bc2c2b9968706f826ddb6146d1
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data, kinds):
pos = 0
out = []
for kind in kinds:
bits = 32 if kind in ('u32', 's32') else 64
maxlen = (bits + 6) // 7
result = 0
shift = 0
n = 0
while True:
if pos >= len(data):
return out + [['unexpected-end', pos]]
byte = data[pos]
pos += 1
n += 1
result |= (byte & 0x7F) << shift
shift += 7
if (byte & 0x80) == 0:
break
if n == maxlen:
return out + [['too-long', pos]]
if kind == 's32' and byte & 0x40:
result -= 1 << shift
if kind == 's32' and not -(1 << 31) <= result < (1 << 31):
return out + [['out-of-range', pos]]
if kind == 'u32' and result >= (1 << 32):
return out + [['out-of-range', pos]]
out.append(result)
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: mixed immediates', ([237, 7, 179, 127, 127], ['u32', 's32', 's64']), [1005, -77, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 1], ['u32']), [268435456]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 1], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([65, 128, 64], ['u32', 'u32']), [65, 8192]),
('negative s64 spanning several bytes', ([255, 255, 255, 255, 255, 95], ['s64']), [-1099511627777]),
('truncated immediate', ([128, 129], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([213, 15, 230, 126, 127], ['u32', 's32', 's64']), [2005, -154, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 2], ['u32']), [536870912]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 2], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([66, 128, 64], ['u32', 'u32']), [66, 8192]),
('negative s64 spanning several bytes', ([254, 255, 255, 255, 255, 95], ['s64']), [-1099511627778]),
('truncated immediate', ([128, 130], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([189, 23, 153, 126, 127], ['u32', 's32', 's64']), [3005, -231, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 3], ['u32']), [805306368]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 3], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([67, 128, 64], ['u32', 'u32']), [67, 8192]),
('negative s64 spanning several bytes', ([253, 255, 255, 255, 255, 95], ['s64']), [-1099511627779]),
('truncated immediate', ([128, 131], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([165, 31, 204, 125, 127], ['u32', 's32', 's64']), [4005, -308, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 4], ['u32']), [1073741824]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 4], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([68, 128, 64], ['u32', 'u32']), [68, 8192]),
('negative s64 spanning several bytes', ([252, 255, 255, 255, 255, 95], ['s64']), [-1099511627780]),
('truncated immediate', ([128, 132], ['u64']), [['unexpected-end', 2]])],
[('regression: mixed immediates', ([141, 39, 255, 124, 127], ['u32', 's32', 's64']), [5005, -385, -1]),
('single byte 0x7F', ([127, 127], ['u32', 's32']), [127, -1]),
('five-byte u32 is the maximum length', ([128, 128, 128, 128, 5], ['u32']), [1342177280]),
('six-byte u32 is too long', ([128, 128, 128, 128, 128, 0, 5], ['u32', 'u32']), [['too-long', 5]]),
('s32 2^31 out of range, -2^31 in range',
([128, 128, 128, 128, 120, 128, 128, 128, 128, 8], ['s32', 's32']),
[-2147483648, ['out-of-range', 10]]),
('u32 with bit 6 set in last byte stays positive', ([69, 128, 64], ['u32', 'u32']), [69, 8192]),
('negative s64 spanning several bytes', ([251, 255, 255, 255, 255, 95], ['s64']), [-1099511627781]),
('truncated immediate', ([128, 133], ['u64']), [['unexpected-end', 2]])]]
for label, args, expected in cases[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: mixed immediates | [1005, -77, 127] | [1005, -77, -1] | Failed |
| single byte 0x7F | [127, -1] | [127, -1] | Passed |
| five-byte u32 is the maximum length | [268435456] | [268435456] | Passed |
| six-byte u32 is too long | [['too-long', 5]] | [['too-long', 5]] | Passed |
| s32 2^31 out of range, -2^31 in range | [-2147483648, ['out-of-range', 10]] | [-2147483648, ['out-of-range', 10]] | Passed |
| u32 with bit 6 set in last byte stays positive | [65, 8192] | [65, 8192] | Passed |
| negative s64 spanning several bytes | [3298534883327] | [-1099511627777] | Failed |
| truncated immediate | [['unexpected-end', 2]] | [['unexpected-end', 2]] | Passed |
SHA-256 / 5259bee85dc1a66a6e3c1e00728627c94b9e7d36019ad56041bedd0802c82987
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
A deterministic, bounded teaching model of one bytecode virtual machine mechanism with a stipulated instruction encoding; it is not a production VM and claims no conformance to any real 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:51:24.423236+00:00.
Case digest / 429b10bff4de74e28f844a5a018dcd285639930c9ca3f1e02531cc4121208f5a