[Fuzz] Add fuzz testing for AdvancedPaste and new pipeline for onboarding OneFuzz (#36329)

* add fuzz

* install .net8

* add spelling check

* refine the pipeline

* add readme and update the test code

* fix spelling error

* change to weekly run
This commit is contained in:
leileizhang 2024-12-19 08:31:10 +08:00 коммит произвёл GitHub
Родитель 799f7396d2
Коммит 43bc811c59
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
12 изменённых файлов: 330 добавлений и 2 удалений

18
.github/actions/spell-check/allow/code.txt поставляемый
Просмотреть файл

@ -78,7 +78,14 @@ sinclairinat
stylecop
uipi
yinwang
myaccess
onmicrosoft
aep
epsf
howto
onefuzzconfig
oip
onefuzzingestionpreparationtool
# KEYS
@ -246,3 +253,12 @@ pwa
AOT
Aot
# YML
onefuzz
# NameInCode
leilzh
#Tools
OIP

55
.pipelines/v2/oneFuzz.yml Normal file
Просмотреть файл

@ -0,0 +1,55 @@
pr: none
trigger: none
schedules:
- cron: "0 0 * * 1"
displayName: Weekly fuzzing submission
branches:
include:
- main
always: true
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
parameters:
- name: platform
type: string
default: x64 # for fuzzing, we only use x64 for now
- name: enableMsBuildCaching
type: boolean
displayName: "Enable MSBuild Caching"
default: false
- name: useVSPreview
type: boolean
displayName: "Build Using Visual Studio Preview"
default: false
stages:
- stage: Build_${{ parameters.platform }}
displayName: Build ${{ parameters.platform }}
jobs:
- template: templates/job-build-project.yml
parameters:
pool:
${{ if eq(variables['System.CollectionId'], 'cb55739e-4afe-46a3-970f-1b49d8ee7564') }}:
name: SHINE-INT-L
${{ else }}:
name: SHINE-OSS-L
${{ if eq(parameters.useVSPreview, true) }}:
demands: ImageOverride -equals SHINE-VS17-Preview
buildPlatforms:
- ${{ parameters.platform }}
buildConfigurations: [Release]
enablePackageCaching: true
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
runTests: true
useVSPreview: ${{ parameters.useVSPreview }}
- stage: OneFuzz
displayName: Fuzz ${{ parameters.platform }}
dependsOn:
- Build_${{parameters.platform}}
jobs:
- template: templates/job-fuzz.yml
parameters:
platform: ${{ parameters.platform }}
configuration: Release

Просмотреть файл

@ -134,6 +134,11 @@ jobs:
sdk: true
version: '6.0'
- template: steps-ensure-dotnet-version.yml
parameters:
sdk: true
version: '8.0'
- template: steps-ensure-dotnet-version.yml
parameters:
sdk: true

Просмотреть файл

@ -0,0 +1,36 @@
parameters:
- name: configuration
type: string
default: "Release"
- name: platform
type: string
default: ""
- name: inputArtifactStem
type: string
default: ""
jobs:
- job: OneFuzz
pool:
vmImage: windows-2022
variables:
ArtifactName: build-${{ parameters.platform }}-${{ parameters.configuration }}${{ parameters.inputArtifactStem }}
steps:
- checkout: self
submodules: false
clean: true
fetchDepth: 1
fetchTags: false
- download: current
displayName: Download artifacts
artifact: $(ArtifactName)
patterns: |-
**/tests/*.FuzzTests/**
- task: onefuzz-task@0
inputs:
onefuzzOSes: Windows
env:
onefuzzDropDirectory: $(Pipeline.Workspace)\$(ArtifactName)\x64\Release\x64\Release\tests
SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Просмотреть файл

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

Просмотреть файл

@ -637,6 +637,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win1
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.FuzzTests", "src\modules\AdvancedPaste\AdvancedPaste.FuzzTests\AdvancedPaste.FuzzTests.csproj", "{7F5B9557-5878-4438-A721-3E28296BA193}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM64 = Debug|ARM64
@ -2821,6 +2823,18 @@ Global
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|x64.Build.0 = Release|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|x86.ActiveCfg = Release|x64
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}.Release|x86.Build.0 = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|ARM64.ActiveCfg = Debug|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|ARM64.Build.0 = Debug|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x64.ActiveCfg = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x64.Build.0 = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x86.ActiveCfg = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Debug|x86.Build.0 = Debug|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|ARM64.ActiveCfg = Release|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|ARM64.Build.0 = Release|ARM64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x64.ActiveCfg = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x64.Build.0 = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x86.ActiveCfg = Release|x64
{7F5B9557-5878-4438-A721-3E28296BA193}.Release|x86.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -3055,6 +3069,7 @@ Global
{89D0E199-B17A-418C-B2F8-7375B6708357} = {A2221D7E-55E7-4BEA-90D1-4F162D670BBF}
{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E} = {CA716AE6-FE5C-40AC-BB8F-2C87912687AC}
{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE} = {9873BA05-4C41-4819-9283-CF45D795431B}
{7F5B9557-5878-4438-A721-3E28296BA193} = {9873BA05-4C41-4819-9283-CF45D795431B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

Просмотреть файл

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\tests\AdvancedPaste.FuzzTests\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\AdvancedPaste\Helpers\JsonHelper.cs" Link="JsonHelper.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MSTest" />
</ItemGroup>
<ItemGroup>
<Using Include="Microsoft.VisualStudio.TestTools.UnitTesting" />
</ItemGroup>
<ItemGroup>
<Content Include="OneFuzzConfig.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,45 @@
# Fuzzing .NET Code with OneFuzz
This document explains the purpose of the project, the rationale for using specific technologies, and key instructions for fuzz testing .NET code using OneFuzz.
## Overview
This project demonstrates fuzz testing for .NET applications. It uses a `.NET 8 (Windows)` project where a code file is linked to the project. The linked file contains the functions required for fuzz testing.
## Why Use .NET 8 (Windows)?
1. **Current Support**: At the time of writing, OneFuzz supports only .NET 8 projects. The Fuzz team is actively working on .NET 9 support.
2. **Interim Solution**: Until .NET 9 support is available, .NET 8 serves as a robust and temporary solution for fuzz testing, enabling direct code linking for efficient development.
## Requesting Access
To log into the production instance of OneFuzz with the CLI, you **must request access**. Visit the internal [OneFuzz Access Request Page](https://myaccess.microsoft.com/@microsoft.onmicrosoft.com#/access-packages/6df691eb-e3d1-444b-b4b2-9e944dc794be) for details.
## How to Fuzz .NET Code
To set up and run fuzz testing on .NET code, follow the detailed guide available [Fuzz .NET Code](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/howto/fuzzing-dotnet-code).
## Running a .NET Fuzz Target Locally
Testing a .NET fuzz target locally requires specific configurations. For a step-by-step guide, see the section on [Running a .NET Fuzz Target Locally](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/howto/fuzzing-dotnet-code#extra-running-a-net-fuzz-target-locally).
## Writing a Good OneFuzzConfig.json
The `OneFuzzConfig.json` file provides critical information for deploying fuzzing jobs using the OneFuzz Ingestion Preparation Tool and Ingestion Service.
### Structure
The primary structure is an array of configuration entries. Outside the array, the `configVersion` field is used to track changes to the configuration schema.
For more details on how to write and structure this file, see the [OneFuzzConfig V3 Documentation](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/onefuzzconfig/onefuzzconfigv3).
## Tools
### OneFuzz Ingestion Preparation (OIP) Tool
The OIP tool helps prepare data for ingestion and fuzz testing. Learn more about [OneFuzz Ingestion Preparation (OIP) Tool](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/oip/onefuzzingestionpreparationtool).
### OneFuzz CLI
The CLI provides commands to manage and execute fuzzing jobs. Download and set up the CLI by following this [guide](https://eng.ms/docs/cloud-ai-platform/azure-edge-platform-aep/aep-security/epsf-edge-and-platform-security-fundamentals/the-onefuzz-service/onefuzz/howto/downloading-cli).

Просмотреть файл

@ -0,0 +1,32 @@
// 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 AdvancedPaste.Helpers;
using Windows.ApplicationModel.DataTransfer;
// OneFuzz currently does not support .NET 9 code testing, so this is a temporary solution.
// Create a .NET 8 project and use a file link to include the code for testing first.
namespace AdvancedPaste.FuzzTests
{
public class FuzzTests
{
public static void FuzzToJsonFromXmlOrCsv(ReadOnlySpan<byte> input)
{
try
{
var dataPackage = new DataPackage();
dataPackage.SetText(input.ToString());
_ = Task.Run(async () => await JsonHelper.ToJsonFromXmlOrCsvAsync(dataPackage.GetView())).Result;
}
catch (Exception ex) when (ex is ArgumentException)
{
// This is an example. 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;
}
}
}
}

Просмотреть файл

@ -0,0 +1,46 @@
// 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.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// This is used for fuzz testing and ensures that the project links only to JsonHelper,
// avoiding unnecessary connections to additional files
namespace ManagedCommon
{
public static class Logger
{
// An empty method to simulate logging information
public static void LogTrace()
{
// Do nothing
}
// An empty method to simulate logging information
public static void LogInfo(string message)
{
// Do nothing
}
// An empty method to simulate logging warnings
public static void LogWarning(string message)
{
// Do nothing
}
// An empty method to simulate logging errors
public static void LogError(string message, Exception? ex = null)
{
// Do nothing
}
public static void LogDebug(string message, Exception? ex = null)
{
// Do nothing
}
}
}

Просмотреть файл

@ -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)]

Просмотреть файл

@ -0,0 +1,47 @@
{
"configVersion": 3,
"entries": [
{
"fuzzer": {
"$type": "libfuzzerDotNet",
"dll": "AdvancedPaste.FuzzTests.dll",
"class": "AdvancedPaste.FuzzTests.FuzzTests",
"method": "FuzzToJsonFromXmlOrCsv",
"FuzzingTargetBinaries": [
"PowerToys.AdvancedPaste.dll"
]
},
"adoTemplate": {
// supply the values appropriate to your
// project, where bugs will be filed
"org": "microsoft",
"project": "OS",
"AssignedTo": "leilzh@microsoft.com",
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "leilzh@microsoft.com",
"skip": false,
"rebootAfterSetup": false,
"oneFuzzJobs": [
// at least one job is required
{
"projectName": "AdvancedPaste",
"targetName": "AdvancedPaste-dotnet-fuzzer"
}
],
"jobDependencies": [
// this should contain, at minimum,
// the DLL and PDB files
// you will need to add any other files required
// (globs are supported)
"AdvancedPaste.FuzzTests.dll",
"AdvancedPaste.FuzzTests.pdb",
"Microsoft.Windows.SDK.NET.dll",
"Newtonsoft.Json.dll",
"WinRT.Runtime.dll"
],
"SdlWorkItemId": 49911822
}
]
}