[CSHARP-930] If any of the keys in a Dictionary contains a null character serialization fails Created: 13/Mar/14  Updated: 13/Apr/16  Resolved: 21/Mar/14

Status: Closed
Project: C# Driver
Component/s: Serialization
Affects Version/s: 1.9
Fix Version/s: 1.9

Type: Bug Priority: Minor - P4
Reporter: Blake Niemyjski Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows


Backwards Compatibility: Fully Compatible

 Description   

I came across the following error when I tried to serialize one of our documents. We submit exception documents with our product. So the following document came from a security scan of some kind.. Anyways mongo blew up and we caught the exception. We have a few hundred reports of this.

The value trying to be inserted is "\u0000\"><script>alert(309)</script>"

System.ArgumentException : Element names cannot contain nulls.
Parameter name: name
at MongoDB.Bson.IO.BsonWriter.WriteName(String name) in BsonWriter.cs: line 506
at MongoDB.Bson.Serialization.Serializers.DictionarySerializer`2.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options) in DictionaryGenericSerializer.cs: line 194
at MongoDB.Bson.Serialization.BsonClassMapSerializer.SerializeMember(BsonWriter bsonWriter, Object obj, BsonMemberMap memberMap) in BsonClassMapSerializer.cs: line 692
at MongoDB.Bson.Serialization.BsonClassMapSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options) in BsonClassMapSerializer.cs: line 432
at MongoDB.Bson.Serialization.BsonSerializer.Serialize(BsonWriter bsonWriter, Type nominalType, Object value, IBsonSerializationOptions options) in BsonSerializer.cs: line 805
at MongoDB.Bson.BsonExtensionMethods.ToJson(Object obj, Type nominalType, IBsonSerializationOptions options, JsonWriterSettings settings) in BsonExtensionMethods.cs: line 304
at MongoDB.Bson.BsonExtensionMethods.ToJson(Object obj, Type nominalType, JsonWriterSettings settings) in BsonExtensionMethods.cs: line 319
at MongoDB.Bson.BsonExtensionMethods.ToJson(Object obj, Type nominalType) in BsonExtensionMethods.cs: line 271
at MongoDB.Bson.BsonExtensionMethods.ToJson(TNominalType obj) in BsonExtensionMethods.cs: line 220



 Comments   
Comment by Githook User [ 21/Mar/14 ]

Author:

{u'username': u'rstam', u'name': u'rstam', u'email': u'robert@10gen.com'}

Message: CSHARP-930: Handle dictionary keys with null characters.
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/779ee62f294608dc7101c936b70e98055800b8a5

Comment by Blake Niemyjski [ 13/Mar/14 ]

Thanks guys for the explanation. I'll add some checks to our code before inserting to try and detect null strings. If we could get a check added into the driver to change the representation automatically that would be sweet for others who are not expecting this behavior.

Comment by Robert Stam [ 13/Mar/14 ]

In your case, the element names are coming from the representation chosen for the dictionary (property G of your class C). You can configure your POCO to use a different representation for dictionaries that will be safe even when some of the dictionary keys have nulls in them (and therefore aren't safe as element names);

public class C
{
    [BsonDictionaryOptions(Representation = DictionaryRepresentation.ArrayOfDocuments)]
    public Dictionary<string, int> G;
}

The resulting JSON will look slightly different though... so this is a schema change for your application:

{ "G" : [{ "k" : "\u0000\"><script>alert(309)</script>", "v" : 1 }] }

There arguably is a bug here though... and here's why: the default representation for a Dictionary<K,V> is Dynamic, which means that the serializer looks at the keys and determines whether the keys are safe to use as element names. If they are safe, then it uses the Document representation, otherwise it uses the ArrayOfArrays representation. The bug is that it isn't looking for nulls.

If your dictionary has keys that are not valid BSON element names, I would recommend you go ahead and force the desired safe representation (ArrayOfArrays or ArrayOfDocuments). With Dynamic some of your dictionaries might be stored as nested documents, while others might be stored as arrays of key value pairs, depending on what the key values are. By explicitly choosing the representation yourself you get a consistent representation. It's also a bit faster at runtime since it no longer has to scan the key values to decide what representation to use.

Comment by Robert Stam [ 13/Mar/14 ]

Nulls are only prohibited by the BSON spec in element names. They are fully supported in string values.

If you suspect your string data might have the occasional null character then make sure you don't use those strings as element names, but instead design your schema so that they are values instead of element names.

Comment by Craig Wilson [ 13/Mar/14 ]

Thanks for the test... MongoDB does not allow nulls inside element names as documented in the bsonspec. See the e_name and the corresponding documentation on a CSTRING.

Since C# is a unicode language, C# is taking your string and converting \u0000 to null. In turn, the .NET driver takes a null and attempts to write it as UTF-8 null. This is what is happening in your test case. It might not be what is happening in your application. You can make the test pass by using a string literal in your test case (or escaping the first slash in your unicode string).

Let me know if this makes sense or if you still think there is an issue.
Craig

Comment by Blake Niemyjski [ 13/Mar/14 ]

I've added a pull request here with a breaking unit test: https://github.com/mongodb/mongo-csharp-driver/pull/178

Generated at Wed Feb 07 21:38:13 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.