Skip to content
This repository has been archived by the owner on Nov 1, 2023. It is now read-only.

Add multi-var target spec, improve errors #2136

Merged
merged 11 commits into from
Jul 7, 2022
111 changes: 87 additions & 24 deletions src/agent/LibFuzzerDotnetLoader/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,28 @@
delegate void TestOneArray(byte[] data);

namespace LibFuzzerDotnetLoader {
class EnvVar
{
// Fuzz targets can be specified by setting this environment variable as `<assembly>:<class>:<method>`.
public const string TARGET = "LIBFUZZER_DOTNET_TARGET";

// Fuzz targets can also be specified by setting each of these environment variables.
public const string ASSEMBLY = "LIBFUZZER_DOTNET_TARGET_ASSEMBLY";
public const string CLASS = "LIBFUZZER_DOTNET_TARGET_CLASS";
public const string METHOD = "LIBFUZZER_DOTNET_TARGET_METHOD";
}

public class Program {
public static void Main(string[] args) {
var target = Environment.GetEnvironmentVariable("LIBFUZZER_DOTNET_TARGET");

if (target == null) {
throw new Exception("`LIBFUZZER_DOTNET_TARGET` not set. " +
"Expected format: \"<assembly-path>:<class>:<static-method>\"");
}

var parts = target.Split(':');
var target = LibFuzzerDotnetTarget.FromEnvironment();

var assemPath = parts[0];
var typeName = parts[1];
var methodName = parts[2];
var assem = Assembly.LoadFrom(target.AssemblyPath);

var assem = Assembly.LoadFrom(assemPath);
var ty = assem.GetType(target.ClassName)??
throw new Exception($"unable to resolve type: {target.ClassName}");

var ty = assem.GetType(typeName);

if (ty == null) {
throw new Exception($"unable to resolve type: {typeName}");
}

var method = ty.GetMethod(methodName);

if (method == null) {
throw new Exception($"unable to resolve method: {methodName}");
}
var method = ty.GetMethod(target.MethodName)??
throw new Exception($"unable to resolve method: {target.MethodName}");

if (TryTestOneSpan(method)) {
return;
Expand All @@ -47,7 +41,7 @@ public static void Main(string[] args) {
return;
}

throw new Exception($"unable to bind method to a known delegate type: {methodName}");
throw new Exception($"unable to bind method to a known delegate type: {target.MethodName}");
}

// Returns `true` if delegate binding succeeded.
Expand Down Expand Up @@ -81,4 +75,73 @@ static bool TryTestOneArray(MethodInfo method) {
return TryTestOne<TestOneArray>(method, t => span => t(span.ToArray()));
}
}

class LibFuzzerDotnetTarget
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
{
public string AssemblyPath { get; }
public string ClassName { get; }
public string MethodName { get; }

public LibFuzzerDotnetTarget(string assemblyPath, string className, string methodName)
{
AssemblyPath = assemblyPath;
ClassName = className;
MethodName = methodName;
}

public static LibFuzzerDotnetTarget FromEnvironment()
{
try {
return FromEnvironmentVarDelimited();
}
catch
{}

try {
return FromEnvironmentVars();
}
catch
{}

throw new Exception("No fuzzing target specified by environment variables");
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
}

static LibFuzzerDotnetTarget FromEnvironmentVars()
{
var assemblyPath = Environment.GetEnvironmentVariable(EnvVar.ASSEMBLY);
var className = Environment.GetEnvironmentVariable(EnvVar.CLASS);
var methodName = Environment.GetEnvironmentVariable(EnvVar.METHOD);

var missing = new List<string>();

if (assemblyPath is null) { missing.Add(EnvVar.ASSEMBLY); }
if (className is null) { missing.Add(EnvVar.CLASS); }
if (methodName is null) { missing.Add(EnvVar.METHOD); }

if (assemblyPath is null || className is null || methodName is null)
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
{
var vars = String.Join(", ", missing);
throw new Exception($"Missing `LIBFUZZER_DOTNET_TARGET` environment variables: {vars}");
}

return new LibFuzzerDotnetTarget(assemblyPath, className, methodName);
}


static LibFuzzerDotnetTarget FromEnvironmentVarDelimited()
{
var target = Environment.GetEnvironmentVariable(EnvVar.TARGET)??
throw new Exception($"`{EnvVar.TARGET}` not set." +
"Expected format: \"<assembly-path>:<class>:<static-method>\"");

var parts = target.Split(':', StringSplitOptions.RemoveEmptyEntries);

if (parts.Length != 3)
{
throw new Exception($"Value of `{EnvVar.TARGET}` is invalid");
ranweiler marked this conversation as resolved.
Show resolved Hide resolved
}

return new LibFuzzerDotnetTarget(parts[0], parts[1], parts[2]);
}
}
}