From 757535359761e05a57e5cfa1f64cc2ba88336e05 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sat, 16 Sep 2023 21:25:50 -0400 Subject: [PATCH] Add nullability to matching library, fix warnings --- .../BinaryObjectScanner.Matching.csproj | 4 + BinaryObjectScanner.Matching/ContentMatch.cs | 66 ++++++++----- .../ContentMatchSet.cs | 58 +++++++++-- BinaryObjectScanner.Matching/Extensions.cs | 16 ++++ BinaryObjectScanner.Matching/IMatch.cs | 4 + BinaryObjectScanner.Matching/MatchSet.cs | 8 ++ BinaryObjectScanner.Matching/MatchUtil.cs | 96 +++++++++++-------- BinaryObjectScanner.Matching/PathMatch.cs | 40 ++++++-- BinaryObjectScanner.Matching/PathMatchSet.cs | 44 ++++++++- 9 files changed, 251 insertions(+), 85 deletions(-) diff --git a/BinaryObjectScanner.Matching/BinaryObjectScanner.Matching.csproj b/BinaryObjectScanner.Matching/BinaryObjectScanner.Matching.csproj index deb03650..8749a9d2 100644 --- a/BinaryObjectScanner.Matching/BinaryObjectScanner.Matching.csproj +++ b/BinaryObjectScanner.Matching/BinaryObjectScanner.Matching.csproj @@ -19,4 +19,8 @@ true + + enable + + diff --git a/BinaryObjectScanner.Matching/ContentMatch.cs b/BinaryObjectScanner.Matching/ContentMatch.cs index ecde1e72..0443c36f 100644 --- a/BinaryObjectScanner.Matching/ContentMatch.cs +++ b/BinaryObjectScanner.Matching/ContentMatch.cs @@ -10,17 +10,25 @@ namespace BinaryObjectScanner.Matching /// /// Content to match /// +#if NET48 public byte?[] Needle { get; set; } +#else + public byte?[]? Needle { get; init; } +#endif /// /// Starting index for matching /// - public int Start { get; set; } + public int Start { get; internal set; } /// /// Ending index for matching /// - public int End { get; set; } +#if NET48 + public int End { get; private set; } +#else + public int End { get; init; } +#endif /// /// Constructor @@ -28,11 +36,15 @@ namespace BinaryObjectScanner.Matching /// Byte array representing the search /// Optional starting index /// Optional ending index +#if NET48 public ContentMatch(byte?[] needle, int start = -1, int end = -1) +#else + public ContentMatch(byte?[]? needle, int start = -1, int end = -1) +#endif { - Needle = needle; - Start = start; - End = end; + this.Needle = needle; + this.Start = start; + this.End = end; } #region Array Matching @@ -46,22 +58,22 @@ namespace BinaryObjectScanner.Matching public (bool success, int position) Match(byte[] stack, bool reverse = false) { // If either array is null or empty, we can't do anything - if (stack == null || stack.Length == 0 || Needle == null || Needle.Length == 0) + if (stack == null || stack.Length == 0 || this.Needle == null || this.Needle.Length == 0) return (false, -1); // If the needle array is larger than the stack array, it can't be contained within - if (Needle.Length > stack.Length) + if (this.Needle.Length > stack.Length) return (false, -1); // Set the default start and end values - int start = Start; - int end = End; + int start = this.Start; + int end = this.End; // If start or end are not set properly, set them to defaults if (start < 0) start = 0; if (end < 0) - end = stack.Length - Needle.Length; + end = stack.Length - this.Needle.Length; for (int i = reverse ? end : start; reverse ? i > start : i < end; i += reverse ? -1 : 1) { @@ -85,21 +97,25 @@ namespace BinaryObjectScanner.Matching /// True if the needle matches the stack at a given index private bool EqualAt(byte[] stack, int index) { + // If the needle is invalid, we can't do anything + if (this.Needle == null) + return false; + // If the index is invalid, we can't do anything if (index < 0) return false; // If we're too close to the end of the stack, return false - if (Needle.Length > stack.Length - index) + if (this.Needle.Length > stack.Length - index) return false; // Loop through and check the value - for (int i = 0; i < Needle.Length; i++) + for (int i = 0; i < this.Needle.Length; i++) { // A null value is a wildcard - if (Needle[i] == null) + if (this.Needle[i] == null) continue; - else if (stack[i + index] != Needle[i]) + else if (stack[i + index] != this.Needle[i]) return false; } @@ -119,22 +135,22 @@ namespace BinaryObjectScanner.Matching public (bool success, int position) Match(Stream stack, bool reverse = false) { // If either array is null or empty, we can't do anything - if (stack == null || stack.Length == 0 || Needle == null || Needle.Length == 0) + if (stack == null || stack.Length == 0 || this.Needle == null || this.Needle.Length == 0) return (false, -1); // If the needle array is larger than the stack array, it can't be contained within - if (Needle.Length > stack.Length) + if (this.Needle.Length > stack.Length) return (false, -1); // Set the default start and end values - int start = Start; - int end = End; + int start = this.Start; + int end = this.End; // If start or end are not set properly, set them to defaults if (start < 0) start = 0; if (end < 0) - end = (int)(stack.Length - Needle.Length); + end = (int)(stack.Length - this.Needle.Length); for (int i = reverse ? end : start; reverse ? i > start : i < end; i += reverse ? -1 : 1) { @@ -158,12 +174,16 @@ namespace BinaryObjectScanner.Matching /// True if the needle matches the stack at a given index private bool EqualAt(Stream stack, int index) { + // If the needle is invalid, we can't do anything + if (this.Needle == null) + return false; + // If the index is invalid, we can't do anything if (index < 0) return false; // If we're too close to the end of the stack, return false - if (Needle.Length > stack.Length - index) + if (this.Needle.Length > stack.Length - index) return false; // Save the current position and move to the index @@ -174,16 +194,16 @@ namespace BinaryObjectScanner.Matching bool matched = true; // Loop through and check the value - for (int i = 0; i < Needle.Length; i++) + for (int i = 0; i < this.Needle.Length; i++) { byte stackValue = (byte)stack.ReadByte(); // A null value is a wildcard - if (Needle[i] == null) + if (this.Needle[i] == null) { continue; } - else if (stackValue != Needle[i]) + else if (stackValue != this.Needle[i]) { matched = false; break; diff --git a/BinaryObjectScanner.Matching/ContentMatchSet.cs b/BinaryObjectScanner.Matching/ContentMatchSet.cs index 4d5a9035..9dc68298 100644 --- a/BinaryObjectScanner.Matching/ContentMatchSet.cs +++ b/BinaryObjectScanner.Matching/ContentMatchSet.cs @@ -20,7 +20,11 @@ namespace BinaryObjectScanner.Matching /// to the protection name, or `null`, in which case it will cause /// the protection to be omitted. /// - public Func, string> GetArrayVersion { get; set; } +#if NET48 + public Func, string> GetArrayVersion { get; private set; } +#else + public Func, string>? GetArrayVersion { get; init; } +#endif /// /// Function to get a content version @@ -32,7 +36,11 @@ namespace BinaryObjectScanner.Matching /// to the protection name, or `null`, in which case it will cause /// the protection to be omitted. /// - public Func, string> GetStreamVersion { get; set; } +#if NET48 + public Func, string> GetStreamVersion { get; private set; } +#else + public Func, string>? GetStreamVersion { get; init; } +#endif #region Generic Constructors @@ -52,6 +60,7 @@ namespace BinaryObjectScanner.Matching #region Array Constructors +#if NET48 public ContentMatchSet(byte?[] needle, Func, string> getArrayVersion, string protectionName) : this(new List { needle }, getArrayVersion, protectionName) { } @@ -67,11 +76,29 @@ namespace BinaryObjectScanner.Matching GetArrayVersion = getArrayVersion; ProtectionName = protectionName; } +#else + public ContentMatchSet(byte?[] needle, Func, string>? getArrayVersion, string protectionName) + : this(new List { needle }, getArrayVersion, protectionName) { } + + public ContentMatchSet(List needles, Func, string>? getArrayVersion, string protectionName) + : this(needles.Select(n => new ContentMatch(n)).ToList(), getArrayVersion, protectionName) { } + + public ContentMatchSet(ContentMatch needle, Func, string>? getArrayVersion, string protectionName) + : this(new List() { needle }, getArrayVersion, protectionName) { } + + public ContentMatchSet(List needles, Func, string>? getArrayVersion, string protectionName) + { + Matchers = needles; + GetArrayVersion = getArrayVersion; + ProtectionName = protectionName; + } +#endif #endregion #region Stream Constructors +#if NET48 public ContentMatchSet(byte?[] needle, Func, string> getStreamVersion, string protectionName) : this(new List { needle }, getStreamVersion, protectionName) { } @@ -87,6 +114,23 @@ namespace BinaryObjectScanner.Matching GetStreamVersion = getStreamVersion; ProtectionName = protectionName; } +#else + public ContentMatchSet(byte?[] needle, Func, string>? getStreamVersion, string protectionName) + : this(new List { needle }, getStreamVersion, protectionName) { } + + public ContentMatchSet(List needles, Func, string>? getStreamVersion, string protectionName) + : this(needles.Select(n => new ContentMatch(n)).ToList(), getStreamVersion, protectionName) { } + + public ContentMatchSet(ContentMatch needle, Func, string>? getStreamVersion, string protectionName) + : this(new List() { needle }, getStreamVersion, protectionName) { } + + public ContentMatchSet(List needles, Func, string>? getStreamVersion, string protectionName) + { + Matchers = needles; + GetStreamVersion = getStreamVersion; + ProtectionName = protectionName; + } +#endif #endregion @@ -96,7 +140,7 @@ namespace BinaryObjectScanner.Matching /// Determine whether all content matches pass /// /// Array to search - /// Tuple of passing status and matching positions + /// Tuple of passing status and matching positions public (bool, List) MatchesAll(byte[] stack) { // If no content matches are defined, we fail out @@ -104,7 +148,7 @@ namespace BinaryObjectScanner.Matching return (false, new List()); // Initialize the position list - List positions = new List(); + var positions = new List(); // Loop through all content matches and make sure all pass foreach (var contentMatch in Matchers) @@ -123,7 +167,7 @@ namespace BinaryObjectScanner.Matching /// Determine whether any content matches pass /// /// Array to search - /// Tuple of passing status and first matching position + /// Tuple of passing status and first matching position public (bool, int) MatchesAny(byte[] stack) { // If no content matches are defined, we fail out @@ -149,7 +193,7 @@ namespace BinaryObjectScanner.Matching /// Determine whether all content matches pass /// /// Stream to search - /// Tuple of passing status and matching positions + /// Tuple of passing status and matching positions public (bool, List) MatchesAll(Stream stack) { // If no content matches are defined, we fail out @@ -176,7 +220,7 @@ namespace BinaryObjectScanner.Matching /// Determine whether any content matches pass /// /// Stream to search - /// Tuple of passing status and first matching position + /// Tuple of passing status and first matching position public (bool, int) MatchesAny(Stream stack) { // If no content matches are defined, we fail out diff --git a/BinaryObjectScanner.Matching/Extensions.cs b/BinaryObjectScanner.Matching/Extensions.cs index a2b535d0..5c6c9e20 100644 --- a/BinaryObjectScanner.Matching/Extensions.cs +++ b/BinaryObjectScanner.Matching/Extensions.cs @@ -33,16 +33,28 @@ namespace BinaryObjectScanner.Matching /// /// Find the first position of one array in another, if possible /// +#if NET48 public static bool FirstPosition(this byte[] stack, byte[] needle, out int position, int start = 0, int end = -1) { byte?[] nullableNeedle = needle != null ? needle.Select(b => (byte?)b).ToArray() : null; return stack.FirstPosition(nullableNeedle, out position, start, end); } +#else + public static bool FirstPosition(this byte[] stack, byte[]? needle, out int position, int start = 0, int end = -1) + { + byte?[]? nullableNeedle = needle != null ? needle.Select(b => (byte?)b).ToArray() : null; + return stack.FirstPosition(nullableNeedle, out position, start, end); + } +#endif /// /// Find the first position of one array in another, if possible /// +#if NET48 public static bool FirstPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1) +#else + public static bool FirstPosition(this byte[] stack, byte?[]? needle, out int position, int start = 0, int end = -1) +#endif { var matcher = new ContentMatch(needle, start, end); (bool found, int foundPosition) = matcher.Match(stack, false); @@ -53,7 +65,11 @@ namespace BinaryObjectScanner.Matching /// /// Find the last position of one array in another, if possible /// +#if NET48 public static bool LastPosition(this byte[] stack, byte?[] needle, out int position, int start = 0, int end = -1) +#else + public static bool LastPosition(this byte[] stack, byte?[]? needle, out int position, int start = 0, int end = -1) +#endif { var matcher = new ContentMatch(needle, start, end); (bool found, int foundPosition) = matcher.Match(stack, true); diff --git a/BinaryObjectScanner.Matching/IMatch.cs b/BinaryObjectScanner.Matching/IMatch.cs index 5f985a9b..615aac9a 100644 --- a/BinaryObjectScanner.Matching/IMatch.cs +++ b/BinaryObjectScanner.Matching/IMatch.cs @@ -2,6 +2,10 @@ { public interface IMatch { +#if NET48 T Needle { get; set; } +#else + T? Needle { get; init; } +#endif } } diff --git a/BinaryObjectScanner.Matching/MatchSet.cs b/BinaryObjectScanner.Matching/MatchSet.cs index 3216b404..4ab3d87f 100644 --- a/BinaryObjectScanner.Matching/MatchSet.cs +++ b/BinaryObjectScanner.Matching/MatchSet.cs @@ -10,11 +10,19 @@ namespace BinaryObjectScanner.Matching /// /// Set of all matchers /// +#if NET48 public IEnumerable Matchers { get; set; } +#else + public IEnumerable? Matchers { get; set; } +#endif /// /// Name of the protection to show /// +#if NET48 public string ProtectionName { get; set; } +#else + public string? ProtectionName { get; set; } +#endif } } \ No newline at end of file diff --git a/BinaryObjectScanner.Matching/MatchUtil.cs b/BinaryObjectScanner.Matching/MatchUtil.cs index a2ff7645..aba1eeb3 100644 --- a/BinaryObjectScanner.Matching/MatchUtil.cs +++ b/BinaryObjectScanner.Matching/MatchUtil.cs @@ -20,11 +20,11 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// List of strings representing the matched protections, null or empty otherwise - public static ConcurrentQueue GetAllMatches( - string file, - byte[] stack, - IEnumerable matchers, - bool includeDebug = false) +#if NET48 + public static ConcurrentQueue GetAllMatches(string file, byte[] stack, IEnumerable matchers, bool includeDebug = false) +#else + public static ConcurrentQueue? GetAllMatches(string file, byte[] stack, IEnumerable? matchers, bool includeDebug = false) +#endif { return FindAllMatches(file, stack, matchers, includeDebug, false); } @@ -37,16 +37,16 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// String representing the matched protection, null otherwise - public static string GetFirstMatch( - string file, - byte[] stack, - IEnumerable matchers, - bool includeDebug = false) +#if NET48 + public static string GetFirstMatch(string file, byte[] stack, IEnumerable matchers, bool includeDebug = false) +#else + public static string? GetFirstMatch(string file, byte[] stack, IEnumerable? matchers, bool includeDebug = false) +#endif { var contentMatches = FindAllMatches(file, stack, matchers, includeDebug, true); if (contentMatches == null || !contentMatches.Any()) return null; - + return contentMatches.First(); } @@ -58,13 +58,12 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// True to stop after the first match, false otherwise - /// List of strings representing the matched protections, null or empty otherwise - private static ConcurrentQueue FindAllMatches( - string file, - byte[] stack, - IEnumerable matchers, - bool includeDebug, - bool stopAfterFirst) + /// List of strings representing the matched protections, null or empty otherwise +#if NET48 + private static ConcurrentQueue FindAllMatches(string file, byte[] stack, IEnumerable matchers, bool includeDebug, bool stopAfterFirst) +#else + private static ConcurrentQueue? FindAllMatches(string file, byte[] stack, IEnumerable? matchers, bool includeDebug, bool stopAfterFirst) +#endif { // If there's no mappings, we can't match if (matchers == null || !matchers.Any()) @@ -121,11 +120,11 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// List of strings representing the matched protections, null or empty otherwise - public static ConcurrentQueue GetAllMatches( - string file, - Stream stack, - IEnumerable matchers, - bool includeDebug = false) +#if NET48 + public static ConcurrentQueue GetAllMatches(string file, Stream stack, IEnumerable matchers, bool includeDebug = false) +#else + public static ConcurrentQueue? GetAllMatches(string file, Stream stack, IEnumerable? matchers, bool includeDebug = false) +#endif { return FindAllMatches(file, stack, matchers, includeDebug, false); } @@ -138,11 +137,11 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// String representing the matched protection, null otherwise - public static string GetFirstMatch( - string file, - Stream stack, - IEnumerable matchers, - bool includeDebug = false) +#if NET48 + public static string GetFirstMatch(string file, Stream stack, IEnumerable matchers, bool includeDebug = false) +#else + public static string? GetFirstMatch(string file, Stream stack, IEnumerable? matchers, bool includeDebug = false) +#endif { var contentMatches = FindAllMatches(file, stack, matchers, includeDebug, true); if (contentMatches == null || !contentMatches.Any()) @@ -159,13 +158,12 @@ namespace BinaryObjectScanner.Matching /// Enumerable of ContentMatchSets to be run on the file /// True to include positional data, false otherwise /// True to stop after the first match, false otherwise - /// List of strings representing the matched protections, null or empty otherwise - private static ConcurrentQueue FindAllMatches( - string file, - Stream stack, - IEnumerable matchers, - bool includeDebug, - bool stopAfterFirst) + /// List of strings representing the matched protections, null or empty otherwise +#if NET48 + private static ConcurrentQueue FindAllMatches(string file, Stream stack, IEnumerable matchers, bool includeDebug, bool stopAfterFirst) +#else + private static ConcurrentQueue? FindAllMatches(string file, Stream stack, IEnumerable? matchers, bool includeDebug, bool stopAfterFirst) +#endif { // If there's no mappings, we can't match if (matchers == null || !matchers.Any()) @@ -245,12 +243,16 @@ namespace BinaryObjectScanner.Matching /// Enumerable of PathMatchSets to be run on the file /// True if any path match is a success, false if all have to match /// String representing the matched protection, null otherwise +#if NET48 public static string GetFirstMatch(string file, IEnumerable matchers, bool any = false) +#else + public static string? GetFirstMatch(string file, IEnumerable matchers, bool any = false) +#endif { var contentMatches = FindAllMatches(new List { file }, matchers, any, true); if (contentMatches == null || !contentMatches.Any()) return null; - + return contentMatches.First(); } @@ -261,12 +263,16 @@ namespace BinaryObjectScanner.Matching /// Enumerable of PathMatchSets to be run on the file /// True if any path match is a success, false if all have to match /// String representing the matched protection, null otherwise +#if NET48 public static string GetFirstMatch(IEnumerable files, IEnumerable matchers, bool any = false) +#else + public static string? GetFirstMatch(IEnumerable files, IEnumerable matchers, bool any = false) +#endif { var contentMatches = FindAllMatches(files, matchers, any, true); if (contentMatches == null || !contentMatches.Any()) return null; - + return contentMatches.First(); } @@ -277,7 +283,7 @@ namespace BinaryObjectScanner.Matching /// Enumerable of PathMatchSets to be run on the file /// True if any path match is a success, false if all have to match /// True to stop after the first match, false otherwise - /// List of strings representing the matched protections, null or empty otherwise + /// List of strings representing the matched protections, null or empty otherwise private static ConcurrentQueue FindAllMatches(IEnumerable files, IEnumerable matchers, bool any, bool stopAfterFirst) { // If there's no mappings, we can't match @@ -292,10 +298,18 @@ namespace BinaryObjectScanner.Matching { // Determine if the matcher passes bool passes; +#if NET48 string firstMatchedString; +#else + string? firstMatchedString; +#endif if (any) { +#if NET48 (bool anyPasses, string matchedString) = matcher.MatchesAny(files); +#else + (bool anyPasses, string? matchedString) = matcher.MatchesAny(files); +#endif passes = anyPasses; firstMatchedString = matchedString; } @@ -305,9 +319,9 @@ namespace BinaryObjectScanner.Matching passes = allPasses; firstMatchedString = matchedStrings.FirstOrDefault(); } - + // If we don't have a pass, just continue - if (!passes) + if (!passes || firstMatchedString == null) continue; // If we there is no version method, just return the protection name @@ -334,7 +348,7 @@ namespace BinaryObjectScanner.Matching return matchedProtections; } - + #endregion } } \ No newline at end of file diff --git a/BinaryObjectScanner.Matching/PathMatch.cs b/BinaryObjectScanner.Matching/PathMatch.cs index 30d297d7..ac8f0e8a 100644 --- a/BinaryObjectScanner.Matching/PathMatch.cs +++ b/BinaryObjectScanner.Matching/PathMatch.cs @@ -11,17 +11,29 @@ namespace BinaryObjectScanner.Matching /// /// String to match /// +#if NET48 public string Needle { get; set; } +#else + public string? Needle { get; init; } +#endif /// /// Match exact casing instead of invariant /// - public bool MatchExact { get; set; } +#if NET48 + public bool MatchExact { get; private set; } +#else + public bool MatchExact { get; init; } +#endif /// /// Match that values end with the needle and not just contains /// - public bool UseEndsWith { get; set; } +#if NET48 + public bool UseEndsWith { get; private set; } +#else + public bool UseEndsWith { get; init; } +#endif /// /// Constructor @@ -29,11 +41,15 @@ namespace BinaryObjectScanner.Matching /// String representing the search /// True to match exact casing, false otherwise /// True to match the end only, false for all contents +#if NET48 public PathMatch(string needle, bool matchExact = false, bool useEndsWith = false) +#else + public PathMatch(string? needle, bool matchExact = false, bool useEndsWith = false) +#endif { - Needle = needle; - MatchExact = matchExact; - UseEndsWith = useEndsWith; + this.Needle = needle; + this.MatchExact = matchExact; + this.UseEndsWith = useEndsWith; } #region Matching @@ -43,23 +59,27 @@ namespace BinaryObjectScanner.Matching /// /// List of strings to search for the given content /// Tuple of success and matched item +#if NET48 public (bool, string) Match(IEnumerable stack) +#else + public (bool, string?) Match(IEnumerable? stack) +#endif { // If either array is null or empty, we can't do anything - if (stack == null || !stack.Any() || Needle == null || Needle.Length == 0) + if (stack == null || !stack.Any() || this.Needle == null || this.Needle.Length == 0) return (false, null); // Preprocess the needle, if necessary - string procNeedle = MatchExact ? Needle : Needle.ToLowerInvariant(); + string procNeedle = this.MatchExact ? this.Needle : this.Needle.ToLowerInvariant(); foreach (string stackItem in stack) { // Preprocess the stack item, if necessary - string procStackItem = MatchExact ? stackItem : stackItem.ToLowerInvariant(); + string procStackItem = this.MatchExact ? stackItem : stackItem.ToLowerInvariant(); - if (UseEndsWith && procStackItem.EndsWith(procNeedle)) + if (this.UseEndsWith && procStackItem.EndsWith(procNeedle)) return (true, stackItem); - else if (!UseEndsWith && procStackItem.Contains(procNeedle)) + else if (!this.UseEndsWith && procStackItem.Contains(procNeedle)) return (true, stackItem); } diff --git a/BinaryObjectScanner.Matching/PathMatchSet.cs b/BinaryObjectScanner.Matching/PathMatchSet.cs index cc84281f..a3e0a26a 100644 --- a/BinaryObjectScanner.Matching/PathMatchSet.cs +++ b/BinaryObjectScanner.Matching/PathMatchSet.cs @@ -18,7 +18,11 @@ namespace BinaryObjectScanner.Matching /// in which case it will be appended to the protection name, or `null`, /// in which case it will cause the protection to be omitted. /// - public Func, string> GetVersion { get; set; } +#if NET48 + public Func, string> GetVersion { get; private set; } +#else + public Func, string>? GetVersion { get; init; } +#endif #region Constructors @@ -28,11 +32,19 @@ namespace BinaryObjectScanner.Matching public PathMatchSet(List needles, string protectionName) : this(needles, null, protectionName) { } +#if NET48 public PathMatchSet(string needle, Func, string> getVersion, string protectionName) : this(new List { needle }, getVersion, protectionName) { } public PathMatchSet(List needles, Func, string> getVersion, string protectionName) : this(needles.Select(n => new PathMatch(n)).ToList(), getVersion, protectionName) { } +#else + public PathMatchSet(string needle, Func, string>? getVersion, string protectionName) + : this(new List { needle }, getVersion, protectionName) { } + + public PathMatchSet(List needles, Func, string>? getVersion, string protectionName) + : this(needles.Select(n => new PathMatch(n)).ToList(), getVersion, protectionName) { } +#endif public PathMatchSet(PathMatch needle, string protectionName) : this(new List() { needle }, null, protectionName) { } @@ -40,6 +52,7 @@ namespace BinaryObjectScanner.Matching public PathMatchSet(List needles, string protectionName) : this(needles, null, protectionName) { } +#if NET48 public PathMatchSet(PathMatch needle, Func, string> getVersion, string protectionName) : this(new List() { needle }, getVersion, protectionName) { } @@ -49,6 +62,17 @@ namespace BinaryObjectScanner.Matching GetVersion = getVersion; ProtectionName = protectionName; } +#else + public PathMatchSet(PathMatch needle, Func, string>? getVersion, string protectionName) + : this(new List() { needle }, getVersion, protectionName) { } + + public PathMatchSet(List needles, Func, string>? getVersion, string protectionName) + { + Matchers = needles; + GetVersion = getVersion; + ProtectionName = protectionName; + } +#endif #endregion @@ -58,7 +82,7 @@ namespace BinaryObjectScanner.Matching /// Determine whether all path matches pass /// /// List of strings to try to match - /// Tuple of passing status and matching values + /// Tuple of passing status and matching values public (bool, List) MatchesAll(IEnumerable stack) { // If no path matches are defined, we fail out @@ -71,8 +95,12 @@ namespace BinaryObjectScanner.Matching // Loop through all path matches and make sure all pass foreach (var pathMatch in Matchers) { +#if NET48 (bool match, string value) = pathMatch.Match(stack); - if (!match) +#else + (bool match, string? value) = pathMatch.Match(stack); +#endif + if (!match || value == null) return (false, new List()); else values.Add(value); @@ -85,8 +113,12 @@ namespace BinaryObjectScanner.Matching /// Determine whether any path matches pass /// /// List of strings to try to match - /// Tuple of passing status and first matching value + /// Tuple of passing status and first matching value +#if NET48 public (bool, string) MatchesAny(IEnumerable stack) +#else + public (bool, string?) MatchesAny(IEnumerable stack) +#endif { // If no path matches are defined, we fail out if (Matchers == null || !Matchers.Any()) @@ -95,7 +127,11 @@ namespace BinaryObjectScanner.Matching // Loop through all path matches and make sure all pass foreach (var pathMatch in Matchers) { +#if NET48 (bool match, string value) = pathMatch.Match(stack); +#else + (bool match, string? value) = pathMatch.Match(stack); +#endif if (match) return (true, value); }