Intelligent Terminal uses LibFuzzer with
Address Sanitizer (ASan) to fuzz-test parsing and input-handling code. Fuzzing
jobs run automatically in CI via the fuzz.yml pipeline and are submitted to
OneFuzz for continuous coverage.
| Project | Path | Targets |
|---|---|---|
| WtcliFuzzer | src/tools/wtcli/ft_fuzzer/ |
BuildSendEventJson, MatchesEventFilter |
| ProtocolFuzzer | src/cascadia/TerminalProtocol/ft_fuzzer/ |
ClassifySendEvent, ParseSplitDirection, ClassifyPaneOutputSource |
| OpenConsoleFuzzer | src/host/ft_fuzzer/ |
WriteCharsLegacy (original host fuzzer) |
Each project contains:
fuzzmain.cpp— fuzzing harness withLLVMFuzzerTestOneInputentry point*-OneFuzzConfig.json— OneFuzz submission configuration*.vcxproj— MSBuild project withFuzzingconfiguration support
Fuzzers are built using the Fuzzing MSBuild configuration, which enables ASan, LibFuzzer instrumentation, and static CRT linkage.
- Visual Studio 2022 (17.10+) with C++ desktop workload
- Windows SDK 10.0.22621.0 or later
From a razzle environment (or directly with MSBuild):
rem One-time setup
tools\razzle.cmd
rem Build all fuzzers (Fuzzing configuration)
bcz Fuzzing
rem Or build individual fuzzers
cd src\tools\wtcli\ft_fuzzer
bcx Fuzzing
cd src\cascadia\TerminalProtocol\ft_fuzzer
bcx FuzzingOutput lands in bin\x64\Fuzzing\:
WtcliFuzzer.exe,.pdb,.libProtocolFuzzer.exe,.pdb,.libclang_rt.asan_dynamic-x86_64.dll(copied by PostBuildEvent)WtcliFuzzer-OneFuzzConfig.json,ProtocolFuzzer-OneFuzzConfig.json
rem Run with no arguments to start fuzzing from scratch
bin\x64\Fuzzing\WtcliFuzzer.exe
rem Run with a corpus directory
bin\x64\Fuzzing\WtcliFuzzer.exe corpus\wtcli\
rem Run a single test case (useful for repro)
bin\x64\Fuzzing\WtcliFuzzer.exe crash-input-fileEach fuzzer also has a manual main() that accepts file paths as arguments,
so you can run individual test cases without the LibFuzzer driver in a
Debug build.
-
Create the project folder under the target module as
ft_fuzzer/. -
Create
fuzzmain.cppwith anLLVMFuzzerTestOneInputentry point:extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Call your target functions with the fuzz input return 0; }
-
Create a
.vcxprojfollowing the pattern in the existing fuzzers. Key requirements in theFuzzingconfiguration:<EnableASAN>true</EnableASAN>and<EnableFuzzer>true</EnableFuzzer>- Preprocessor defines:
_DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION - Link
clang_rt.fuzzer_MT-$(OCClangArchitectureName).lib - PostBuildEvent to copy
clang_rt.asan_dynamic-x86_64.dllto$(OutDir)
The repo's
common.build.pre.propsalready provides ASan flags, coverage instrumentation, andFUZZING_BUILDdefine for theFuzzingconfiguration. -
Create an OneFuzzConfig JSON (use a unique name like
<ProjectName>-OneFuzzConfig.jsonto avoid collisions in the shared output directory):{ "configVersion": 3, "entries": [ { "Fuzzer": { "$type": "libfuzzer", "FuzzingHarnessExecutableName": "YourFuzzer.exe", "FuzzingTargetBinaries": ["YourFuzzer.exe"], "FuzzingEntrypoint": "LLVMFuzzerTestOneInput" }, "adoTemplate": { "org": "microsoft", "project": "Dart", "AssignedTo": "your-alias@microsoft.com", "AreaPath": "OS\\Windows Client and Services\\WinPD\\DFX-Developer Fundamentals and Experiences\\DEFT\\SALT", "IterationPath": "OS\\Future" }, "jobNotificationEmail": "your-alias@microsoft.com", "skip": false, "rebootAfterSetup": false, "oneFuzzJobs": [ { "projectName": "IntelligentTerminal.YourModule", "targetName": "YourModule_Fuzzer" } ], "jobDependencies": [ "YourFuzzer.exe", "YourFuzzer.pdb", "YourFuzzer.lib", "clang_rt.asan_dynamic-x86_64.dll" ], "SdlWorkItemId": 62007365, "SdlWorkItemProjectUrl": "https://dev.azure.com/microsoft/OS" } ] } -
Add a
CopyFileToFoldersitem in the vcxproj for your config:<ItemGroup> <CopyFileToFolders Include="YourFuzzer-OneFuzzConfig.json" /> </ItemGroup>
-
Register in the solution — add the new vcxproj to
OpenConsole.slnxunder the appropriate solution folder. -
Add a submission step in
build/pipelines/fuzz.ymlif the pipeline does not auto-discover OneFuzzConfig files:- bash: | onefuzz template libfuzzer basic ... OpenConsole $test_name ... displayName: Submit OneFuzz Job — YourFuzzer env: target_exe_path: $(Build.ArtifactStagingDirectory)/YourFuzzer.exe test_name: YourTargetName
The fuzzing pipeline is defined in build/pipelines/fuzz.yml:
- Build stage — builds all projects with
Configuration=Fuzzingon x64 - Submit stage — downloads build artifacts and submits each fuzzer to OneFuzz with the configured notification and ADO work item settings
The pipeline triggers on pushes to main (excluding docs/, samples/,
tools/).
Each fuzzer's OneFuzzConfig JSON controls:
| Field | Purpose |
|---|---|
FuzzingHarnessExecutableName |
The fuzzer executable name |
FuzzingTargetBinaries |
Binaries being fuzz-tested (for claims) |
FuzzingEntrypoint |
Entry function (LLVMFuzzerTestOneInput) |
SdlWorkItemId |
SDL task ID for linking bugs and claims |
SdlWorkItemProjectUrl |
ADO project URL for the SDL work item |
adoTemplate |
Where bugs are filed (org, project, area path) |
jobNotificationEmail |
Email for job completion notifications |
jobDependencies |
Files to include alongside the fuzzer |