Skip to content

Commit

Permalink
Fixed InternetAddressList.TryParse() to fail on invalid input
Browse files Browse the repository at this point in the history
Fixes issue #762
  • Loading branch information
jstedfast committed Feb 10, 2022
1 parent 8b0c652 commit 52891c1
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 36 deletions.
42 changes: 42 additions & 0 deletions MimeKit/AddressParserFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// AddressParserFlags.cs
//
// Author: Jeffrey Stedfast <[email protected]>
//
// Copyright (c) 2013-2022 .NET Foundation and Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//

using System;

namespace MimeKit {
[Flags]
enum AddressParserFlags
{
AllowMailboxAddress = 1 << 0,
AllowGroupAddress = 1 << 1,
ThrowOnError = 1 << 2,
Internal = 1 << 3,

TryParse = AllowMailboxAddress | AllowGroupAddress,
InternalTryParse = TryParse | Internal,
Parse = TryParse | ThrowOnError
}
}
2 changes: 1 addition & 1 deletion MimeKit/GroupAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ static bool TryParse (ParserOptions options, byte[] text, ref int index, int end
if (throwOnError)
flags |= AddressParserFlags.ThrowOnError;

if (!InternetAddress.TryParse (options, text, ref index, endIndex, 0, flags, out var address)) {
if (!InternetAddress.TryParse (flags, options, text, ref index, endIndex, 0, out var address)) {
group = null;
return false;
}
Expand Down
35 changes: 13 additions & 22 deletions MimeKit/InternetAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,8 +539,9 @@ internal static bool TryParseMailbox (ParserOptions options, byte[] text, int st
return true;
}

static bool TryParseGroup (ParserOptions options, byte[] text, int startIndex, ref int index, int endIndex, int groupDepth, string name, int codepage, bool throwOnError, out InternetAddress address)
static bool TryParseGroup (AddressParserFlags flags, ParserOptions options, byte[] text, int startIndex, ref int index, int endIndex, int groupDepth, string name, int codepage, out InternetAddress address)
{
bool throwOnError = (flags & AddressParserFlags.ThrowOnError) != 0;
Encoding encoding;

try {
Expand All @@ -555,7 +556,7 @@ static bool TryParseGroup (ParserOptions options, byte[] text, int startIndex, r
while (index < endIndex && (text[index] == ':' || text[index].IsBlank ()))
index++;

if (InternetAddressList.TryParse (options, text, ref index, endIndex, true, groupDepth, throwOnError, out var members))
if (InternetAddressList.TryParse (flags | AddressParserFlags.AllowMailboxAddress, options, text, ref index, endIndex, true, groupDepth, out var members))
address = new GroupAddress (encoding, name, members);
else
address = new GroupAddress (encoding, name);
Expand All @@ -573,17 +574,7 @@ static bool TryParseGroup (ParserOptions options, byte[] text, int startIndex, r
return true;
}

[Flags]
internal enum AddressParserFlags {
AllowMailboxAddress = 1 << 0,
AllowGroupAddress = 1 << 1,
ThrowOnError = 1 << 2,

TryParse = AllowMailboxAddress | AllowGroupAddress,
Parse = TryParse | ThrowOnError
}

internal static bool TryParse (ParserOptions options, byte[] text, ref int index, int endIndex, int groupDepth, AddressParserFlags flags, out InternetAddress address)
internal static bool TryParse (AddressParserFlags flags, ParserOptions options, byte[] text, ref int index, int endIndex, int groupDepth, out InternetAddress address)
{
bool throwOnError = (flags & AddressParserFlags.ThrowOnError) != 0;
int minWordCount = options.AllowUnquotedCommasInAddresses ? 0 : 1;
Expand Down Expand Up @@ -765,7 +756,7 @@ internal static bool TryParse (ParserOptions options, byte[] text, ref int index
if (codepage == -1)
codepage = 65001;

return TryParseGroup (options, text, startIndex, ref index, endIndex, groupDepth + 1, MimeUtils.Unquote (name), codepage, throwOnError, out address);
return TryParseGroup (flags, options, text, startIndex, ref index, endIndex, groupDepth + 1, MimeUtils.Unquote (name), codepage, out address);
}

if ((flags & AddressParserFlags.AllowMailboxAddress) == 0) {
Expand Down Expand Up @@ -906,7 +897,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde
int endIndex = startIndex + length;
int index = startIndex;

if (!TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.TryParse, out address))
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, endIndex, 0, out address))
return false;

if (!ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, false)) {
Expand Down Expand Up @@ -973,7 +964,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde
int endIndex = buffer.Length;
int index = startIndex;

if (!TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.TryParse, out address))
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, endIndex, 0, out address))
return false;

if (!ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, false) || index != endIndex) {
Expand Down Expand Up @@ -1029,7 +1020,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, out InternetA
int endIndex = buffer.Length;
int index = 0;

if (!TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.TryParse, out address))
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, endIndex, 0, out address))
return false;

