Skip to content

Commit d72c677

Browse files
committed
Fix object deserialization when type is not assignable
1 parent 6d9ac62 commit d72c677

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

LiteDB.Tests/Mapper/Mapper_Tests.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using FluentAssertions;
2+
using System;
3+
using System.Reflection;
24
using Xunit;
35

46
namespace LiteDB.Tests.Mapper
@@ -17,5 +19,33 @@ public void ToDocument_ReturnsNull_WhenFail()
1719
var doc2 = _mapper.ToDocument(typeof(int[]), array);
1820
doc2.Should<BsonDocument>().Be(null);
1921
}
22+
23+
[Fact]
24+
public void Class_Not_Assignable()
25+
{
26+
using (var db = new LiteDatabase(":memory:"))
27+
{
28+
var col = db.GetCollection<MyClass>("Test");
29+
col.Insert(new MyClass { Id = 1, Member = null });
30+
var type = typeof(OtherClass);
31+
var typeName = type.FullName + ", " + type.GetTypeInfo().Assembly.GetName().Name;
32+
33+
db.Execute($"update Test set Member = {{_id: 1, Name: null, _type: \"{typeName}\"}} where _id = 1");
34+
35+
Func<MyClass> func = (() => col.FindById(1));
36+
func.Should().Throw<LiteException>();
37+
}
38+
}
39+
40+
public class MyClass
41+
{
42+
public int Id { get; set; }
43+
public MyClass Member { get; set; }
44+
}
45+
46+
public class OtherClass
47+
{
48+
public string Name { get; set; }
49+
}
2050
}
2151
}

LiteDB/Client/Mapper/BsonMapper.Deserialize.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,12 @@ public object Deserialize(Type type, BsonValue value)
167167
// test if value is object and has _type
168168
if (doc.TryGetValue("_type", out var typeField) && typeField.IsString)
169169
{
170-
type = _typeNameBinder.GetType(typeField.AsString);
170+
var actualType = _typeNameBinder.GetType(typeField.AsString);
171171

172-
if (type == null) throw LiteException.InvalidTypedName(typeField.AsString);
172+
if (actualType == null) throw LiteException.InvalidTypedName(typeField.AsString);
173+
if (!type.IsAssignableFrom(actualType)) throw LiteException.DataTypeNotAssignable(type.FullName, actualType.FullName);
174+
175+
type = actualType;
173176
}
174177
// when complex type has no definition (== typeof(object)) use Dictionary<string, object> to better set values
175178
else if (type == typeof(object))

LiteDB/Utils/LiteException.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class LiteException : Exception
5151
public const int INVALID_INITIALSIZE = 211;
5252
public const int INVALID_NULL_CHAR_STRING = 212;
5353
public const int INVALID_FREE_SPACE_PAGE = 213;
54+
public const int DATA_TYPE_NOT_ASSIGNABLE = 214;
5455

5556
#endregion
5657

@@ -306,6 +307,11 @@ internal static LiteException InvalidFreeSpacePage(uint pageID, int freeBytes, i
306307
return new LiteException(INVALID_FREE_SPACE_PAGE, $"An operation that would corrupt page {pageID} was prevented. The operation required {length} free bytes, but the page had only {freeBytes} available.");
307308
}
308309

310+
internal static LiteException DataTypeNotAssignable(string type1, string type2)
311+
{
312+
return new LiteException(DATA_TYPE_NOT_ASSIGNABLE, $"Data type {type1} is not assignable from data type {type2}");
313+
}
314+
309315
#endregion
310316
}
311317
}

0 commit comments

Comments
 (0)