Skip to content

Commit f979f8f

Browse files
committed
Add Static Analysis CI tools
1 parent 5140cc3 commit f979f8f

File tree

8 files changed

+318
-26
lines changed

8 files changed

+318
-26
lines changed
Lines changed: 281 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
name: Static Analysis
2+
3+
# START OF COMMON SECTION
4+
on:
5+
schedule:
6+
# Run nightly at 2 AM UTC
7+
- cron: '0 2 * * *'
8+
workflow_dispatch:
9+
10+
concurrency:
11+
group: ${{ github.workflow }}-${{ github.ref }}
12+
cancel-in-progress: true
13+
# END OF COMMON SECTION
14+
15+
jobs:
16+
cppcheck:
17+
name: cppcheck Static Analysis
18+
runs-on: ubuntu-22.04
19+
timeout-minutes: 30
20+
steps:
21+
- name: Checkout wolfProvider
22+
uses: actions/checkout@v4
23+
with:
24+
fetch-depth: 1
25+
26+
- name: Install dependencies
27+
run: |
28+
sudo apt-get update
29+
sudo apt-get install -y cppcheck
30+
31+
- name: Build dependencies (OpenSSL and wolfSSL)
32+
run: |
33+
OPENSSL_TAG=openssl-3.5.4 WOLFSSL_TAG=master ./scripts/build-wolfprovider.sh 2>&1 | tail -100 || true
34+
# We only need the build to succeed enough to have headers available
35+
36+
- name: Generate configure script
37+
run: |
38+
./autogen.sh || true
39+
40+
- name: Configure to generate config.h
41+
run: |
42+
OPENSSL_INSTALL_DIR="$PWD/openssl-install"
43+
WOLFSSL_INSTALL_DIR="$PWD/wolfssl-install"
44+
45+
# Configure to generate config.h (needed for cppcheck)
46+
./configure \
47+
--with-openssl="$OPENSSL_INSTALL_DIR" \
48+
--with-wolfssl="$WOLFSSL_INSTALL_DIR" \
49+
--prefix="$PWD/wolfprov-install" \
50+
>/dev/null 2>&1 || true
51+
52+
- name: Run cppcheck
53+
run: |
54+
# Configure include paths for cppcheck
55+
OPENSSL_INC="$PWD/openssl-install/include"
56+
WOLFSSL_INC="$PWD/wolfssl-install/include"
57+
WOLFPROV_INC="$PWD/include"
58+
59+
# Run cppcheck on source files only (tests can be analyzed separately if needed)
60+
# Use --force and suppress noValidConfiguration to proceed even with incomplete config
61+
cppcheck \
62+
--enable=all \
63+
--suppress=missingIncludeSystem \
64+
--suppress=unusedFunction \
65+
--suppress=unmatchedSuppression \
66+
--suppress=noValidConfiguration \
67+
--inline-suppr \
68+
--force \
69+
--error-exitcode=0 \
70+
-I "$OPENSSL_INC" \
71+
-I "$WOLFSSL_INC" \
72+
-I "$WOLFPROV_INC" \
73+
--platform=unix64 \
74+
src/ 2>&1 | tee cppcheck-output.txt || true
75+
76+
# Display output (filter out noValidConfiguration messages and progress)
77+
grep -v "noValidConfiguration" cppcheck-output.txt | \
78+
grep -v "^Checking " | \
79+
grep -v "^[0-9]*/[0-9]* files checked" | \
80+
grep -v "^nofile:0:0: information:" || true
81+
82+
# Count errors and warnings (count lines with error:/warning: that are actual issues)
83+
# Use wc -l for more reliable counting, and strip whitespace
84+
ERROR_COUNT=$(grep -E "^src/.*:[0-9]+:[0-9]+:.*error:" cppcheck-output.txt 2>/dev/null | wc -l | tr -d '[:space:]' || echo "0")
85+
WARNING_COUNT=$(grep -E "^src/.*:[0-9]+:[0-9]+:.*warning:" cppcheck-output.txt 2>/dev/null | wc -l | tr -d '[:space:]' || echo "0")
86+
87+
# Ensure we have valid integers (default to 0 if empty)
88+
ERROR_COUNT=${ERROR_COUNT:-0}
89+
WARNING_COUNT=${WARNING_COUNT:-0}
90+
91+
echo "cppcheck found $ERROR_COUNT errors and $WARNING_COUNT warnings"
92+
93+
# Fail only if critical errors found (adjust threshold as needed)
94+
if [ "${ERROR_COUNT}" -gt 0 ] 2>/dev/null; then
95+
echo "cppcheck found errors"
96+
exit 1
97+
fi
98+
99+
- name: Upload cppcheck results
100+
if: always()
101+
uses: actions/upload-artifact@v4
102+
with:
103+
name: cppcheck-results
104+
path: cppcheck-output.txt
105+
retention-days: 7
106+
107+
scan-build:
108+
name: clang Static Analyzer (scan-build)
109+
runs-on: ubuntu-22.04
110+
timeout-minutes: 45
111+
steps:
112+
- name: Checkout wolfProvider
113+
uses: actions/checkout@v4
114+
with:
115+
fetch-depth: 1
116+
117+
- name: Install dependencies
118+
run: |
119+
sudo apt-get update
120+
sudo apt-get install -y clang clang-tools build-essential autoconf automake libtool pkg-config
121+
122+
- name: Build dependencies (OpenSSL and wolfSSL)
123+
run: |
124+
OPENSSL_TAG=openssl-3.5.4 WOLFSSL_TAG=master ./scripts/build-wolfprovider.sh 2>&1 | tail -100 || true
125+
126+
- name: Generate configure script
127+
run: |
128+
./autogen.sh
129+
130+
- name: Configure project for scan-build
131+
run: |
132+
OPENSSL_INSTALL_DIR="$PWD/openssl-install"
133+
WOLFSSL_INSTALL_DIR="$PWD/wolfssl-install"
134+
135+
# Configure with clang (scan-build will wrap it later)
136+
CC=clang ./configure \
137+
--with-openssl="$OPENSSL_INSTALL_DIR" \
138+
--with-wolfssl="$WOLFSSL_INSTALL_DIR" \
139+
--prefix="$PWD/wolfprov-install"
140+
141+
- name: Build library with scan-build
142+
run: |
143+
# Clean any previous build artifacts
144+
make clean || true
145+
146+
# Build only the library with scan-build wrapping clang
147+
# scan-build intercepts compiler calls, so we need to ensure CC is set to clang
148+
# Use --use-cc and --use-c++ to explicitly tell scan-build which compiler to wrap
149+
scan-build -o scan-build-output \
150+
--use-cc=clang \
151+
--use-c++=clang++ \
152+
make -j$(nproc) CC=clang libwolfprov.la 2>&1 | tee scan-build-log.txt || true
153+
154+
# scan-build returns 0 even if build fails, so we check exit status explicitly
155+
echo "Build completed (scan-build may have reports even if build partially failed)"
156+
157+
- name: Check scan-build results
158+
run: |
159+
# Find the latest scan-build report directory
160+
REPORT_DIR=$(find scan-build-output -maxdepth 1 -type d -name "scan-build-*" | sort -r | head -1)
161+
162+
if [ -z "$REPORT_DIR" ] || [ ! -d "$REPORT_DIR" ]; then
163+
echo "No scan-build report directory found"
164+
exit 0
165+
fi
166+
167+
# Count bugs found
168+
BUG_COUNT=$(find "$REPORT_DIR" -name "*.html" | wc -l)
169+
echo "scan-build found $BUG_COUNT potential issues"
170+
171+
# Display summary
172+
if [ -f "$REPORT_DIR/index.html" ]; then
173+
echo "View detailed report in scan-build-output/index.html"
174+
# Extract text summary if possible
175+
grep -o '<title>.*</title>' "$REPORT_DIR/index.html" || true
176+
fi
177+
178+
# Fail if critical bugs found (adjust threshold as needed)
179+
if [ "$BUG_COUNT" -gt 50 ]; then
180+
echo "Too many issues found by scan-build"
181+
exit 1
182+
fi
183+
184+
- name: Upload scan-build results
185+
if: always()
186+
uses: actions/upload-artifact@v4
187+
with:
188+
name: scan-build-results
189+
path: scan-build-output/
190+
retention-days: 7
191+
192+
infer:
193+
name: Facebook Infer Static Analysis
194+
runs-on: ubuntu-22.04
195+
timeout-minutes: 60
196+
steps:
197+
- name: Checkout wolfProvider
198+
uses: actions/checkout@v4
199+
with:
200+
fetch-depth: 1
201+
202+
- name: Install dependencies
203+
run: |
204+
sudo apt-get update
205+
sudo apt-get install -y build-essential autoconf automake libtool pkg-config python3 opam
206+
207+
# Install Infer
208+
VERSION=1.1.0
209+
cd /tmp
210+
wget https://github.com/facebook/infer/releases/download/v${VERSION}/infer-linux64-v${VERSION}.tar.xz
211+
tar xf infer-linux64-v${VERSION}.tar.xz
212+
sudo mv infer-linux64-v${VERSION} /opt/infer
213+
sudo ln -sf /opt/infer/bin/infer /usr/local/bin/infer
214+
215+
- name: Build dependencies (OpenSSL and wolfSSL)
216+
run: |
217+
OPENSSL_TAG=openssl-3.5.4 WOLFSSL_TAG=master ./scripts/build-wolfprovider.sh 2>&1 | tail -100 || true
218+
219+
- name: Generate configure script
220+
run: |
221+
./autogen.sh
222+
223+
- name: Configure project
224+
run: |
225+
OPENSSL_INSTALL_DIR="$PWD/openssl-install"
226+
WOLFSSL_INSTALL_DIR="$PWD/wolfssl-install"
227+
228+
./configure \
229+
--with-openssl="$OPENSSL_INSTALL_DIR" \
230+
--with-wolfssl="$WOLFSSL_INSTALL_DIR" \
231+
--prefix="$PWD/wolfprov-install" \
232+
CC=clang
233+
234+
- name: Clean build for Infer
235+
run: |
236+
make clean || true
237+
rm -rf infer-out
238+
239+
- name: Run Infer analysis
240+
run: |
241+
# Run infer on the build (it wraps the compilation)
242+
# Build only the library to avoid test compilation issues
243+
# Explicitly set CC=clang for make
244+
infer run -- make -j$(nproc) CC=clang libwolfprov.la 2>&1 | tee infer-log.txt || true
245+
246+
# Generate text report
247+
if [ -d infer-out ]; then
248+
infer report --issues-csv infer-report.csv 2>&1 || true
249+
infer report --issues-txt infer-report.txt 2>&1 || true
250+
251+
# Display summary
252+
if [ -f infer-report.txt ]; then
253+
echo "=== Infer Analysis Summary ==="
254+
cat infer-report.txt
255+
256+
# Count issues
257+
ISSUE_COUNT=$(grep -c "Found.*issue" infer-report.txt || echo "0")
258+
echo "Infer found issues (check infer-report.txt for details)"
259+
260+
# Fail if too many critical issues (adjust threshold as needed)
261+
if [ "$ISSUE_COUNT" -gt 100 ]; then
262+
echo "Too many issues found by Infer"
263+
exit 1
264+
fi
265+
fi
266+
else
267+
echo "Infer did not produce output directory"
268+
fi
269+
270+
- name: Upload Infer results
271+
if: always()
272+
uses: actions/upload-artifact@v4
273+
with:
274+
name: infer-results
275+
path: |
276+
infer-out/
277+
infer-report.txt
278+
infer-report.csv
279+
infer-log.txt
280+
retention-days: 7
281+
if-no-files-found: ignore

