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

Add a Fuzzing configuration and a version of conhost that can be fuzzed #9604

Merged
11 commits merged into from
Mar 29, 2021

Conversation

DHowett
Copy link
Member

@DHowett DHowett commented Mar 24, 2021

This commit introduces a new build configuration, "Fuzzing", which
enables the new address sanitizer (shipped in VS 16.9) and code
coverage over the entire solution. Only a small subset of projects
(those comprising original conhost, right now) are selected to build in
this configuration, and even then only in Fuzzing|x64.

It also adds a fuzzing-adapted build of conhost, which makes no server
connections and handles no client applications. To do this, I've
replicated a bit of the console startup routine into fuzzmain.cpp and
made up some fake data. This is the bare minimum required to boot up
Win32 interactivity (or VT interactivity!) and pretend that a process
has connected.

If we don't pretend that a process has connected, "conhost" will exit
immediately. If we don't forge the process list, conhost will exit. If
we can't provide a server handle, we can't provide a "device comm".

Minor changes were necessary to server/host such that they would accept
a preexisting "device comm". We use this new behavior to provide a
"null" one that only hangs up threads and otherwise responds to requests
successfully.

This fuzzing-adapted build links LLVM's libFuzzer, which is an excellent
coverage-based fuzzer that will produce a corpus of inputs that exercise
unique codepaths. Eventually, we can use this to generate known-"good"
inputs for anything.

I've gone ahead and added a fuzz function that yeets bytes directly into
WriteCharsLegacy, which was the original reason I went down this path.

The implementation of LLVMFuzzerTestOneInput should be replaced with
whatever you want to fuzz.

@github-actions
Copy link

Misspellings found, please review:

  • asan
  • fsanitize
  • fuzzmain
  • libsancov
  • VAKUE
