Repository: sharkdp/fd
File: src/main.rs (Rust)

Code before:
    Ok(if opts.glob && !pattern.is_empty() {
        let glob = GlobBuilder::new(pattern).literal_separator(true).build()?;
        glob.regex().to_owned()
    } else if opts.fixed_strings {
        // Treat pattern as literal string if '--fixed-strings' is used
        regex::escape(pattern)
    } else {
        String::from(pattern)
    })
}

fn check_path_separator_length(path_separator: Option<&str>) -> Result<()> {
    match (cfg!(windows), path_separator) {
        (true, Some(sep)) if sep.len() > 1 => Err(anyhow!(
            "A path separator must be exactly one byte, but \
                 the given separator is {} bytes: '{}'.\n\
                 In some shells on Windows, '/' is automatically \
                 expanded. Try to use '//' instead.",
            sep.len(),
            sep
        )),
        _ => Ok(()),
    }
}

fn construct_config(mut opts: Opts, pattern_regexps: &Vec<String>) -> Result<Config> {
    // The search will be case-sensitive if the command line flag is set or
    // if the pattern has an uppercase character (smart case).
    let case_sensitive = !opts.ignore_case
        && (opts.case_sensitive
            || pattern_regexps
                .iter()
                .any(|pat| pattern_has_uppercase_char(pat)));

    let path_separator = opts
        .path_separator
        .take()
        .or_else(filesystem::default_path_separator);
    let actual_path_separator = path_separator
        .clone()
        .unwrap_or_else(|| std::path::MAIN_SEPARATOR.to_string());
    check_path_separator_length(path_separator.as_deref())?;

    let size_limits = std::mem::take(&mut opts.size);
    let time_constraints = extract_time_constraints(&opts)?;
    #[cfg(unix)]
    let owner_constraint: Option<OwnerFilter> = opts.owner;

    #[cfg(windows)]
    let ansi_colors_support =
        ansi_term::enable_ansi_support().is_ok() || std::env::var_os("TERM").is_some();

Review comment (security):
This should probably be:

```suggestion
fn construct_config(mut opts: Opts, pattern_regexps: &[String]) -> Result<Config> {
```
(note that a `Vec<String>` will implicitly dereference to a `&[String]`, so `&pattern_regexps` would still fit the type)

We could almost get away with just accepting an iterator, except that we would need to be able to iterate over it it twice in order to determine if we should be case sensitive or not if the options aren't expllicit. 

Code after:
        regex::escape(pattern)
    } else {
        String::from(pattern)
    })
}

fn check_path_separator_length(path_separator: Option<&str>) -> Result<()> {
    match (cfg!(windows), path_separator) {
        (true, Some(sep)) if sep.len() > 1 => Err(anyhow!(
            "A path separator must be exactly one byte, but \
                 the given separator is {} bytes: '{}'.\n\
                 In some shells on Windows, '/' is automatically \
                 expanded. Try to use '//' instead.",
            sep.len(),
            sep
        )),
        _ => Ok(()),
    }
}

fn construct_config(mut opts: Opts, pattern_regexps: &[String]) -> Result<Config> {
    // The search will be case-sensitive if the command line flag is set or
    // if any of the patterns has an uppercase character (smart case).
    let case_sensitive = !opts.ignore_case
        && (opts.case_sensitive
            || pattern_regexps
                .iter()
                .any(|pat| pattern_has_uppercase_char(pat)));

    let path_separator = opts
        .path_separator
        .take()
        .or_else(filesystem::default_path_separator);
    let actual_path_separator = path_separator
        .clone()
        .unwrap_or_else(|| std::path::MAIN_SEPARATOR.to_string());
    check_path_separator_length(path_separator.as_deref())?;

    let size_limits = std::mem::take(&mut opts.size);
    let time_constraints = extract_time_constraints(&opts)?;
    #[cfg(unix)]
    let owner_constraint: Option<OwnerFilter> = opts.owner.and_then(OwnerFilter::filter_ignore);

    #[cfg(windows)]
    let ansi_colors_support =
        ansi_term::enable_ansi_support().is_ok() || std::env::var_os("TERM").is_some();
    #[cfg(not(windows))]
    let ansi_colors_support = true;

    let interactive_terminal = atty::is(Stream::Stdout);
    let colored_output = match opts.color {