Nesting

The maximum nesting level of control structures in a function.

Interpretation

The attribute that nesting is expected to quantify is complexity. A file that is complex to comprehend, change, and/or test is likely to have a high value for the nesting metric.

Evidence

Nesting has been empirically-validated to be associated with historical vulnerabilities in software in the following peer-reviewed research studies:

  1. To Fear or Not to Fear That is the Question: Code Characteristics of a Vulnerable Function with an Existing Exploit [2]

The empirical evidence overwhelming supports the notion that a source code file with high nesting is more likely to contain a security vulnerability.

Implications

The security implication(s) of a file having high nesting could be one or more of the following:

  • Complex file is likely to be harder to comprehend, change, and/or test and, as a result, may increase the potential for latent vulnerabilities.

Mitigations

The theoretical mitigation to lowering the nesting of a file is to have source code files only include simpler constructs with limited use of statements that alter control flow. However, the theoretical mitigation is not practical because modern software is inherently complex. Therefore, the risk of latent vulnerabilities in a file with high cyclomatic complexity could be mitigated using one or more of the following suggestions:

  • Refactor functions in the file to simplify the constructs used leveraging common design patterns when appropriate.

Implementation

In our implementation of the metric, we use SciTools Understand™ to collect the nesting metric from source code files.

The source code of the implementation of the metric will be made available on GitHub. If you need to collect the metric from your project, the implementation will also be made available as a container image on Docker Hub.

Languages

The metric implementation is limited to projects written in C/C++, C#, Ada, Basic, Fortran, Java, Jovial, Pascal, Python, Web.

Example(s)

In this section, we present examples of the metric collected from popular open-source software projects.

Chromium

In this subsection, we present examples of the metric collected from the Chromium, the open-source project behind the Google Chrome web browser.

The metric examples presented here were collected at 6b9bf768231f commit to the master branch of the Chromium source code repository.

Summary

Chromium Nesting Distribution
Figure 1.1
Chromium Nesting Discriminatory
Figure 1.2

Shown in Figure 1.1 is the distribution of the metric collected from source code files in the Chromium project. Shown in Figure 1.2 is the comparison of the distribution of the metric collected from source code files in the Chromium project that were not historically vulnerable and those that were.

Thresholds

The thresholds of the metric in the Chromium project determined using the approach prescribed by Alves et al. [1] is shown in the table below.

Metric Range value < 3 3 ≤ value < 4 4 ≤ value < 5 5 ≤ value
Risk Level Low Medium High Critical

Risky Files

The thresholds are used to classify source code files into appropriate risk levels. Shown below are the top and bottom three source code files from the Chromium project in each of the three non-trivial risk levels.

Path Nesting Percentile
third_party/crashpad/crashpad/snapshot/fuchsia/memory_map_fuchsia.cc 3 74.7901
media/audio/win/device_enumeration_win.cc 3 74.7901
third_party/blink/renderer/platform/fonts/font_selection_types_test.cc 3 74.7901
...
chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc 3 74.7901
components/autofill/core/browser/field_filler.cc 3 74.7901
third_party/tcmalloc/gperftools-2.0/chromium/src/tests/stack_trace_table_test.cc 3 74.7901

Path Nesting Percentile
third_party/blink/renderer/core/html/html_slot_element_test.cc 4 84.8791
net/url_request/url_fetcher_core.cc 4 84.8791
cc/layers/picture_layer_impl.cc 4 84.8791
...
ppapi/examples/mouse_lock/mouse_lock.cc 4 84.8791
third_party/sqlite/patched/src/rowset.c 4 84.8791
chrome/browser/android/search_permissions/search_geolocation_disclosure_tab_helper.cc 4 84.8791

Path Nesting Percentile
base/nix/xdg_util.cc 5 92.4416
chrome/browser/ui/app_list/app_launch_event_logger.cc 5 92.4416
components/subresource_filter/content/renderer/subresource_filter_agent.cc 5 92.4416
...
third_party/libxml/src/testapi.c 10 99.9763
third_party/zlib/infback.c 11 99.9800
third_party/libpng/pngrutil.c 13 100

OpenBSD

In this subsection, we present examples of the metric collected from the UNIX-like operating system developed by the OpenBSD project.

The metric examples presented here were collected at dbdab68da3b commit to the master branch of the OpenBSD source code repository.

Summary

OpenBSD Nesting Distribution
Figure 2.1
OpenBSD Nesting Discriminatory
Figure 2.2

Shown in Figure 2.1 is the distribution of the metric collected from source code files in the OpenBSD project. Shown in Figure 2.2 is the comparison of the distribution of the metric collected from source code files in the OpenBSD project that were not historically vulnerable and those that were.

Thresholds

The thresholds of the metric in the OpenBSD project determined using the approach prescribed by Alves et al. [1] is shown in the table below.

Metric Range value < 5 5 ≤ value < 6 6 ≤ value < 7 7 ≤ value
Risk Level Low Medium High Critical

Risky Files

The thresholds are used to classify source code files into appropriate risk levels. Shown below are the top and bottom three source code files from the OpenBSD project in each of the three non-trivial risk levels.

Path Nesting Percentile
lib/libcurses/base/lib_refresh.c 5 70.4750
gnu/llvm/tools/lldb/source/Host/common/PseudoTerminal.cpp 5 70.4750
usr.sbin/unbound/iterator/iter_scrub.c 5 70.4750
...
gnu/gcc/libstdc++-v3/src/tree.cc 5 70.4750
gnu/llvm/lib/Target/Hexagon/HexagonBitSimplify.cpp 5 70.4750
gnu/gcc/gcc/tree-cfgcleanup.c 5 70.4750

Path Nesting Percentile
gnu/llvm/tools/clang/lib/Sema/TreeTransform.h 6 84.6915
sbin/pfctl/pfctl_optimize.c 6 84.6915
gnu/gcc/intl/localealias.c 6 84.6915
...
gnu/lib/libiberty/src/make-relative-prefix.c 6 84.6915
games/backgammon/teachgammon/ttext2.c 6 84.6915
gnu/gcc/gcc/print-rtl.c 6 84.6915

Path Nesting Percentile
gnu/gcc/gcc/var-tracking.c 7 93.0274
gnu/llvm/lib/CodeGen/MachinePipeliner.cpp 7 93.0274
gnu/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp 7 93.0274
...
gnu/usr.bin/gcc/gcc/conflict.c 16 99.9910
gnu/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp 16 99.9910
gnu/usr.bin/perl/numeric.c 20 100

Reference(s)

[1] Tiago L. Alves, Christiaan Ypma, and Joost Visser. 2010. Deriving Metric Thresholds From Benchmark Data. In Proceedings of the 26th International Conference on Software Maintenance (ICSM '10). 1-10. https://doi.org/10.1109/ICSM.2010.5609747

[2] Awad Younis, Yashwant Malaiya, Charles Anderson, and Indrajit Ray. 2016. To Fear or Not to Fear That is the Question: Code Characteristics of a Vulnerable Function with an Existing Exploit. In Proceedings of the 6th ACM Conference on Data and Application Security and Privacy (CODASPY '16). New York, NY, USA, 97–104. https://doi.org/10.1145/2857705.2857750