-
Notifications
You must be signed in to change notification settings - Fork 19
Delegates
The Logical Analyzer has 4 Delegate extensibility points. These allow you to extend the functionality of Logical Analyzer to your own custom operations and arbitrary complex objects.
The property parsing delegate provides a way to parse object types that Logical Analyzer doesn't support natively.
public delegate (bool Processed, object? Result) PropertyExtractionDelegate(object? obj, string index);
As an example, in Attack Surface Analyzer we extend Logical Analyzer property parsing to support our usage of TpmAlgId in dictionaries. link
public static (bool, object?) ParseCustomAsaProperties(object? obj, string index)
{
switch (obj)
{
case Dictionary<(TpmAlgId, uint), byte[]> algDict:
var elements = Convert.ToString(index, CultureInfo.InvariantCulture)?.Trim('(').Trim(')').Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (Enum.TryParse(typeof(TpmAlgId), elements.First(), out object? result) &&
result is TpmAlgId Algorithm && uint.TryParse(elements.Last(), out uint Index) &&
algDict.TryGetValue((Algorithm, Index), out byte[]? byteArray))
{
return (true, byteArray);
}
else
{
return (true, null);
}
}
return (false, null);
}
The value extraction property provides an extension mechanism to provide a way to turn an object into extracted strings for Logical Analyzer to compare.
public delegate (bool Processed, IEnumerable<string> valsExtracted, IEnumerable<KeyValuePair<string, string>> dictExtracted) ObjectToValuesDelegate(object? obj);
In Attack Surface Analyzer we also extend Value extraction to support our usage of TpmAlgId in dictionaries. link
public static (bool Processed, IEnumerable<string> valsExtracted, IEnumerable<KeyValuePair<string, string>> dictExtracted) ParseCustomAsaObjectValues(object? obj)
{
if (obj is Dictionary<(TpmAlgId, uint), byte[]> algDict)
{
return (true,Array.Empty<string>(), algDict.ToList().Select(x => new KeyValuePair<string, string>(x.Key.ToString(), Convert.ToBase64String(x.Value))).ToList());
}
return (false, Array.Empty<string>(), Array.Empty<KeyValuePair<string,string>>());
}
The Custom Operation Delegate allows you to extend Logical Analyzer with your own custom operation or operations.
public delegate bool OperationDelegate(Clause clause, IEnumerable<string>? valsToCheck, IEnumerable<KeyValuePair<string, string>> dictToCheck);
In the tests we test extending with a custom Operation
var analyzer = new Analyzer();
analyzer.CustomOperationDelegate = fooOperation;
bool fooOperation(clause, listValues, dictionaryValues) =>
{
if (clause.Operation == OPERATION.CUSTOM)
{
if (clause.CustomOperation == "FOO")
{
return true;
}
}
return false;
};
If you want to perform extra validation on your rules (for example after adding a custom operation) you can also extend the rule verification process with your own delegate.
public delegate IEnumerable<Violation> ValidationDelegate(Rule r, Clause c);
The tests contain this example of adding a validation delegate.
analyzer.CustomOperationValidationDelegate = parseFooOperations;
IEnumerable<Violation> parseFooOperations(Rule r, Clause c)
{
switch (c.CustomOperation)
{
case "FOO":
if (!c.Data.Any())
{
yield return new Violation("FOO Operation expects data", r, c);
}
break;
default:
yield return new Violation($"{c.CustomOperation} is unexpected", r, c);
break;
}
};