Ejemplo n.º 1
0
        private static void GenerateProgram(FuzzlynOptions options)
        {
            ParallelOptions po = new ParallelOptions
            {
                MaxDegreeOfParallelism = options.Parallelism
            };

            int numGenerated = 0;

            Parallel.For(0, options.NumPrograms, po, i =>
            {
                CodeGenerator gen          = new CodeGenerator(options);
                CompilationUnitSyntax unit = gen.GenerateProgram(true);
                if (options.Output)
                {
                    string asString = unit.NormalizeWhitespace().ToFullString();
                    Console.Write(asString);
                }
                else
                {
                    Compile(gen, unit);
                }

                int numGen = Interlocked.Increment(ref numGenerated);
                if (numGen % 100 == 0)
                {
                    Console.Title = $"{numGen}/{options.NumPrograms} programs generated, {s_numDeviating} examples found";
                }
            });

            ExecuteQueue();
        }
Ejemplo n.º 2
0
 public CodeGenerator(FuzzlynOptions options)
 {
     Options = options;
     Random  = new Randomizer(options);
     Types   = new TypeManager(Random);
     Statics = new StaticsManager(Random, Types);
     Methods = new MethodManager(Random, Types, Statics);
 }
Ejemplo n.º 3
0
        private static void RemoveFixedPrograms(FuzzlynOptions options, string dir)
        {
            string[]     files      = Directory.GetFiles(dir, "*.cs");
            List <ulong> toRereduce = new List <ulong>();

            for (int i = 0; i < files.Length; i++)
            {
                Console.Title = $"Processing {i + 1}/{files.Length}";

                string          contents = File.ReadAllText(files[i]);
                MatchCollection matches  = Regex.Matches(contents, "// Seed: ([0-9]+)");
                if (matches.Count != 1)
                {
                    continue;
                }

                ulong seed = ulong.Parse(matches[0].Groups[1].Value);
                options.Seed = seed;
                var cg = new CodeGenerator(options);
                CompilationUnitSyntax original = cg.GenerateProgram(false);

                CompileResult debug   = Compiler.Compile(original, Compiler.DebugOptions);
                CompileResult release = Compiler.Compile(original, Compiler.ReleaseOptions);

                if (debug.CompileErrors.Length > 0 || release.CompileErrors.Length > 0)
                {
                    continue;
                }

                if (debug.RoslynException != null || release.RoslynException != null)
                {
                    continue;
                }

                ProgramPairResults execResults = ProgramExecutor.RunPair(new ProgramPair(debug.Assembly, release.Assembly));
                if (execResults.DebugResult.Checksum != execResults.ReleaseResult.Checksum ||
                    execResults.DebugResult.ExceptionType != execResults.ReleaseResult.ExceptionType)
                {
                    // Execute the reduced form to see if we get interesting behavior.
                    // Otherwise we may need to rereduce it.
                    if (!IsReducedVersionInteresting(execResults, contents))
                    {
                        toRereduce.Add(seed);
                        Console.WriteLine("Marking {0} for rereduction", Path.GetFileName(files[i]));
                    }

                    continue;
                }

                Console.WriteLine("Removing {0}", Path.GetFileName(files[i]));
                File.Delete(files[i]);
            }

            const string rereduceFile = "Rereduce_required.txt";

            File.WriteAllText(rereduceFile, string.Join(Environment.NewLine, toRereduce));
            Console.WriteLine("Wrote {0} seeds to be rereduced to '{1}'", toRereduce.Count, Path.GetFullPath(rereduceFile));
        }
Ejemplo n.º 4
0
        private static void GenerateProgramsAndOutput(FuzzlynOptions options)
        {
            void Output(CompilationUnitSyntax unit, ulong seed)
            {
                Console.WriteLine(unit.NormalizeWhitespace().ToFullString());
            }

            GeneratePrograms(options, Output);
        }