if (!ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, false) || index != endIndex) {
Expand Down Expand Up @@ -1080,7 +1071,7 @@ public static bool TryParse (ParserOptions options, string text, out InternetAdd
int endIndex = buffer.Length;
int index = 0;

if (!TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.TryParse, out address))
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, endIndex, 0, out address))
return false;

if (!ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, false) || index != endIndex) {
Expand Down Expand Up @@ -1140,7 +1131,7 @@ public static InternetAddress Parse (ParserOptions options, byte[] buffer, int s
int endIndex = startIndex + length;
int index = startIndex;

TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.Parse, out var address);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, endIndex, 0, out var address);

ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, true);

Expand Down Expand Up @@ -1205,7 +1196,7 @@ public static InternetAddress Parse (ParserOptions options, byte[] buffer, int s
int endIndex = buffer.Length;
int index = startIndex;

TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.Parse, out var address);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, endIndex, 0, out var address);

ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, true);

Expand Down Expand Up @@ -1264,7 +1255,7 @@ public static InternetAddress Parse (ParserOptions options, byte[] buffer)
int endIndex = buffer.Length;
int index = 0;

TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.Parse, out var address);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, endIndex, 0, out var address);

ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, true);

Expand Down Expand Up @@ -1320,7 +1311,7 @@ public static InternetAddress Parse (ParserOptions options, string text)
int endIndex = buffer.Length;
int index = 0;

TryParse (options, buffer, ref index, endIndex, 0, AddressParserFlags.Parse, out var address);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, endIndex, 0, out var address);

ParseUtils.SkipCommentsAndWhiteSpace (buffer, ref index, endIndex, true);

Expand Down
27 changes: 16 additions & 11 deletions MimeKit/InternetAddressList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -568,9 +568,9 @@ void AddressChanged (object sender, EventArgs e)
OnChanged ();
}

