Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/art/art/tools/dexfuzz/src/dexfuzz/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 16 kB image not shown  

Quelle  Options.java

  Sprache: JAVA
 

/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package dexfuzz;

import dexfuzz.Log.LogTag;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Stores options for dexfuzz.
 */

public class Options {
  /**
   * Constructor has been disabled for this class, which should only be used statically.
   */

  private Options() { }

  // KEY VALUE OPTIONS
  public static final List<String> inputFileList = new ArrayList<String>();
  public static String outputFile = "";
  public static long rngSeed = -1;
  public static boolean usingProvidedSeed = false;
  public static int methodMutations = 3;
  public static int minMethods = 2;
  public static int maxMethods = 10;
  public static final Map<String,Integer> mutationLikelihoods = new HashMap<String,Integer>();
  public static String executeClass = "Main";
  public static String deviceName = "";
  public static boolean usingSpecificDevice = false;
  public static int repeat = 1;
  public static int divergenceRetry = 10;
  public static String executeDirectory = "/data/art-test";
  public static String androidRoot = "";
  public static String dumpMutationsFile = "mutations.dump";
  public static String loadMutationsFile = "mutations.dump";
  public static String reportLogFile = "report.log";
  public static String uniqueDatabaseFile = "unique_progs.db";

  // FLAG OPTIONS
  public static boolean execute;
  public static boolean executeOnHost;
  public static boolean noBootImage;
  public static boolean useInterpreter;
  public static boolean useOptimizing;
  public static boolean useArchArm;
  public static boolean useArchArm64;
  public static boolean useArchX86;
  public static boolean useArchX86_64;
  public static boolean skipHostVerify;
  public static boolean shortTimeouts;
  public static boolean dumpOutput;
  public static boolean dumpVerify;
  public static boolean mutateLimit;
  public static boolean reportUnique;
  public static boolean skipMutation;
  public static boolean dumpMutations;
  public static boolean loadMutations;
  public static boolean runBisectionSearch;
  public static boolean quiet;

  /**
   * Print out usage information about dexfuzz, and then exit.
   */

  public static void usage() {
    Log.always("DexFuzz Usage:");
    Log.always("  --input=<file>         : Seed DEX file to be fuzzed");
    Log.always("                           (Can specify multiple times.)");
    Log.always("  --inputs=<file>        : Directory containing DEX files to be fuzzed.");
    Log.always("  --output=<file>        : Output DEX file to be produced");
    Log.always("");
    Log.always("  --execute              : Execute the resulting fuzzed program");
    Log.always("    --host               : Execute on host");
    Log.always("    --device=<device>    : Execute on an ADB-connected-device, where <device> is");
    Log.always("                           the argument given to adb -s. Default execution mode.");
    Log.always("    --execute-dir=<dir>  : Push tests to this directory to execute them.");
    Log.always("                           (Default: /data/art-test)");
    Log.always("    --android-root=<dir> : Set path where dalvikvm should look for binaries.");
    Log.always("                           Use this when pushing binaries to a custom location.");
    Log.always("    --no-boot-image      : Use this flag when boot.art is not available.");
    Log.always("    --skip-host-verify   : When executing, skip host-verification stage");
    Log.always("    --execute-class=<c>  : When executing, execute this class (default: Main)");
    Log.always("");
    Log.always("    --interpreter        : Include the Interpreter in comparisons");
    Log.always("    --optimizing         : Include the Optimizing Compiler in comparisons");
    Log.always("");
    Log.always("    --arm                : Include ARM backends in comparisons");
    Log.always("    --arm64              : Include ARM64 backends in comparisons");
    Log.always("    --allarm             : Short for --arm --arm64");
    Log.always("    --x86                : Include x86 backends in comparisons");
    Log.always("    --x86-64             : Include x86-64 backends in comparisons");
    Log.always("");
    Log.always("    --dump-output        : Dump outputs of executed programs");
    Log.always("    --dump-verify        : Dump outputs of verification");
    Log.always("    --repeat=<n>         : Fuzz N programs, executing each one.");
    Log.always("    --short-timeouts     : Shorten timeouts (faster; use if");
    Log.always("                           you want to focus on output divergences)");
    Log.always("    --divergence-retry=<n> : Number of retries when checking if test is");
    Log.always("                           self-divergent. (Default: 10)");
    Log.always("  --seed=<seed>          : RNG seed to use");
    Log.always("  --method-mutations=<n> : Maximum number of mutations to perform on each method.");
    Log.always("                           (Default: 3)");
    Log.always("  --min-methods=<n>      : Minimum number of methods to mutate. (Default: 2)");
    Log.always("  --max-methods=<n>      : Maximum number of methods to mutate. (Default: 10)");
    Log.always("  --one-mutation         : Short for --method-mutations=1 ");
    Log.always("                             --min-methods=1 --max-methods=1");
    Log.always("  --likelihoods=<file>   : A file containing a table of mutation likelihoods");
    Log.always("  --mutate-limit         : Mutate only methods whose names end with _MUTATE");
    Log.always("  --skip-mutation        : Do not actually mutate the input, just output it");
    Log.always("                           after parsing");
    Log.always("");
    Log.always("  --dump-mutations[=<file>] : Dump an editable set of mutations applied");
    Log.always("                              to <file> (default: mutations.dump)");
    Log.always("  --load-mutations[=<file>] : Load and apply a set of mutations");
    Log.always("                              from <file> (default: mutations.dump)");
    Log.always("  --log=<tag>            : Set more verbose logging level: DEBUG, INFO, WARN");
    Log.always("  --report=<file>        : Use <file> to report results when using --repeat");
    Log.always("                           (Default: report.log)");
    Log.always("  --report-unique        : Print out information about unique programs generated");
    Log.always("  --unique-db=<file>     : Use <file> store results about unique programs");
    Log.always("                           (Default: unique_progs.db)");
    Log.always("  --bisection-search     : Run bisection search for divergences");
    Log.always("  --quiet                : Disables progress log");
    Log.always("");
    System.exit(0);
  }

