in Tpm2Tester/TestSubstrate/TestFuzzer.cs [1294:1419]
List<FuzzableMember> TraverseTpmStructure(Type t, object o, FieldFilter filter)
{
var fuzzableVals = new List<FuzzableMember>();
if (o == null)
{
return fuzzableVals;
}
// recurse
var members = new List<MemberInfo>();
foreach (var bf in new BindingFlags[] {BindingFlags.Public, BindingFlags.NonPublic})
{
var candidateMembers = t.GetMembers(BindingFlags.Instance | bf);
foreach (var mi in candidateMembers)
{
var memberAttrs = mi.CustomAttributes;
foreach (var a in memberAttrs)
{
if (a.AttributeType.Name != "MarshalAsAttribute")
{
continue;
}
var arg1 = a.ConstructorArguments[1];
if (arg1.ArgumentType == typeof(MarshalType))
{
var marshalType = (MarshalType)arg1.Value;
if (marshalType != MarshalType.ArrayCount &&
marshalType != MarshalType.LengthOfStruct &&
marshalType != MarshalType.UnionSelector)
{
members.Add(mi);
}
}
break;
}
}
}
FuzzDbg.Trace(t.ToString());
FuzzDbg.Indent();
foreach (var memInfo in members)
{
Type memType = Globs.GetMemberType(memInfo);
object member = Globs.GetMember(memInfo, o);
if (member == null)
{
if (!filter.HasFlag(FieldFilter.NonNull))
{
// TODO: Update CmdComplexity based on the type info
fuzzableVals.Add(new FuzzableMember(memInfo, o, 0));
if (memInfo.Name != "inPrivate")
FuzzDbg.Trace("Leaf 'Nil': {0} {1}", memType, memInfo.Name);
}
continue;
}
Type actualType = member.GetType();
if (actualType.GetTypeInfo().IsSubclassOf(typeof(TpmStructureBase)))
{
// TODO: Update CmdComplexity based on the type info
FuzzDbg.Trace("Tpm Structure: {0} {1} {2}", memType, actualType, memInfo.Name);
fuzzableVals.AddRange(TraverseTpmStructure(actualType, member, filter));
RememberValidStruct(memType, member);
}
else if (actualType.IsArray && actualType != typeof(byte[]))
{
FuzzDbg.Trace("Array: {0} {1} {2}", memType, actualType, memInfo.Name);
var arr = (Array)member;
Type elementType = actualType.GetElementType();
foreach (object e in arr)
{
fuzzableVals.AddRange(TraverseTpmStructure(elementType, e, filter));
}
RememberValidStruct(memType, member);
}
else if ( !filter.HasFlag(FieldFilter.Buffer)
|| actualType == typeof(byte[]))
{
int complexity = 0;
if (actualType.GetTypeInfo().IsEnum)
{
complexity = Enum.GetValues(actualType).Length / 4 + 4;
if (memInfo is PropertyInfo)
{
Type uType = Enum.GetUnderlyingType(actualType);
object origVal = Convert.ChangeType(member, uType);
Globs.SetMember(memInfo, o, Enum.ToObject(actualType,
Globs.IncrementValue(origVal, 1)));
object newVal = Convert.ChangeType(
Globs.GetMember(memInfo, o), uType);
if (newVal.Equals(origVal))
{
// A property without setter
FuzzDbg.Trace("Property w/o setter: {0} {1}", actualType, memInfo.Name);
continue;
}
}
}
else if (actualType == typeof(byte[]))
{
complexity = 16;
}
else if (o.GetType() == typeof(TpmHandle))
{
// TPM_RH, PCR, transient, persistent, NV, session, arbitrary
complexity = Enum.GetValues(typeof(TpmRh)).Length / 4 + 6 * 2;
}
else
{
// An integer value
complexity = 4;
}
FuzzDbg.Trace("Leaf '{0}': {0} {1}", filter.HasFlag(FieldFilter.Buffer) ? "Buf" : "Val", actualType, memInfo.Name);
CmdComplexity += complexity;
fuzzableVals.Add(new FuzzableMember(memInfo, o, complexity));
}
else
{
Debug.Assert("Unidentified field type" == "");
}
}
FuzzDbg.Unindent();
return fuzzableVals;
}