diff options
author | Jan Tattermusch <jtattermusch@users.noreply.github.com> | 2015-11-05 18:41:05 -0800 |
---|---|---|
committer | Jan Tattermusch <jtattermusch@users.noreply.github.com> | 2015-11-05 18:41:05 -0800 |
commit | ffe25c76eac55347d74bef508410f90f01f1db85 (patch) | |
tree | fa9638179b72bf9e763d1d76993f958546869301 /csharp/src/Google.Protobuf/JsonTokenizer.cs | |
parent | 1470ced7ce6f8f5b42e0747ebbea1754db4a3310 (diff) | |
parent | 6fa17e759737e3225c6cc4ba830b921428c50781 (diff) | |
download | protobuf-ffe25c76eac55347d74bef508410f90f01f1db85.tar.gz protobuf-ffe25c76eac55347d74bef508410f90f01f1db85.tar.bz2 protobuf-ffe25c76eac55347d74bef508410f90f01f1db85.zip |
Merge pull request #941 from jskeet/recursion-limit
Add recursion limit handling to JSON parsing.
Diffstat (limited to 'csharp/src/Google.Protobuf/JsonTokenizer.cs')
-rw-r--r-- | csharp/src/Google.Protobuf/JsonTokenizer.cs | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs index 5ed1e449..6589427a 100644 --- a/csharp/src/Google.Protobuf/JsonTokenizer.cs +++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs @@ -58,6 +58,13 @@ namespace Google.Protobuf private readonly PushBackReader reader; private JsonToken bufferedToken; private State state; + private int objectDepth = 0; + + /// <summary> + /// Returns the depth of the stack, purely in objects (not collections). + /// Informally, this is the number of remaining unclosed '{' characters we have. + /// </summary> + internal int ObjectDepth { get { return objectDepth; } } internal JsonTokenizer(TextReader reader) { @@ -66,6 +73,8 @@ namespace Google.Protobuf containerStack.Push(ContainerType.Document); } + // TODO: Why do we allow a different token to be pushed back? It might be better to always remember the previous + // token returned, and allow a parameterless Rewind() method (which could only be called once, just like the current PushBack). internal void PushBack(JsonToken token) { if (bufferedToken != null) @@ -73,6 +82,14 @@ namespace Google.Protobuf throw new InvalidOperationException("Can't push back twice"); } bufferedToken = token; + if (token.Type == JsonToken.TokenType.StartObject) + { + objectDepth--; + } + else if (token.Type == JsonToken.TokenType.EndObject) + { + objectDepth++; + } } /// <summary> @@ -95,6 +112,14 @@ namespace Google.Protobuf { var ret = bufferedToken; bufferedToken = null; + if (ret.Type == JsonToken.TokenType.StartObject) + { + objectDepth++; + } + else if (ret.Type == JsonToken.TokenType.EndObject) + { + objectDepth--; + } return ret; } if (state == State.ReaderExhausted) @@ -142,10 +167,12 @@ namespace Google.Protobuf ValidateState(ValueStates, "Invalid state to read an open brace: "); state = State.ObjectStart; containerStack.Push(ContainerType.Object); + objectDepth++; return JsonToken.StartObject; case '}': ValidateState(State.ObjectAfterProperty | State.ObjectStart, "Invalid state to read a close brace: "); PopContainer(); + objectDepth--; return JsonToken.EndObject; case '[': ValidateState(ValueStates, "Invalid state to read an open square bracket: "); |