Skip to content

Commit ad3612a

Browse files
committed
Add NPE checks for lists parameters and their contents
JAVA-2265
1 parent f5c484b commit ad3612a

12 files changed

+235
-3
lines changed

driver-async/src/main/com/mongodb/async/client/AggregateIterableImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ private BsonValue getAggregateOutCollection(final List<BsonDocument> aggregateLi
196196
private List<BsonDocument> createBsonDocumentList() {
197197
List<BsonDocument> aggregateList = new ArrayList<BsonDocument>(pipeline.size());
198198
for (Bson document : pipeline) {
199+
if (document == null) {
200+
throw new IllegalArgumentException("pipeline can not contain a null value");
201+
}
199202
aggregateList.add(document.toBsonDocument(documentClass, codecRegistry));
200203
}
201204
return aggregateList;

driver-async/src/main/com/mongodb/async/client/MongoCollectionImpl.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,13 @@ public void bulkWrite(final List<? extends WriteModel<? extends TDocument>> requ
261261
@Override
262262
public void bulkWrite(final List<? extends WriteModel<? extends TDocument>> requests, final BulkWriteOptions options,
263263
final SingleResultCallback<BulkWriteResult> callback) {
264+
notNull("requests", requests);
264265
List<WriteRequest> writeRequests = new ArrayList<WriteRequest>(requests.size());
265266
for (WriteModel<? extends TDocument> writeModel : requests) {
266267
WriteRequest writeRequest;
267-
if (writeModel instanceof InsertOneModel) {
268+
if (writeModel == null) {
269+
throw new IllegalArgumentException("requests can not contain a null value");
270+
} else if (writeModel instanceof InsertOneModel) {
268271
TDocument document = ((InsertOneModel<TDocument>) writeModel).getDocument();
269272
if (getCodec() instanceof CollectibleCodec) {
270273
((CollectibleCodec<TDocument>) getCodec()).generateIdIfAbsentFromDocument(document);
@@ -338,8 +341,12 @@ public void insertMany(final List<? extends TDocument> documents, final SingleRe
338341
@Override
339342
public void insertMany(final List<? extends TDocument> documents, final InsertManyOptions options,
340343
final SingleResultCallback<Void> callback) {
344+
notNull("documents", documents);
341345
List<InsertRequest> requests = new ArrayList<InsertRequest>(documents.size());
342346
for (TDocument document : documents) {
347+
if (document == null) {
348+
throw new IllegalArgumentException("documents can not contain a null value");
349+
}
343350
if (getCodec() instanceof CollectibleCodec) {
344351
document = ((CollectibleCodec<TDocument>) getCodec()).generateIdIfAbsentFromDocument(document);
345352
}
@@ -502,6 +509,9 @@ public void createIndexes(final List<IndexModel> indexes, final SingleResultCall
502509

503510
List<IndexRequest> indexRequests = new ArrayList<IndexRequest>(indexes.size());
504511
for (IndexModel model : indexes) {
512+
if (model == null) {
513+
throw new IllegalArgumentException("indexes can not contain a null value");
514+
}
505515
indexRequests.add(new IndexRequest(toBsonDocument(model.getKeys()))
506516
.name(model.getOptions().getName())
507517
.background(model.getOptions().isBackground())

driver-async/src/main/com/mongodb/async/client/MongoDatabaseImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,12 @@ public void createView(final String viewName, final String viewOn, final List<?
217217
}
218218

219219
private List<BsonDocument> createBsonDocumentList(final List<? extends Bson> pipeline) {
220+
notNull("pipeline", pipeline);
220221
List<BsonDocument> bsonDocumentPipeline = new ArrayList<BsonDocument>(pipeline.size());
221222
for (Bson obj : pipeline) {
223+
if (obj == null) {
224+
throw new IllegalArgumentException("pipeline can not contain a null value");
225+
}
222226
bsonDocumentPipeline.add(obj.toBsonDocument(BsonDocument.class, codecRegistry));
223227
}
224228
return bsonDocumentPipeline;

driver-async/src/test/unit/com/mongodb/async/client/AggregateIterableSpecification.groovy

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,16 @@ class AggregateIterableSpecification extends Specification {
304304

305305
then:
306306
thrown(IllegalArgumentException)
307+
308+
when:
309+
def results = new FutureResultCallback()
310+
mongoIterable = new AggregateIterableImpl(namespace, Document, Document, codecRegistry, readPreference,
311+
readConcern, writeConcern, Stub(AsyncOperationExecutor), [null])
312+
mongoIterable.into(target, results)
313+
results.get()
314+
315+
then:
316+
thrown(IllegalArgumentException)
307317
}
308318

309319
}

driver-async/src/test/unit/com/mongodb/async/client/MongoCollectionSpecification.groovy

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.mongodb.WriteConcernResult
2929
import com.mongodb.WriteError
3030
import com.mongodb.async.AsyncBatchCursor
3131
import com.mongodb.async.FutureResultCallback
32+
import com.mongodb.async.SingleResultCallback
3233
import com.mongodb.bulk.BulkWriteError
3334
import com.mongodb.bulk.BulkWriteResult
3435
import com.mongodb.bulk.BulkWriteUpsert
@@ -59,6 +60,7 @@ import com.mongodb.client.model.UpdateOptions
5960
import com.mongodb.client.result.DeleteResult
6061
import com.mongodb.client.result.UpdateResult
6162
import com.mongodb.client.test.Worker
63+
import com.mongodb.operation.AsyncOperationExecutor
6264
import com.mongodb.operation.CountOperation
6365
import com.mongodb.operation.CreateIndexesOperation
6466
import com.mongodb.operation.DistinctOperation
@@ -334,6 +336,26 @@ class MongoCollectionSpecification extends Specification {
334336
readConcern, writeConcern, executor, [new Document('$match', 1)]))
335337
}
336338

339+
def 'should validate the aggregation pipeline data correctly'() {
340+
given:
341+
def executor = new TestOperationExecutor([])
342+
def collection = new MongoCollectionImpl(namespace, Document, codecRegistry, readPreference, writeConcern, readConcern, executor)
343+
344+
when:
345+
collection.aggregate(null)
346+
347+
then:
348+
thrown(IllegalArgumentException)
349+
350+
when:
351+
def results = new FutureResultCallback()
352+
collection.aggregate([null]).into([], results)
353+
results.get()
354+
355+
then:
356+
thrown(IllegalArgumentException)
357+
}
358+
337359
def 'should create MapReduceIterable correctly'() {
338360
given:
339361
def executor = new TestOperationExecutor([])
@@ -418,6 +440,18 @@ class MongoCollectionSpecification extends Specification {
418440
def executor = new TestOperationExecutor([new MongoException('failure')])
419441
def collection = new MongoCollectionImpl(namespace, Document, codecRegistry, readPreference, writeConcern, readConcern, executor)
420442

443+
when:
444+
collection.bulkWrite(null, new FutureResultCallback<BulkWriteResult>())
445+
446+
then:
447+
thrown(IllegalArgumentException)
448+
449+
when:
450+
collection.bulkWrite([null], new FutureResultCallback<BulkWriteResult>())
451+
452+
then:
453+
thrown(IllegalArgumentException)
454+
421455
when: 'a codec is missing its acceptable to immediately throw'
422456
collection.bulkWrite([new InsertOneModel(new Document('_id', 1))], new FutureResultCallback<BulkWriteResult>())
423457

@@ -516,6 +550,25 @@ class MongoCollectionSpecification extends Specification {
516550
WriteConcern.UNACKNOWLEDGED | new TestOperationExecutor([unacknowledged(), unacknowledged(), unacknowledged()])
517551
}
518552

553+
def 'should validate the insertMany data correctly'() {
554+
given:
555+
def collection = new MongoCollectionImpl(namespace, Document, codecRegistry, readPreference, writeConcern, readConcern,
556+
Stub(AsyncOperationExecutor))
557+
def callback = Stub(SingleResultCallback)
558+
559+
when:
560+
collection.insertMany(null, callback)
561+
562+
then:
563+
thrown(IllegalArgumentException)
564+
565+
when:
566+
collection.insertMany([null], callback)
567+
568+
then:
569+
thrown(IllegalArgumentException)
570+
}
571+
519572
def 'deleteOne should use MixedBulkWriteOperation correctly'() {
520573
given:
521574
def collection = new MongoCollectionImpl(namespace, Document, codecRegistry, readPreference, writeConcern, readConcern, executor)
@@ -1045,6 +1098,25 @@ class MongoCollectionSpecification extends Specification {
10451098
indexName == 'aIndex'
10461099
}
10471100

1101+
def 'should validate the createIndexes data correctly'() {
1102+
given:
1103+
def collection = new MongoCollectionImpl(namespace, Document, codecRegistry, readPreference, writeConcern, readConcern,
1104+
Stub(AsyncOperationExecutor))
1105+
def callback = Stub(SingleResultCallback)
1106+
1107+
when:
1108+
collection.createIndexes(null, callback)
1109+
1110+
then:
1111+
thrown(IllegalArgumentException)
1112+
1113+
when:
1114+
collection.createIndexes([null], callback)
1115+
1116+
then:
1117+
thrown(IllegalArgumentException)
1118+
}
1119+
10481120
def 'should use ListIndexesOperations correctly'() {
10491121
given:
10501122
def asyncCursor = Stub(AsyncBatchCursor) {

driver-async/src/test/unit/com/mongodb/async/client/MongoDatabaseSpecification.groovy

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ import com.mongodb.MongoNamespace
2020
import com.mongodb.ReadConcern
2121
import com.mongodb.WriteConcern
2222
import com.mongodb.async.FutureResultCallback
23+
import com.mongodb.async.SingleResultCallback
2324
import com.mongodb.client.model.Collation
2425
import com.mongodb.client.model.CreateCollectionOptions
2526
import com.mongodb.client.model.CreateViewOptions
2627
import com.mongodb.client.model.IndexOptionDefaults
2728
import com.mongodb.client.model.ValidationAction
2829
import com.mongodb.client.model.ValidationLevel
2930
import com.mongodb.client.model.ValidationOptions
31+
import com.mongodb.operation.AsyncOperationExecutor
3032
import com.mongodb.operation.CommandReadOperation
3133
import com.mongodb.operation.CreateCollectionOperation
3234
import com.mongodb.operation.CreateViewOperation
@@ -283,6 +285,26 @@ class MongoDatabaseSpecification extends Specification {
283285
[new BsonDocument('$match', new BsonDocument('x', BsonBoolean.TRUE))], writeConcern).collation(collation))
284286
}
285287

288+
def 'should validate the createView pipeline data correctly'() {
289+
given:
290+
def viewName = 'view1'
291+
def viewOn = 'col1'
292+
def database = new MongoDatabaseImpl(name, codecRegistry, readPreference, writeConcern, readConcern, Stub(AsyncOperationExecutor))
293+
def callback = Stub(SingleResultCallback)
294+
295+
when:
296+
database.createView(viewName, viewOn, null, callback)
297+
298+
then:
299+
thrown(IllegalArgumentException)
300+
301+
when:
302+
database.createView(viewName, viewOn, [null], callback)
303+
304+
then:
305+
thrown(IllegalArgumentException)
306+
}
307+
286308
def 'should pass the correct options to getCollection'() {
287309
given:
288310
def codecRegistry = fromProviders([new BsonValueCodecProvider()])

driver/src/main/com/mongodb/AggregateIterableImpl.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ private AggregateToCollectionOperation createAggregateToCollectionOperation(fina
185185
private List<BsonDocument> createBsonDocumentList(final List<? extends Bson> pipeline) {
186186
List<BsonDocument> aggregateList = new ArrayList<BsonDocument>(pipeline.size());
187187
for (Bson obj : pipeline) {
188+
if (obj == null) {
189+
throw new IllegalArgumentException("pipeline can not contain a null value");
190+
}
188191
aggregateList.add(obj.toBsonDocument(documentClass, codecRegistry));
189192
}
190193
return aggregateList;

driver/src/main/com/mongodb/MongoCollectionImpl.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,10 +251,13 @@ public BulkWriteResult bulkWrite(final List<? extends WriteModel<? extends TDocu
251251
@Override
252252
@SuppressWarnings("unchecked")
253253
public BulkWriteResult bulkWrite(final List<? extends WriteModel<? extends TDocument>> requests, final BulkWriteOptions options) {
254+
notNull("requests", requests);
254255
List<WriteRequest> writeRequests = new ArrayList<WriteRequest>(requests.size());
255256
for (WriteModel<? extends TDocument> writeModel : requests) {
256257
WriteRequest writeRequest;
257-
if (writeModel instanceof InsertOneModel) {
258+
if (writeModel == null) {
259+
throw new IllegalArgumentException("requests can not contain a null value");
260+
} else if (writeModel instanceof InsertOneModel) {
258261
TDocument document = ((InsertOneModel<TDocument>) writeModel).getDocument();
259262
if (getCodec() instanceof CollectibleCodec) {
260263
document = ((CollectibleCodec<TDocument>) getCodec()).generateIdIfAbsentFromDocument(document);
@@ -306,6 +309,7 @@ public void insertOne(final TDocument document) {
306309

307310
@Override
308311
public void insertOne(final TDocument document, final InsertOneOptions options) {
312+
notNull("document", document);
309313
TDocument insertDocument = document;
310314
if (getCodec() instanceof CollectibleCodec) {
311315
insertDocument = ((CollectibleCodec<TDocument>) getCodec()).generateIdIfAbsentFromDocument(document);
@@ -320,8 +324,12 @@ public void insertMany(final List<? extends TDocument> documents) {
320324

321325
@Override
322326
public void insertMany(final List<? extends TDocument> documents, final InsertManyOptions options) {
327+
notNull("documents", documents);
323328
List<InsertRequest> requests = new ArrayList<InsertRequest>(documents.size());
324329
for (TDocument document : documents) {
330+
if (document == null) {
331+
throw new IllegalArgumentException("documents can not contain a null value");
332+
}
325333
if (getCodec() instanceof CollectibleCodec) {
326334
document = ((CollectibleCodec<TDocument>) getCodec()).generateIdIfAbsentFromDocument(document);
327335
}
@@ -453,9 +461,11 @@ public String createIndex(final Bson keys, final IndexOptions indexOptions) {
453461
@Override
454462
public List<String> createIndexes(final List<IndexModel> indexes) {
455463
notNull("indexes", indexes);
456-
457464
List<IndexRequest> indexRequests = new ArrayList<IndexRequest>(indexes.size());
458465
for (IndexModel model : indexes) {
466+
if (model == null) {
467+
throw new IllegalArgumentException("indexes can not contain a null value");
468+
}
459469
indexRequests.add(new IndexRequest(toBsonDocument(model.getKeys()))
460470
.name(model.getOptions().getName())
461471
.background(model.getOptions().isBackground())

driver/src/main/com/mongodb/MongoDatabaseImpl.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,12 @@ public void createView(final String viewName, final String viewOn, final List<?
210210
}
211211

212212
private List<BsonDocument> createBsonDocumentList(final List<? extends Bson> pipeline) {
213+
notNull("pipeline", pipeline);
213214
List<BsonDocument> bsonDocumentPipeline = new ArrayList<BsonDocument>(pipeline.size());
214215
for (Bson obj : pipeline) {
216+
if (obj == null) {
217+
throw new IllegalArgumentException("pipeline can not contain a null value");
218+
}
215219
bsonDocumentPipeline.add(obj.toBsonDocument(BsonDocument.class, codecRegistry));
216220
}
217221
return bsonDocumentPipeline;

driver/src/test/unit/com/mongodb/AggregateIterableSpecification.groovy

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,13 @@ class AggregateIterableSpecification extends Specification {
148148

149149
then:
150150
thrown(CodecConfigurationException)
151+
152+
when: 'pipeline contains null'
153+
new AggregateIterableImpl(namespace, Document, Document, codecRegistry, readPreference, readConcern, writeConcern, executor,
154+
[null]).iterator()
155+
156+
then:
157+
thrown(IllegalArgumentException)
151158
}
152159

153160
def 'should follow the MongoIterable interface as expected'() {

0 commit comments

Comments
 (0)