From 6605060b18e3a3cfb67aba10f67c93a4b56a645d Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 21 May 2026 13:59:18 -0700 Subject: [PATCH] CI: more smoke coverage + header self-sufficiency - Add AddressSanitizer entry to smoke matrix (--enable-all + -fsanitize=address). - Add check-headers workflow: 214 public wolfssl/*.h compile standalone. - Fix quic.h, rng_bank.h, Renesas/renesas-fspsm-crypt.h to be self-sufficient. - Remove no-tls.yml (its single config is already covered by os-check.yml). --- .github/scripts/check-headers.sh | 99 +++++++++++++++++++ .github/workflows/check-headers.yml | 43 ++++++++ .github/workflows/no-tls.yml | 50 ---------- .github/workflows/smoke-test.yml | 24 ++++- wolfssl/quic.h | 16 ++- .../port/Renesas/renesas-fspsm-crypt.h | 1 + wolfssl/wolfcrypt/rng_bank.h | 1 + 7 files changed, 171 insertions(+), 63 deletions(-) create mode 100755 .github/scripts/check-headers.sh create mode 100644 .github/workflows/check-headers.yml delete mode 100644 .github/workflows/no-tls.yml diff --git a/.github/scripts/check-headers.sh b/.github/scripts/check-headers.sh new file mode 100755 index 0000000000..33bdd7f345 --- /dev/null +++ b/.github/scripts/check-headers.sh @@ -0,0 +1,99 @@ +#!/usr/bin/env bash +# +# check-headers.sh +# +# Verifies that every public-facing wolfSSL header compiles standalone +# from a fresh consumer's perspective: +# +# #include +# #include +# int main(void) { return 0; } +# +# Catches the common breakage where a header silently relies on a +# transitive include from an earlier `.c` file and stops compiling +# when downstream code includes it first. +# +# Requires: +# * ./configure has been run (so wolfssl/options.h exists). +# * gcc and standard build env. +# +# Usage: +# .github/scripts/check-headers.sh # scan default header set +# .github/scripts/check-headers.sh # scan a specific list + +set -u + +ROOT="$(git rev-parse --show-toplevel)" +cd "$ROOT" || exit 2 + +if [ ! -f wolfssl/options.h ]; then + echo "::error::wolfssl/options.h not found - run ./configure first" >&2 + exit 2 +fi + +CC="${CC:-gcc}" +GHA="${GITHUB_ACTIONS:-}" + +emit() { + local file="$1" msg="$2" + if [ -n "$GHA" ]; then + printf '::error file=%s,line=1,title=header-self-include::%s\n' "$file" "$msg" + else + printf '%s: %s\n' "$file" "$msg" + fi +} + +# Default scope: public wolfssl headers excluding vendor/port subdirs and +# files that are intentionally not standalone-includable. +if [ "$#" -gt 0 ]; then + HEADERS=("$@") +else + # Exclusions: + # * generated / private / test-data headers. + # * wolfcrypt math backends (tfm vs sp_int are mutually exclusive). + # * port/* headers whose first-line vendor SDK include can't be + # satisfied in a generic CI environment (mcapi.h, kcapi.h, + # em_device.h, fsl_dcp.h, hw/inout.h, etc.) or that reference + # vendor-only types. Fix the offending header's vendor #include + # with an #ifdef guard and drop the exclusion in a follow-up. + mapfile -t HEADERS < <( + git ls-files 'wolfssl/*.h' 'wolfssl/wolfcrypt/*.h' \ + 'wolfssl/wolfcrypt/port/**/*.h' 'wolfssl/openssl/*.h' \ + | grep -vE '^wolfssl/(options|internal|certs_test|certs_test_sm|debug-trace-error-codes|debug-untrace-error-codes)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/(fips_test|selftest|tfm)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/aria/aria-crypt(ocb)?\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/autosar/(CryIf|Crypto)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/caam/(caam_driver|caam_qnx|wolfcaam_hash)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/kcapi/' \ + | grep -vE '^wolfssl/wolfcrypt/port/nxp/(dcp_port|se050_port)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/Renesas/(renesas_fspsm_internal|renesas-rx64-hw-crypt|renesas-tsip-crypt|renesas_tsip_internal)\.h$' \ + | grep -vE '^wolfssl/wolfcrypt/port/silabs/silabs_aes\.h$' + ) +fi + +TMPDIR="$(mktemp -d)" +trap 'rm -rf "$TMPDIR"' EXIT + +FAIL=0 +PASS=0 +for h in "${HEADERS[@]}"; do + [ -f "$h" ] || continue + cat > "$TMPDIR/test.c" < +#include <$h> +int main(void) { return 0; } +EOF + if out="$("$CC" -I. -c -o /dev/null "$TMPDIR/test.c" 2>&1)"; then + PASS=$((PASS + 1)) + else + FAIL=$((FAIL + 1)) + first_err="$(printf '%s' "$out" | grep -E 'error:' | head -1 | sed 's/.*error: //')" + emit "$h" "header does not compile standalone: ${first_err:-(see build log)}" + if [ -z "$GHA" ]; then + printf '%s\n' "$out" | head -8 | sed 's/^/ /' + fi + fi +done + +echo "check-headers: $PASS pass, $FAIL fail" +[ "$FAIL" -eq 0 ] diff --git a/.github/workflows/check-headers.yml b/.github/workflows/check-headers.yml new file mode 100644 index 0000000000..dbc3aa6151 --- /dev/null +++ b/.github/workflows/check-headers.yml @@ -0,0 +1,43 @@ +name: Check Headers + +# Verifies every public-facing wolfSSL header compiles standalone with +# only wolfssl/options.h included first. Catches the common breakage +# where a header silently relies on a transitive include from an +# earlier .c file and stops compiling from a fresh consumer. +# +# Runs on drafts (fast static check). + +on: + push: + branches: [ master, main ] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + branches: [ master, main ] + +concurrency: + group: check-headers-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + check: + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + uses: ./.github/actions/install-apt-deps + with: + packages: autoconf automake libtool build-essential + + - name: autogen + run: ./autogen.sh + + - name: configure --enable-all + run: ./configure --enable-all + + - name: Run check-headers + run: ./.github/scripts/check-headers.sh diff --git a/.github/workflows/no-tls.yml b/.github/workflows/no-tls.yml deleted file mode 100644 index cbc4834441..0000000000 --- a/.github/workflows/no-tls.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: --disable-tls Tests - -# START OF COMMON SECTION -on: - push: - branches: [ 'release/**' ] - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - branches: [ '*' ] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true -# END OF COMMON SECTION - -jobs: - make_check: - strategy: - matrix: - config: [ - # Add new configs here - '--disable-tls --enable-all CFLAGS="-pedantic -Wdeclaration-after-statement -Wnull-dereference -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', - ] - name: make check - if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }} - runs-on: ubuntu-24.04 - # This should be a safe limit for the tests to run. - timeout-minutes: 6 - steps: - - uses: actions/checkout@v4 - name: Checkout wolfSSL - - - name: Test wolfSSL - run: | - ./autogen.sh - ./configure ${{ matrix.config }} - make -j 4 - make check - - - name: Print errors - if: ${{ failure() }} - run: | - for file in scripts/*.log - do - if [ -f "$file" ]; then - echo "${file}:" - cat "$file" - echo "========================================================================" - fi - done diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index 5e9c7ac466..8c2f875c09 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -62,6 +62,12 @@ jobs: args: "--enable-psk --enable-dtls --enable-dtls13 --enable-dtls-mtu --enable-aesccm --enable-opensslextra" - name: integration args: "--enable-openssh --enable-lighty --enable-stunnel --enable-opensslextra" + # AddressSanitizer (UBSAN excluded - current master has known + # left-shift UB in auto-generated SP math). + - name: sanitize-asan + args: "--enable-all" + cflags: "-fsanitize=address -fno-omit-frame-pointer -g -O1" + ldflags: "-fsanitize=address" env: MAKE_CFLAGS: "-Werror" steps: @@ -111,10 +117,20 @@ jobs: if: steps.merge_check.outputs.skip != 'true' run: ./configure ${{ matrix.config.args }} - - name: make (CFLAGS=-Werror) + - name: make if: steps.merge_check.outputs.skip != 'true' - run: make -j$(nproc) CFLAGS="$MAKE_CFLAGS" + env: + ENTRY_CFLAGS: ${{ matrix.config.cflags }} + ENTRY_LDFLAGS: ${{ matrix.config.ldflags }} + run: | + FLAGS="${ENTRY_CFLAGS:-$MAKE_CFLAGS}" + make -j"$(nproc)" CFLAGS="$FLAGS" LDFLAGS="$ENTRY_LDFLAGS" - - name: make check (CFLAGS=-Werror) + - name: make check if: steps.merge_check.outputs.skip != 'true' - run: make check CFLAGS="$MAKE_CFLAGS" + env: + ENTRY_CFLAGS: ${{ matrix.config.cflags }} + ENTRY_LDFLAGS: ${{ matrix.config.ldflags }} + run: | + FLAGS="${ENTRY_CFLAGS:-$MAKE_CFLAGS}" + make check CFLAGS="$FLAGS" LDFLAGS="$ENTRY_LDFLAGS" diff --git a/wolfssl/quic.h b/wolfssl/quic.h index a644b6d3d2..cdce23ca49 100644 --- a/wolfssl/quic.h +++ b/wolfssl/quic.h @@ -35,13 +35,10 @@ #ifndef NO_STDINT_H #include #endif +#include /* size_t */ -/* QUIC operates on three encryption levels which determine - * which keys/algos are used for de-/encryption. These are - * kept separately for incoming and outgoing data and. - * Due to the nature of UDP, more than one might be in use - * at the same time due to resends or out-of-order arrivals. - */ +/* Defined before ssl.h: openssl/ssl.h pulls quic.h mid-include and + * references WOLFSSL_ENCRYPTION_LEVEL and WOLFSSL_QUIC_METHOD. */ typedef enum wolfssl_encryption_level_t { wolfssl_encryption_initial = 0, wolfssl_encryption_early_data, @@ -49,11 +46,12 @@ typedef enum wolfssl_encryption_level_t { wolfssl_encryption_application } WOLFSSL_ENCRYPTION_LEVEL; - -/* All QUIC related callbacks to the application. - */ typedef struct wolfssl_quic_method_t WOLFSSL_QUIC_METHOD; +#include + + +/* All QUIC related callbacks to the application. */ struct wolfssl_quic_method_t { /** * Provide secrets to the QUIC stack when they become available in the SSL diff --git a/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h b/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h index 71d8dbf295..8a3bd25e20 100644 --- a/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h +++ b/wolfssl/wolfcrypt/port/Renesas/renesas-fspsm-crypt.h @@ -22,6 +22,7 @@ #define __RENESAS_FSPSM_CRYPT_H__ #include +#include /* uint8_t */ #ifdef __cplusplus extern "C" { diff --git a/wolfssl/wolfcrypt/rng_bank.h b/wolfssl/wolfcrypt/rng_bank.h index d26b41a5e5..bdc8577fdc 100644 --- a/wolfssl/wolfcrypt/rng_bank.h +++ b/wolfssl/wolfcrypt/rng_bank.h @@ -32,6 +32,7 @@ #define WOLF_CRYPT_RNG_BANK_H #include +#include #ifdef WC_RNG_BANK_SUPPORT