1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Core - Hardened data model paths against hidden inherited members

This commit is contained in:
Robert 2021-05-25 23:58:44 +02:00
parent 42fdf44df9
commit bb55f2e1bb

View File

@ -17,6 +17,7 @@ namespace Artemis.Core
private DataModel? _dynamicDataModel; private DataModel? _dynamicDataModel;
private Type? _dynamicDataModelType; private Type? _dynamicDataModelType;
private DataModelPropertyAttribute? _dynamicDataModelAttribute; private DataModelPropertyAttribute? _dynamicDataModelAttribute;
private PropertyInfo? _property;
internal DataModelPathSegment(DataModelPath dataModelPath, string identifier, string path) internal DataModelPathSegment(DataModelPath dataModelPath, string identifier, string path)
{ {
@ -99,7 +100,7 @@ namespace Artemis.Core
return null; return null;
// If this is not the first segment in a path, the property is located on the previous segment // If this is not the first segment in a path, the property is located on the previous segment
return Previous?.GetPropertyType()?.GetProperty(Identifier); return Previous?.GetPropertyType()?.GetProperties().FirstOrDefault(p => p.Name == Identifier);
} }
/// <summary> /// <summary>
@ -209,14 +210,18 @@ namespace Artemis.Core
accessorExpression = expression; accessorExpression = expression;
// A static segment just needs to access the property or filed // A static segment just needs to access the property or filed
else if (Type == DataModelPathSegmentType.Static) else if (Type == DataModelPathSegmentType.Static)
accessorExpression = Expression.PropertyOrField(expression, Identifier); {
accessorExpression = _property != null
? Expression.Property(expression, _property)
: Expression.PropertyOrField(expression, Identifier);
}
// A dynamic segment calls the generic method DataModel.DynamicChild<T> and provides the identifier as an argument // A dynamic segment calls the generic method DataModel.DynamicChild<T> and provides the identifier as an argument
else else
{ {
accessorExpression = Expression.Call( accessorExpression = Expression.Call(
expression, expression,
nameof(DataModel.GetDynamicChildValue), nameof(DataModel.GetDynamicChildValue),
_dynamicDataModelType != null ? new[] { _dynamicDataModelType } : null, _dynamicDataModelType != null ? new[] {_dynamicDataModelType} : null,
Expression.Constant(Identifier) Expression.Constant(Identifier)
); );
} }
@ -243,8 +248,11 @@ namespace Artemis.Core
private void DetermineStaticType(Type previousType) private void DetermineStaticType(Type previousType)
{ {
PropertyInfo? property = previousType.GetProperty(Identifier, BindingFlags.Public | BindingFlags.Instance); // Situations in which AmbiguousMatchException occurs ...
Type = property == null ? DataModelPathSegmentType.Invalid : DataModelPathSegmentType.Static; //
// ...derived type declares a property that hides an inherited property with the same name, by using the new modifier
_property = previousType.GetProperties(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(p => p.Name == Identifier);
Type = _property == null ? DataModelPathSegmentType.Invalid : DataModelPathSegmentType.Static;
} }
#region IDisposable #region IDisposable