Ejemplo n.º 5
0
        private static void ReduceProgram(FuzzlynOptions options)
        {
            var cg = new CodeGenerator(options);
            CompilationUnitSyntax original = cg.GenerateProgram(true);
            Reducer reducer = new Reducer(original, options.Seed.Value);
            CompilationUnitSyntax reduced = reducer.Reduce();

            Console.WriteLine(reduced.NormalizeWhitespace().ToFullString());
        }
Ejemplo n.º 6
0
        private static void ReduceProgram(FuzzlynOptions options, string reduceDebugGitDir)
        {
            var cg = new CodeGenerator(options);
            CompilationUnitSyntax original = cg.GenerateProgram();

            Reducer reducer = new Reducer(original, options.Seed.Value, options.ReduceWithChildProcesses, reduceDebugGitDir);
            CompilationUnitSyntax reduced = reducer.Reduce();

            Console.WriteLine(reduced.NormalizeWhitespace().ToFullString());
        }
Ejemplo n.º 7
0
        private static void GeneratePrograms(FuzzlynOptions options, Action <CompilationUnitSyntax, ulong> action)
        {
            ParallelOptions po = new ParallelOptions
            {
                MaxDegreeOfParallelism = options.Parallelism
            };

            int numGenerated = 0;

            Parallel.For(0, options.NumPrograms, po, i =>
            {
                CodeGenerator gen          = new CodeGenerator(options);
                CompilationUnitSyntax unit = gen.GenerateProgram();
                action(unit, gen.Random.Seed);
                int numGen = Interlocked.Increment(ref numGenerated);
                if (numGen % 100 == 0)
                {
                    Console.Title = $"{numGen}/{options.NumPrograms} programs generated, {s_numDeviating} examples found";
                }
            });
        }
Ejemplo n.º 8
0
        private static void GenerateProgramsAndGetStats(FuzzlynOptions options)
        {
            List <double> sizes = new List <double>();

            void AddProgramSize(CompilationUnitSyntax unit, ulong seed)
            {
                unit = unit.NormalizeWhitespace();
                double size = unit.ToFullString().Length;

                lock (sizes)
                {
                    sizes.Add(size);
                    if (sizes.Count % 500 != 0)
                    {
                        return;
                    }

                    Console.WriteLine("Stats of {0} examples", sizes.Count);
                    Console.WriteLine("Average program size: {0:F2} KiB", sizes.Average() / 1024.0);
                    Console.WriteLine("Min program size: {0} B", sizes.Min());
                    Console.WriteLine("Max program size: {0} KiB", sizes.Max() / 1024.0);
                    Console.WriteLine("# programs < 2 KiB: {0}", sizes.Count(s => s < 2048));
                    Console.WriteLine("10th percentiles:");
                    List <double> sortedSizes           = sizes.OrderBy(s => s).ToList();
                    int           programsPerPercentile = sortedSizes.Count / 10;
                    for (int i = 0; i < 10; i++)
                    {
                        double min = sortedSizes[i * programsPerPercentile];
                        double max = i == 9 ? sortedSizes.Last() : sortedSizes[(i + 1) * programsPerPercentile];
                        Console.WriteLine("{0:F2} KiB <= size <{1} {2:F2} KiB: {3} programs", min / 1024, i == 9 ? "=" : "", max / 1024, programsPerPercentile);
                    }

                    Console.WriteLine();
                }
            }

            GeneratePrograms(options, AddProgramSize);
        }
Ejemplo n.º 9
0
 private static void GenerateProgramsAndCheck(FuzzlynOptions options)
 {
     GeneratePrograms(options, Compile);
     ExecuteQueue();
 }