To accept these changes, run the following commands from this repository on this branch
pushd $(git rev-parse --show-toplevel)
perl -e '
my @expect_files=qw('".github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt"');
@ARGV=@expect_files;
my @stale=qw('"aspnet boostorg BSODs Cac COINIT dahall fde fea fmtlib isocpp mintty NVDA pinam QOL remoting unte vcrt what3words xamarin "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^(?:$re)(?:(?:\r|\n)*$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect/da24f7d9390a71648a81f17fc1eefc6e2d27bcbf.txt";
use File::Path qw(make_path);
make_path ".github/actions/spelling/expect";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"asan cac coinit fsanitize fuzzmain libsancov Remoting VAKUE "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
popd
✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. You can copy the contents of each perl command excluding the outer ' marks and dropping any '"/"' quotation mark pairs into a file and then run perl file.pl from the root of the repository to run the code. Alternatively, you can manually insert the items...

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/dictionary/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/dictionary/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

🗜️ If you see a bunch of garbage and it relates to a binary-ish string, please add a file path to the .github/actions/spelling/excludes.txt file instead of just accepting the garbage.

File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

@@ -39,7 +39,11 @@ try
{
Globals& Globals = ServiceLocator::LocateGlobals();

Globals.pDeviceComm = new ConDrvDeviceComm(Server);
if (!Globals.pDeviceComm)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these were the only changes necessary to conhost.
The only reason they are necessary is so that I can pass an invalid server handle 😄

@miniksa
Copy link
Member

miniksa commented Mar 24, 2021

dev/duhowett/fuzzywuzzy

👀

@github-actions
Copy link

Misspellings found, please review:

  • asan
  • fsanitize
  • fuzzmain
  • libsancov
  • VAKUE
To accept these changes, run the following commands from this repository on this branch
pushd $(git rev-parse --show-toplevel)
perl -e '
my @expect_files=qw('".github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt"');
@ARGV=@expect_files;
my @stale=qw('"aspnet boostorg BSODs Cac COINIT dahall fde fea fmtlib isocpp mintty NVDA pinam QOL remoting unte vcrt what3words xamarin "');
my $re=join "|", @stale;
my $suffix=".".time();
my $previous="";
sub maybe_unlink { unlink($_[0]) if $_[0]; }
while (<>) {
  if ($ARGV ne $old_argv) { maybe_unlink($previous); $previous="$ARGV$suffix"; rename($ARGV, $previous); open(ARGV_OUT, ">$ARGV"); select(ARGV_OUT); $old_argv = $ARGV; }
  next if /^(?:$re)(?:(?:\r|\n)*$| .*)/; print;
}; maybe_unlink($previous);'
perl -e '
my $new_expect_file=".github/actions/spelling/expect/da1e1a693e0358b7944e0c964d25c47fba0ce062.txt";
use File::Path qw(make_path);
make_path ".github/actions/spelling/expect";
open FILE, q{<}, $new_expect_file; chomp(my @words = <FILE>); close FILE;
my @add=qw('"asan cac coinit fsanitize fuzzmain libsancov Remoting VAKUE "');
my %items; @items{@words} = @words x (1); @items{@add} = @add x (1);
@words = sort {lc($a) cmp lc($b)} keys %items;
open FILE, q{>}, $new_expect_file; for my $word (@words) { print FILE "$word\n" if $word =~ /\w/; };
close FILE;'
popd
✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. You can copy the contents of each perl command excluding the outer ' marks and dropping any '"/"' quotation mark pairs into a file and then run perl file.pl from the root of the repository to run the code. Alternatively, you can manually insert the items...

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/dictionary/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/dictionary/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

🗜️ If you see a bunch of garbage and it relates to a binary-ish string, please add a file path to the .github/actions/spelling/excludes.txt file instead of just accepting the garbage.

File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

@WSLUser
Copy link
Contributor

WSLUser commented Mar 25, 2021

So is this the result of discussions mentioned in #7638 and will be part of CI?

@miniksa
Copy link
Member

miniksa commented Mar 25, 2021

So is this the result of discussions mentioned in #7638 and will be part of CI?

Sort of. It just so happened to be Fix Hack Learn week this week and @DHowett was playing with fuzzers to try to tackle the WriteCharsLegacy problem while I attended a talk from the fuzzing team (who own OneFuzz) and am asking them how we can do some sort of CI that is GH-initiated instead of private-OS-side initiated. I have a meeting about it in the next week or two and I'd love to see us run some fuzz things in CI... though it might have to be nightly and not per-PR or rolling. We'll see.

@WSLUser
Copy link
Contributor

WSLUser commented Mar 25, 2021

though it might have to be nightly and not per-PR or rolling. We'll see.

I think nightly would be best to keep the CI from becoming too slow and each WT/conhost release should have the results published somewhere for the public to review. That GH Action they publish is still likely the best way forward.

@miniksa
Copy link
Member

miniksa commented Mar 25, 2021

though it might have to be nightly and not per-PR or rolling. We'll see.

I think nightly would be best to keep the CI from becoming too slow and each WT/conhost release should have the results published somewhere for the public to review. That GH Action they publish is still likely the best way forward.

Thanks for your input.

@DHowett DHowett marked this pull request as ready for review March 25, 2021 16:13
@DHowett
Copy link
Member Author

DHowett commented Mar 25, 2021

I've marked this PR as "ready for review" and filled out the body.

@DHowett DHowett changed the title [DRAFT] Add a Fuzzing configuration and a version of conhost that can be fuzzed Add a Fuzzing configuration and a version of conhost that can be fuzzed Mar 25, 2021
@miniksa miniksa added Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase labels Mar 26, 2021
Copy link
Member

@miniksa miniksa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good. Just the two comments but I trust you to resolve them before hitting merge so I'm just gonna leave the Approve check.

Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I look forward to messing up the configuration on more projects in the future

Comment on lines +1182 to +1188
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|Any CPU.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Win32
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x64.ActiveCfg = Debug|x64
{099193A0-1E43-4BBC-BA7F-7B351E1342DF}.Fuzzing|x86.ActiveCfg = Fuzzing|Win32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one's got a weird mix of debug/fuzzing

Comment on lines +2148 to +2154
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|Any CPU.ActiveCfg = Debug|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|ARM.ActiveCfg = Debug|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|ARM64.ActiveCfg = Fuzzing|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|x64.ActiveCfg = Debug|Any CPU
{376FE273-6B84-4EB5-8B30-8DE9D21B022C}.Fuzzing|x86.ActiveCfg = Fuzzing|Any CPU
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same with this one, but it's all Any Cpu so maybe that doesn't matter?

Comment on lines +2737 to +2743
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|Any CPU.ActiveCfg = Debug|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|ARM.ActiveCfg = Debug|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|ARM64.ActiveCfg = Fuzzing|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|DotNet_x86Test.ActiveCfg = Debug|Any CPU
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|x64.ActiveCfg = Debug|x64
{1588FD7C-241E-4E7D-9113-43735F3E6BAD}.Fuzzing|x86.ActiveCfg = Fuzzing|x86
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another mixed|any cpu

Comment on lines +3012 to +3018
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|Any CPU.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|ARM.ActiveCfg = Fuzzing|ARM
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|ARM64.ActiveCfg = Fuzzing|ARM64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|DotNet_x64Test.ActiveCfg = Fuzzing|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|DotNet_x86Test.ActiveCfg = Release|Any CPU
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x64.ActiveCfg = Release|x64
{F75E29D0-D288-478B-8D83-2C190F321A3F}.Fuzzing|x86.ActiveCfg = Release|x86
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curiously mixed (release, fuzzing)|any cpu

@DHowett
Copy link
Member Author

DHowett commented Mar 29, 2021

So @zadjii-msft, the mixed weird tuples are because those projects are just not selected to build in the fuzzing config. The burden of fixing the mapping would be on the person who enables one of them :)

anyCPU is the most annoying obviously, since it’s a CPU type that only 3 of our 3,100 projects have so we need to carry it around like an empty husk

@zadjii-msft
Copy link
Member

we should almost just add a separate sln for those 😐

@DHowett
Copy link
Member Author

DHowett commented Mar 29, 2021

Validation Steps Performed

I've been running conhost fuzzing for hours!

Right now, the WCL fuzzer is completely stateful since we never clear/reset the buffer. It appends and appends and appends and leaks heaps of memory (for some reason...).

The code in the fuzz function is written in a very "if you can find it, use it" way. I'm calling weird stuff from all over the codebase because it does what we need.

I have been treating this as a magic input generator. If I am looking at WriteCharsLegacy, and I wonder "what sort of input will get me to this line of code?" I can literally set a breakpoint and half a second later I'm staring at inputs that got me there. It's freaking amazing.

@DHowett DHowett added the AutoMerge Marked for automatic merge by the bot when requirements are met label Mar 29, 2021
@ghost
Copy link

ghost commented Mar 29, 2021

Hello @DHowett!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

@ghost ghost merged commit 12275c8 into main Mar 29, 2021
@ghost ghost deleted the dev/duhowett/fuzzywuzzy branch March 29, 2021 14:23
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Output Related to output processing (inserting text into buffer, retrieving buffer text, etc.) AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Task It's a feature request, but it doesn't really need a major design. Product-Conhost For issues in the Console codebase
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants