OpenSSL Communities

Adding clang-tidy checks to OpenSSL

FW Frederik Wedel-Heinen Thu 1 Jan 2026 7:41AM Public Seen by 116

Proposal: Optional clang-tidy Support for the OpenSSL Codebase

I would like to gauge interest (beyond my own) in adding clang-tidy support to the OpenSSL codebase.
clang-tidy is a static analysis and linting tool based on Clang that provides a wide range of correctness, security, performance, and readability checks.

https://clang.llvm.org/extra/clang-tidy/

In general, code flagged by linters such as clang-tidy is not necessarily incorrect. For that reason, the intent is not to introduce an overly strict or disruptive ruleset. Instead, the goal is to selectively enable checks that provide actionable feedback and are suitable for OpenSSL’s portability, performance, and security requirements.

clang-tidy is supported by many IDEs and editors, allowing contributors to receive feedback directly in their source view during development.

Summary

This proposal suggests:

  • Adding a .clang-tidy configuration file to the OpenSSL repository

  • Adding an optional CI job that runs clang-tidy with a curated set of checks

  • Documenting how the .clang-tidy configuration is managed and evolved

  • Documenting how contributors can run clang-tidy locally

  • Defining a clear strategy for handling false positives and suppressions

The goal is to improve code quality and maintainability incrementally, without introducing undue burden on contributors or reviewers.

Scope and enforcement philosophy

The intent is not to enforce all available clang-tidy checks.

Instead, the proposal is to:

  • Enable broad check families initially

  • Explicitly blacklist checks that:

    • currently fail extensively on the existing codebase, and/or

    • are considered inappropriate for OpenSSL’s coding style or design constraints

  • Gradually enable additional checks over time, only when accompanied by fixes in the same pull request

This avoids introducing large numbers of pre-existing violations and allows improvements to be reviewed incrementally.

Handling false positives and suppressions

clang-tidy inevitably produces false positives, particularly in macro-heavy, highly portable C code such as OpenSSL.

The proposed approach is:

  • Prefer configuration-level suppression via .clang-tidy over source code annotations

  • Use directory-local .clang-tidy files where a check is inappropriate for a specific subtree

  • Use // NOLINT or // NOLINTNEXTLINE comments sparingly and with justification, only when a false positive cannot reasonably be addressed through configuration

  • Avoid blanket suppression of entire check families unless there is broad agreement that they are unsuitable

This approach keeps the source code largely free of tool-specific annotations while still allowing practical use of clang-tidy.

Proposed ruleset strategy

Initial configuration:

  • Enable broad families:

    • clang-analyzer-,

    • bugprone-,

    • portability-,

    • performance-,

    • readability-,

    • misc-,

    • concurrency-,

    • cert-,


  • Explicitly disable checks that are incompatible with OpenSSL’s coding standard and/or not clearly beneficial.

The .clang-tidy file would be maintained alongside the codebase and updated as checks are enabled or disabled.

Example: running clang-tidy locally

Example workflow on macOS (requires clang-tidy, bear, and xargs):

./config
make clean
bear -- make
find ssl crypto providers test apps -name '*.c' \
  | xargs -P$(sysctl -n hw.ncpu) -n1 \
    clang-tidy -p . \
  > clang-tidy.out 2>&1

Results from a local run

I ran clang-tidy on OpenSSL master
(commit: 0755a8ef905800ebc4ee022f880119f3e67b64bc)
on macOS, using the ruleset described above.

The following checks produced findings that may be worth considering for future enforcement:

bugprone-implicit-widening-of-multiplication-result
bugprone-macro-parentheses
bugprone-misplaced-widening-cast
bugprone-narrowing-conversions
bugprone-suspicious-string-compare
bugprone-switch-missing-default-case
bugprone-too-small-loop-variable
cert-err34-c
clang-analyzer-deadcode.DeadStores
clang-analyzer-security.ArrayBound
concurrency-mt-unsafe
misc-unused-parameters
performance-no-int-to-ptr
readability-avoid-nested-conditional-operator
readability-avoid-unconditional-preprocessor-if
readability-duplicate-include
readability-inconsistent-declaration-parameter-name
readability-magic-numbers
readability-misleading-indentation
readability-non-const-parameter
readability-redundant-casting
readability-redundant-control-flow
readability-redundant-declaration
readability-redundant-preprocessor

Not all of these are necessarily appropriate to enforce, but they serve as a starting point for discussion.

NH

Neil Horman Fri 2 Jan 2026 2:43PM

Generally speaking, I'd be in favor of something like this, though I think we need to be very careful here how we go about it.

A few notes:

1) clang-tidy doesn't understand our template files (i.e. our perl-ified .in and .inc files). As such it seems we need to be careful to only run this linting on built trees, so we don't run afoul of any diagnostic errors for type definitions we define in generated headers.

2) We will want to be very careful about what lint checks we are willing to enable. for instance, running with only the concurrency-mt-unsafe check on my local tree reports about 150 errors indicating usafe mutithread usage, mostly centering around the getenv, strerror, and exit functions, all of which are defined in posix as MT-SAFE, so there some question in my mind as to what clang-tidy is trying to get us to do there, and what our expectations are.

3) For checks we are willing to enable, we should ensure that any enablement is only done after a run of tidy produces no errors/warnings against that check. Some of these even trivial checks above produce 1000's of errors, and I would hate to enable something like this only to have it ignored because its too much of a lift for people with follow on patches to have to clean up the mess.

I'd be in favor of doing something like:

1) Create a ci job to run clang-tidy on the source tree as part of a pull request

2) Check in a .clang-tidy file that enables 0 checks (i.e. the trivial case)

3) Create a long running issue for anyone interested to scrub the tree of various errors and enable the corresponding check.

It might make for a series of "good first issue", work efforts to expose people to the source tree, but doing broad based tree-wide cleanups.

FW

Frederik Wedel-Heinen Thu 8 Jan 2026 6:38PM

Here's a PR of your proposed first step :) https://github.com/openssl/openssl/pull/29580