aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Skeet <jonskeet@google.com>2016-01-15 13:54:17 +0000
committerJon Skeet <jonskeet@google.com>2016-01-15 13:54:17 +0000
commit8866d6a80ed30e1ff32f1c5420f1a803c26fa13a (patch)
treea8022daaeddffe7bec332e14538b1cbff490b312
parent52db5139c4f122bbd34ef34b4103d0b650e7c218 (diff)
downloadprotobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.tar.gz
protobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.tar.bz2
protobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.zip
Reject JSON containing the same oneof field twice
-rw-r--r--csharp/src/Google.Protobuf.Test/JsonParserTest.cs7
-rw-r--r--csharp/src/Google.Protobuf/JsonParser.cs15
2 files changed, 22 insertions, 0 deletions
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index fb5e083e..bfbde364 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -895,6 +895,13 @@ namespace Google.Protobuf
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>
/// 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).
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index 92029e06..b1a24800 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -168,6 +168,10 @@ namespace Google.Protobuf
}
var descriptor = message.Descriptor;
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)
{
token = tokenizer.Next();
@@ -183,6 +187,17 @@ namespace Google.Protobuf
FieldDescriptor 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);
}
else