Skip to content

Commit a0d854f

Browse files
Yoonena-ji
authored andcommitted
Prevented cloning immutable Mongo objects
1 parent e8e0a3d commit a0d854f

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

dd-java-agent/instrumentation/mongo/common/src/main/java/datadog/trace/instrumentation/mongo/MongoCommentInjector.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ public static BsonDocument injectComment(String dbmComment, CommandStartedEvent
2828
return event != null ? event.getCommand() : null;
2929
}
3030

31-
BsonDocument command = event.getCommand().clone();
31+
// Create a mutable copy by constructing a new BsonDocument and copying all entries
32+
// This handles both regular BsonDocument and immutable RawBsonDocument/ByteBufBsonDocument
33+
BsonDocument command = new BsonDocument();
34+
command.putAll(event.getCommand());
3235

3336
try {
3437
for (String commentKey : new String[] {"comment", "$comment"}) {

dd-java-agent/instrumentation/mongo/common/src/test/groovy/MongoCommentInjectorTest.groovy

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package datadog.trace.instrumentation.mongo
22

3+
import com.mongodb.event.CommandStartedEvent
34
import datadog.trace.agent.test.InstrumentationSpecification
45
import datadog.trace.api.config.TraceInstrumentationConfig
56
import datadog.trace.api.sampling.PrioritySampling
67
import org.bson.BsonDocument
78
import org.bson.BsonString
9+
import org.bson.RawBsonDocument
810

911
class MongoCommentInjectorTest extends InstrumentationSpecification {
1012
@Override
@@ -99,4 +101,69 @@ class MongoCommentInjectorTest extends InstrumentationSpecification {
99101
comment.contains("ddh='localhost'")
100102
comment.contains("dddb='testdb'")
101103
}
104+
105+
def "injectComment handles immutable RawBsonDocument"() {
106+
setup:
107+
// Enable DBM propagation for this test
108+
injectSysConfig(TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE, "service")
109+
110+
// Create a RawBsonDocument (immutable) by encoding a regular BsonDocument
111+
def mutableDoc = new BsonDocument("find", new BsonString("collection"))
112+
def rawDoc = new RawBsonDocument(mutableDoc, new org.bson.codecs.BsonDocumentCodec())
113+
def dbmComment = "dddbs='test-service',dde='test'"
114+
115+
// Verify RawBsonDocument.clone() returns immutable document
116+
def cloned = rawDoc.clone()
117+
when:
118+
cloned.put("test", new BsonString("value"))
119+
then:
120+
thrown(UnsupportedOperationException)
121+
122+
when:
123+
// Create CommandStartedEvent with RawBsonDocument
124+
def event = new CommandStartedEvent(
125+
1, // requestId
126+
null, // connectionDescription
127+
"testdb", // databaseName
128+
"find", // commandName
129+
rawDoc // command (immutable)
130+
)
131+
132+
// This should NOT throw UnsupportedOperationException with the fix
133+
BsonDocument result = MongoCommentInjector.injectComment(dbmComment, event)
134+
135+
then:
136+
// Should successfully inject comment
137+
result != null
138+
result.containsKey("comment")
139+
result.get("comment").asString().getValue() == dbmComment
140+
// Should be a different object (not the immutable original)
141+
!result.is(rawDoc)
142+
}
143+
144+
def "injectComment handles mutable BsonDocument"() {
145+
setup:
146+
// Enable DBM propagation for this test
147+
injectSysConfig(TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE, "service")
148+
149+
def originalCommand = new BsonDocument("find", new BsonString("collection"))
150+
def dbmComment = "dddbs='test-service',dde='test'"
151+
152+
def event = new CommandStartedEvent(
153+
1, // requestId
154+
null, // connectionDescription
155+
"testdb", // databaseName
156+
"find", // commandName
157+
originalCommand // command (mutable)
158+
)
159+
160+
when:
161+
BsonDocument result = MongoCommentInjector.injectComment(dbmComment, event)
162+
163+
then:
164+
result != null
165+
result.containsKey("comment")
166+
result.get("comment").asString().getValue() == dbmComment
167+
!result.is(originalCommand)
168+
}
102169
}

0 commit comments

Comments
 (0)