class
Analyzer::Cpp::Cli
- Analyzer::Cpp::Cli
- Analyzer
- Reference
- Object
Overview
Surfaces the command-line attack surface of C++ programs as cli://
endpoints: one endpoint per (sub)command with named options
(param_type "flag"), positional arguments ("argument") and consumed
environment variables ("env"). Covers CLI11, getopt/getopt_long, cxxopts,
boost::program_options, gflags, Abseil Flags and p-ranav/argparse, plus
gated getenv reads.
Line-scan analyzer (Go/Ruby/Rust CLI house style) merging endpoints by URL. There is no C++ engine, so it subclasses Analyzer directly.
Included Modules
Defined in:
analyzer/analyzers/cpp/cli.crConstant Summary
-
ABSL_FLAG_MARK =
/\bABSL_FLAG\s*\(/ -
Abseil Flags.
ABSL_FLAG(type, name, default, help)— the type is matched with a depth-aware manual scan (seeabsl_flag_names) rather than a character-class regex, so a template type with a top-level comma (e.g.std::map<std::string,int>) doesn't truncate/misparse the name field. -
ADD_FLAG =
/(\w+)\s*(?:\.|->)\s*add_flag\s*\(\s*"([^"]+)"/ -
ADD_OPTION =
/(\w+)\s*(?:\.|->)\s*add_option\s*\(\s*"([^"]+)"/ -
APP_DECL =
/\bCLI::App\s+(\w+)/ -
CLI11. Variable-mapped: an option/flag binds to its receiver variable (app vs a subcommand), so a root option declared after a subcommand isn't mis-attributed to it.
-
ARGPARSE_ADD_ARG =
/(\w+)\s*(?:\.|->)\s*add_argument\s*\(\s*"([^"]+)"(?:\s*,\s*"([^"]+)")?/ -
ARGPARSE_DECL =
/\bargparse::ArgumentParser\s+(\w+)\s*\(\s*"([^"]+)"/ -
p-ranav/argparse. Declare-then-register style: an ArgumentParser variable's role (root vs subcommand) is only known once it's observed either as the receiver of
.parse_args(argc, argv)/ owner side of.add_subparser(...), or by elimination when it's the file's only declared parser. Resolved once per file inresolve_argparse_varsbefore options are attributed, so declaration order in the file never decides which parser is root (a helper-function-local parser can never be mistaken for the real root). -
ARGPARSE_PARSE =
/(\w+)\s*(?:\.|->)\s*parse_args\s*\(\s*argc\s*,\s*argv\s*\)/ -
ARGPARSE_SUBPARSER =
/(\w+)\s*(?:\.|->)\s*add_subparser\s*\(\s*(\w+)\s*\)/ -
ARGV_IDX =
/\bargv\s*\[\s*(\d+)\s*\]/ -
CLI_MARKERS_RE =
Regex.union("CLI::App", "getopt", "struct option", "cxxopts::", "program_options", "DEFINE_string", "DEFINE_int", "DEFINE_bool", "ABSL_FLAG", "argparse::ArgumentParser") -
Whitespace-tolerant substring markers (no trailing "(" on macro-style entries) so this gate can never diverge from what the extraction regexes above actually accept, e.g.
ABSL_FLAG (int32_t, ...)with a space before the paren is valid C++ and must not be silently skipped. Precompiled as a single Regex.union so the per-file evidence gate costs one PCRE2 match instead of up to ten naive substring scans. -
CPP_TEST_PATH_RE =
Regex.new((Regex.union("/test/", "/tests/", "_test.", "test_", ".test.")).source, Regex::Options::IGNORE_CASE) -
Precompiled union for the per-file test-path skip gate (cpp_test_path?), matched via String#matches? instead of five naive substring scans.
-
EXTS =
[".cpp", ".cc", ".cxx", ".c++", ".hpp", ".hh", ".hxx"] -
GETENV =
/\b(?:std::)?getenv\s*\(\s*"([^"]+)"/ -
GETOPT_CALL =
/\bgetopt(?:_long)?\s*\([^,]+,[^,]+,\s*"([^"]*)"/ -
GFLAGS_DEF =
/\bDEFINE_(?:string|int32|int64|bool|double|uint32|uint64)\s*\(\s*(\w+)/ -
gflags.
-
LONG_OPT_ENTRY =
/\{\s*"([A-Za-z0-9][\w-]*)"\s*,\s*(?:no_argument|required_argument|optional_argument|\d)/ -
getopt_long struct option entries + short spec.
-
OPTS_CALL =
/add_options\s*\(\s*\)/ -
OPTS_PAIR =
/(?<!\w)\(\s*"([A-Za-z0-9][\w,-]*)"\s*,/ -
cxxopts / boost::program_options option specs are bare
("name", ...)grouping/chaining calls — the(is preceded by)or whitespace, not an identifier (which would make it a helper call like default_value(...)). -
SUBCOMMAND =
/(?:\.|->)\s*add_subcommand\s*\(\s*"([^"]+)"/ -
SUBCOMMAND_VAR =
/(\w+)\s*=\s*\w+\s*(?:\.|->)\s*add_subcommand\s*\(\s*"([^"]+)"/ -
WEB_RE =
/\b(?:Crow|crow|drogon|httplib|oatpp)\b|Crow::|drogon::|httplib::|oatpp::/
Class Method Summary
Instance Method Summary
- #analyze
-
#tech : String
Instance-side view of the same declaration.
Instance methods inherited from class Analyzer
analyze
analyze,
base_path : String
base_path,
base_paths : Array(String)
base_paths,
base_relative_path(path : String) : String
base_relative_path,
callees_needed? : Bool
callees_needed?,
content_matches?(content : String, markers : Regex) : Bool
content_matches?,
http_header_name(name : String) : String | Nil
http_header_name,
line_number_for_index(content : String, char_index : Int32) : Int32
line_number_for_index,
logger : NoirLogger
logger,
parallel_analyze(files : Array(String), &block : String -> Nil)
parallel_analyze,
read_file_content(path : String) : String
read_file_content,
result : Array(Endpoint)
result,
tech : String
tech,
unique_params(params : Array(Param)) : Array(Param)
unique_params,
url : String
url,
web_root_path(path : String, markers : Array(String)) : String
web_root_path
Constructor methods inherited from class Analyzer
new(options : Hash(String, YAML::Any))
new
Macros inherited from class Analyzer
analyzer_for(tech)
analyzer_for
Instance methods inherited from module FileHelper
all_files : Array(String)
all_files,
get_files_by_basename(basename : String) : Array(String)
get_files_by_basename,
get_files_by_extension(extension : String) : Array(String)
get_files_by_extension,
get_files_by_extensions(extensions : Array(String)) : Array(String)
get_files_by_extensions,
get_files_by_prefix(prefix : String) : Array(String)
get_files_by_prefix,
get_files_by_prefix_and_extension(prefix : String, extension : String) : Array(String)
get_files_by_prefix_and_extension,
get_files_by_relative_path(relative_path : String, root : String = "") : Array(String)
get_files_by_relative_path,
get_public_dir_files(base_path : String, folder : String) : Array(String)
get_public_dir_files,
get_public_files(base_path : String, anchors : Array(String) = ["shard.yml", "Gemfile"]) : Array(String)
get_public_files,
walked_path(expanded : String) : String
walked_path
Class Method Detail
Instance Method Detail
Instance-side view of the same declaration. The per-file rescues live on
this base class, which has no way to name the analyzer that is running
inside them, so a skipped file could not be attributed to a tech.
Deriving it from analyzer_for keeps the name written exactly once.