  /**
   * Given a flag option (one that does not feature an =), handle it
   * accordingly. Report an error and print usage info if the flag is not
   * recognised.
   */

  private static void handleFlagOption(String flag) {
    if (flag.equals("execute")) {
      execute = true;
    } else if (flag.equals("host")) {
      executeOnHost = true;
    } else if (flag.equals("no-boot-image")) {
      noBootImage = true;
    } else if (flag.equals("skip-host-verify")) {
      skipHostVerify = true;
    } else if (flag.equals("interpreter")) {
      useInterpreter = true;
    } else if (flag.equals("optimizing")) {
      useOptimizing = true;
    } else if (flag.equals("arm")) {
      useArchArm = true;
    } else if (flag.equals("arm64")) {
      useArchArm64 = true;
    } else if (flag.equals("allarm")) {
      useArchArm = true;
      useArchArm64 = true;
    } else if (flag.equals("x86")) {
      useArchX86 = true;
    } else if (flag.equals("x86-64")) {
      useArchX86_64 = true;
    } else if (flag.equals("mutate-limit")) {
      mutateLimit = true;
    } else if (flag.equals("report-unique")) {
      reportUnique = true;
    } else if (flag.equals("dump-output")) {
      dumpOutput = true;
    } else if (flag.equals("dump-verify")) {
      dumpVerify = true;
    } else if (flag.equals("short-timeouts")) {
      shortTimeouts = true;
    } else if (flag.equals("skip-mutation")) {
      skipMutation = true;
    } else if (flag.equals("dump-mutations")) {
      dumpMutations = true;
    } else if (flag.equals("load-mutations")) {
      loadMutations = true;
    } else if (flag.equals("one-mutation")) {
      methodMutations = 1;
      minMethods = 1;
      maxMethods = 1;
    } else if (flag.equals("bisection-search")) {
      runBisectionSearch = true;
    } else if (flag.equals("quiet")) {
      quiet = true;
    } else if (flag.equals("help")) {
      usage();
    } else {
      Log.error("Unrecognised flag: --" + flag);
      usage();
    }
  }

  /**
   * Given a key-value option (one that features an =), handle it
   * accordingly. Report an error and print usage info if the key is not
   * recognised.
   */

  private static void handleKeyValueOption(String key, String value) {
    if (key.equals("input")) {
      inputFileList.add(value);
    } else if (key.equals("inputs")) {
      File folder = new File(value);
      if (folder.listFiles() == null) {
        Log.errorAndQuit("Specified argument to --inputs is not a directory!");
      }
      for (File file : folder.listFiles()) {
        String inputName = value + "/" + file.getName();
        Log.always("Adding " + inputName + " to input seed files.");
        inputFileList.add(inputName);
      }
    } else if (key.equals("output")) {
      outputFile = value;
    } else if (key.equals("seed")) {
      rngSeed = Long.parseLong(value);
      usingProvidedSeed = true;
    } else if (key.equals("method-mutations")) {
      methodMutations = Integer.parseInt(value);
    } else if (key.equals("min-methods")) {
      minMethods = Integer.parseInt(value);
    } else if (key.equals("max-methods")) {
      maxMethods = Integer.parseInt(value);
    } else if (key.equals("repeat")) {
      repeat = Integer.parseInt(value);
    } else if (key.equals("divergence-retry")) {
      divergenceRetry = Integer.parseInt(value);
    } else if (key.equals("log")) {
      Log.setLoggingLevel(LogTag.valueOf(value.toUpperCase()));
    } else if (key.equals("likelihoods")) {
      setupMutationLikelihoodTable(value);
    } else if (key.equals("dump-mutations")) {
      dumpMutations = true;
      dumpMutationsFile = value;
    } else if (key.equals("load-mutations")) {
      loadMutations = true;
      loadMutationsFile = value;
    } else if (key.equals("report")) {
      reportLogFile = value;
    } else if (key.equals("unique-db")) {
      uniqueDatabaseFile = value;
    } else if (key.equals("execute-class")) {
      executeClass = value;
    } else if (key.equals("device")) {
      deviceName = value;
      usingSpecificDevice = true;
    } else if (key.equals("execute-dir")) {
      executeDirectory = value;
    } else if (key.equals("android-root")) {
      androidRoot = value;
    } else {
      Log.error("Unrecognised key: --" + key);
      usage();
    }
  }

