From 65cdba0242185db6dd016c9f65818358308b95b0 Mon Sep 17 00:00:00 2001 From: Kartik Kenchi Date: Wed, 14 Oct 2026 23:08:00 +0530 Subject: [PATCH] fix: reject empty attribute type in ParseDN --- v3/dn.go | 17 +++++++++++++---- v3/dn_test.go | 4 ++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/v3/dn.go b/v3/dn.go index a1244864..9ad99efe 100644 --- a/v3/dn.go +++ b/v3/dn.go @@ -282,13 +282,21 @@ func ParseDN(str string) (*DN, error) { } var ( - rdn = &RelativeDN{} - attr = &AttributeTypeAndValue{} - escaping bool + rdn = &RelativeDN{} + attr = &AttributeTypeAndValue{} + escaping bool + // typeSet records whether the current attribute's type has been + // consumed. attr.Type being empty cannot serve as that marker: setType + // accepts a segment that decodes to the empty string, and treating the + // type as still unset would let a second '=' re-bind it, silently + // swallowing the empty leading segment ("=a=b" would parse as "a=b"). + // The empty type itself is rejected by the length checks below. + typeSet bool startPos int appendAttributesToRDN = func(end bool) { rdn.Attributes = append(rdn.Attributes, attr) attr = &AttributeTypeAndValue{} + typeSet = false if end { dn.RDNs = append(dn.RDNs, rdn) rdn = &RelativeDN{} @@ -307,10 +315,11 @@ func ParseDN(str string) (*DN, error) { escaping = false case char == '\\': escaping = true - case char == '=' && len(attr.Type) == 0: + case char == '=' && !typeSet: if err := attr.setType(str[startPos:i]); err != nil { return nil, err } + typeSet = true startPos = i + 1 case char == ',' || char == '+' || char == ';': if len(attr.Type) == 0 { diff --git a/v3/dn_test.go b/v3/dn_test.go index 81e6b732..06f912a8 100644 --- a/v3/dn_test.go +++ b/v3/dn_test.go @@ -228,6 +228,10 @@ func TestErrorDNParsing(t *testing.T) { "cn=Jim\\0Test": "failed to decode escaped character: encoding/hex: invalid byte: U+0054 'T'", "cn=Jim\\0": "failed to decode escaped character: encoding/hex: invalid byte: 0", "DC=example,=net": "DN ended with incomplete type, value pair", + "=DC=example": "DN ended with incomplete type, value pair", + "DC=example,=DC=net": "DN ended with incomplete type, value pair", + "cn=a+=cn=b": "DN ended with incomplete type, value pair", + "=cn=admin,dc=net": "incomplete type, value pair", "1=#0402486": "failed to decode BER encoding: encoding/hex: odd length hex string", "1=#0402486900": "failed to decode BER encoding: trailing bytes after value", "1=#04024869ffff,DC=net": "failed to decode BER encoding: trailing bytes after value",