diff --git a/.github/actions/spell-check/allow/code.txt b/.github/actions/spell-check/allow/code.txt
index b9a7ad1d6349..8c53e5282757 100644
--- a/.github/actions/spell-check/allow/code.txt
+++ b/.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
diff --git a/.pipelines/v2/oneFuzz.yml b/.pipelines/v2/oneFuzz.yml
new file mode 100644
index 000000000000..2bcbf360503b
--- /dev/null
+++ b/.pipelines/v2/oneFuzz.yml
@@ -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
diff --git a/.pipelines/v2/templates/job-build-project.yml b/.pipelines/v2/templates/job-build-project.yml
index 1933b74e8de9..ff082d35379b 100644
--- a/.pipelines/v2/templates/job-build-project.yml
+++ b/.pipelines/v2/templates/job-build-project.yml
@@ -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
diff --git a/.pipelines/v2/templates/job-fuzz.yml b/.pipelines/v2/templates/job-fuzz.yml
new file mode 100644
index 000000000000..b4e380194e65
--- /dev/null
+++ b/.pipelines/v2/templates/job-fuzz.yml
@@ -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)
diff --git a/.pipelines/verifyDepsJsonLibraryVersions.ps1 b/.pipelines/verifyDepsJsonLibraryVersions.ps1
index 7d5fc02c1095..3837514b4667 100644
--- a/.pipelines/verifyDepsJsonLibraryVersions.ps1
+++ b/.pipelines/verifyDepsJsonLibraryVersions.ps1
@@ -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
diff --git a/PowerToys.sln b/PowerToys.sln
index 1e0926876f74..a3101d8fac5c 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -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}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj
new file mode 100644
index 000000000000..f22ee39381d4
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/AdvancedPaste.FuzzTests.csproj
@@ -0,0 +1,26 @@
+
+
+ net8.0-windows10.0.19041.0
+ latest
+ enable
+ enable
+
+
+ ..\..\..\..\$(Platform)\$(Configuration)\tests\AdvancedPaste.FuzzTests\
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md
new file mode 100644
index 000000000000..7e83a77b8fa5
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Fuzz.md
@@ -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).
+
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/FuzzTests.cs b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/FuzzTests.cs
new file mode 100644
index 000000000000..a23618862c78
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/FuzzTests.cs
@@ -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 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;
+ }
+ }
+ }
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Logger.cs b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Logger.cs
new file mode 100644
index 000000000000..4f47fe5713e8
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/Logger.cs
@@ -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
+ }
+ }
+}
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/MSTestSettings.cs b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/MSTestSettings.cs
new file mode 100644
index 000000000000..5b05c0b86e3f
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/MSTestSettings.cs
@@ -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)]
diff --git a/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/OneFuzzConfig.json b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/OneFuzzConfig.json
new file mode 100644
index 000000000000..41bdc8c58ad2
--- /dev/null
+++ b/src/modules/AdvancedPaste/AdvancedPaste.FuzzTests/OneFuzzConfig.json
@@ -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
+ }
+ ]
+}