Skip to content

Fix several issues related to keyasint tag option#757

Merged
fxamacker merged 3 commits intomasterfrom
fxamacker/fix-keyasint
Mar 30, 2026
Merged

Fix several issues related to keyasint tag option#757
fxamacker merged 3 commits intomasterfrom
fxamacker/fix-keyasint

Conversation

@fxamacker
Copy link
Copy Markdown
Owner

This PR fixes several issues related to keyasint.

These issues were identified and fixed while refactoring code and tests related to keyasint.

  • DECODING: Previously, decoding a CBOR map integer key to a Go struct field using keyasint could overflow if the value is greater than math.MaxInt64. This library never encodes such CBOR map keys by using keyasint, so this involves decoding CBOR data created by other means.

    This commit rejects CBOR map integer keys that exceed math.MaxInt64 when decoding to a struct field using keyasint.

  • DECODING: Previously, decoding a CBOR map’s string key can match a Go struct field with the keyasint option if the text key matches the string representation of the integer key. For example, CBOR map key "1" can match a struct field with tag cbor:"1,keyasint".

    This commit prevents the string representation of an integer from matching the Go struct field tagged by keyasint by separating the keyasint field name and non-keyasint into separate namespaces. CBOR map integer keys are matched to struct fields with the keyasint option, and CBOR map string keys are matched to struct fields without the keyasint option.

  • ENCODING & DECODING: Previously, integer keys specified by keyasint tags were normalized after deduplication, allowing fields with the same normalized integer keys. As a result, the CBOR map integer key matched the first field with the same normalized value. Also, it was possible to encode duplicate keys with the same normalized values.

    This commit prevents duplicate integer keys by normalizing keyasint tag values before deduplication, and normalized duplicate keyasint fields are ignored. This is the same way we currently handle duplicate string-key fields, which matches the behavior of encoding/json.

This PR also updated .golangci.yml to version 2.

This commit fixes several issues related to keyasint.

These issues were identified and fixed while refactoring code
and tests related to keyasint.

1. DECODING: Previously, decoding a CBOR map integer key to a
   Go struct field using keyasint could overflow if the value
   is greater than math.MaxInt64.

   This commit rejects CBOR map integer keys that exceed
   math.MaxInt64 when decoding to a struct field using keyasint.

2. DECODING: Previously, decoding a CBOR map’s string key can match
   a Go struct field with the keyasint option if the text key matches
   the string representation of the integer key.  For example, CBOR
   map key "1" can match a struct field with tag `cbor:"1,keyasint"`.

   This commit prevents the string representation of an integer from
   matching the Go struct field tagged by keyasint by separating the
   keyasint field name and non-keyasint into separate namespaces.
   CBOR map integer keys are matched to struct fields with the keyasint
   option, and CBOR map string keys are matched to struct fields without
   the keyasint option.

3. ENCODING & DECODING: Previously, integer keys specified by keyasint
   tags were normalized after deduplication, allowing fields with the
   same normalized integer keys.  As a result, the CBOR map integer
   key matched the first field with the same normalized value.  Also,
   it was possible to encode duplicate keys with the same normalized values.

   This commit prevents duplicate integer keys by normalizing keyasint
   tag values before deduplication, and normalized duplicate keyasint
   fields are ignored.  This is the same way we currently handle
   duplicate string-key fields, which matches the behavior of encoding/json.
@fxamacker fxamacker self-assigned this Mar 30, 2026
Copy link
Copy Markdown
Contributor

@x448 x448 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

b.Fatalf("invalid test assumption: field name %q longer than 23 bytes", f.Name)
}
buf.WriteByte(byte(0x60 + len(f.Name)))
buf.WriteByte(byte(0x60 + len(f.Name))) //nolint:gosec
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not important, but the //nolint: comments should include a reason.

@fxamacker fxamacker merged commit e8b10c3 into master Mar 30, 2026
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants