Skip to content

Delegates

Gabe Stocco edited this page Jul 16, 2020 · 28 revisions

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.

Property Parsing

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);
}

Value Extraction

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>>());
}

Custom Operation

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;
};

Rule Validation

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;
    }
};
Clone this wiki locally