  private static void setupMutationLikelihoodTable(String tableFilename) {
    try {
      BufferedReader reader = new BufferedReader(new FileReader(tableFilename));
      String line = reader.readLine();
      while (line != null) {
        line = line.replaceAll("\\s+"" ");
        String[] entries = line.split(" ");
        String name = entries[0].toLowerCase();
        int likelihood = Integer.parseInt(entries[1]);
        if (likelihood > 100) {
          likelihood = 100;
        }
        if (likelihood < 0) {
          likelihood = 0;
        }
        mutationLikelihoods.put(name, likelihood);
        line = reader.readLine();
      }
      reader.close();
    } catch (FileNotFoundException e) {
      Log.error("Unable to open mutation probability table file: " + tableFilename);
    } catch (IOException e) {
      Log.error("Unable to read mutation probability table file: " + tableFilename);
    }
  }

  /**
   * Called by the DexFuzz class during program initialisation to parse
   * the program's command line arguments.
   * @return If options were successfully read and validated.
   */

  public static boolean readOptions(String[] args) {
    for (String arg : args) {
      if (!(arg.startsWith("--"))) {
        Log.error("Unrecognised option: " + arg);
        usage();
      }

      // cut off the --
      arg = arg.substring(2);

      // choose between a --X=Y option (keyvalue) and a --X option (flag)
      if (arg.contains("=")) {
        String[] split = arg.split("=");
        handleKeyValueOption(split[0], split[1]);
      } else {
        handleFlagOption(arg);
      }
    }

    return validateOptions();
  }

  /**
   * Checks if the current options settings are valid, called after reading
   * all options.
   * @return If the options are valid or not.
   */

  private static boolean validateOptions() {
    // Deal with option assumptions.
    if (inputFileList.isEmpty()) {
      File seedFile = new File("fuzzingseed.dex");
      if (seedFile.exists()) {
        Log.always("Assuming --input=fuzzingseed.dex");
        inputFileList.add("fuzzingseed.dex");
      } else {
        Log.errorAndQuit("No input given, and couldn't find fuzzingseed.dex!");
        return false;
      }
    }

    if (outputFile.equals("")) {
      Log.always("Assuming --output=fuzzingseed_fuzzed.dex");
      outputFile = "fuzzingseed_fuzzed.dex";
    }


    if (mutationLikelihoods.isEmpty()) {
      File likelihoodsFile = new File("likelihoods.txt");
      if (likelihoodsFile.exists()) {
        Log.always("Assuming --likelihoods=likelihoods.txt ");
        setupMutationLikelihoodTable("likelihoods.txt");
      } else {
        Log.always("Using default likelihoods (see README for values)");
      }
    }

    // Now check for hard failures.
    if (repeat < 1) {
      Log.error("--repeat must be at least 1!");
      return false;
    }
    if (divergenceRetry < 0) {
      Log.error("--divergence-retry cannot be negative!");
      return false;
    }
    if (usingProvidedSeed && repeat > 1) {
      Log.error("Cannot use --repeat with --seed");
      return false;
    }
    if (loadMutations && dumpMutations) {
      Log.error("Cannot both load and dump mutations");
      return false;
    }
    if (repeat == 1 && inputFileList.size() > 1) {
      Log.error("Must use --repeat if you have provided more than one input");
      return false;
    }
    if (methodMutations < 0) {
      Log.error("Cannot use --method-mutations with a negative value.");
      return false;
    }
    if (minMethods < 0) {
      Log.error("Cannot use --min-methods with a negative value.");
      return false;
    }
    if (maxMethods < 0) {
      Log.error("Cannot use --max-methods with a negative value.");
      return false;
    }
    if (maxMethods < minMethods) {
      Log.error("Cannot use --max-methods that's smaller than --min-methods");
      return false;
    }
    if (executeOnHost && usingSpecificDevice) {
      Log.error("Cannot use --host and --device!");
      return false;
    }
    if (execute) {
      // When host-execution mode is specified, we don't need to select an architecture.
      if (!executeOnHost) {
        if (!(useArchArm
            || useArchArm64
            || useArchX86
            || useArchX86_64)) {
          Log.error("No architecture to execute on was specified!");
          return false;
        }
      } else {
        // TODO: Select the correct architecture. For now, just assume x86.
        useArchX86 = true;
      }
      if ((useArchArm || useArchArm64) && (useArchX86 || useArchX86_64)) {
        Log.error("Did you mean to specify ARM and x86?");
        return false;
      }
      int backends = 0;
      if (useInterpreter) {
        backends++;
      }
      if (useOptimizing) {
        backends++;
      }
      if (useArchArm && useArchArm64) {
        // Could just be comparing optimizing-ARM versus optimizing-ARM64?
        backends++;
      }
      if (backends < 2) {
        Log.error("Not enough backends specified! Try --optimizing --interpreter!");
        return false;
      }
    }

    return true;
  }
}

Messung V0.5 in Prozent
C=88 H=93 G=90

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.