internal static bool TryParse (ParserOptions options, byte[] text, ref int index, int endIndex, bool isGroup, int groupDepth, bool throwOnError, out List<InternetAddress> addresses)
internal static bool TryParse (AddressParserFlags flags, ParserOptions options, byte[] text, ref int index, int endIndex, bool isGroup, int groupDepth, out List<InternetAddress> addresses)
{
var flags = throwOnError ? InternetAddress.AddressParserFlags.Parse : InternetAddress.AddressParserFlags.TryParse;
bool throwOnError = (flags & AddressParserFlags.ThrowOnError) != 0;
var list = new List<InternetAddress> ();

addresses = null;
Expand All @@ -589,7 +589,12 @@ internal static bool TryParse (ParserOptions options, byte[] text, ref int index
if (isGroup && text[index] == (byte) ';')
break;

if (!InternetAddress.TryParse (options, text, ref index, endIndex, groupDepth, flags, out var address)) {
if (!InternetAddress.TryParse (flags, options, text, ref index, endIndex, groupDepth, out var address)) {
if ((flags & AddressParserFlags.Internal) == 0) {
// Note: If flags contains the ThrowOnError flag, then InternetAddress.TryParse() would have thrown.
return false;
}

// skip this address...
while (index < endIndex && text[index] != (byte) ',' && (!isGroup || text[index] != (byte) ';'))
index++;
Expand Down Expand Up @@ -642,7 +647,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde

int index = startIndex;

if (!TryParse (options, buffer, ref index, startIndex + length, false, 0, false, out var addrlist)) {
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, startIndex + length, false, 0, out var addrlist)) {
addresses = null;
return false;
}
Expand Down Expand Up @@ -701,7 +706,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, int startInde

int index = startIndex;

if (!TryParse (options, buffer, ref index, buffer.Length, false, 0, false, out var addrlist)) {
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist)) {
addresses = null;
return false;
}
Expand Down Expand Up @@ -753,7 +758,7 @@ public static bool TryParse (ParserOptions options, byte[] buffer, out InternetA

int index = 0;

if (!TryParse (options, buffer, ref index, buffer.Length, false, 0, false, out var addrlist)) {
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist)) {
addresses = null;
return false;
}
Expand Down Expand Up @@ -802,7 +807,7 @@ public static bool TryParse (ParserOptions options, string text, out InternetAdd
var buffer = Encoding.UTF8.GetBytes (text);
int index = 0;

if (!TryParse (options, buffer, ref index, buffer.Length, false, 0, false, out var addrlist)) {
if (!TryParse (AddressParserFlags.TryParse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist)) {
addresses = null;
return false;
}
Expand Down Expand Up @@ -859,7 +864,7 @@ public static InternetAddressList Parse (ParserOptions options, byte[] buffer, i

int index = startIndex;

TryParse (options, buffer, ref index, startIndex + length, false, 0, true, out var addrlist);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, startIndex + length, false, 0, out var addrlist);

return new InternetAddressList (addrlist);
}
Expand Down Expand Up @@ -917,7 +922,7 @@ public static InternetAddressList Parse (ParserOptions options, byte[] buffer, i

int index = startIndex;

TryParse (options, buffer, ref index, buffer.Length, false, 0, true, out var addrlist);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist);

return new InternetAddressList (addrlist);
}
Expand Down Expand Up @@ -968,7 +973,7 @@ public static InternetAddressList Parse (ParserOptions options, byte[] buffer)

int index = 0;

TryParse (options, buffer, ref index, buffer.Length, false, 0, true, out var addrlist);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist);

return new InternetAddressList (addrlist);
}
Expand Down Expand Up @@ -1016,7 +1021,7 @@ public static InternetAddressList Parse (ParserOptions options, string text)
var buffer = Encoding.UTF8.GetBytes (text);
int index = 0;

TryParse (options, buffer, ref index, buffer.Length, false, 0, true, out var addrlist);
TryParse (AddressParserFlags.Parse, options, buffer, ref index, buffer.Length, false, 0, out var addrlist);

return new InternetAddressList (addrlist);
}
Expand Down
2 changes: 1 addition & 1 deletion MimeKit/MailboxAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,7 @@ internal static bool TryParse (ParserOptions options, byte[] text, ref int index
if (throwOnError)
flags |= AddressParserFlags.ThrowOnError;

if (!TryParse (options, text, ref index, endIndex, 0, flags, out var address)) {
if (!InternetAddress.TryParse (flags, options, text, ref index, endIndex, 0, out var address)) {
mailbox = null;
return false;
}
Expand Down
2 changes: 1 addition & 1 deletion MimeKit/MimeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2470,7 +2470,7 @@ void AddAddresses (Header header, InternetAddressList list)
int index = 0;

// parse the addresses in the new header and add them to our address list
if (!InternetAddressList.TryParse (Headers.Options, header.RawValue, ref index, length, false, 0, false, out var parsed))
if (!InternetAddressList.TryParse (AddressParserFlags.InternalTryParse, Headers.Options, header.RawValue, ref index, length, false, 0, out var parsed))
return;

list.Changed -= InternetAddressListChanged;
Expand Down
8 changes: 8 additions & 0 deletions UnitTests/InternetAddressListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -915,5 +915,13 @@ public void TestParseMailboxWithAddrspecAsUnquotedName ()
}

#endregion

[Test]
public void TestTryParseFailsWithInvalidAddrSpec ()
{
const string text = "[email protected]";

Assert.IsFalse (InternetAddressList.TryParse (text, out _));
}
}
}

0 comments on commit 52891c1

Please sign in to comment.