A bare builtins.ValueError escapes NumberField on the most common negative-length schema shape — the same class of defect #805 set out to eliminate, and one that neither #811's guard nor #827's refinement can see, because it fires before FieldBase.length is ever consulted.
NumberField.__call__ sets self._bit_length = self._length * 8 and then evaluates 1 << self._bit_length whenever bit_length was not supplied. With the shape used at pcapkit/protocols/schema/internet/hip.py:734 — NumberField(length=lambda pkt: pkt['len'] - 4, signed=False) — measured on 3.14:
len= 8 -> resolved= 4 template='>I' .length=4
len= 4 -> resolved= 0 template='>0s' .length=0
len= 3 -> resolved=-1 ValueError: negative shift count is BaseError=False
len= 0 -> resolved=-4 ValueError: negative shift count is BaseError=False
is BaseError=False is the problem: a caller cannot catch this as a pcapkit error, which is exactly what #805/#811 were about. A truncated or malformed len field on the wire is enough to trigger it.
Same live shape at hopopt.py:722, hip.py:758, :760, :823, :1325, :1338, and ipv6_opts.py:727.
The fix belongs where the shift happens — validate the resolved length before computing bit_length, and raise ProtocolError from pcapkit.utilities.exceptions naming the field and the resolved value, consistent with what FieldBase.length now does for a negative template.
Found by #827's cross-review while checking that PR's regex, and reproduced here independently. Worth noting that #827's docstring reasoning surveys "every template this package builds from a resolved field length" and walks past this path, since it never reaches a template at all.
A bare
builtins.ValueErrorescapesNumberFieldon the most common negative-length schema shape — the same class of defect #805 set out to eliminate, and one that neither #811's guard nor #827's refinement can see, because it fires beforeFieldBase.lengthis ever consulted.NumberField.__call__setsself._bit_length = self._length * 8and then evaluates1 << self._bit_lengthwheneverbit_lengthwas not supplied. With the shape used atpcapkit/protocols/schema/internet/hip.py:734—NumberField(length=lambda pkt: pkt['len'] - 4, signed=False)— measured on 3.14:is BaseError=Falseis the problem: a caller cannot catch this as apcapkiterror, which is exactly what#805/#811 were about. A truncated or malformedlenfield on the wire is enough to trigger it.Same live shape at
hopopt.py:722,hip.py:758,:760,:823,:1325,:1338, andipv6_opts.py:727.The fix belongs where the shift happens — validate the resolved length before computing
bit_length, and raiseProtocolErrorfrompcapkit.utilities.exceptionsnaming the field and the resolved value, consistent with whatFieldBase.lengthnow does for a negative template.Found by #827's cross-review while checking that PR's regex, and reproduced here independently. Worth noting that #827's docstring reasoning surveys "every template this package builds from a resolved field length" and walks past this path, since it never reaches a template at all.