using System; using System.Collections.Generic; using System.IO; namespace StellaOps.Scanner.Analyzers.Lang.Go.Internal; internal static class GoBinaryScanner { private static readonly ReadOnlyMemory BuildInfoMagic = new byte[] { 0xFF, (byte)' ', (byte)'G', (byte)'o', (byte)' ', (byte)'b', (byte)'u', (byte)'i', (byte)'l', (byte)'d', (byte)'i', (byte)'n', (byte)'f', (byte)':' }; public static IEnumerable EnumerateCandidateFiles(string rootPath) { var enumeration = new EnumerationOptions { RecurseSubdirectories = true, IgnoreInaccessible = true, AttributesToSkip = FileAttributes.Device | FileAttributes.ReparsePoint, MatchCasing = MatchCasing.CaseSensitive, }; foreach (var path in Directory.EnumerateFiles(rootPath, "*", enumeration)) { yield return path; } } public static bool TryReadBuildInfo(string filePath, out string? goVersion, out string? moduleData) { goVersion = null; moduleData = null; try { var info = new FileInfo(filePath); if (!info.Exists || info.Length < 64 || info.Length > 128 * 1024 * 1024) { return false; } var data = File.ReadAllBytes(filePath); var span = new ReadOnlySpan(data); var offset = span.IndexOf(BuildInfoMagic.Span); if (offset < 0) { return false; } var view = span[offset..]; return GoBuildInfoDecoder.TryDecode(view, out goVersion, out moduleData); } catch (IOException) { return false; } catch (UnauthorizedAccessException) { return false; } } }