The ILNP nonce builders size their option with math.ceil(nonce.bit_length() // 8), which is floor division — math.ceil on an int is a no-op — so the declared length is wrong for every nonce whose bit length is not a multiple of 8.
The two sites
pcapkit/protocols/internet/hopopt.py:1889 len=math.ceil(nonce.bit_length() // 8),
pcapkit/protocols/internet/ipv6_opts.py:1892 len=math.ceil(nonce.bit_length() // 8),
Both are the ILNP Nonce option builder.
The codebase already knows the correct form, in eight other places
pcapkit/protocols/internet/hip.py:3156 len=4 + math.ceil(random.bit_length() / 8),
pcapkit/protocols/internet/hip.py:3334 pub_len = math.ceil(pub_val.bit_length() / 8)
pcapkit/protocols/internet/hip.py:4276 len=math.ceil(id.bit_length() / 8),
pcapkit/protocols/internet/hip.py:4302 len=math.ceil(id.bit_length() / 8),
pcapkit/protocols/internet/mh.py:7947 id_len = max(1, math.ceil(identifier.bit_length() / 8))
and pcapkit/protocols/internet/mh.py:7936 carries a comment that states the distinction outright:
id_len = math.ceil(identifier.bit_length() / 8) was the right …
So this is a two-site typo against an established convention, not an unresolved design question.
Measured
math.ceil(n // 8) versus math.ceil(n / 8), executed on origin/main (13a75dfcd):
value=1 bit_length=1 floor=0 correct=1 WRONG
value=2 bit_length=2 floor=0 correct=1 WRONG
value=42 bit_length=6 floor=0 correct=1 WRONG
value=127 bit_length=7 floor=0 correct=1 WRONG
value=255 bit_length=8 floor=1 correct=1
value=256 bit_length=9 floor=1 correct=2 WRONG
value=65536 bit_length=17 floor=2 correct=3 WRONG
Small nonces are the worst case, not boundary values: any nonce below 256 is sized at zero octets. Only a bit length that is an exact multiple of 8 gives the right answer.
Why the test suite does not catch it
There is no ILNP entry in EXPECTED_FAILURES in tests/protocols/test_option_roundtrip_unit.py — confirmed by importing it rather than grepping, since it is built with ** unpacking; 45 entries, none ILNP-related. So the round-trip case passes, which means it is landing on a nonce whose bit length happens to divide by 8.
That is the same blind spot that hid the identical defect in pcapkit/corekit/fields/numbers.py: #591's repair-path suite used 0xFF, 0xFFFF, 0xFFFFFFFF, 0xFFFFFFFFFFFFFFFF and 0x800001 — bit lengths 8, 16, 32, 64 and 24, every one an exact multiple of 8, precisely where floor division and the ceiling agree. A fix here needs a nonce whose bit length is not a multiple of 8, and ideally one below 256.
Notes
The ILNP nonce builders size their option with
math.ceil(nonce.bit_length() // 8), which is floor division —math.ceilon anintis a no-op — so the declared length is wrong for every nonce whose bit length is not a multiple of 8.The two sites
Both are the ILNP Nonce option builder.
The codebase already knows the correct form, in eight other places
and
pcapkit/protocols/internet/mh.py:7936carries a comment that states the distinction outright:So this is a two-site typo against an established convention, not an unresolved design question.
Measured
math.ceil(n // 8)versusmath.ceil(n / 8), executed onorigin/main(13a75dfcd):Small nonces are the worst case, not boundary values: any nonce below 256 is sized at zero octets. Only a bit length that is an exact multiple of 8 gives the right answer.
Why the test suite does not catch it
There is no ILNP entry in
EXPECTED_FAILURESintests/protocols/test_option_roundtrip_unit.py— confirmed by importing it rather than grepping, since it is built with**unpacking; 45 entries, none ILNP-related. So the round-trip case passes, which means it is landing on a nonce whose bit length happens to divide by 8.That is the same blind spot that hid the identical defect in
pcapkit/corekit/fields/numbers.py: #591's repair-path suite used0xFF,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFFand0x800001— bit lengths 8, 16, 32, 64 and 24, every one an exact multiple of 8, precisely where floor division and the ceiling agree. A fix here needs a nonce whose bit length is not a multiple of 8, and ideally one below 256.Notes
numbers.py:198; that file's fix is fix(corekit): size the width repair with a real ceiling, not a floored one (#599) #600 and does not touch these two sites, which is why this is filed separately.pcapkit/protocols/internet/hip.py:3200usesmath.ceil(… / 4)rather than/ 8. That may be deliberate — a nibble count rather than an octet count — and I have not established which, so it is recorded here as worth a look rather than as a defect.