Esempio n. 1
0
 def test_minimize_ir_minimization_possible(self):
     # Add an invalid codegen flag to inject an error into the running of the
     # sample. The error is unconditional so IR minimization should be able to
     # reduce the sample to a minimal function (just returns a parameter).
     s = sample.Sample(
         'fn main(x: u8) -> u8 { -x }',
         sample.SampleOptions(codegen=True,
                              codegen_args=('--invalid_flag!!!', )),
         sample.parse_args_batch('bits[8]:7\nbits[8]:100'))
     success = test_base.TempFileCleanup.SUCCESS  # type: test_base.TempFileCleanup
     run_dir = self.create_tempdir(cleanup=success).full_path
     with self.assertRaises(sample_runner.SampleError):
         run_fuzz.run_sample(s, run_dir=run_dir)
     minimized_ir_path = run_fuzz.minimize_ir(s, run_dir)
     self.assertIsNotNone(minimized_ir_path)
     self.assertIn('ir_minimizer_test.sh', os.listdir(run_dir))
     # Sanity check the minimized IR.
     with open(minimized_ir_path, 'r') as f:
         contents = f.read()
         self.assertIn('package ', contents)
         self.assertIn('fn ', contents)
         # It should be reduced to simply a literal.
         self.assertIn('ret literal', contents)
     # And verify the minimized IR parses.
     subprocess.check_call([PARSE_IR, minimized_ir_path])
Esempio n. 2
0
def main(argv):
    if len(argv) != 2:
        raise app.UsageError(
            'Invalid command-line arguments; want {} <crasher path>'.format(
                argv[0]))

    with gfile.open(argv[1], 'r') as f:
        smp = sample.Sample.from_crasher(f.read())
    if FLAGS.simulator:
        smp = smp._replace(options=smp.options._replace(
            simulator=FLAGS.simulator))

    run_dir = FLAGS.run_dir if FLAGS.run_dir else tempfile.mkdtemp(
        'run_crasher_')

    print(f'Running crasher in directory {run_dir}')
    try:
        run_fuzz.run_sample(smp, run_dir)
    except sample_runner.SampleError:
        print('FAILURE')
        return 1

    print('SUCCESS')
    if not FLAGS.run_dir:
        # Remove the directory if it is temporary.
        shutil.rmtree(run_dir)
    return 0
Esempio n. 3
0
 def test_minimize_ir_no_minimization_possible(self):
   # Verify that IR minimization at least generates a minimization test script
   # and doesn't blow up if the IR is not minimizable. In this case, "not
   # minimizable" means that no error is ever generated when running the
   # sample.
   s = sample.Sample('fn main(x: u8) -> u8 { -x }', sample.SampleOptions(),
                     sample.parse_args_batch('bits[8]:7\nbits[8]:100'))
   success = test_base.TempFileCleanup.SUCCESS  # type: test_base.TempFileCleanup
   run_dir = self.create_tempdir(cleanup=success).full_path
   run_fuzz.run_sample(s, run_dir=run_dir)
   self.assertIsNone(run_fuzz.minimize_ir(s, run_dir))
   dir_contents = os.listdir(run_dir)
   self.assertIn('ir_minimizer_test.sh', dir_contents)
Esempio n. 4
0
 def test_minimize_jit_interpreter_mismatch(self):
   s = sample.Sample('fn main(x: u8) -> u8 { !x }', sample.SampleOptions(),
                     sample.parse_args_batch('bits[8]:0xff\nbits[8]:0x42'))
   success = test_base.TempFileCleanup.SUCCESS  # type: test_base.TempFileCleanup
   run_dir = self.create_tempdir(cleanup=success).full_path
   run_fuzz.run_sample(s, run_dir=run_dir)
   minimized_ir_path = run_fuzz.minimize_ir(
       s, run_dir, inject_jit_result='bits[32]:0x0')
   self.assertIsNotNone(minimized_ir_path)
   with open(minimized_ir_path, 'r') as f:
     contents = f.read()
     self.assertIn('package ', contents)
     self.assertIn('fn ', contents)
     # It should be reduced to simply a literal.
     self.assertIn('ret literal', contents)
   # And verify the minimized IR parses.
   subprocess.check_call([PARSE_IR, minimized_ir_path])
def do_worker_task(workerno: int,
                   queue: Optional[mp.Queue],
                   crash_path: Text,
                   summary_path: Optional[Text] = None,
                   save_temps_path: Optional[Text] = None,
                   minimize_ir: bool = True) -> None:
  """Runs worker task, receiving commands from generator and executing them."""
  queue = queue or multiprocess.get_user_data()[workerno]
  crashers = 0
  calls = 0
  print('---- Started worker {}'.format(workerno))
  sys.stdout.flush()
  start = datetime.datetime.now()

  # Local file to write the summary information to before writing out to the
  # potentially remote (i.e. CNS) summary file. Avoids a potential CNS write
  # with every sample. Instead data is written out in batches.
  summary_file = os.path.join(summary_path, 'summary_%d.binarypb' %
                              workerno) if summary_path else None
  summary_temp_file = tempfile.mkstemp(
      prefix='temp_summary_')[1] if summary_path else None

  i = 0  # Silence pylint warning.
  for i in itertools.count():
    message = queue.get()
    if message.command == Command.STOP:
      break
    assert message.command == Command.RUN, message.command
    calls += len(message.sample.args_batch)
    run_dir = None
    if save_temps_path:
      run_dir = os.path.join(save_temps_path, str(message.sampleno))
      os.makedirs(run_dir)
    else:
      run_dir = tempfile.mkdtemp(prefix='run_fuzz_')

    try:
      run_fuzz.run_sample(
          message.sample,
          run_dir,
          summary_file=summary_temp_file,
          generate_sample_ns=message.generate_sample_ns)
    except sample_runner.SampleError as e:
      crashers += 1
      record_crasher(workerno, message.sampleno, minimize_ir, message.sample,
                     run_dir, crash_path, crashers, str(e))

    if summary_file and i % 25 == 0:
      # Append the local temporary summary file to the actual, potentially
      # remote one, and delete the temporary file.
      with gfile.open(summary_temp_file, 'rb') as f:
        summaries = f.read()
      with gfile.open(summary_file, 'ab+') as f:
        f.write(summaries)
      gfile.remove(summary_temp_file)

    if not save_temps_path:
      shutil.rmtree(run_dir)

    # TODO(leary): 2020-08-28 Turn this into an option.
    if i != 0 and i % 16 == 0:
      elapsed = (datetime.datetime.now() - start).total_seconds()
      print('---- Worker {:3}: {:8.2f} samples/s {:8.2f} calls/s'.format(
          workerno, i / elapsed, calls / elapsed))
      sys.stdout.flush()

  elapsed = (datetime.datetime.now() - start).total_seconds()
  print(
      '---- Worker {:3} finished! {:3} crashers; {:8.2f} samples/s; {:8.2f} calls/s'
      .format(workerno, crashers, i / elapsed, calls / elapsed))
  sys.stdout.flush()
def benchmark_worker(run_dir: Text, smp: sample.Sample):
    print('Running!')
    run_fuzz.run_sample(smp, run_dir)