Open
Description
Go version
go version go1.24.0 darwin/amd64
Output of go env
in your module/workspace:
AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/thebinary/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/thebinary/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/5y/zx7mp2554txbzk7870s69nd00000gp/T/go-build178868391=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/Volumes/DataHD/Builds/go/src/local/mysnmp/go.mod'
GOMODCACHE='/Volumes/DataHD/Builds/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Volumes/DataHD/Builds/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/thebinary/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.24.0'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
On a 64-bit machine, I tried to Marshal
and then Unmarshal
the asn1.ObjectIdentifier
with all SubOIDs <= MaxInt32 and some SubOIDs > MaxInt32 separately
https://go.dev/play/p/4CDcLlS1LLm
What did you see happen?
For ObjectIdentifier with SubOIDs <= MaxInt32, Marshal and Unmarshal both works without any error.
But, for ObjectIdentifier with some SubOIDs > MaxInt32, Mashal
works without any error but Unmarshal
throws an error.
OUTPUT:
==== All SubOIDs <= MaxInt32 =====
INPUT=1.2.2147483647
Marshal bytes=[6 6 42 135 255 255 255 127] ; error=<nil>
Unmarshal OID=1.2.2147483647 ; error=<nil>
==== One SubOID > MaxInt32 =====
INPUT=1.2.2147483648
Marshal bytes=[6 6 42 136 128 128 128 0] ; error=<nil>
Unmarshal OID=1.2.0.0.0.0.0 ; error=asn1: structure error: base 128 integer too large
What did you expect to see?
Marshal
works, so Unmarshal
should also work.
EXPECTED OUTPUT:
==== All SubOIDs <= MaxInt32 =====
INPUT=1.2.2147483647
Marshal bytes=[6 6 42 135 255 255 255 127] ; error=<nil>
Unmarshal OID=1.2.2147483647 ; error=<nil>
==== One SubOID > MaxInt32 =====
INPUT=1.2.2147483648
Marshal bytes=[6 6 42 136 128 128 128 0] ; error=<nil>
Unmarshal OID=1.2.2147483648 ; error=<nil>
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
gabyhelp commentedon Feb 12, 2025
Related Issues
Related Code Changes
Related Discussions
(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)
thebinary commentedon Feb 12, 2025
go/src/encoding/asn1/asn1.go
Line 322 in 30f5158
I find this check is what is limiting the
Unmarshal
.The following patch resolves the issue
This will not resolve the issue for 32-bit architecture. But
Marshal
andUnmarshal
will be consistent on both the architecture for suboids greater than 2^31-1 i.e. working on 64-bit but not in 32-bit (which I suppose does wont work right now as well since ObjectIdentifier itself is defined as []int).dmitshur commentedon Feb 12, 2025
CC @golang/security.
rolandshoemaker commentedon Feb 13, 2025
We limit Unmarshal to 32 bit OID components so that we get consistent behavior across platforms, as such I don't expect we will change this to support larger components only on systems with 64 bit integers. Perhaps we should make Marshal fail just so we have parity, but that would be a breaking change.
Really, if you care about larger OIDs with large components, you should use the crypto/x509.OID type, which was explicitly designed to solve this problem.
thebinary commentedon Feb 13, 2025
Thank you for the info on
crypto/x509.OID
type.May be including the info in documentation of
asn1.ObjectIdentifier
can be beneficial, for others as well, who may stumble upon this case.Got your point. But there seems to be a catch here, in go ecosystem I have found
Marshal
andUnmarshal
being complimentary always, which breaks in this case and so is an unexpected behavior. Which I expect is at least documented.And for documenting unxpected behavior, I think we have two options:
Make no implementation changes and document the diff in Marshal and Unmarshal of asn1.ObjectIdentifier and the info to use
crypto/x509.OID
for cases where SubOIDs may be greater than MaxInt32.Allow Unmarshal in 64-bit machines like Marshal (fixing inconsistency) and document the diff in asn1.ObjectIdentifier on 32/64-bit machines and the suggestion to use
crypto/x509.OID
for architecture consistency for cases where SubOIDs may be greater than MaxInt32.