[JAVA-3634] Multiple reads of BsonBinary UUID return different results Created: 27/Feb/20  Updated: 28/Oct/23  Resolved: 28/Feb/20

Status: Closed
Project: Java Driver
Component/s: BSON
Affects Version/s: 3.12.1
Fix Version/s: 3.12.2, 4.0.0

Type: Bug Priority: Major - P3
Reporter: Aaron MacKenzie Assignee: Jeffrey Yemin
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Java Source File TestUuid.java    
Backwards Compatibility: Minor Change

 Description   

Issue

If a BsonBinary object is read multiple times by the UUID codec it returns a different result each time. The first read returns the correct data, all reads after are incorrect. From looking at the UuidCodec code it looks like the codec does operations on the underlying BsonBinary byte array which is causing it to change.

I originally found this issue in 3.8 and was able to reproduce it in 3.12.1. I also found that the issue only exists for the JAVA_LEGACY and C_SHARP_LEGACY UuidRepresentations.

 

Expected Behavior

When a UUID is read from a BsonBinary object, the BsonBinary object is left unchanged.

 

Steps to Reproduce

Simple test to recreate the issue. The second read's assert fails.

@Test
 public void testMultiReadUuid()
 {
   String key = "key";
   UUID uuid = UUID.randomUUID();
   UuidRepresentation uuidRepresentation = UuidRepresentation.JAVA_LEGACY;
   BsonDocument doc = new BsonDocument().append(key, new BsonBinary(uuid, uuidRepresentation));
  try (BsonReader reader = new BsonDocumentReader(doc))
   {
     reader.readStartDocument();
     reader.readName(key);
     // First read success
     Assert.assertEquals(uuid, new UuidCodec(uuidRepresentation).decode(reader, DecoderContext.builder().build()));
     reader.readEndDocument();
   }
  try (BsonReader reader = new BsonDocumentReader(doc))
   {
     reader.readStartDocument();
     reader.readName(key);
     // Second read fail
     Assert.assertEquals(uuid, new UuidCodec(uuidRepresentation).decode(reader, DecoderContext.builder().build()));
     reader.readEndDocument();
   }
 }



 Comments   
Comment by Githook User [ 28/Feb/20 ]

Author:

{'username': 'jyemin', 'name': 'Jeff Yemin', 'email': 'jeff.yemin@mongodb.com'}

Message: Add comment to BsonBinary#getData indicating that it returns the internal copy of the array

JAVA-3634
Branch: 3.12.x
https://github.com/mongodb/mongo-java-driver/commit/55391dfb21e165e75d5cfa7f89c4edbdc1ee7b88

Comment by Githook User [ 28/Feb/20 ]

Author:

{'username': 'jyemin', 'name': 'Jeff Yemin', 'email': 'jeff.yemin@mongodb.com'}

Message: UuidHelper copies the array before modifying it

Previously, the assumption was that the caller owned the array
and didn't care if it was modified, but that assumptions was
not correct

JAVA-3634
Branch: 3.12.x
https://github.com/mongodb/mongo-java-driver/commit/cfd3b5c9ad41d0028e239060ed14d0c3861d392f

Comment by Githook User [ 28/Feb/20 ]

Author:

{'name': 'Jeff Yemin', 'username': 'jyemin', 'email': 'jeff.yemin@mongodb.com'}

Message: Add comment to BsonBinary#getData indicating that it returns the internal copy of the array

JAVA-3634
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/7a5eda8d4235291df21282a674913bd846b31038

Comment by Githook User [ 28/Feb/20 ]

Author:

{'name': 'Jeff Yemin', 'username': 'jyemin', 'email': 'jeff.yemin@mongodb.com'}

Message: UuidHelper copies the array before modifying it

Previously, the assumption was that the caller owned the array
and didn't care if it was modified, but that assumptions was
not correct

JAVA-3634
Branch: master
https://github.com/mongodb/mongo-java-driver/commit/333c8a7bef5db9b27b5f5ec1dfce02e81350551f

Comment by Githook User [ 28/Feb/20 ]

Author:

{'username': 'jyemin', 'name': 'Jeff Yemin', 'email': 'jeff.yemin@mongodb.com'}

Message: Add comment to BsonBinary#getData indicating that it returns the internal copy of the array

JAVA-3634
Branch: 4.0.x
https://github.com/mongodb/mongo-java-driver/commit/bb63b1c61b497e3255dc9cd70eb164140e6be6d0

Comment by Githook User [ 28/Feb/20 ]

Author:

{'username': 'jyemin', 'name': 'Jeff Yemin', 'email': 'jeff.yemin@mongodb.com'}

Message: UuidHelper copies the array before modifying it

Previously, the assumption was that the caller owned the array
and didn't care if it was modified, but that assumptions was
not correct

JAVA-3634
Branch: 4.0.x
https://github.com/mongodb/mongo-java-driver/commit/94316953a9ba088e00cb143b62b1c5800cc6fbc4

Comment by Jeffrey Yemin [ 27/Feb/20 ]

https://github.com/jyemin/mongo-java-driver/pull/363

Comment by Jeffrey Yemin [ 27/Feb/20 ]

Oh, that's really interesting. The UuidCodec is assuming that it "owns" the BsonBinary returned from BsonReader#readBinaryData. But that contract is not specified, and in fact BsonDocumentReader returns a reference to the instance in the BsonDocument rather than a copy. So we have to decide what the contract is, and then enforce it.

Thanks for reporting this. I would actually consider it a major bug, so I'm going to leave the priority alone.

Comment by Aaron MacKenzie [ 27/Feb/20 ]

I thought I selected a minor bug but apparently not. You can change the issue to a minor priority as the issue has a workaround.

Generated at Thu Feb 08 09:00:04 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.