diff --git a/attributes.go b/attributes.go index ed4a9b6..f4cf261 100644 --- a/attributes.go +++ b/attributes.go @@ -162,19 +162,34 @@ func (m *Message) Get(t AttrType) ([]byte, error) { return v.Value, nil } -// AttrLengthError occurs when len(v) > Max. -type AttrLengthError struct { +// AttrOverflowErr occurs when len(v) > Max. +type AttrOverflowErr struct { Type AttrType Max int Got int } -func (e AttrLengthError) Error() string { +func (e AttrOverflowErr) Error() string { return fmt.Sprintf("Length of %s attribute %d exceeds maximum %d", e.Type, e.Got, e.Max, ) } +// AttrLengthErr means that length for attribute is invalid. +type AttrLengthErr struct { + Attr AttrType + Got int + Expected int +} + +func (e AttrLengthErr) Error() string { + return fmt.Sprintf("incorrect length for %s: got %d, expected %d", + e.Attr, + e.Got, + e.Expected, + ) +} + // STUN aligns attributes on 32-bit boundaries, attributes whose content // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of // padding so that its value contains a multiple of 4 bytes. The diff --git a/attributes_test.go b/attributes_test.go index 4612cae..9716769 100644 --- a/attributes_test.go +++ b/attributes_test.go @@ -61,7 +61,7 @@ func TestPadding(t *testing.T) { } func TestAttrLengthError_Error(t *testing.T) { - err := AttrLengthError{ + err := AttrOverflowErr{ Got: 100, Max: 50, Type: AttrLifetime, diff --git a/errorcode.go b/errorcode.go index 04fd592..2de37db 100644 --- a/errorcode.go +++ b/errorcode.go @@ -34,7 +34,11 @@ var ErrReasonLengthTooBig = errors.New("reason for ERROR-CODE is too big") func (c ErrorCodeAttribute) AddTo(m *Message) error { value := make([]byte, 0, errorCodeReasonMaxB) if len(c.Reason) > errorCodeReasonMaxB { - return ErrReasonLengthTooBig + return &AttrOverflowErr{ + Got: len(c.Reason) + errorCodeReasonStart, + Max: errorCodeReasonMaxB + errorCodeReasonStart, + Type: AttrErrorCode, + } } value = value[:errorCodeReasonStart+len(c.Reason)] number := byte(c.Code % errorCodeModulo) // error code modulo 100 diff --git a/fingerprint.go b/fingerprint.go index cedcf07..633934c 100644 --- a/fingerprint.go +++ b/fingerprint.go @@ -68,10 +68,11 @@ func (FingerprintAttr) Check(m *Message) error { return err } if len(b) != fingerprintSize { - return newDecodeErr("message", - "fingerprint", - "bad length", - ) + return &AttrLengthErr{ + Expected: fingerprintSize, + Got: len(b), + Attr: AttrFingerprint, + } } val := bin.Uint32(b) attrStart := len(m.Raw) - (fingerprintSize + attributeHeaderSize) diff --git a/fuzz.go b/fuzz.go index 5531710..e11265e 100644 --- a/fuzz.go +++ b/fuzz.go @@ -118,6 +118,10 @@ func FuzzSetters(data []byte) int { // We allow decoding some text attributes // when their length is too big, but // not encoding. + _, ok := err.(*AttrOverflowErr) + if !ok { + panic(err) + } return 1 } m3.WriteHeader() diff --git a/textattrs.go b/textattrs.go index 5f0e228..ca77a95 100644 --- a/textattrs.go +++ b/textattrs.go @@ -113,7 +113,7 @@ type TextAttribute []byte // is less than 0, no check is performed. func (v TextAttribute) AddToAs(m *Message, t AttrType, maxLen int) error { if maxLen > 0 && len(v) > maxLen { - return &AttrLengthError{ + return &AttrOverflowErr{ Max: maxLen, Got: len(v), Type: t, diff --git a/textattrs_test.go b/textattrs_test.go index e64de9e..c09c09d 100644 --- a/textattrs_test.go +++ b/textattrs_test.go @@ -38,8 +38,8 @@ func TestSoftware_GetFrom(t *testing.T) { func TestSoftware_AddTo_Invalid(t *testing.T) { m := New() s := make(Software, 1024) - if err, ok := s.AddTo(m).(*AttrLengthError); !ok { - t.Errorf("AddTo should return *AttrLengthError, got: %v", err) + if err, ok := s.AddTo(m).(*AttrOverflowErr); !ok { + t.Errorf("AddTo should return *AttrOverflowErr, got: %v", err) } if err := s.GetFrom(m); err != ErrAttributeNotFound { t.Errorf("GetFrom should return %q, got: %v", ErrAttributeNotFound, err) @@ -87,7 +87,7 @@ func TestUsername(t *testing.T) { m.WriteHeader() t.Run("Bad length", func(t *testing.T) { badU := make(Username, 600) - if err, ok := badU.AddTo(m).(*AttrLengthError); !ok { + if err, ok := badU.AddTo(m).(*AttrOverflowErr); !ok { t.Errorf("expected length error, got %v", err) } }) @@ -163,8 +163,8 @@ func TestRealm_GetFrom(t *testing.T) { func TestRealm_AddTo_Invalid(t *testing.T) { m := New() r := make(Realm, 1024) - if err, ok := r.AddTo(m).(*AttrLengthError); !ok || err.Type != AttrRealm { - t.Errorf("AddTo should return *AttrLengthError, got: %v", err) + if err, ok := r.AddTo(m).(*AttrOverflowErr); !ok || err.Type != AttrRealm { + t.Errorf("AddTo should return *AttrOverflowErr, got: %v", err) } if err := r.GetFrom(m); err != ErrAttributeNotFound { t.Errorf("GetFrom should return %q, got: %v", ErrAttributeNotFound, err) @@ -204,8 +204,8 @@ func TestNonce_GetFrom(t *testing.T) { func TestNonce_AddTo_Invalid(t *testing.T) { m := New() n := make(Nonce, 1024) - if err, ok := n.AddTo(m).(*AttrLengthError); !ok || err.Type != AttrNonce { - t.Errorf("AddTo should return *AttrLengthError, got: %v", err) + if err, ok := n.AddTo(m).(*AttrOverflowErr); !ok || err.Type != AttrNonce { + t.Errorf("AddTo should return *AttrOverflowErr, got: %v", err) } if err := n.GetFrom(m); err != ErrAttributeNotFound { t.Errorf("GetFrom should return %q, got: %v", ErrAttributeNotFound, err)