Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 7 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/actions/spell-check/allow/code.txt
Original file line number Diff line number Diff line change
Expand Up @@ -246,3 +246,9 @@ pwa

AOT
Aot

# YML
onefuzz

# NameInCode
leilzh
55 changes: 55 additions & 0 deletions .pipelines/v2/oneFuzz.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
pr: none
trigger: none

schedules:
- cron: "0 0 * * *"
displayName: Daily 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
5 changes: 5 additions & 0 deletions .pipelines/v2/templates/job-build-project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
36 changes: 36 additions & 0 deletions .pipelines/v2/templates/job-fuzz.yml
Original file line number Diff line number Diff line change
@@ -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
Fixed Show fixed Hide fixed
inputs:
onefuzzOSes: Windows
Fixed Show fixed Hide fixed
env:
onefuzzDropDirectory: $(Pipeline.Workspace)\$(ArtifactName)\x64\Release\x64\Release\tests
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
2 changes: 1 addition & 1 deletion .pipelines/verifyDepsJsonLibraryVersions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 15 additions & 0 deletions PowerToys.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
yeelam-gordon marked this conversation as resolved.
Show resolved Hide resolved
<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>
45 changes: 45 additions & 0 deletions src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md
Original file line number Diff line number Diff line change
@@ -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.

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

myaccess is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

onmicrosoft is not a recognized word. (unrecognized-spelling)

## How to Fuzz .NET Code

To set up and run fuzz testing on .NET code, follow the detailed guide available [here](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).

Check failure

Code scanning / check-spelling

Forbidden Pattern Error

[here\]\( matches a line_forbidden.patterns entry: "\(?i\)\(?:>|\\\[\)\(?:\(?:click |\)here|this\(?=\\\\]\\\\([^&#92;&#92;&#92;&#92;)&#92;]+:/\)|link|\(?:read |\)more\(?!</value\)\)\(?:</|\\\\]\\\\(\)". \(forbidden-pattern\)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

aep is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

aep is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

epsf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

howto is not a recognized word. (unrecognized-spelling)

## 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).

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

aep is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

aep is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

epsf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

howto is not a recognized word. (unrecognized-spelling)

## 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).

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

aep is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

epsf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

onefuzzconfig is not a recognized word. (unrecognized-spelling)

## Tools

### OneFuzz Ingestion Preparation (OIP) Tool

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

OIP is not a recognized word. (unrecognized-spelling)

The OIP tool helps prepare data for ingestion and fuzz testing. Learn more about it [here](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).

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

OIP is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Forbidden Pattern Error

[here\]\( matches a line_forbidden.patterns entry: "\(?i\)\(?:>|\\\[\)\(?:\(?:click |\)here|this\(?=\\\\]\\\\([^&#92;&#92;&#92;&#92;)&#92;]+:/\)|link|\(?:read |\)more\(?!</value\)\)\(?:</|\\\\]\\\\(\)". \(forbidden-pattern\)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

epsf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

oip is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

onefuzzingestionpreparationtool is not a recognized word. (unrecognized-spelling)

### 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).

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

epsf is not a recognized word. (unrecognized-spelling)

Check failure

Code scanning / check-spelling

Unrecognized Spelling Error

howto is not a recognized word. (unrecognized-spelling)

32 changes: 32 additions & 0 deletions src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/FuzzTests.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
46 changes: 46 additions & 0 deletions src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Logger.cs
Original file line number Diff line number Diff line change
@@ -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
}
}
}
Original file line number Diff line number Diff line change
@@ -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)]
Original file line number Diff line number Diff line change
@@ -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": "[email protected]",
Fixed Show fixed Hide fixed
"AreaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys",
"IterationPath": "OS\\Future"
},
"jobNotificationEmail": "[email protected]",
Fixed Show fixed Hide fixed
"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
}
]
}
Loading