Skip to content

Commit

Permalink
Add TypeNameFuzzer (#107206)
Browse files Browse the repository at this point in the history
Co-authored-by: Miha Zupan <[email protected]>
Co-authored-by: Adam Sitnik <[email protected]>
  • Loading branch information
3 people authored Sep 2, 2024
1 parent 5b33115 commit 48ae967
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
8 changes: 8 additions & 0 deletions eng/pipelines/libraries/fuzzing/deploy-to-onefuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ extends:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Send TextEncodingFuzzer to OneFuzz

- task: onefuzz-task@0
inputs:
onefuzzOSes: 'Windows'
env:
onefuzzDropDirectory: $(fuzzerProject)/deployment/TypeNameFuzzer
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
displayName: Send TypeNameFuzzer to OneFuzz

- task: onefuzz-task@0
inputs:
onefuzzOSes: 'Windows'
Expand Down
26 changes: 26 additions & 0 deletions src/libraries/Fuzzing/DotnetFuzzing/Dictionaries/typename.dict
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
" "
"0"
","
"[*["
" System.Int32 "
"System.Int32&&"
"System.Int32[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]"
"System.Int32[*******************************]"
"System.Int32[][][][][][][][][][][][][][][][][][][][]"
".NoNamespace"
"Namespace.Ko\xC5\x9B\xC4\x87"
"Declaring+Nested"
"Declaring+Deep+Deeper+Nested"
"Declaring+Deep+Deeper+Nested, Lib"
"MyNamespace.MyType+NestedType"
"Pointer*******"
"Generic`1[[A]]"
"Generic`2[[A],[B]]"
"Generic`3[[A],[B],[C]]"
"Generic`3[A,B,C]"
"Generic`2[[System.Int32, mscorlib, Version=4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934],[System.Boolean, mscorlib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
"Generic`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089], System.Boolean, [System.Byte, other, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"
"TypeNameWith\\TheEscapingCharacter"
"TypeNameWith[[]]NestedSquareBrackets"
"TypeNameWith\\[]+*&,AllSpecialCharacters"
"System.Reflection.Metadata.Tests.TypeNameTests+NestedGeneric_0`1+NestedGeneric_1`2+NestedGeneric_2`3+NestedNonGeneric_3[[System.Int32, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.String, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Boolean, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int16, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Byte, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.SByte, System.Private.CoreLib, Version=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Reflection.Metadata.Tests, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"
65 changes: 65 additions & 0 deletions src/libraries/Fuzzing/DotnetFuzzing/Fuzzers/TypeNameFuzzer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Buffers;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
using System.Text;

namespace DotnetFuzzing.Fuzzers
{
internal sealed class TypeNameFuzzer : IFuzzer
{
public string[] TargetAssemblies { get; } = ["System.Reflection.Metadata"];
public string[] TargetCoreLibPrefixes => [];
public string Dictionary => "typename.dict";

public void FuzzTarget(ReadOnlySpan<byte> bytes)
{
Span<char> charSpan = new char[Encoding.UTF8.GetCharCount(bytes)];
Encoding.UTF8.GetChars(bytes, charSpan);
using var poisonAfter = PooledBoundedMemory<char>.Rent(charSpan, PoisonPagePlacement.After);
using var poisonBefore = PooledBoundedMemory<char>.Rent(charSpan, PoisonPagePlacement.Before);

Test(poisonAfter.Span);
Test(poisonBefore.Span);
}

private static void Test(Span<char> testSpan)
{
if (TypeName.TryParse(testSpan, out TypeName? result1))
{
TypeName result2 = TypeName.Parse(testSpan);
Assert.Equal(result1.Name, result2.Name);
Assert.Equal(result1.FullName, result2.FullName);
Assert.Equal(result1.AssemblyQualifiedName, result2.AssemblyQualifiedName);
Assert.Equal(result1.IsSimple, result2.IsSimple);
Assert.Equal(result1.IsNested, result2.IsNested);
Assert.Equal(result1.IsArray, result2.IsArray);
Assert.Equal(result1.GetNodeCount(), result2.GetNodeCount());
if (result1.AssemblyName != null)
{
Assert.Equal(result1.AssemblyName.Name, result2.AssemblyName!.Name);
Assert.Equal(result1.AssemblyName.FullName, result2.AssemblyName.FullName);
Assert.Equal(result1.AssemblyName.CultureName, result2.AssemblyName.CultureName);
Assert.Equal(result1.AssemblyName.Version?.ToString(), result2.AssemblyName.Version?.ToString());
}
else
{
Assert.Equal(result1.AssemblyName, result2.AssemblyName);
}
}
else
{
try
{
TypeName.Parse(testSpan);
Assert.Equal(true, false); // should never succeed
}
catch (ArgumentException) { }
catch (InvalidOperationException) { }
}
}
}
}

0 comments on commit 48ae967

Please sign in to comment.