AppType.get(port, proto=<combined flag>) misses the lookup, mints an unknown member, and permanently displaces the real member in the single-bit buckets. Reproduced deterministically in a clean process:
get(7, proto=tcp) -> echo # correct
get(7, proto=tcp|udp) -> unknown (8182 -> 8183 members)
get(7, proto=tcp) -> unknown # the real member is gone
Cause
__members_proto__ (pcapkit/const/reg/apptype.py:81) is keyed on single TransportProtocol bits — tcp, udp, sctp, dccp, undefined. A combined flag is never a key, so the lookup misses, _missing_ mints an unknown member, and the registration path then files that member into each single-bit bucket the combined flag covers, overwriting whatever was there.
Impact
5,354 of 8,182 members (65%) are multi-transport, so the natural round-trip AppType.get(m.port, proto=m.proto) triggers this for most of the registry. The corruption is process-lifetime and silent.
Shipped parsing is not affected: every in-library call site passes a single bit — protocols/transport/tcp.py:615-616, udp.py:203-204, sctp.py:581-582. The hazard is the public API and anything that round-trips a member's own proto.
Notes
AppType.get(port, proto=<combined flag>)misses the lookup, mints anunknownmember, and permanently displaces the real member in the single-bit buckets. Reproduced deterministically in a clean process:Cause
__members_proto__(pcapkit/const/reg/apptype.py:81) is keyed on singleTransportProtocolbits —tcp,udp,sctp,dccp,undefined. A combined flag is never a key, so the lookup misses,_missing_mints anunknownmember, and the registration path then files that member into each single-bit bucket the combined flag covers, overwriting whatever was there.Impact
5,354 of 8,182 members (65%) are multi-transport, so the natural round-trip
AppType.get(m.port, proto=m.proto)triggers this for most of the registry. The corruption is process-lifetime and silent.Shipped parsing is not affected: every in-library call site passes a single bit —
protocols/transport/tcp.py:615-616,udp.py:203-204,sctp.py:581-582. The hazard is the public API and anything that round-trips a member's ownproto.Notes
str-keyed branch at:30622. This one is about combined flags and it displaces rather than merely mints._missing_'s 766 range branches take noprotoparameter, soget(6010, proto='udp')returns a tcp member and a second identical call raisesTypeError.