Repository navigation
Bound the ALTERNATE_TIME_OFFSET_INDICATOR displayName by the TLV length - #590
protonnegativo wants to merge 1 commit into
Conversation
The decoder required a lengthField of at least 20, but the TLV is 15 octets of fixed fields followed by a PTPText, so an empty or one-character displayName (lengthField 16 or 18) made the whole packet fail to decode. The displayName was also read from the rest of the buffer, so a text length octet larger than the TLV picked up the bytes of the next TLV. The encoder dropped the displayName length octet when the name was empty.
|
Hi @protonnegativo! Thank you for your pull request and welcome to our community. Action RequiredIn order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you. ProcessIn order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA. Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks! |
|
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks! |
|
Hi @protonnegativo! Could you please check why Fuzz test is failing on this PR? |
Summary
AlternateTimeOffsetIndicatorTLVdid not handle short displayNames correctly, in either direction.The TLV body is 15 octets of fixed fields (keyField, currentOffset, jumpSeconds, timeOfNextJump) followed by a PTPText displayName, which is 1 + N octets plus a pad octet when needed. So the smallest valid
lengthFieldis 16.UnmarshalBinaryrequiredlengthField >= 20. An ATOI with an empty displayName (lengthField16) or a one-character one (18) failed withexpected TLV ... to have length of at least 20. BecausereadTLVsreturns that error, the whole Announce failed inDecodePacket.b[tlvHeadSize+15:], which is the rest of the packet. If the text length octet claimed more than the TLV holds, the name quietly took in the bytes of the next TLV. For example, an ATOI withlengthField20 and length octet 8, followed by an ALTERNATE_RESPONSE_PORT TLV, decoded withDisplayName == "PTP\x00\x80\x01\x00\x02"and no error.MarshalBinaryTowrote only the 15 fixed octets and left out the mandatory PTPText length octet (19 bytes instead of 20).The fix:
b[tlvHeadSize+15 : tlvHeadSize+lengthField], whichcheckTLVLengthalready guarantees is in range;MarshalBinarycovers the extra octet, sotlvMinSizeis unchanged.Behaviour change worth knowing: an ATOI whose displayName length octet runs past its
lengthFieldnow returns an error instead of decoding with a garbage name, andlengthField16-19 is now accepted.Test Plan
Added three tests in
ptp/protocol/tlvs_test.go:Bytesround trip);MarshalBinaryToround trip, covers the pad octet);Without the change to
tlvs.go:With it:
Also ran
go test ./ptp/...(all ok),go vet ./ptp/protocol/,gofmt -l ptp/protocol(clean), andgo test ./ptp/protocol -run '^$' -fuzz '^FuzzDecodePacket$' -fuzztime 30s(no failures).