Skip to content

Commit 5c06e5d

Browse files
authored
Add .NET Libraries fuzzing targets and automation (#101993)
* Initial fuzzing setup * Initial pipeline * Install sharpfuzz to the working directory * Initial instructions * Add a few helpful links * Enable OneFuzz deployment task * Remove BlameAlias default * Speed up headers fuzzer * Add BoundedMemory reference * Use BoundedMemory in SearchValues targets * Swap property order * Add a UTF8 fuzzing target * Reuse instrumented assemblies when unchanged * Add support for using dictionaries * Add simple json fuzzing target * Mention SharpFuzz in THIRD-PARTY-NOTICES.TXT * Tweak readme * Don't reuse assembly if prefixes changed * Temporarily disable dictionary files * Avoid name conflicts between CI jobs and test submissions * Add some basic OneFuzz docs * Add PooledBoundedMemory to fuzzer sample * Typo * More docs * Avoid transcoding overhead in Json fuzzer * Enable cron schedule * Tweak docs * Fix OneFuzz dictionary file paths * Workaround OneFuzz issue with multiple jobs in deployment * Clarify what alias to use * Test JsonDocument instead of JsonSerializer * Get rid of BlameAlias * Tweak getters * Remove a few unused helpers * Tweak OneFuzz workaround comment * Remove StringBuilder use * Avoid misaligned-span UB
1 parent 7452305 commit 5c06e5d

20 files changed

+1438
-0
lines changed

THIRD-PARTY-NOTICES.TXT

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,3 +1345,32 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
13451345
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13461346

13471347
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1348+
1349+
License for SharpFuzz and related samples
1350+
--------------------------------------
1351+
1352+
https://github.com/Metalnem/sharpfuzz
1353+
https://github.com/Metalnem/dotnet-fuzzers
1354+
https://github.com/Metalnem/libfuzzer-dotnet
1355+
1356+
MIT License
1357+
1358+
Copyright (c) 2018 Nemanja Mijailovic
1359+
1360+
Permission is hereby granted, free of charge, to any person obtaining a copy
1361+
of this software and associated documentation files (the "Software"), to deal
1362+
in the Software without restriction, including without limitation the rights
1363+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1364+
copies of the Software, and to permit persons to whom the Software is
1365+
furnished to do so, subject to the following conditions:
1366+
1367+
The above copyright notice and this permission notice shall be included in all
1368+
copies or substantial portions of the Software.
1369+
1370+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1371+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1372+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1373+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1374+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1375+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1376+
SOFTWARE.
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
trigger: none
2+
3+
schedules:
4+
- cron: "0 10 * * *" # 10 AM UTC
5+
displayName: OneFuzz deployment nightly run
6+
branches:
7+
include:
8+
- main
9+
10+
variables:
11+
- template: ../variables.yml
12+
- name: fuzzerProject
13+
value: $(Build.SourcesDirectory)/src/libraries/Fuzzing/DotnetFuzzing
14+
- name: dotnetPath
15+
value: $(Build.SourcesDirectory)/.dotnet/dotnet
16+
17+
extends:
18+
template: /eng/pipelines/common/templates/pipeline-with-resources.yml
19+
parameters:
20+
stages:
21+
- stage: Build
22+
jobs:
23+
- job: windows
24+
displayName: Build & Deploy to OneFuzz
25+
timeoutInMinutes: 120
26+
pool:
27+
name: $(DncEngInternalBuildPool)
28+
demands: ImageOverride -equals windows.vs2022.amd64
29+
30+
steps:
31+
- checkout: self
32+
clean: true
33+
fetchDepth: 1
34+
lfs: false
35+
36+
- powershell: |
37+
cd $(Build.SourcesDirectory)
38+
./build.cmd clr+libs+packs+host -rc Checked -c Debug
39+
displayName: Build runtime (checked + debug)
40+
41+
- powershell: |
42+
cd $(fuzzerProject)
43+
$(dotnetPath) publish -o publish
44+
displayName: Build Fuzzing targets
45+
46+
- powershell: |
47+
cd $(fuzzerProject)
48+
$(dotnetPath) tool install --tool-path . SharpFuzz.CommandLine
49+
displayName: Install SharpFuzz.CommandLine
50+
51+
- powershell: |
52+
cd $(fuzzerProject)
53+
publish/DotnetFuzzing.exe prepare-onefuzz deployment
54+
displayName: Prepare OneFuzz deployment
55+
56+
# OneFuzz can't currently handle a single deployment where multiple jobs share similar assemblies/pdbs.
57+
# As a workaround, we emit a task for every fuzzing target individually.
58+
# https://fuzzfest.visualstudio.com/Onefuzz/_workitems/edit/191504/ is tracking this issue.
59+
# - task: onefuzz-task@0
60+
# inputs:
61+
# onefuzzOSes: 'Windows'
62+
# env:
63+
# onefuzzDropDirectory: $(fuzzerProject)/deployment
64+
# SYSTEM_ACCESSTOKEN: $(System.AccessToken)
65+
# displayName: Send to OneFuzz
66+
67+
# ONEFUZZ_TASK_WORKAROUND_START
68+
- task: onefuzz-task@0
69+
inputs:
70+
onefuzzOSes: 'Windows'
71+
env:
72+
onefuzzDropDirectory: $(fuzzerProject)/deployment/HttpHeadersFuzzer
73+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
74+
displayName: Send HttpHeadersFuzzer to OneFuzz
75+
76+
- task: onefuzz-task@0
77+
inputs:
78+
onefuzzOSes: 'Windows'
79+
env:
80+
onefuzzDropDirectory: $(fuzzerProject)/deployment/JsonDocumentFuzzer
81+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
82+
displayName: Send JsonDocumentFuzzer to OneFuzz
83+
84+
- task: onefuzz-task@0
85+
inputs:
86+
onefuzzOSes: 'Windows'
87+
env:
88+
onefuzzDropDirectory: $(fuzzerProject)/deployment/SearchValuesByteCharFuzzer
89+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
90+
displayName: Send SearchValuesByteCharFuzzer to OneFuzz
91+
92+
- task: onefuzz-task@0
93+
inputs:
94+
onefuzzOSes: 'Windows'
95+
env:
96+
onefuzzDropDirectory: $(fuzzerProject)/deployment/SearchValuesStringFuzzer
97+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
98+
displayName: Send SearchValuesStringFuzzer to OneFuzz
99+
100+
- task: onefuzz-task@0
101+
inputs:
102+
onefuzzOSes: 'Windows'
103+
env:
104+
onefuzzDropDirectory: $(fuzzerProject)/deployment/UTF8Fuzzer
105+
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
106+
displayName: Send UTF8Fuzzer to OneFuzz
107+
# ONEFUZZ_TASK_WORKAROUND_END

src/libraries/Fuzzing/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
TempNugetCache
2+
publish
3+
deployment
4+
inputs
5+
crash-*
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project>
2+
<PropertyGroup>
3+
<NetCoreAppCurrentVersion>9.0</NetCoreAppCurrentVersion>
4+
<NetCoreAppCurrent>net$(NetCoreAppCurrentVersion)</NetCoreAppCurrent>
5+
<ProductVersion>$(NetCoreAppCurrentVersion).0</ProductVersion>
6+
<TestUtilities>..\..\Common\tests\TestUtilities</TestUtilities>
7+
</PropertyGroup>
8+
</Project>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<Project>
2+
</Project>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.11.34807.36
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotnetFuzzing", "DotnetFuzzing\DotnetFuzzing.csproj", "{002673BF-11AE-4072-9CBE-FC312BF68613}"
7+
EndProject
8+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6DDAE3F1-325F-468C-92DB-5947A3AD757E}"
9+
ProjectSection(SolutionItems) = preProject
10+
.gitignore = .gitignore
11+
..\..\..\eng\pipelines\libraries\fuzzing\deploy-to-onefuzz.yml = ..\..\..\eng\pipelines\libraries\fuzzing\deploy-to-onefuzz.yml
12+
Directory.Build.props = Directory.Build.props
13+
Directory.Build.targets = Directory.Build.targets
14+
nuget.config = nuget.config
15+
README.md = README.md
16+
OneFuzz.md = OneFuzz.md
17+
EndProjectSection
18+
EndProject
19+
Global
20+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
21+
Debug|Any CPU = Debug|Any CPU
22+
Release|Any CPU = Release|Any CPU
23+
EndGlobalSection
24+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
25+
{002673BF-11AE-4072-9CBE-FC312BF68613}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26+
{002673BF-11AE-4072-9CBE-FC312BF68613}.Debug|Any CPU.Build.0 = Debug|Any CPU
27+
{002673BF-11AE-4072-9CBE-FC312BF68613}.Release|Any CPU.ActiveCfg = Release|Any CPU
28+
{002673BF-11AE-4072-9CBE-FC312BF68613}.Release|Any CPU.Build.0 = Release|Any CPU
29+
EndGlobalSection
30+
GlobalSection(SolutionProperties) = preSolution
31+
HideSolutionNode = FALSE
32+
EndGlobalSection
33+
GlobalSection(ExtensibilityGlobals) = postSolution
34+
SolutionGuid = {0BAD3B6E-67D4-418D-A45F-49B3F79168DF}
35+
EndGlobalSection
36+
EndGlobal
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace DotnetFuzzing;
5+
6+
internal static class Assert
7+
{
8+
// Feel free to add any other helpers as needed.
9+
10+
public static void Equal<T>(T expected, T actual)
11+
{
12+
if (!EqualityComparer<T>.Default.Equals(expected, actual))
13+
{
14+
Throw(expected, actual);
15+
}
16+
17+
static void Throw(T expected, T actual) =>
18+
throw new Exception($"Expected={expected} Actual={actual}");
19+
}
20+
21+
public static void SequenceEqual<T>(ReadOnlySpan<T> expected, ReadOnlySpan<T> actual)
22+
{
23+
if (!expected.SequenceEqual(actual))
24+
{
25+
Throw(expected, actual);
26+
}
27+
28+
static void Throw(ReadOnlySpan<T> expected, ReadOnlySpan<T> actual)
29+
{
30+
Equal(expected.Length, actual.Length);
31+
32+
int diffIndex = expected.CommonPrefixLength(actual);
33+
34+
throw new Exception($"Expected={expected[diffIndex]} Actual={actual[diffIndex]} at index {diffIndex}");
35+
}
36+
}
37+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"0"
2+
"7"
3+
","
4+
":"
5+
"2.1e24"
6+
7+
"true"
8+
"false"
9+
"null"
10+
11+
"\"\""
12+
"\"\":"
13+
14+
"{}"
15+
",{}"
16+
":{}"
17+
"{\"\":0}"
18+
"{{}}"
19+
20+
"[]"
21+
",[]"
22+
":[]"
23+
"[0]"
24+
"[[]]"
25+
26+
"''"
27+
"\\"
28+
"\\b"
29+
"\\f"
30+
"\\n"
31+
"\\r"
32+
"\\t"
33+
"\\u0000"
34+
"\\x00"
35+
"\\0"
36+
"\\uD800\\uDC00"
37+
"\\uDBFF\\uDFFF"
38+
39+
"\"\":0"
40+
"//"
41+
"/**/"
42+
43+
44+
# Things like geojson, json-ld, ...
45+
"$ref"
46+
"type"
47+
"coordinates"
48+
"@context"
49+
"@id"
50+
"@type"
51+
52+
# Strings with truncated special values
53+
"{\"foo\":fa"
54+
"{\"foo\":t"
55+
"{\"foo\":nul"
56+
57+
"{"
58+
"}"
59+
"\"qty\": 1, \"qty\": -1"
60+
"\"qty\": 1, \"qty\\ud800\": -1"
61+
"\"qty\": 1, \"qt\\y\": -1"
62+
"/*"
63+
"*/"
64+
"\""
65+
"1.7976931348623157e+308"
66+
"5e-324"
67+
"9007199254740991"
68+
"-9007199254740991"
69+
70+
"}="
71+
72+
",,"
73+
"{\"\":"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>$(NetCoreAppCurrent)-windows</TargetFramework>
6+
<PublishSelfContained>true</PublishSelfContained>
7+
<ImplicitUsings>enable</ImplicitUsings>
8+
<Nullable>enable</Nullable>
9+
<EnablePreviewFeatures>True</EnablePreviewFeatures>
10+
<NoWarn>CA2252</NoWarn>
11+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
12+
</PropertyGroup>
13+
14+
<ItemGroup>
15+
<PackageReference Include="SharpFuzz" Version="2.1.1" />
16+
</ItemGroup>
17+
18+
<ItemGroup>
19+
<FrameworkReference Update="Microsoft.NETCore.App" RuntimeFrameworkVersion="$(ProductVersion)-dev" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<Compile Include="$(TestUtilities)\System\Buffers\BoundedMemory.*" Link="TestUtilities\%(Filename)%(Extension)" />
24+
<Compile Include="$(TestUtilities)\System\Buffers\PoisonPagePlacement.cs" Link="TestUtilities\PoisonPagePlacement.cs" />
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<None Update="Dictionaries\*">
29+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
30+
</None>
31+
</ItemGroup>
32+
33+
</Project>

0 commit comments

Comments
 (0)