src/wp_aes_aead.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static int wp_aead_tls_init(wp_AeadCtx* ctx, unsigned char* aad, size_t aadLen)
223223
{
224224
int ok = 1;
225225
unsigned char *buf = ctx->buf;
226-
size_t len;
226+
size_t len = 0;
227227
/* CCM will have a tag length set. */
228228
size_t tagLen = (ctx->tagLen != UNINITIALISED_SIZET) ? ctx->tagLen :
229229
EVP_GCM_TLS_TAG_LEN;

src/wp_dec_epki2pki.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ static int wp_epki2pki_decode(wp_Epki2Pki* ctx, OSSL_CORE_BIO* coreBio,
187187
{
188188
int ok = 1;
189189
int done = 0;
190-
int rc;
190+
int rc = 0;
191191
unsigned char* data = NULL;
192192
word32 len = 0;
193193
char password[1024];
194-
size_t passwordLen;
194+
size_t passwordLen = 0;
195195
word32 tradIdx = 0;
196196

197197
WOLFPROV_ENTER(WP_LOG_COMP_PK, "wp_epki2pki_decode");

src/wp_dec_pem2der.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,12 @@ static int wp_pem2der_decode_data(const unsigned char* data, word32 len,
207207
{
208208
int ok = 1;
209209
int done = 0;
210-
int rc;
211-
int algoId;
212-
int type;
210+
int rc = 0;
211+
int algoId = 0;
212+
int type = 0;
213213
const char* dataType = NULL;
214214
const char* dataFormat = NULL;
215-
int obj;
215+
int obj = 0;
216216
EncryptedInfo info;
217217
DerBuffer* der = NULL;
218218
OSSL_PARAM params[5];

src/wp_ecc_kmgmt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2222,9 +2222,9 @@ static int wp_ecc_decode_pki(wp_Ecc* ecc, unsigned char* data, word32 len)
22222222
/* Keys decoded from pki should always have public key */
22232223
if (ecc->key.type == ECC_PRIVATEKEY_ONLY) {
22242224
#ifdef ECC_TIMING_RESISTANT
2225-
rc = wc_ecc_make_pub_ex(&ecc->key, NULL, &ecc->rng);
2225+
(void)wc_ecc_make_pub_ex(&ecc->key, NULL, &ecc->rng);
22262226
#else
2227-
rc = wc_ecc_make_pub_ex(&ecc->key, NULL, NULL);
2227+
(void)wc_ecc_make_pub_ex(&ecc->key, NULL, NULL);
22282228
#endif
22292229
}
22302230
ecc->hasPub = 1;

src/wp_mac_sig.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,10 @@ static int wp_mac_digest_sign_init(wp_MacSigCtx *ctx, const char *mdName,
187187
wp_Mac *mac, const OSSL_PARAM params[])
188188
{
189189
int ok = 1;
190-
unsigned char* priv;
191-
size_t privLen;
192-
const char* cipherName;
193-
const char* properties;
190+
unsigned char* priv = NULL;
191+
size_t privLen = 0;
192+
const char* cipherName = NULL;
193+
const char* properties = NULL;
194194
OSSL_PARAM lParams[4];
195195
int lParamSz = 0;
196196

src/wp_rsa_kem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,8 @@ static int wp_rsasve_generate(wp_RsaKemCtx* ctx, unsigned char* out,
294294
size_t* outLen, unsigned char* secret, size_t* secretLen)
295295
{
296296
int ok = 1;
297-
word32 nLen;
298-
word32 oLen;
297+
word32 nLen = 0;
298+
word32 oLen = 0;
299299
RsaKey* rsa = NULL;
300300

301301
WOLFPROV_ENTER(WP_LOG_COMP_RSA, "wp_rsasve_generate");

0 commit comments

Comments
 (0)