Fix several issues related to keyasint tag option#757
Merged
Conversation
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.
x448
approved these changes
Mar 30, 2026
| 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 |
Contributor
There was a problem hiding this comment.
Not important, but the //nolint: comments should include a reason.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.ymlto version 2.