Commit 8866d6a8 authored by Jon Skeet's avatar Jon Skeet

Reject JSON containing the same oneof field twice

parent 52db5139
...@@ -895,6 +895,13 @@ namespace Google.Protobuf ...@@ -895,6 +895,13 @@ namespace Google.Protobuf
Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json)); Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
} }
[Test]
public void OneofDuplicate_Invalid()
{
string json = "{ \"oneofString\": \"x\", \"oneofUint32\": 10 }";
Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseJson(json));
}
/// <summary> /// <summary>
/// Various tests use strings which have quotes round them for parsing or as the result /// Various tests use strings which have quotes round them for parsing or as the result
/// of formatting, but without those quotes being specified in the tests (for the sake of readability). /// of formatting, but without those quotes being specified in the tests (for the sake of readability).
......
...@@ -168,6 +168,10 @@ namespace Google.Protobuf ...@@ -168,6 +168,10 @@ namespace Google.Protobuf
} }
var descriptor = message.Descriptor; var descriptor = message.Descriptor;
var jsonFieldMap = descriptor.Fields.ByJsonName(); var jsonFieldMap = descriptor.Fields.ByJsonName();
// All the oneof fields we've already accounted for - we can only see each of them once.
// The set is created lazily to avoid the overhead of creating a set for every message
// we parsed, when oneofs are relatively rare.
HashSet<OneofDescriptor> seenOneofs = null;
while (true) while (true)
{ {
token = tokenizer.Next(); token = tokenizer.Next();
...@@ -183,6 +187,17 @@ namespace Google.Protobuf ...@@ -183,6 +187,17 @@ namespace Google.Protobuf
FieldDescriptor field; FieldDescriptor field;
if (jsonFieldMap.TryGetValue(name, out field)) if (jsonFieldMap.TryGetValue(name, out field))
{ {
if (field.ContainingOneof != null)
{
if (seenOneofs == null)
{
seenOneofs = new HashSet<OneofDescriptor>();
}
if (!seenOneofs.Add(field.ContainingOneof))
{
throw new InvalidProtocolBufferException($"Multiple values specified for oneof {field.ContainingOneof.Name}");
}
}
MergeField(message, field, tokenizer); MergeField(message, field, tokenizer);
} }
else else
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment