Skip to content

Commit

Permalink
[YetiCommon] Scramble test binaries
Browse files Browse the repository at this point in the history
Applies b -> 255-b for every byte of the test binaries of
ModuleParserTests in order to prevent binary detection.

Also works around a bug in ElfSharp where files are not always closed,
see konrad-kruczynski/elfsharp#91. This
lead to errors deleting temp files.

GitOrigin-RevId: 107cfffd226c69dde2ad2d3bdd378be2aba3ef55
  • Loading branch information
ljusten authored and copybara-github committed Jan 10, 2023
1 parent 13c79be commit bb8038c
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 45 deletions.
65 changes: 52 additions & 13 deletions YetiCommon.Tests/ModuleParserTests.ParseBuildIdInfo.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.IO;
using System;
using System.IO;
using NUnit.Framework;

namespace YetiCommon.Tests
Expand All @@ -19,13 +20,16 @@ public partial class ModuleParserTests
"FDF485D6-E134-4825-885F-03517602265D-00000001")]
public void ParseBuildId_Succeeds(string filename, ModuleFormat format, string buildId)
{
string path = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData",
"ModuleParserTests", filename);
var moduleParser = new ModuleParser();
BuildIdInfo output = moduleParser.ParseBuildIdInfo(path, format);
string scrambledPath = Path.Combine(TestContext.CurrentContext.TestDirectory,
"TestData", "ModuleParserTests", filename);
using (TempFile tmpFile = Unscramble(scrambledPath))
{
var moduleParser = new ModuleParser();
BuildIdInfo output = moduleParser.ParseBuildIdInfo(tmpFile.Path, format);

Assert.IsFalse(output.HasError);
Assert.True(output.Data.Matches(new BuildId(buildId), format));
Assert.IsFalse(output.HasError);
Assert.True(output.Data.Matches(new BuildId(buildId), format));
}
}

[Test]
Expand All @@ -49,13 +53,48 @@ public void ParseBuildId_FileNotFound([Values] ModuleFormat format)
[TestCase("hello_dotnet_dll.dat", ModuleFormat.Pdb)]
public void ParseBuildId_IncorrectFormat(string filename, ModuleFormat format)
{
string path = Path.Combine(TestContext.CurrentContext.TestDirectory, "TestData",
"ModuleParserTests", filename);
var moduleParser = new ModuleParser();
BuildIdInfo output = moduleParser.ParseBuildIdInfo(path, format);
string scrambledPath = Path.Combine(TestContext.CurrentContext.TestDirectory,
"TestData", "ModuleParserTests", filename);
using (TempFile tmpFile = Unscramble(scrambledPath))
{
var moduleParser = new ModuleParser();
BuildIdInfo output = moduleParser.ParseBuildIdInfo(tmpFile.Path, format);

Assert.IsTrue(output.HasError);
Assert.That(
output.Error.Equals(ErrorStrings.InvalidSymbolFileFormat(tmpFile.Path, format)));
}
}

class TempFile : IDisposable
{
public string Path { get; } = System.IO.Path.GetTempFileName();

public void Dispose()
{
File.Delete(Path);
}
}

/// <summary>
/// Unscrambles test data to addresses a Google policy that does not allow us to check in
/// binaries.
/// </summary>
/// <param name="filename">Name of the scrambled file in TestData\ModuleParserTests</param>
/// <returns>Unscrambled TempFile</returns>
TempFile Unscramble(string filename)
{
string scrambledPath = Path.Combine(TestContext.CurrentContext.TestDirectory,
"TestData", "ModuleParserTests", filename);
byte[] data = File.ReadAllBytes(scrambledPath);
for (int i = 0; i < data.Length; i++)
{
data[i] = (byte)(255 - data[i]);
}

Assert.IsTrue(output.HasError);
Assert.That(output.Error.Equals(ErrorStrings.InvalidSymbolFileFormat(path, format)));
TempFile file = new TempFile();
File.WriteAllBytes(file.Path, data);
return file;
}
}
}
2 changes: 1 addition & 1 deletion YetiCommon.Tests/TestData/ModuleParserTests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

The ModuleParserTests parse different binary test files. To prevent detection
of binaries in the code base, and accidental execution, the files have been
named `.dat`.
scrambled by applying b -> 255-b for every byte and named `.dat`.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_cpp_exe.dat
Binary file not shown.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_cpp_pdb.dat
Binary file not shown.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_dotnet_dll.dat
Binary file not shown.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_dotnet_exe.dat
Binary file not shown.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_dotnet_pdb.dat
Binary file not shown.
Binary file modified YetiCommon.Tests/TestData/ModuleParserTests/hello_elf.dat
Binary file not shown.
69 changes: 38 additions & 31 deletions YetiCommon/ModuleParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,30 +111,34 @@ public BuildIdInfo ParseBuildIdInfo(string filepath, ModuleFormat format)
BuildIdInfo ParseBuildIdFromElf(string filepath)
{
var output = new BuildIdInfo();
if (!ELFReader.TryLoad(filepath, out IELF elfReader))
{
output.AddError(ErrorStrings.InvalidSymbolFileFormat(filepath, ModuleFormat.Elf));
return output;
}

using (elfReader)
using (Stream stream = File.OpenRead(filepath))
{
if (!elfReader.TryGetSection(_buildIdName, out ISection buildIdSection))
if (!ELFReader.TryLoad(stream, false, out IELF elfReader))
{
output.AddError(
ErrorStrings.FailedToReadBuildId(filepath, ErrorStrings.EmptyBuildId));
ErrorStrings.InvalidSymbolFileFormat(filepath, ModuleFormat.Elf));
return output;
}

if (buildIdSection is INoteSection buildIdNoteSection)
{
byte[] contents = buildIdNoteSection.Description;
output.Data = ParseBuildIdValue(contents);
}
else
using (elfReader)
{
output.AddError(
ErrorStrings.FailedToReadBuildId(filepath, ErrorStrings.EmptyBuildId));
if (!elfReader.TryGetSection(_buildIdName, out ISection buildIdSection))
{
output.AddError(
ErrorStrings.FailedToReadBuildId(filepath, ErrorStrings.EmptyBuildId));
return output;
}

if (buildIdSection is INoteSection buildIdNoteSection)
{
byte[] contents = buildIdNoteSection.Description;
output.Data = ParseBuildIdValue(contents);
}
else
{
output.AddError(
ErrorStrings.FailedToReadBuildId(filepath, ErrorStrings.EmptyBuildId));
}
}
}

Expand Down Expand Up @@ -382,26 +386,29 @@ public bool IsValidElf(string filepath, bool isDebugInfoFile, out string errorMe
return false;
}

if (!ELFReader.TryLoad(filepath, out IELF elfReader))
{
return false;
}

using (elfReader)
using (Stream stream = File.OpenRead(filepath))
{
if (!isDebugInfoFile)
if (!ELFReader.TryLoad(stream, false, out IELF elfReader))
{
// If we are not to check the presence of .debug_info, it is sufficient that
// the file has a valid ELF format.
return true;
return false;
}

if (elfReader.TryGetSection(_debugInfoName, out ISection _))
using (elfReader)
{
return true;
}
if (!isDebugInfoFile)
{
// If we are not to check the presence of .debug_info, it is sufficient that
// the file has a valid ELF format.
return true;
}

errorMessage += ErrorStrings.MissingDebugInfoInSymbolFile(filepath);
if (elfReader.TryGetSection(_debugInfoName, out ISection _))
{
return true;
}

errorMessage += ErrorStrings.MissingDebugInfoInSymbolFile(filepath);
}
}

return false;
Expand Down

0 comments on commit bb8038c

Please sign in to comment.