Skip to content

Commit a1706a3

Browse files
reinaldocoelho_cpreinaldocoelho_cp
authored andcommitted
RFC2047 deep recursion error.
In RFC2047, there is OutputTokens method that processes recursively the tokens that were previously generated. The problem is that depending on the application and the list size, recursion provides stack overflow error. To solve, includes the concept of pages in the structure and concatenate pages at the end to avoid a very deep recursion.
1 parent 50da9b2 commit a1706a3

2 files changed

Lines changed: 50 additions & 18 deletions

File tree

Class Library/ActiveUp.Net.Common/Rfc2047/Rfc2047Codec.cs

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,36 +28,59 @@ public static string Decode(string input)
2828
if (!tokenEnumerator.MoveNext())
2929
return string.Empty;
3030

31-
var firstToken = WrapTokensAndLinkThem(tokenEnumerator);
31+
var tokenPages = WrapTokensAndLinkThem(tokenEnumerator);
3232

33-
var output = OutputTokens(firstToken);
33+
var output = "";
34+
foreach (var token in tokenPages)
35+
{
36+
output += OutputTokens(token);
37+
}
3438
if (isSurroundedByComments)
3539
return "(" + output + ")";
3640
return output;
3741
}
3842

39-
private static TokenBase WrapTokensAndLinkThem(IEnumerator<string> tokenEnumerator)
43+
private static Queue<TokenBase> WrapTokensAndLinkThem(IEnumerator<string> tokenEnumerator)
4044
{
41-
var firstToken = WrapToken(tokenEnumerator.Current);
42-
var lastWord = (firstToken is Separator) ? null : firstToken;
43-
var lastSeparator = (firstToken is Separator) ? firstToken : null;
45+
var tokenBasePages = new Queue<TokenBase>();
46+
bool mustContinue = true;
4447

45-
while (tokenEnumerator.MoveNext())
48+
// Break in pages because biggest token list made exception when process recursive OutputTokens.
49+
while (mustContinue)
4650
{
47-
var wrappedToken = WrapToken(tokenEnumerator.Current);
48-
if (wrappedToken is Separator)
51+
mustContinue = false;
52+
var firstToken = WrapToken(tokenEnumerator.Current);
53+
var lastWord = (firstToken is Separator) ? null : firstToken;
54+
var lastSeparator = (firstToken is Separator) ? firstToken : null;
55+
56+
var tokenCount = 0;
57+
while (tokenEnumerator.MoveNext())
4958
{
50-
lastWord.NextSeparator = wrappedToken;
51-
lastSeparator = wrappedToken;
52-
continue;
59+
tokenCount++;
60+
var wrappedToken = WrapToken(tokenEnumerator.Current);
61+
if (wrappedToken is Separator)
62+
{
63+
lastWord.NextSeparator = wrappedToken;
64+
lastSeparator = wrappedToken;
65+
continue;
66+
}
67+
68+
if (lastWord != null)
69+
lastWord.NextWord = wrappedToken;
70+
lastSeparator.NextWord = wrappedToken;
71+
lastWord = wrappedToken;
72+
73+
if (tokenCount >= 500)
74+
{
75+
mustContinue = true;
76+
tokenEnumerator.MoveNext();
77+
break;
78+
}
5379
}
54-
55-
if (lastWord != null)
56-
lastWord.NextWord = wrappedToken;
57-
lastSeparator.NextWord = wrappedToken;
58-
lastWord = wrappedToken;
80+
tokenBasePages.Enqueue(firstToken);
5981
}
60-
return firstToken;
82+
83+
return tokenBasePages;
6184
}
6285

6386
private static string OutputTokens(TokenBase token)

0 commit comments

Comments
 (0)