coding: rewrite _asn1_tag_der() to avoid the tag buffer overrun (#49)

Rewrites _asn1_tag_der() so the one-byte overrun in the old reverse-copy loop (issue #49) is impossible by construction. Since ASN1_MAX_TAG_SIZE (4) only ever leaves room for one, two, or three base-128 tag digits, the long form is spelled out directly as one branch per length — most significant digit first, writing straight to the output with no scratch buffer and no loops — as suggested by @jas in the issue.

Tag numbers too large to fit in ASN1_MAX_TAG_SIZE bytes (greater than 2^21 - 1) are now rejected with ASN1_VALUE_NOT_VALID in _asn1_insert_tag_der(). Previously such a tag made _asn1_tag_der() write one byte past the end of its 4-byte buffer (a bounded, one-byte stack overflow whose value is the tag's low 7 bits) while still reporting success. A compile-time guard requires ASN1_MAX_TAG_SIZE == 4, which the unrolled branches assume, so the build breaks loudly rather than silently mis-encoding if that size is ever changed.

Adds tests/Test_tag.c covering:

  • positive: [APPLICATION 200000] (needs the full three base-128 tag bytes) and [APPLICATION 2097151] (the largest representable tag number) encode to their known-good DER;
  • negative: [APPLICATION 2097152] and [APPLICATION 4294967295] (tags too large to encode) are rejected with ASN1_VALUE_NOT_VALID. Before the rewrite, [APPLICATION 2097152] made _asn1_tag_der() emit a five-byte tag — one byte past its ASN1_MAX_TAG_SIZE buffer — and AddressSanitizer reported a stack-buffer-overflow.

Closes #49

Edited by Thomas Grainger

Merge request reports

Loading