Ejemplo n.º 10
0
        private static void Main(string[] args)
        {
            ulong?         seed                   = null;
            int?           numPrograms            = null;
            int?           parallelism            = null;
            FuzzlynOptions options                = null;
            bool           help                   = false;
            bool           dumpOptions            = false;
            bool?          output                 = null;
            bool?          executePrograms        = null;
            bool?          enableChecksumming     = null;
            bool?          reduce                 = null;
            bool?          reduceInChildProcesses = null;
            string         reduceDebugGitDir      = null;
            string         removeFixed            = null;
            bool?          stats                  = null;
            OptionSet      optionSet              = new OptionSet
            {
                { "seed=|s=", "Seed to use when generating a single program", (ulong v) => seed = v },
                { "parallelism=", "Number of cores to use", (int?p) => parallelism = p },
                { "num-programs=|n=", "Number of programs to generate", (int v) => numPrograms = v },
                {
                    "options=",
                    "Path to options.json. Command-line options will override options from this file.",
                    s => options = JsonConvert.DeserializeObject <FuzzlynOptions>(File.ReadAllText(s))
                },
                { "dump-options", "Dump options to stdout and do nothing else", v => dumpOptions = v != null },
                { "output-source", "Output program source instead of feeding them directly to Roslyn and execution", v => output = v != null },
                { "execute-programs", "Accept programs to execute on stdin and report back differences", v => executePrograms = v != null },
                { "checksum", "Enable or disable checksumming in the generated code", v => enableChecksumming = v != null },
                { "reduce", "Reduce program to a minimal example", v => reduce = v != null },
                { "reduce-use-child-processes", "Check reduced example candidates in child processes", v => reduceInChildProcesses = v != null },
                { "reduce-debug-git-dir=", "Create reduce path in specified dir (must not exists beforehand)", v => reduceDebugGitDir = v },
                { "remove-fixed=", "Remove fixed programs in directory", v => removeFixed = v },
                { "stats", "Generate a bunch of programs and record their sizes", v => stats = v != null },
                { "help|h", v => help = v != null }
            };

            string error = null;

            try
            {
                List <string> leftover = optionSet.Parse(args);
                if (leftover.Any())
                {
                    error = "Unknown arguments: " + string.Join(" ", leftover);
                }
            }
            catch (OptionException ex)
            {
                error = ex.Message;
            }

            if (error != null)
            {
                Console.WriteLine("Fuzzlyn: {0}", error);
                Console.WriteLine("Use --help for help.");
                return;
            }

            if (help)
            {
                Console.WriteLine("Usage: fuzzlyn.exe");
                optionSet.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (executePrograms.HasValue && executePrograms.Value)
            {
                ProgramExecutor.Run();
                return;
            }

            if (options == null)
            {
                options = new FuzzlynOptions();
            }

            if (seed.HasValue)
            {
                options.Seed = seed.Value;
            }
            if (numPrograms.HasValue)
            {
                options.NumPrograms = numPrograms.Value;
            }
            if (parallelism.HasValue)
            {
                options.Parallelism = parallelism.Value;
            }
            if (output.HasValue)
            {
                options.Output = output.Value;
            }
            if (enableChecksumming.HasValue)
            {
                options.EnableChecksumming = enableChecksumming.Value;
            }
            if (reduce.HasValue)
            {
                options.Reduce = reduce.Value;
            }
            if (reduceInChildProcesses.HasValue)
            {
                options.ReduceWithChildProcesses = reduceInChildProcesses.Value;
            }
            if (stats.HasValue)
            {
                options.Stats = stats.Value;
            }

            if (options.NumPrograms != 1 && options.Seed.HasValue)
            {
                Console.WriteLine("Error: Must specify exactly 1 program if a seed is specified.");
                return;
            }

            if (options.Reduce && !options.Seed.HasValue)
            {
                Console.WriteLine("Error: Cannot reduce without a seed.");
                return;
            }

            if (dumpOptions)
            {
                Console.Write(JsonConvert.SerializeObject(options, Formatting.Indented));
                return;
            }

            string val = Environment.GetEnvironmentVariable("COMPlus_TieredCompilation");

            if (val != "0")
            {
                Console.WriteLine(
                    "Please set the COMPlus_TieredCompilation environment variable " +
                    "to \"0\" before starting Fuzzlyn.");
                Console.WriteLine("For cmd use \"set COMPlus_TieredCompilation=0\".");
                Console.WriteLine("For powershell use \"$env:COMPlus_TieredCompilation='0'\"");
                Console.WriteLine("For bash use \"export COMPlus_TieredCompilation=0\"");
                Console.WriteLine("For Visual Studio, check the debug tab");
            }
            else if (removeFixed != null)
            {
                RemoveFixedPrograms(options, removeFixed);
            }
            else if (options.Reduce)
            {
                ReduceProgram(options, reduceDebugGitDir);
            }
            else if (options.Stats)
            {
                GenerateProgramsAndGetStats(options);
            }
            else if (options.Output)
            {
                GenerateProgramsAndOutput(options);
            }
            else
            {
                GenerateProgramsAndCheck(options);
            }

            if (Debugger.IsAttached)
            {
                Console.ReadLine();
            }
        }
Ejemplo n.º 11
0
        private static void RemoveFixedPrograms(FuzzlynOptions options, string dir)
        {
            const string rereduceFile = "Rereduce_required.txt";

            string[] files = Directory.GetFiles(dir, "*.cs").OrderBy(p => p.ToLowerInvariant()).ToArray();
            for (int i = 0; i < files.Length; i++)
            {
                Console.Title = $"Processing {i + 1}/{files.Length}";

                string          contents = File.ReadAllText(files[i]);
                MatchCollection matches  = Regex.Matches(contents, "// Seed: ([0-9]+)");
                if (matches.Count != 1)
                {
                    continue;
                }

                ulong seed = ulong.Parse(matches[0].Groups[1].Value);
                Console.Write("Processing {0}: ", seed);

                options.Seed = seed;
                var cg = new CodeGenerator(options);
                CompilationUnitSyntax original = cg.GenerateProgram();

                CompileResult debug   = Compiler.Compile(original, Compiler.DebugOptions);
                CompileResult release = Compiler.Compile(original, Compiler.ReleaseOptions);

                if (debug.CompileErrors.Length > 0 || release.CompileErrors.Length > 0)
                {
                    Console.WriteLine("Compiler error");
                    continue;
                }

                if (debug.RoslynException != null || release.RoslynException != null)
                {
                    Console.WriteLine("Compiler exception");
                    continue;
                }

                ProgramPairResults execResults = ProgramExecutor.RunSeparately(
                    new List <ProgramPair> {
                    new ProgramPair(false, debug.Assembly, release.Assembly)
                })
                                                 ?.Single();

                if (execResults == null)
                {
                    Console.WriteLine("Crashed sub-process, still interesting");
                    continue;
                }

                if (execResults.DebugResult.Checksum != execResults.ReleaseResult.Checksum ||
                    execResults.DebugResult.ExceptionType != execResults.ReleaseResult.ExceptionType)
                {
                    // Execute the reduced form to see if we get interesting behavior.
                    // Otherwise we may need to rereduce it.
                    // HOAX: Currently IsReducedVersionInteresting runs the programs
                    // in our own process, so we are conservative and do not run programs
                    // that may crash us (it is possible that the unreduced example does not
                    // crash, but that the reduced does.
                    if (contents.Contains("Crashes the runtime") || IsReducedVersionInteresting(execResults, contents))
                    {
                        Console.WriteLine("Still interesting");
                    }
                    else
                    {
                        File.AppendAllText(rereduceFile, seed + Environment.NewLine);
                        Console.WriteLine("Marked for rereduction");
                    }

                    continue;
                }

                Console.WriteLine("Deleted, no longer interesting");
                File.Delete(files[i]);
            }
        }
Ejemplo n.º 12
0
 public Randomizer(FuzzlynOptions options)
 {
     Options = options;
     Seed    = options.Seed ?? Rng.GenSeed();
     Rng     = Rng.FromSplitMix64Seed(Seed);
 }
Ejemplo n.º 13
0
        private static void Main(string[] args)
        {
            ulong?         seed               = null;
            int?           numPrograms        = null;
            int?           parallelism        = null;
            FuzzlynOptions options            = null;
            bool           help               = false;
            bool           dumpOptions        = false;
            bool?          output             = null;
            bool?          executePrograms    = null;
            bool?          enableChecksumming = null;
            bool?          reduce             = null;
            string         removeFixed        = null;
            OptionSet      optionSet          = new OptionSet
            {
                { "seed=|s=", "Seed to use when generating a single program", (ulong v) => seed = v },
                { "parallelism=", "Number of cores to use", (int?p) => parallelism = p },
                { "num-programs=|n=", "Number of programs to generate", (int v) => numPrograms = v },
                {
                    "options=",
                    "Path to options.json. Command-line options will override options from this file.",
                    s => options = JsonConvert.DeserializeObject <FuzzlynOptions>(File.ReadAllText(s))
                },
                { "dump-options", "Dump options to stdout and do nothing else", v => dumpOptions = v != null },
                { "output-source", "Output program source instead of feeding them directly to Roslyn and execution", v => output = v != null },
                { "execute-programs", "Accept programs to execute on stdin and report back differences", v => executePrograms = v != null },
                { "checksum", "Enable or disable checksumming in the generated code", v => enableChecksumming = v != null },
                { "reduce", "Reduce program to a minimal example", v => reduce = v != null },
                { "remove-fixed=", "Remove fixed programs in directory", v => removeFixed = v },
                { "help|h", v => help = v != null }
            };


            string error = null;

            try
            {
                List <string> leftover = optionSet.Parse(args);
                if (leftover.Any())
                {
                    error = "Unknown arguments: " + string.Join(" ", leftover);
                }
            }
            catch (OptionException ex)
            {
                error = ex.Message;
            }

            if (error != null)
            {
                Console.WriteLine("Fuzzlyn: {0}", error);
                Console.WriteLine("Use --help for help.");
                return;
            }

            if (help)
            {
                Console.WriteLine("Usage: fuzzlyn.exe");
                optionSet.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (executePrograms.HasValue && executePrograms.Value)
            {
                ProgramExecutor.Run();
                return;
            }

            if (options == null)
            {
                options = new FuzzlynOptions();
            }

            if (seed.HasValue)
            {
                options.Seed = seed.Value;
            }
            if (numPrograms.HasValue)
            {
                options.NumPrograms = numPrograms.Value;
            }
            if (parallelism.HasValue)
            {
                options.Parallelism = parallelism.Value;
            }
            if (output.HasValue)
            {
                options.Output = output.Value;
            }
            if (enableChecksumming.HasValue)
            {
                options.EnableChecksumming = enableChecksumming.Value;
            }
            if (reduce.HasValue)
            {
                options.Reduce = reduce.Value;
            }

            if (options.NumPrograms != 1 && options.Seed.HasValue)
            {
                Console.WriteLine("Error: Must specify exactly 1 program if a seed is specified.");
                return;
            }

            if (options.NumPrograms != 1 && options.Output)
            {
                Console.WriteLine("Error: Must specify exactly 1 program if output is desired.");
                return;
            }

            if (options.Reduce && !options.Seed.HasValue)
            {
                Console.WriteLine("Error: Cannot reduce without a seed.");
                return;
            }

            if (dumpOptions)
            {
                Console.Write(JsonConvert.SerializeObject(options, Formatting.Indented));
                return;
            }

            if (removeFixed != null)
            {
                RemoveFixedPrograms(options, removeFixed);
                return;
            }

            if (options.Reduce)
            {
                ReduceProgram(options);
            }
            else
            {
                GenerateProgram(options);
            }
        }