Skip to content

Commit 81e245c

Browse files
authored
Merge pull request #142 from LinuxJedi/scan-build
Fix things found in scan-build
2 parents 38bed75 + dc5bf02 commit 81e245c

File tree

4 files changed

+296
-11
lines changed

4 files changed

+296
-11
lines changed

.github/workflows/scan-build.yml

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# wolfPKCS11 Scan-Build Static Analysis Workflow
2+
#
3+
# This workflow performs comprehensive static analysis on the wolfPKCS11 codebase
4+
# using Clang Static Analyzer (scan-build) to identify potential bugs, security
5+
# vulnerabilities, and code quality issues across different build configurations.
6+
#
7+
# Features:
8+
# - Matrix build testing both standard and TPM-enabled configurations
9+
# - Comprehensive analysis using Clang Static Analyzer
10+
# - HTML report generation for detailed issue review
11+
# - Zero-tolerance policy: any bugs found will fail the build
12+
# - Artifact upload for detailed review of analysis results
13+
#
14+
# Configurations tested:
15+
# 1. Standard Build - Default wolfPKCS11 configuration
16+
# 2. NSS Build - wolfPKCS11 with NSS support
17+
# 3. TPM Build - wolfPKCS11 with TPM support via wolfTPM and IBM TPM simulator
18+
# 4. NSS+TPM Build - wolfPKCS11 with both NSS and TPM support
19+
#
20+
# The workflow generates detailed HTML reports and summaries available as artifacts
21+
# for each configuration, enabling developers to review and address identified issues.
22+
23+
name: wolfPKCS11 Scan-Build Analysis
24+
25+
on:
26+
push:
27+
branches: [ 'master', 'main', 'release/**' ]
28+
pull_request:
29+
branches: [ '*' ]
30+
31+
jobs:
32+
scan-build:
33+
runs-on: ubuntu-latest
34+
35+
strategy:
36+
fail-fast: false
37+
matrix:
38+
config:
39+
- name: "Standard Build"
40+
configure_flags: ""
41+
- name: "NSS Build"
42+
configure_flags: "--enable-nss"
43+
- name: "TPM Build"
44+
configure_flags: "--enable-tpm"
45+
- name: "NSS+TPM Build"
46+
configure_flags: "--enable-nss --enable-tpm"
47+
48+
steps:
49+
# Checkout wolfPKCS11
50+
- uses: actions/checkout@v4
51+
52+
# Install build dependencies
53+
- name: Install dependencies
54+
run: |
55+
sudo apt-get update
56+
sudo apt-get install -y \
57+
build-essential \
58+
autoconf \
59+
automake \
60+
libtool \
61+
clang \
62+
clang-tools \
63+
pkg-config \
64+
git \
65+
libnss3-dev \
66+
libnspr4-dev
67+
68+
# Build and install wolfSSL
69+
- name: Build and install wolfSSL
70+
run: |
71+
git clone https://github.com/wolfSSL/wolfssl.git
72+
cd wolfssl
73+
./autogen.sh
74+
./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 \
75+
C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP"
76+
make -j$(nproc)
77+
sudo make install
78+
sudo ldconfig
79+
cd ..
80+
81+
# Setup IBM Software TPM (only if TPM enabled)
82+
- name: Setup IBM Software TPM
83+
if: contains(matrix.config.configure_flags, '--enable-tpm')
84+
run: |
85+
git clone https://github.com/kgoldman/ibmswtpm2.git
86+
cd ibmswtpm2/src
87+
make
88+
./tpm_server &
89+
cd ../..
90+
91+
# Build and install wolfTPM (only if TPM enabled)
92+
- name: Build and install wolfTPM
93+
if: contains(matrix.config.configure_flags, '--enable-tpm')
94+
run: |
95+
git clone https://github.com/wolfSSL/wolftpm.git
96+
cd wolftpm
97+
./autogen.sh
98+
./configure --enable-swtpm
99+
make -j$(nproc)
100+
sudo make install
101+
sudo ldconfig
102+
cd ..
103+
104+
# Configure wolfPKCS11
105+
- name: Configure wolfPKCS11 (${{ matrix.config.name }})
106+
run: |
107+
./autogen.sh
108+
if [ -n "${{ matrix.config.configure_flags }}" ]; then
109+
CC=clang CXX=clang++ ./configure --enable-all --enable-debug ${{ matrix.config.configure_flags }}
110+
else
111+
CC=clang CXX=clang++ ./configure --enable-all --enable-debug
112+
fi
113+
114+
# Run scan-build analysis
115+
- name: Run scan-build analysis (${{ matrix.config.name }})
116+
run: |
117+
# Create output directory for scan-build reports
118+
mkdir -p scan-build-reports
119+
120+
# Run scan-build with comprehensive checkers and fail on any bugs
121+
echo "Running scan-build analysis..."
122+
echo "Working directory: $(pwd)"
123+
echo "Environment variables:"
124+
env | grep -E "(CC|CXX|CFLAGS|LDFLAGS|LD_LIBRARY_PATH)" || echo "No relevant env vars set"
125+
126+
# Run scan-build and capture both stdout and stderr
127+
scan-build -o scan-build-reports \
128+
--status-bugs \
129+
--use-cc=clang \
130+
--use-c++=clang++ \
131+
-enable-checker alpha.core.BoolAssignment \
132+
-enable-checker alpha.core.CallAndMessageUnInitRefArg \
133+
-enable-checker alpha.core.CastSize \
134+
-enable-checker alpha.core.CastToStruct \
135+
-enable-checker alpha.core.Conversion \
136+
-enable-checker alpha.core.DynamicTypeChecker \
137+
-enable-checker alpha.core.FixedAddr \
138+
-enable-checker alpha.core.IdenticalExpr \
139+
-enable-checker alpha.core.PointerArithm \
140+
-enable-checker alpha.core.PointerSub \
141+
-enable-checker alpha.core.SizeofPtr \
142+
-enable-checker alpha.core.TestAfterDivZero \
143+
-enable-checker alpha.security.ArrayBound \
144+
-enable-checker alpha.security.ArrayBoundV2 \
145+
-enable-checker alpha.security.MallocOverflow \
146+
-enable-checker alpha.security.ReturnPtrRange \
147+
-enable-checker alpha.unix.SimpleStream \
148+
-enable-checker alpha.unix.cstring.BufferOverlap \
149+
-enable-checker alpha.unix.cstring.NotNullTerminated \
150+
-enable-checker alpha.unix.cstring.OutOfBounds \
151+
-enable-checker security.FloatLoopCounter \
152+
-enable-checker security.insecureAPI.UncheckedReturn \
153+
make -j$(nproc) > scan-build-output.txt 2>&1
154+
155+
# Check if scan-build found any issues
156+
SCAN_EXIT_CODE=$?
157+
158+
# Count warnings and errors from the output
159+
WARNINGS=0
160+
ERRORS=0
161+
BUGS_FOUND=0
162+
163+
if [ -s scan-build-output.txt ]; then
164+
WARNINGS=$(grep -c "warning:" scan-build-output.txt 2>/dev/null || echo "0")
165+
ERRORS=$(grep -c "error:" scan-build-output.txt 2>/dev/null || echo "0")
166+
167+
# Check for "bugs found" message - scan-build uses this format
168+
if grep -q "bugs found" scan-build-output.txt; then
169+
BUGS_FOUND=$(grep -o "[0-9]\+ bugs found" scan-build-output.txt | head -1 | cut -d' ' -f1 2>/dev/null || echo "0")
170+
fi
171+
172+
# Also check for "No bugs found" message
173+
if grep -q "No bugs found" scan-build-output.txt; then
174+
BUGS_FOUND=0
175+
fi
176+
fi
177+
178+
# Display summary
179+
echo ""
180+
echo "=== Scan-Build Analysis Summary ==="
181+
echo "Configuration: ${{ matrix.config.name }}"
182+
echo "Warnings: $WARNINGS"
183+
echo "Errors: $ERRORS"
184+
echo "Bugs found: $BUGS_FOUND"
185+
echo "Scan-build exit code: $SCAN_EXIT_CODE"
186+
echo "Timestamp: $(date)"
187+
188+
# Create summary file for artifacts
189+
echo "Configuration: ${{ matrix.config.name }}" > scan-build-summary.txt
190+
echo "Warnings: $WARNINGS" >> scan-build-summary.txt
191+
echo "Errors: $ERRORS" >> scan-build-summary.txt
192+
echo "Bugs found: $BUGS_FOUND" >> scan-build-summary.txt
193+
echo "Scan-build exit code: $SCAN_EXIT_CODE" >> scan-build-summary.txt
194+
echo "Timestamp: $(date)" >> scan-build-summary.txt
195+
196+
# Display scan-build output (first 50 lines to avoid log overflow)
197+
if [ -s scan-build-output.txt ]; then
198+
echo ""
199+
echo "=== Scan-Build Output (First 50 lines) ==="
200+
head -50 scan-build-output.txt
201+
TOTAL_LINES=$(wc -l < scan-build-output.txt)
202+
if [ "$TOTAL_LINES" -gt 50 ]; then
203+
echo "... (truncated, full output available in artifacts - $TOTAL_LINES total lines)"
204+
fi
205+
fi
206+
207+
# List generated HTML reports
208+
if [ -d "scan-build-reports" ]; then
209+
REPORT_COUNT=$(find scan-build-reports -name "*.html" -type f 2>/dev/null | wc -l)
210+
REPORT_DIRS=$(find scan-build-reports -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)
211+
echo ""
212+
echo "Generated $REPORT_COUNT HTML report files in $REPORT_DIRS report directories"
213+
if [ "$REPORT_COUNT" -gt 0 ]; then
214+
echo "HTML reports available in artifacts for detailed analysis"
215+
find scan-build-reports -name "*.html" -type f 2>/dev/null | head -10 | sed 's/^/ /'
216+
fi
217+
if [ "$REPORT_DIRS" -gt 0 ]; then
218+
echo "Report directories:"
219+
find scan-build-reports -mindepth 1 -maxdepth 1 -type d 2>/dev/null | head -5 | sed 's/^/ /'
220+
fi
221+
else
222+
echo ""
223+
echo "No scan-build-reports directory found"
224+
fi
225+
226+
# Fail the build if scan-build found bugs or returned non-zero exit code
227+
if [ "$SCAN_EXIT_CODE" -ne 0 ] || [ "$BUGS_FOUND" -gt 0 ]; then
228+
echo ""
229+
echo "❌ Scan-build analysis failed"
230+
echo "Exit code: $SCAN_EXIT_CODE"
231+
echo "Bugs found: $BUGS_FOUND"
232+
echo "Warnings: $WARNINGS"
233+
echo "Errors: $ERRORS"
234+
echo ""
235+
echo "This indicates potential bugs or static analysis issues were found."
236+
echo "Please review the detailed reports in the artifacts and fix the issues."
237+
echo ""
238+
echo "Recent scan-build output:"
239+
if [ -s scan-build-output.txt ]; then
240+
tail -20 scan-build-output.txt | sed 's/^/ /'
241+
fi
242+
exit 1
243+
else
244+
echo ""
245+
echo "✅ Scan-build analysis passed successfully"
246+
echo "No static analysis issues detected in ${{ matrix.config.name }} configuration"
247+
fi
248+
249+
# Upload scan-build reports and logs
250+
- name: Upload scan-build artifacts
251+
if: failure()
252+
uses: actions/upload-artifact@v4
253+
with:
254+
name: scan-build-reports-${{ matrix.config.name }}-${{ github.run_number }}
255+
path: |
256+
scan-build-reports/
257+
scan-build-output.txt
258+
scan-build-summary.txt
259+
test-suite.log
260+
config.log
261+
retention-days: 14
262+
if-no-files-found: warn
263+
264+
# Upload failure logs (additional step for easier debugging)
265+
- name: Upload failure logs
266+
if: failure()
267+
uses: actions/upload-artifact@v4
268+
with:
269+
name: scan-build-failure-logs-${{ matrix.config.name }}-${{ github.run_number }}
270+
path: |
271+
scan-build-output.txt
272+
scan-build-summary.txt
273+
config.log
274+
test-suite.log
275+
src/*.lo
276+
src/*.o
277+
retention-days: 7
278+
if-no-files-found: ignore

examples/obj_list.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ int obj_list(int argc, char* argv[])
543543
int ret;
544544
CK_RV rv;
545545
const char* libName = WOLFPKCS11_DLL_FILENAME;
546-
CK_SESSION_HANDLE session;
546+
CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
547547

548548
#ifndef WOLFPKCS11_NO_ENV
549549
if (!XGETENV("WOLFPKCS11_TOKEN_PATH")) {

src/internal.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,8 +2648,10 @@ static void wp11_Object_Decode_Cert(WP11_Object* object)
26482648
*/
26492649
static void wp11_Object_Decode_Trust(WP11_Object* object)
26502650
{
2651-
XMEMCPY((unsigned char*)&object->data.trust, object->keyData,
2652-
object->keyDataLen);
2651+
if (object->keyData != NULL) {
2652+
XMEMCPY((unsigned char*)&object->data.trust, object->keyData,
2653+
object->keyDataLen);
2654+
}
26532655
object->encoded = 0;
26542656
}
26552657
#endif
@@ -7880,10 +7882,10 @@ int WP11_Object_SetTrust(WP11_Object* object, unsigned char** data,
78807882
{
78817883
WP11_Trust* trust;
78827884

7883-
if (data[0] == NULL && len[0] != WC_SHA_DIGEST_SIZE)
7885+
if (data[0] == NULL || len[0] != WC_SHA_DIGEST_SIZE)
78847886
return BAD_FUNC_ARG;
78857887

7886-
if (data[1] == NULL && len[1] != WC_MD5_DIGEST_SIZE)
7888+
if (data[1] == NULL || len[1] != WC_MD5_DIGEST_SIZE)
78877889
return BAD_FUNC_ARG;
78887890

78897891
if (object->onToken)

tests/debug_test.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <stdio.h>
2424
#include <string.h>
2525
#include <stdlib.h>
26+
#include <errno.h>
2627

2728
#ifdef HAVE_CONFIG_H
2829
#include <wolfpkcs11/config.h>
@@ -70,15 +71,19 @@ static int check_debug_output(void)
7071
return 0;
7172
}
7273

74+
errno = 0;
7375
stdout = original_stdout;
7476
rewind(capture_file);
7577

76-
while (fgets(buffer, sizeof(buffer), capture_file)) {
77-
if (strstr(buffer, "WOLFPKCS11 ENTER:") ||
78-
strstr(buffer, "WOLFPKCS11 LEAVE:") ||
79-
strstr(buffer, "WOLFPKCS11:")) {
80-
found_debug = 1;
81-
break;
78+
if (!errno)
79+
{
80+
while (fgets(buffer, sizeof(buffer), capture_file) != NULL) {
81+
if (strstr(buffer, "WOLFPKCS11 ENTER:") ||
82+
strstr(buffer, "WOLFPKCS11 LEAVE:") ||
83+
strstr(buffer, "WOLFPKCS11:")) {
84+
found_debug = 1;
85+
break;
86+
}
8287
}
8388
}
8489

0 commit comments

Comments
 (0)