Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized function calls.
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace StellaOps.Scanner.Emit.Reachability;
|
||||
|
||||
public enum ReachabilityState
|
||||
{
|
||||
Unknown = 0,
|
||||
Conditional = 1,
|
||||
Reachable = 2,
|
||||
Unreachable = 3
|
||||
}
|
||||
|
||||
public enum ReachabilityEvidenceKind
|
||||
{
|
||||
StaticPath,
|
||||
RuntimeHit,
|
||||
RuntimeSinkHit,
|
||||
Guard,
|
||||
Mitigation
|
||||
}
|
||||
|
||||
public readonly record struct ReachabilityEvidence(
|
||||
ReachabilityEvidenceKind Kind,
|
||||
string? Reference = null);
|
||||
|
||||
public sealed record ReachabilityLatticeResult(
|
||||
ReachabilityState State,
|
||||
double Score);
|
||||
|
||||
public static class ReachabilityLattice
|
||||
{
|
||||
public static ReachabilityLatticeResult Evaluate(IEnumerable<ReachabilityEvidence> rawEvidence)
|
||||
{
|
||||
var evidence = rawEvidence
|
||||
.Where(e => Enum.IsDefined(typeof(ReachabilityEvidenceKind), e.Kind))
|
||||
.OrderBy(e => e.Kind)
|
||||
.ThenBy(e => e.Reference ?? string.Empty, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
|
||||
var hasRuntimeSinkHit = evidence.Any(e => e.Kind is ReachabilityEvidenceKind.RuntimeSinkHit);
|
||||
var hasRuntimeHit = evidence.Any(e => e.Kind is ReachabilityEvidenceKind.RuntimeHit or ReachabilityEvidenceKind.RuntimeSinkHit);
|
||||
var hasStaticPath = evidence.Any(e => e.Kind is ReachabilityEvidenceKind.StaticPath);
|
||||
var guardCount = evidence.Count(e => e.Kind is ReachabilityEvidenceKind.Guard);
|
||||
var mitigationCount = evidence.Count(e => e.Kind is ReachabilityEvidenceKind.Mitigation);
|
||||
|
||||
var score = 0.0;
|
||||
var state = ReachabilityState.Unknown;
|
||||
|
||||
if (hasStaticPath)
|
||||
{
|
||||
state = ReachabilityState.Conditional;
|
||||
score += 0.50;
|
||||
}
|
||||
|
||||
if (hasRuntimeHit)
|
||||
{
|
||||
state = ReachabilityState.Reachable;
|
||||
score += 0.30;
|
||||
if (hasRuntimeSinkHit)
|
||||
{
|
||||
score += 0.10;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hasRuntimeHit && guardCount > 0)
|
||||
{
|
||||
state = state switch
|
||||
{
|
||||
ReachabilityState.Reachable => ReachabilityState.Conditional,
|
||||
ReachabilityState.Conditional => ReachabilityState.Unknown,
|
||||
_ => state
|
||||
};
|
||||
score = Math.Max(score - 0.20 * guardCount, 0);
|
||||
}
|
||||
|
||||
if (!hasRuntimeHit && mitigationCount > 0)
|
||||
{
|
||||
state = ReachabilityState.Unreachable;
|
||||
score = Math.Max(score - 0.30 * mitigationCount, 0);
|
||||
}
|
||||
|
||||
if (state == ReachabilityState.Unknown && score <= 0 && evidence.Count == 0)
|
||||
{
|
||||
return new ReachabilityLatticeResult(ReachabilityState.Unknown, 0);
|
||||
}
|
||||
|
||||
var capped = Math.Clamp(score, 0, 1);
|
||||
var rounded = Math.Round(capped, 2, MidpointRounding.AwayFromZero);
|
||||
return new ReachabilityLatticeResult(state, rounded);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user