[Fuzz] Add fuzz testing for Hosts (#37516)

* add hostsfile fuzztests templates code

* modify  typos of hostsfile

* add hosts file

* add hosts fuzz to pipeline

* modify varify depjson rule

* fuzz validIPv4

* update  .net7 to .net 8

* add valid6/validhosts tests on hosts

* catch all exception

* update onefuzzconfig.json to add 3 test cases

* add fuzz writeasync tests and fill exception

* add writeasync onefuzz config

* add dll of writeasync in job dependencies

* for testing az

* change file

* use mock filesystem in hosts tests projct

* fix spell erro

* fix spell erro and change notations

* update test

* fix space erro in code

* install python

* update

* test

* use powershell

* remove unused dll in oneconfig.json


* change download artifacts

* update

* test

* add

* test

* merge

* az

* change

* update

* test cli

* add debug

* test large

* fix

* use templete

* remove pdb file filter in job test project

* fix x64 python install

* for testing

* add

* fix

* use 3.11.1

* change for test

* revert some testing file

* update the file name for spelling check

* use azure cli zip

* use aka.ms

* rename the zip file

* remove test artifactname

* add exception and job dependencies

* Remove the limitation of fuzzing only on hosts

* add fuzz readme

* remove unused changes and space

* fix x86 in sln and remove newtonsoft.json.dll in oneconfig.json

* readd wrapper.dll in oneconfig.json

* drop randomsplit when fuzz writeasync and remove unuseful package

---------
This commit is contained in:
chenmy77
2025-02-20 10:39:42 +08:00
committed by GitHub
parent 0592e74d3d
commit a1a02889d5
8 changed files with 387 additions and 607 deletions

View File

@@ -263,6 +263,10 @@ onefuzz
# NameInCode
leilzh
mengyuanchen
# DllName
testhost
#Tools
OIP
OIP

View File

@@ -15,7 +15,7 @@ Param(
$referencedFileVersionsPerDll = @{}
$totalFailures = 0
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones*,MouseJump.Common.UnitTests*,AdvancedPaste.FuzzTests* | ForEach-Object {
Get-ChildItem $targetDir -Recurse -Filter *.deps.json -Exclude UITests-FancyZones*,MouseJump.Common.UnitTests*,*.FuzzTests* | ForEach-Object {
# Temporarily exclude FancyZones UI tests because of Appium.WebDriver dependencies
$depsJsonFullFileName = $_.FullName
$depsJsonFileName = $_.Name

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
# Create Fuzzing Tests in your .NET Code Project
This document provides a step-by-step guide for integrating fuzzing tests into your .NET project.
### Step1: Add a Fuzzing Test Project
Create a new test project within your module folder. Ensure the project name follows the format *.FuzzTests*.
### step2: Add FuzzTests and OneFuzzConfig.json to your fuzzing test project
Follow the instructions in [Fuzz.md](https://github.com/microsoft/PowerToys/blob/main/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md) from AdvancedPaste.FuzzTests to properly integrate fuzzing tests into your project.
Configuring **OneFuzzConfig.json**:
1. Update the dll, class, method, and FuzzingTargetBinaries field in the fuzzers list.
2. Modify the AssignedTo field in the adoTemplate list.
3. Set the jobNotificationEmail to your Microsoft email account.
4. Update the projectName and targetName fields in the oneFuzzJobs list.
5. Define job dependencies in the following directory:
Example:
```PowerToys\x64\Debug\tests\Hosts.FuzzTests\net8.0-windows10.0.19041.0```
# step3: Configure the OneFuzz Pipeline
Modify the patterns in the job steps within [job-fuzz.yml](https://github.com/microsoft/PowerToys/blob/main/.pipelines/v2/templates/job-fuzz.yml) to match your fuzzing project name.
Example:
```
- download: current
displayName: Download artifacts
artifact: $(ArtifactName)
patterns: |-
**/tests/Hosts.FuzzTests/**
```
# step4: Submit OneFuzz Pipeline and Verify Results on the OneFuzz Platform
After executing the tests, check your email for the job link. Click the link to review the fuzzing test results.

View File

@@ -0,0 +1,101 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.IO.Abstractions.TestingHelpers;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Hosts.Tests.Mocks;
using HostsUILib.Helpers;
using HostsUILib.Models;
using HostsUILib.Settings;
using Moq;
namespace Hosts.FuzzTests
{
public class FuzzTests
{
private static Mock<IUserSettings> _userSettings;
private static Mock<IElevationHelper> _elevationHelper;
// Case1 Fuzzing method for ValidIPv4
public static void FuzzValidIPv4(ReadOnlySpan<byte> input)
{
try
{
string address = System.Text.Encoding.UTF8.GetString(input);
bool isValid = ValidationHelper.ValidIPv4(address);
}
catch (Exception ex) when (ex is RegexMatchTimeoutException)
{
throw;
}
}
// Case2: fuzzing method for ValidIPv6
public static void FuzzValidIPv6(ReadOnlySpan<byte> input)
{
try
{
string address = System.Text.Encoding.UTF8.GetString(input);
bool isValid = ValidationHelper.ValidIPv6(address);
}
catch (Exception ex) when (ex is RegexMatchTimeoutException)
{
throw;
}
}
// Case3: fuzzing method for ValidHosts
public static void FuzzValidHosts(ReadOnlySpan<byte> input)
{
try
{
string hosts = System.Text.Encoding.UTF8.GetString(input);
bool isValid = ValidationHelper.ValidHosts(hosts, true);
}
catch (Exception ex) when (ex is RegexMatchTimeoutException)
{
// It's important to filter out any *expected* exceptions from our code here.
// However, catching all exceptions is considered an anti-pattern because it may suppress legitimate
// issues, such as a NullReferenceException thrown by our code. In this case, we still re-throw
// the exception, as the ToJsonFromXmlOrCsvAsync method is not expected to throw any exceptions.
throw;
}
}
public static void FuzzWriteAsync(ReadOnlySpan<byte> data)
{
try
{
_userSettings = new Mock<IUserSettings>();
_elevationHelper = new Mock<IElevationHelper>();
_elevationHelper.Setup(m => m.IsElevated).Returns(true);
var fileSystem = new CustomMockFileSystem();
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
string input = System.Text.Encoding.UTF8.GetString(data);
// Since the WriteAsync method does not involve content parsing, we won't fuzz the additionalLines in the hosts file.
string additionalLines = " ";
string hosts = input;
string address = input;
string comments = input;
var entries = new List<Entry>
{
new Entry(1, hosts, address, comments, true),
};
// fuzzing WriteAsync
_ = Task.Run(async () => await service.WriteAsync(additionalLines, entries));
}
catch (Exception ex) when (ex is ArgumentException)
{
throw;
}
}
}
}

View File

@@ -0,0 +1,51 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\Hosts.FuzzTests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\Hosts.Tests\Mocks\CustomMockFileSystem.cs" Link="CustomMockFileSystem.cs" />
<Compile Include="..\Hosts.Tests\Mocks\MockFileSystemWatcher.cs" Link="MockFileSystemWatcher.cs" />
<Compile Include="..\Hosts.Tests\Mocks\MockFileSystemWatcherFactory.cs" Link="MockFileSystemWatcherFactory.cs" />
<Compile Include="..\HostsUILib\Consts.cs" Link="Consts.cs" />
<Compile Include="..\HostsUILib\Helpers\ValidationHelper.cs" Link="ValidationHelper.cs" />
<Compile Include="..\HostsUILib\Exceptions\NotRunningElevatedException.cs" Link="NotRunningElevatedException.cs" />
<Compile Include="..\HostsUILib\Exceptions\ReadOnlyHostsException.cs" Link="ReadOnlyHostsException.cs" />
<Compile Include="..\HostsUILib\Helpers\HostsService.cs" Link="HostsService.cs" />
<Compile Include="..\HostsUILib\Helpers\IElevationHelper.cs" Link="IElevationHelper.cs" />
<Compile Include="..\HostsUILib\Helpers\IHostsService.cs" Link="IHostsService.cs" />
<Compile Include="..\HostsUILib\Helpers\ILogger.cs" Link="ILogger.cs" />
<Compile Include="..\HostsUILib\Helpers\LoggerInstance.cs" Link="LoggerInstance.cs" />
<Compile Include="..\HostsUILib\Models\AddressType.cs" Link="AddressType.cs" />
<Compile Include="..\HostsUILib\Models\Entry.cs" Link="Entry.cs" />
<Compile Include="..\HostsUILib\Models\HostsData.cs" Link="HostsData.cs" />
<Compile Include="..\HostsUILib\Settings\HostsAdditionalLinesPosition.cs" Link="HostsAdditionalLinesPosition.cs" />
<Compile Include="..\HostsUILib\Settings\HostsEncoding.cs" Link="HostsEncoding.cs" />
<Compile Include="..\HostsUILib\Settings\IUserSettings.cs" Link="IUserSettings.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Moq" />
<PackageReference Include="MSTest" />
<PackageReference Include="System.IO.Abstractions" />
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="System.IO.Abstractions.TestingHelpers" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<Content Include="OneFuzzConfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,5 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]

View File

@@ -0,0 +1,178 @@
{
"configVersion": 3,
"entries": [
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidIPv4",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "Hosts",
"targetName": "Hosts-dotnet-fuzzer-Ipv4"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
"SdlWorkItemId": 49911822
},
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidIPv6",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "Hosts",
"targetName": "Hosts-dotnet-fuzzer-Ipv6"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
"SdlWorkItemId": 49911822
},
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzValidHosts",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "Hosts",
"targetName": "Hosts-dotnet-fuzzer-hosts"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll"
],
"SdlWorkItemId": 49911822
},
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "Hosts.FuzzTests.dll",
"class": "Hosts.FuzzTests.FuzzTests",
"method": "FuzzWriteAsync",
"FuzzingTargetBinaries": [
"PowerToys.Hosts.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "mengyuanchen@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "mengyuanchen@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "Hosts",
"targetName": "Hosts-dotnet-fuzzer-WriteAsync"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"Hosts.FuzzTests.dll",
"Hosts.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"WinRT.Runtime.dll",
"Moq.dll",
"testhost.dll",
"Castle.Core.dll",
"System.IO.Abstractions.dll",
"CommunityToolkit.Mvvm.dll",
"System.IO.Abstractions.TestingHelpers.dll",
"TestableIO.System.IO.Abstractions.dll",
"TestableIO.System.IO.Abstractions.TestingHelpers.dll",
"TestableIO.System.IO.Abstractions.Wrappers.dll"
],
"SdlWorkItemId": 49911822
}
]
}