Skip to main content

McCabe++ (mcpp): cyclomatic complexity and other vulnerability-related code metrics

Project description

McCabe++ (mcpp)

mcpp measures typical code complexity metrics like McCabe's cyclomatic complexity.

The goal of this project is to provide a re-usable script to analyze C/C++ source code and extract complexity metrics from it. The implemented metrics are taken from the paper

LEOPARD: Identifying Vulnerable Code for Vulnerability Assessment through Program Metrics

This tool is released as part of our research in vulnerability discovery and has been used in our paper

SoK: Where to Fuzz? Assessing Target Selection Methods in Directed Fuzzing"

See also the corresponding repo.

Complexity Metrics

Dimension ID Metric Description
CD1: Function C1 cyclomatic complexity
CD2: Loop Structures C2 number of loops
C3 number of nested loops
C4 maximum nesting level of loops

Vulnerability Metrics

Dimension ID Metric Description
VD1: Dependency V1 number of parameter variables
V2 number of variables as parameters for callee function
VD2: Pointers V3 number of pointer arithmetic
V4 number of variables involved in pointer arithmetic
V5 maximum number of pointer arithmetic operations a variable is involved in
VD3: Control Structures V6 number of nested control structures
V7 maximum nesting level of control structures
V8 maximum number of control-dependent control structures
V9 maximum number of data-dependent control structures
V10 number of if structures without else
V11 number of variables involved in control predicates

Setup

Build a docker container which performs the setup automatically or run the installation on your local machine:

pip install .

Note: It is recommended to install packages in virtual environments.

Usage

From Python

Simply import mcpp and then use the extract function (or one of its variants).

from pathlib import Path
from mcpp import extract

input_dir = Path("some/dir")
in_files = list(input_dir.glob("**/*.c"))
result = extract(in_files)

# to extract only a subset of the metrics
result = extract(in_files, ["V1", "C3"])

# full list of metrics:
from mcpp import METRICS
print(list(METRICS.keys()))

CLI

Configuration parameters can be changed in config.yaml or directly on the CLI with e.g. mcpp paths.out_root=some/dir.

Using all defaults:

mcpp                # with default params like input directory, see config.yaml

Changing params from command line:

mcpp in_path=/some/dir/single_source out_path=single_source_metrics.json
mcpp metrics=\[C1,C2,V4\]

Or by passing a changed config.yaml:

  • -cp (config_path) specifies the absolute path to the directory where the config file is located
  • -cn (config_name) specifies the name of the config file
mcpp -cp /some/other/dir -cn myconfig.yaml

Try out the example:

mcpp in_path=examples/data/source paths.out_root=examples/data-out
cat examples/data-out/complexity.json

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcpp-1.2.0.tar.gz (11.0 kB view hashes)

Uploaded Source

Built Distribution

mcpp-1.2.0-py3-none-any.whl (11.2 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page