-
Notifications
You must be signed in to change notification settings - Fork 69
Windows
halfempty can be used to minimize testcases of Windows software from within the Windows Subsystem for Linux. You can invoke windows software from within your script, monitor the result and return a status to halfempty.
Follow the standard Linux installation instructions from within the WSL environment.
First, make sure that cdb.exe
is in your $PATH
, it's part of the Debugging Tools For Windows, which comes with the Windows SDK.
$ which cdb.exe
/mnt/c/Program Files (x86)/Windows Kits/10/Debuggers/x64/cdb.exe
Now you can write a simple script to call cdb, here is an example:
#!/bin/sh
tmpinput=`mktemp` && cat > ${tmpinput}
wininput=`wslpath -am ${tmpinput}`
tmpoutput=`mktemp`
winoutput=`wslpath -am ${tmpoutput}`
trap 'rm -f ${tmpinput} ${tmpoutput}; exit ${result:=1}' EXIT
# Run your test case, this example exits after the first exception.
cdb.exe -sxd wob -logo "${winoutput}" -c 'g;q' test.exe "${wininput}"
# Search the log for a crash.
if grep -q 'Access violation - code c0000005' ${tmpoutput}; then
result=0 # Keep this file.
else
result=1 # No crash.
fi
Let's see this work with a simple test program, this simple c program might crash if the input contains the character 'X'.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char line[1024] = {0};
FILE *input;
if (argc != 2)
return 1;
input = fopen(argv[1], "r");
if (input == NULL)
return 1;
while (fread(line, 1, sizeof(line) - 1, input) > 0) {
if (strchr(line, 'X'))
*(char *)(0) = 'C';
}
fclose(input);
return 0;
}
I just compiled it like this:
cl /nologo test.c
Now run halfempty with the example script above and some sample text.
$ cp /usr/share/dict/words input
$ chmod +x cdbdemo.sh
$ halfempty cdbdemo.sh input
╭│ │ ── halfempty ───────────────────────────────────────────────── v0.30 ──
╰│ 8│ A fast, parallel testcase minimization tool
╰───╯ ───────────────────────────────────────────────────────── by @taviso ──
Input file "input" is now 971578 bytes, starting strategy "bisect"...
Verifying the original input executes successfully... (skip with --noverify)
The original input file succeeded after 1.2 seconds.
New finalized size: 971578 (depth=2) real=0.0s, user=0.0s, speedup=~-0.0s
New finalized size: 485789 (depth=5) real=1.4s, user=3.5s, speedup=~2.1s
New finalized size: 242895 (depth=7) real=2.6s, user=6.3s, speedup=~3.7s
New finalized size: 121448 (depth=8) real=3.8s, user=7.5s, speedup=~3.8s
New finalized size: 60725 (depth=11) real=5.2s, user=11.4s, speedup=~6.2s
New finalized size: 30364 (depth=12) real=6.5s, user=12.9s, speedup=~6.4s
New finalized size: 15184 (depth=15) real=7.6s, user=15.8s, speedup=~8.2s
New finalized size: 7594 (depth=16) real=8.1s, user=16.4s, speedup=~8.3s
New finalized size: 3799 (depth=18) real=9.0s, user=18.1s, speedup=~9.1s
New finalized size: 1902 (depth=20) real=9.9s, user=19.8s, speedup=~9.9s
New finalized size: 954 (depth=23) real=10.6s, user=22.2s, speedup=~11.5s
New finalized size: 480 (depth=25) real=11.5s, user=23.8s, speedup=~12.3s
New finalized size: 243 (depth=26) real=12.3s, user=24.6s, speedup=~12.3s
New finalized size: 125 (depth=29) real=13.1s, user=27.0s, speedup=~13.8s
New finalized size: 66 (depth=31) real=13.9s, user=28.7s, speedup=~14.8s
New finalized size: 37 (depth=32) real=14.9s, user=29.7s, speedup=~14.8s
New finalized size: 23 (depth=35) real=15.6s, user=31.8s, speedup=~16.1s
New finalized size: 16 (depth=36) real=16.3s, user=32.6s, speedup=~16.3s
New finalized size: 9 (depth=38) real=17.2s, user=34.2s, speedup=~17.0s
New finalized size: 6 (depth=40) real=18.1s, user=35.9s, speedup=~17.8s
New finalized size: 3 (depth=41) real=18.7s, user=36.7s, speedup=~18.0s
New finalized size: 2 (depth=42) real=19.5s, user=37.4s, speedup=~17.9s
New finalized size: 1 (depth=43) real=20.2s, user=38.0s, speedup=~17.8s
Reached the end of our path through tree, all nodes were finalized
262 nodes failed, 60 worked, 12 discarded, 1 collapsed
168.974 seconds of compute was required for final path
Strategy "bisect" complete, output 1 bytes
Input file "input" is now 1 bytes, starting strategy "zero"...
Verifying the original input executes successfully... (skip with --noverify)
The original input file succeeded after 0.7 seconds.
New finalized size: 1 (depth=2) real=0.0s, user=0.0s, speedup=~-0.0s
Reached the end of our path through tree, all nodes were finalized
0 nodes failed, 1 worked, 0 discarded, 1 collapsed
0.715 seconds of compute was required for final path
Strategy "zero" complete, output 1 bytes
All work complete, generating output halfempty.out (size: 1)
$ uname -r
4.4.0-18362-Microsoft
$ xxd halfempty.out
00000000: 58 X
halfempty correctly found that just the letter 'X' was enough to cause the crash!
cdb
supports a scripting language that you can use to examine the program state in your halfempty script, you invoke cdb with the -cf filename
argument to run your script.
A simple example to get you started would be testing that a crash is at the expected location:
.if (@rip == target!foo+123) { .printf "__crashed__\n" }
Now you can search the the log for __crashed__
.