Prevent null refs when copying a property with a null value

* Fix aspnet/AspNetCore#3559 Json Patch: System.NullReferenceException while trying to use copy operation from property with null value.

* Fix aspnet/AspNetCore#3559: Missing tests added.
This commit is contained in:
Alexander Shabunevich 2018-11-09 01:29:34 +03:00 committed by Pranav K
parent 891ae28851
commit bf9fd0d106
6 changed files with 66 additions and 4 deletions

View File

@ -229,7 +229,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Adapters
if (TryGetValue(operation.from, objectToApplyTo, operation, out var propertyValue))
{
// Create deep copy
var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue.GetType());
var copyResult = ConversionResultProvider.CopyTo(propertyValue, propertyValue?.GetType());
if (copyResult.CanBeConverted)
{
Add(operation.path,

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNetCore.JsonPatch.Internal
var targetType = typeToConvertTo;
if (value == null)
{
return new ConversionResult(IsNullableType(typeToConvertTo), null);
return new ConversionResult(canBeConverted: true, convertedInstance: null);
}
else if (typeToConvertTo.IsAssignableFrom(value.GetType()))
{

View File

@ -503,7 +503,7 @@ namespace Microsoft.AspNetCore.JsonPatch
}
/// <summary>
/// Copy the value at specified location to the target location. Willr esult in, for example:
/// Copy the value at specified location to the target location. Will result in, for example:
/// { "op": "copy", "from": "/a/b/c", "path": "/a/b/e" }
/// </summary>
/// <param name="from">source location</param>

View File

@ -159,6 +159,25 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests
Assert.Equal("A", targetObject.AnotherStringProperty);
}
[Fact]
public void CopyNullStringProperty_ToAnotherStringProperty()
{
// Arrange
dynamic targetObject = new ExpandoObject();
targetObject.StringProperty = null;
targetObject.AnotherStringProperty = "B";
var patchDocument = new JsonPatchDocument();
patchDocument.Copy("StringProperty", "AnotherStringProperty");
// Act
patchDocument.ApplyTo(targetObject);
// Assert
Assert.Null(targetObject.AnotherStringProperty);
}
[Fact]
public void MoveIntegerValue_ToAnotherIntegerProperty()
{

View File

@ -175,7 +175,30 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests
// Assert
Assert.Equal("A", targetObject.SimpleObject.AnotherStringProperty);
}
}
[Fact]
public void CopyNullStringProperty_ToAnotherStringProperty()
{
// Arrange
var targetObject = new SimpleObjectWithNestedObject()
{
SimpleObject = new SimpleObject()
{
StringProperty = null,
AnotherStringProperty = "B"
}
};
var patchDocument = new JsonPatchDocument<SimpleObjectWithNestedObject>();
patchDocument.Copy(o => o.SimpleObject.StringProperty, o => o.SimpleObject.AnotherStringProperty);
// Act
patchDocument.ApplyTo(targetObject);
// Assert
Assert.Null(targetObject.SimpleObject.AnotherStringProperty);
}
[Fact]
public void Copy_DeepClonesObject()

View File

@ -46,6 +46,26 @@ namespace Microsoft.AspNetCore.JsonPatch.IntegrationTests
Assert.Equal("A", targetObject.AnotherStringProperty);
}
[Fact]
public void CopyNullStringProperty_ToAnotherStringProperty()
{
// Arrange
var targetObject = new SimpleObject()
{
StringProperty = null,
AnotherStringProperty = "B"
};
var patchDocument = new JsonPatchDocument();
patchDocument.Copy("StringProperty", "AnotherStringProperty");
// Act
patchDocument.ApplyTo(targetObject);
// Assert
Assert.Null(targetObject.AnotherStringProperty);
}
[Fact]
public void MoveIntegerProperty_ToAnotherIntegerProperty()
{