Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 66ad089

Browse files
committed
Avoid JSON separator recursion for CWE-674
TinyJsonReader previously skipped JSON separators with a recursive ReadNextToken call, so a long separator sequence supplied to ConvertFromJson could consume one stack frame per separator and terminate the process. Change separator skipping to stay within the tokenizer loop instead, preserving the existing tokenization behavior without stack growth. Add regression coverage that converts a long separator-prefixed JSON value successfully.
1 parent 06ea249 commit 66ad089

2 files changed

Lines changed: 65 additions & 53 deletions

File tree

src/MessagePack/Internal/TinyJsonReader.cs

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -137,62 +137,64 @@ private static bool IsWordBreak(char c)
137137

138138
private void ReadNextToken()
139139
{
140-
this.SkipWhiteSpace();
141-
142-
var intChar = this.reader.Peek();
143-
if (intChar == -1)
140+
while (true)
144141
{
145-
this.TokenType = TinyJsonToken.None;
146-
return;
147-
}
142+
this.SkipWhiteSpace();
148143

149-
var c = (char)intChar;
150-
switch (c)
151-
{
152-
case '{':
153-
this.TokenType = TinyJsonToken.StartObject;
154-
return;
155-
case '}':
156-
this.TokenType = TinyJsonToken.EndObject;
157-
return;
158-
case '[':
159-
this.TokenType = TinyJsonToken.StartArray;
160-
return;
161-
case ']':
162-
this.TokenType = TinyJsonToken.EndArray;
163-
return;
164-
case '"':
165-
this.TokenType = TinyJsonToken.String;
166-
return;
167-
case '0':
168-
case '1':
169-
case '2':
170-
case '3':
171-
case '4':
172-
case '5':
173-
case '6':
174-
case '7':
175-
case '8':
176-
case '9':
177-
case '-':
178-
this.TokenType = TinyJsonToken.Number;
179-
return;
180-
case 't':
181-
this.TokenType = TinyJsonToken.True;
182-
return;
183-
case 'f':
184-
this.TokenType = TinyJsonToken.False;
185-
return;
186-
case 'n':
187-
this.TokenType = TinyJsonToken.Null;
188-
return;
189-
case ',':
190-
case ':':
191-
this.reader.Read();
192-
this.ReadNextToken();
144+
var intChar = this.reader.Peek();
145+
if (intChar == -1)
146+
{
147+
this.TokenType = TinyJsonToken.None;
193148
return;
194-
default:
195-
throw new TinyJsonException("Invalid String:" + c);
149+
}
150+
151+
var c = (char)intChar;
152+
switch (c)
153+
{
154+
case '{':
155+
this.TokenType = TinyJsonToken.StartObject;
156+
return;
157+
case '}':
158+
this.TokenType = TinyJsonToken.EndObject;
159+
return;
160+
case '[':
161+
this.TokenType = TinyJsonToken.StartArray;
162+
return;
163+
case ']':
164+
this.TokenType = TinyJsonToken.EndArray;
165+
return;
166+
case '"':
167+
this.TokenType = TinyJsonToken.String;
168+
return;
169+
case '0':
170+
case '1':
171+
case '2':
172+
case '3':
173+
case '4':
174+
case '5':
175+
case '6':
176+
case '7':
177+
case '8':
178+
case '9':
179+
case '-':
180+
this.TokenType = TinyJsonToken.Number;
181+
return;
182+
case 't':
183+
this.TokenType = TinyJsonToken.True;
184+
return;
185+
case 'f':
186+
this.TokenType = TinyJsonToken.False;
187+
return;
188+
case 'n':
189+
this.TokenType = TinyJsonToken.Null;
190+
return;
191+
case ',':
192+
case ':':
193+
this.reader.Read();
194+
continue;
195+
default:
196+
throw new TinyJsonException("Invalid String:" + c);
197+
}
196198
}
197199
}
198200

tests/MessagePack.Tests/ToJsonTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,16 @@ public void ComplexToJson()
4747
this.JsonConvert(json, LZ4Standard).Is(json);
4848
}
4949

50+
[Fact]
51+
[Trait("CWE", "674")]
52+
public void ConvertFromJsonSkipsLongSeparatorRunIteratively()
53+
{
54+
var json = new string(',', 200_000) + "null";
55+
var msgpack = MessagePackSerializer.ConvertFromJson(json);
56+
57+
MessagePackSerializer.ConvertToJson(msgpack).Is("null");
58+
}
59+
5060
[Fact]
5161
public void FloatJson()
5262
{

0 commit comments

Comments
 (0)