Skip to content

asn1: decode Counter64 as unsigned so values >= 2^63 are not rejected (#36) - #37

Open
youdie006 wants to merge 1 commit into
roboplc:mainfrom
youdie006:fix/36-counter64-unsigned-decode
Open

asn1: decode Counter64 as unsigned so values >= 2^63 are not rejected (#36)#37
youdie006 wants to merge 1 commit into
roboplc:mainfrom
youdie006:fix/36-counter64-unsigned-decode

Conversation

@youdie006

Copy link
Copy Markdown

Fixes #36.

Problem

Counter64 is an unsigned INTEGER (0..2^64-1) (RFC 2578). A value with bit 63 set is BER-encoded with a leading 0x00 sign octet, so it occupies 9 octets. read_snmp_counter64 decoded it through the signed read_i64_type / decode_i64, which rejects anything longer than 8 octets with AsnIntOverflow.

Worse, Varbinds::next treats any decode failure as the end of the sequence, so the failing Counter64 varbind and every varbind after it are silently dropped. A response whose only high Counter64 is at the end returns zero varbinds; a u64::MAX counter in the middle of a 3-varbind response yields just one.

Fix

Decode Counter64 through a dedicated unsigned path (decode_u64) that accepts up to 8 octets, or 9 octets when the extra leading octet is the 0x00 sign pad. This is scoped to the value-decode bug; the broader Varbinds::next "treat error as end-of-sequence" behavior is left as a separate concern (as suggested in the issue).

Test

Added read_counter64_large_values covering a small value, 2^63, and u64::MAX. Red-green verified with cargo test: before the change the 2^63 / u64::MAX cases fail with AsnIntOverflow; after, they decode correctly. The full test suite passes (11 lib + 6 integration), and cargo fmt --check / cargo clippy are clean.


Disclosure: I used AI assistance (Claude) while preparing this change. I verified the encoding against RFC 2578, ran the tests (red-green) and the full suite, and take responsibility for the contribution.

Counter64 is an unsigned INTEGER (0..2^64-1). A value with bit 63 set is
BER-encoded with a leading 0x00 sign octet and therefore occupies 9 octets.
read_snmp_counter64 decoded it through the signed decode_i64, which rejects
anything longer than 8 octets with AsnIntOverflow. Because Varbinds treats a
decode error as the end of the sequence, the offending varbind and every
varbind after it were silently dropped from the response.

Decode Counter64 through a dedicated unsigned path that accepts up to 8
octets, or 9 octets when the extra leading octet is the 0x00 sign pad. Add
regression tests for 2^63 and u64::MAX.

Fixes roboplc#36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Counter64 at or above 2^63 is undecodable, and silently truncates the rest of the response

1 participant