<commit_before>/*

   honggfuzz - cmdline parsing

   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

   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.

*/

#include "cmdline.h"

#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "common.h"
#include "log.h"

#define AB ANSI_BOLD
#define AC ANSI_CLEAR
#define ANSI_BOLD "\033[1m"
#define ANSI_CLEAR "\033[0m"

struct custom_option {
    struct option opt;
    const char *descr;
};

static bool checkFor_FILE_PLACEHOLDER(char **args)
{
    for (int x = 0; args[x]; x++) {
        if (strstr(args[x], _HF_FILE_PLACEHOLDER))
            return true;
    }
    return false;
}

static const char *cmdlineYesNo(bool yes)
{
    return (yes ? "true" : "false");
}

static void cmdlineHelp(const char *pname, struct custom_option *opts)
{
    LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
    LOG_HELP_BOLD("Options:");
    for (int i = 0; opts[i].opt.name; i++) {
        if (isprint(opts[i].opt.val)) {
            LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
                          "|-", opts[i].opt.val,
                          opts[i].opt.has_arg == required_argument ? "[val]" : "");
        } else {
            LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
                          opts[i].opt.has_arg == required_argument ? "[val]" : "");
        }
        LOG_HELP("\t%s", opts[i].descr);
    }
    LOG_HELP_BOLD("\nExamples:");
    LOG_HELP(" Run the binary over a mutated file chosen from the directory");
    LOG_HELP_BOLD("  " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
    LOG_HELP(" As above, provide input over STDIN:");
    LOG_HELP_BOLD("  " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg" AC);
#if defined(_HF_ARCH_LINUX)
    LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks (coverage):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_ip -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_ip_addr -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
#endif                          /* defined(_HF_ARCH_LINUX) */
}

static void cmdlineUsage(const char *pname, struct custom_option *opts)
{
    cmdlineHelp(pname, opts);
    exit(0);
}

static bool cmdlineIsANumber(const char *s)
{
    for (int i = 0; s[i]; s++) {
        if (!isdigit(s[i]) && s[i] != 'x') {
            return false;
        }
    }
    return true;
}

rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
{
    struct rlimit cur;
    if (getrlimit(res, &cur) == -1) {
        PLOG_F("getrlimit(%d)", res);
    }
    if (strcasecmp(optarg, "max") == 0) {
        return cur.rlim_max;
    }
    if (strcasecmp(optarg, "def") == 0) {
        return cur.rlim_cur;
    }
    if (cmdlineIsANumber(optarg) == false) {
        LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
    }
    rlim_t val = strtoul(optarg, NULL, 0) * mul;
    if (val == ULONG_MAX && errno != 0) {
        PLOG_F("strtoul('%s', 0)", optarg);
    }
    return val;
}

bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
{
    /*  *INDENT-OFF* */
    (*hfuzz) = (honggfuzz_t) {
        .cmdline = NULL,
        .inputFile = NULL,
        .nullifyStdio = false,
        .useScreen = true,
        .fuzzStdin = false,
        .saveUnique = true,
        .fileExtn = "fuzz",
        .workDir = ".",
        .flipRate = 0.001f,
        .externalCommand = NULL,
        .dictionaryFile = NULL,
        .dictionary = NULL,
        .dictionaryCnt = 0,<commit_msg>Cast rlim_t to unsigned long<commit_after>/*

   honggfuzz - cmdline parsing

   -----------------------------------------

   Copyright 2014 Google Inc. All Rights Reserved.

   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.

*/

#include "cmdline.h"

#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "common.h"
#include "log.h"

#define AB ANSI_BOLD
#define AC ANSI_CLEAR
#define ANSI_BOLD "\033[1m"
#define ANSI_CLEAR "\033[0m"

struct custom_option {
    struct option opt;
    const char *descr;
};

static bool checkFor_FILE_PLACEHOLDER(char **args)
{
    for (int x = 0; args[x]; x++) {
        if (strstr(args[x], _HF_FILE_PLACEHOLDER))
            return true;
    }
    return false;
}

static const char *cmdlineYesNo(bool yes)
{
    return (yes ? "true" : "false");
}

static void cmdlineHelp(const char *pname, struct custom_option *opts)
{
    LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
    LOG_HELP_BOLD("Options:");
    for (int i = 0; opts[i].opt.name; i++) {
        if (isprint(opts[i].opt.val)) {
            LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
                          "|-", opts[i].opt.val,
                          opts[i].opt.has_arg == required_argument ? "[val]" : "");
        } else {
            LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
                          opts[i].opt.has_arg == required_argument ? "[val]" : "");
        }
        LOG_HELP("\t%s", opts[i].descr);
    }
    LOG_HELP_BOLD("\nExamples:");
    LOG_HELP(" Run the binary over a mutated file chosen from the directory");
    LOG_HELP_BOLD("  " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
    LOG_HELP(" As above, provide input over STDIN:");
    LOG_HELP_BOLD("  " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg" AC);
#if defined(_HF_ARCH_LINUX)
    LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks (coverage):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_ip -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_ip_addr -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
    LOG_HELP(" Run the binary over a dynamic file, maximize custom counters (experimental):");
    LOG_HELP_BOLD("  " PROG_NAME " --linux_perf_custom -- /usr/bin/tiffinfo -D "
                  _HF_FILE_PLACEHOLDER);
#endif                          /* defined(_HF_ARCH_LINUX) */
}

static void cmdlineUsage(const char *pname, struct custom_option *opts)
{
    cmdlineHelp(pname, opts);
    exit(0);
}

static bool cmdlineIsANumber(const char *s)
{
    for (int i = 0; s[i]; s++) {
        if (!isdigit(s[i]) && s[i] != 'x') {
            return false;
        }
    }
    return true;
}

rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
{
    struct rlimit cur;
    if (getrlimit(res, &cur) == -1) {
        PLOG_F("getrlimit(%d)", res);
    }
    if (strcasecmp(optarg, "max") == 0) {
        return cur.rlim_max;
    }
    if (strcasecmp(optarg, "def") == 0) {
        return cur.rlim_cur;
    }
    if (cmdlineIsANumber(optarg) == false) {
        LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
    }
    rlim_t val = strtoul(optarg, NULL, 0) * mul;
    if ((unsigned long)val == ULONG_MAX && errno != 0) {
        PLOG_F("strtoul('%s', 0)", optarg);
    }
    return val;
}

bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
{
    /*  *INDENT-OFF* */
    (*hfuzz) = (honggfuzz_t) {
        .cmdline = NULL,
        .inputFile = NULL,
        .nullifyStdio = false,
        .useScreen = true,
        .fuzzStdin = false,
        .saveUnique = true,
        .fileExtn = "fuzz",
        .workDir = ".",
        .flipRate = 0.001f,
        .externalCommand = NULL,
        .dictionaryFile = NULL,
        .dictionary = NULL,
        .dictionaryCnt = 0,
{'fraction_non_alphanumeric': 0.1435148118494796, 'fraction_numerical': 0.006204963971176942, 'mean_word_length': 2.5261115031757235, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6732629', 'n_tokens_mistral': 3597, 'n_tokens_neox': 3488, 'n_words': 918}