Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GODRIVER-2796 Update ObjectIDAsHexString behavior. #1694

Merged
merged 5 commits into from
Jul 25, 2024

Conversation

qingyang-hu
Copy link
Collaborator

GODRIVER-2796

Summary

  • Update ObjectIDAsHexString behavior: disable DecodeObjectIDAsHex and return an error by default
  • Cleanup EncodeContext and DecodeContext.

Background & Motivation

@mongodb-drivers-pr-bot mongodb-drivers-pr-bot bot added the priority-3-low Low Priority PR for Review label Jun 28, 2024
Copy link
Contributor

mongodb-drivers-pr-bot bot commented Jun 28, 2024

API Change Report

./bson

incompatible changes

(*DecodeContext).BinaryAsSlice: removed
(*DecodeContext).DefaultDocumentM: removed
(*DecodeContext).UseJSONStructTags: removed
(*DecodeContext).UseLocalTimeZone: removed
(*DecodeContext).ZeroMaps: removed
(*DecodeContext).ZeroStructs: removed
(*EncodeContext).ErrorOnInlineDuplicates: removed
(*EncodeContext).NilByteSliceAsEmpty: removed
(*EncodeContext).NilMapAsEmpty: removed
(*EncodeContext).NilSliceAsEmpty: removed
(*EncodeContext).OmitZeroStruct: removed
(*EncodeContext).StringifyMapKeysWithFmt: removed
(*EncodeContext).UseJSONStructTags: removed
DecodeContext.Truncate: removed
EncodeContext.MinSize: removed
ValueCodec: removed

compatible changes

(*Decoder).ObjectIDAsHexString: added

@@ -75,6 +76,30 @@ func NewRespectNilValuesMgoRegistry() *Registry {
return reg
}

func mgoStringDecodeValue(dc DecodeContext, vr ValueReader, val reflect.Value) error {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Keep the compatible mgo behavior.

@qingyang-hu qingyang-hu marked this pull request as ready for review June 28, 2024 19:05
// TODO(GODRIVER-2796): Return an error here instead of decoding to a garbled string.
byteArray := [12]byte(oid)
str = string(byteArray[:])
return emptyValue, fmt.Errorf("decoding an object ID to a hexadecimal string is disabled by default")
Copy link
Collaborator

Choose a reason for hiding this comment

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

As noted in the GODRIVER-2796 the underlying bytes are an object id. What was the original intention of this? Is it because the hex representation requires more bytes? Here is a playground illustrating this point: https://go.dev/play/p/6Iif2VPXb3J

If we determine this is not appropriate behavior, we should update the error to be more clear about what we are preventing:

decoding an object ID to a non-hexadecimal string representation is not supported

Copy link
Collaborator

@matthewdale matthewdale Jul 19, 2024

Choose a reason for hiding this comment

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

I believe the original intent of this code in the Go Driver was for mgo compatibility. See an example of the mgo behavior here. That is supported by the context of PR #213, which added the code.

However, it's not clear why that behavior was supported by default, either in mgo or in the Go Driver. My best guess is that it was an oversight and unintentional in both cases because the result of interpreting object ID bytes as a string is almost always invalid UTF-8, which could cause issues with lots of systems.

Edit: The mgo bson.ObjectId underlying type is actually a string instead of a [12]byte, which makes it easier to unintentionally convert object ID values to a string during unmarshaling. Interestingly, both the Go Driver and mgo also support storing generic binary BSON data as a string. There's actually explicit code in mgo to decode binary as a string (see here), so that seems intentional.

@@ -14,7 +14,6 @@ import (
// stringCodec is the Codec used for string values.
type stringCodec struct {
// DecodeObjectIDAsHex specifies if object IDs should be decoded as their hex representation.
// If false, a string made from the raw object ID bytes will be used. Defaults to true.
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should note that a false value will now result in a decoding error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've added the comments in DecodeContext.

@@ -58,12 +57,10 @@ func (sc *stringCodec) decodeType(_ DecodeContext, vr ValueReader, t reflect.Typ
if err != nil {
return emptyValue, err
}
if sc.decodeObjectIDAsHex {
if sc.decodeObjectIDAsHex || dc.objectIDAsHexString {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's unclear to me how decodeObjectIDAsHex could ever be set in a non-testing environment. Can we remove this field from stringCodec?

matthewdale
matthewdale previously approved these changes Jul 19, 2024
Copy link
Collaborator

@matthewdale matthewdale left a comment

Choose a reason for hiding this comment

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

Looks good, pending resolving open comment threads. 👍

bson/decoder.go Outdated
Comment on lines 98 to 100
func (d *Decoder) DefaultDocumentD() {
d.defaultDocumentD = true
d.dc.defaultDocumentType = reflect.TypeOf(D{})
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I believe this is stale and was removed by another PR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've removed DefaultDocumentD after merging the master branch.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Both positive and negative cases are covered in "decoder_test.go".

@qingyang-hu qingyang-hu added priority-2-medium Medium Priority PR for Review and removed priority-3-low Low Priority PR for Review labels Jul 21, 2024
@matthewdale matthewdale self-requested a review July 25, 2024 17:06
Copy link
Collaborator

@matthewdale matthewdale left a comment

Choose a reason for hiding this comment

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

Looks good! 👍

@qingyang-hu qingyang-hu merged commit e31ff26 into mongodb:master Jul 25, 2024
27 of 33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
priority-2-medium Medium Priority PR for Review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants