Skip to content

Commit 0be5ae3

Browse files
committed
CSHARP-595: corrected issue with infinite recursion when converting a BsonValue to another BsonValue.
1 parent 40e69fe commit 0be5ae3

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed

Bson/ObjectModel/BsonValue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1543,7 +1543,7 @@ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
15431543
case BsonType.Double: return Convert.ChangeType(this.AsDouble, conversionType, provider);
15441544
case BsonType.Int32: return Convert.ChangeType(this.AsInt32, conversionType, provider);
15451545
case BsonType.Int64: return Convert.ChangeType(this.AsInt64, conversionType, provider);
1546-
case BsonType.ObjectId: return Convert.ChangeType(this, conversionType, provider);
1546+
case BsonType.ObjectId: return Convert.ChangeType(this.AsObjectId, conversionType, provider);
15471547
case BsonType.String: return Convert.ChangeType(this.AsString, conversionType, provider);
15481548
default: throw new InvalidCastException();
15491549
}

Bson/ObjectModel/ObjectId.cs

Lines changed: 103 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace MongoDB.Bson
2929
/// Represents an ObjectId (see also BsonObjectId).
3030
/// </summary>
3131
[Serializable]
32-
public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>
32+
public struct ObjectId : IComparable<ObjectId>, IEquatable<ObjectId>, IConvertible
3333
{
3434
// private static fields
3535
private static ObjectId __emptyInstance = default(ObjectId);
@@ -464,5 +464,107 @@ public override string ToString()
464464
{
465465
return BsonUtils.ToHexString(Pack(_timestamp, _machine, _pid, _increment));
466466
}
467+
468+
// explicit IConvertible implementation
469+
TypeCode IConvertible.GetTypeCode()
470+
{
471+
return TypeCode.Object;
472+
}
473+
474+
bool IConvertible.ToBoolean(IFormatProvider provider)
475+
{
476+
throw new InvalidCastException();
477+
}
478+
479+
byte IConvertible.ToByte(IFormatProvider provider)
480+
{
481+
throw new InvalidCastException();
482+
}
483+
484+
char IConvertible.ToChar(IFormatProvider provider)
485+
{
486+
throw new InvalidCastException();
487+
}
488+
489+
DateTime IConvertible.ToDateTime(IFormatProvider provider)
490+
{
491+
throw new InvalidCastException();
492+
}
493+
494+
decimal IConvertible.ToDecimal(IFormatProvider provider)
495+
{
496+
throw new InvalidCastException();
497+
}
498+
499+
double IConvertible.ToDouble(IFormatProvider provider)
500+
{
501+
throw new InvalidCastException();
502+
}
503+
504+
short IConvertible.ToInt16(IFormatProvider provider)
505+
{
506+
throw new InvalidCastException();
507+
}
508+
509+
int IConvertible.ToInt32(IFormatProvider provider)
510+
{
511+
throw new InvalidCastException();
512+
}
513+
514+
long IConvertible.ToInt64(IFormatProvider provider)
515+
{
516+
throw new InvalidCastException();
517+
}
518+
519+
sbyte IConvertible.ToSByte(IFormatProvider provider)
520+
{
521+
throw new InvalidCastException();
522+
}
523+
524+
float IConvertible.ToSingle(IFormatProvider provider)
525+
{
526+
throw new InvalidCastException();
527+
}
528+
529+
string IConvertible.ToString(IFormatProvider provider)
530+
{
531+
return ToString();
532+
}
533+
534+
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
535+
{
536+
switch (Type.GetTypeCode(conversionType))
537+
{
538+
case TypeCode.String:
539+
return ((IConvertible)this).ToString(provider);
540+
case TypeCode.Object:
541+
if (conversionType == typeof(BsonObjectId))
542+
{
543+
return new BsonObjectId(this);
544+
}
545+
if (conversionType == typeof(BsonString))
546+
{
547+
return new BsonString(((IConvertible)this).ToString(provider));
548+
}
549+
break;
550+
}
551+
552+
throw new InvalidCastException();
553+
}
554+
555+
ushort IConvertible.ToUInt16(IFormatProvider provider)
556+
{
557+
throw new InvalidCastException();
558+
}
559+
560+
uint IConvertible.ToUInt32(IFormatProvider provider)
561+
{
562+
throw new InvalidCastException();
563+
}
564+
565+
ulong IConvertible.ToUInt64(IFormatProvider provider)
566+
{
567+
throw new InvalidCastException();
568+
}
467569
}
468570
}

BsonUnitTests/BsonUnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
<Compile Include="IO\BsonDocumentWriterTests.cs" />
116116
<Compile Include="IO\JsonReaderTests.cs" />
117117
<Compile Include="IO\JsonScannerTests.cs" />
118+
<Compile Include="Jira\CSharp595Tests.cs" />
118119
<Compile Include="Jira\CSharp102Tests.cs" />
119120
<Compile Include="Jira\CSharp104Tests.cs" />
120121
<Compile Include="Jira\CSharp116Tests.cs" />

BsonUnitTests/Jira/CSharp595Tests.cs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* Copyright 2010-2012 10gen Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Generic;
18+
using System.Linq;
19+
using System.Text;
20+
using NUnit.Framework;
21+
22+
using MongoDB.Bson;
23+
using MongoDB.Bson.Serialization;
24+
25+
namespace MongoDB.BsonUnitTests.Jira.CSharp595
26+
{
27+
[TestFixture]
28+
public class CSharp595Tests
29+
{
30+
[Test]
31+
public void TestDoesNotThrowStackOverflowExceptionWhenConvertingToSelfType()
32+
{
33+
BsonObjectId id1 = BsonObjectId.GenerateNewId();
34+
BsonObjectId id2 = null;
35+
Assert.DoesNotThrow(() =>
36+
{
37+
id2 = (BsonObjectId)((IConvertible)id1).ToType(typeof(BsonObjectId), null);
38+
});
39+
40+
Assert.AreEqual(id1, id2);
41+
}
42+
43+
[Test]
44+
public void TestDoesNotThrowStackOverflowExceptionWhenConvertingToBsonString()
45+
{
46+
BsonObjectId id1 = BsonObjectId.GenerateNewId();
47+
BsonString id2 = null;
48+
Assert.DoesNotThrow(() =>
49+
{
50+
id2 = (BsonString)((IConvertible)id1).ToType(typeof(BsonString), null);
51+
});
52+
53+
Assert.AreEqual(id1.ToString(), id2.AsString);
54+
}
55+
}
56+
}

0 commit comments

Comments
 (0)