diff options
author | Jon Skeet <jonskeet@google.com> | 2016-01-15 13:54:17 +0000 |
---|---|---|
committer | Jon Skeet <jonskeet@google.com> | 2016-01-15 13:54:17 +0000 |
commit | 8866d6a80ed30e1ff32f1c5420f1a803c26fa13a (patch) | |
tree | a8022daaeddffe7bec332e14538b1cbff490b312 /csharp | |
parent | 52db5139c4f122bbd34ef34b4103d0b650e7c218 (diff) | |
download | protobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.tar.gz protobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.tar.bz2 protobuf-8866d6a80ed30e1ff32f1c5420f1a803c26fa13a.zip |
Reject JSON containing the same oneof field twice
Diffstat (limited to 'csharp')
-rw-r--r-- | csharp/src/Google.Protobuf.Test/JsonParserTest.cs | 7 | ||||
-rw-r--r-- | csharp/src/Google.Protobuf/JsonParser.cs | 15 |
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 |