Skip to content

Commit 515b776

Browse files
authored
chore: add more tests, fuzzing, and a separate fuzz Workflow (#1352)
Signed-off-by: egibs <20933572+egibs@users.noreply.github.com>
1 parent f9716b0 commit 515b776

104 files changed

Lines changed: 4531 additions & 346 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/fuzz.yaml

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# Copyright 2026 Chainguard, Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
name: Fuzz Tests
5+
6+
on:
7+
push:
8+
branches:
9+
- "main"
10+
schedule:
11+
# Run weekly on Sunday at midnight UTC
12+
- cron: "0 0 * * 0"
13+
workflow_dispatch:
14+
inputs:
15+
fuzz_target:
16+
description: "Specific fuzzer to run (leave empty for all)"
17+
required: false
18+
default: ""
19+
type: string
20+
fuzz_time:
21+
description: "Fuzz duration per target (e.g., 30s, 1m, 5m)"
22+
required: false
23+
default: "30s"
24+
type: choice
25+
options:
26+
- "10s"
27+
- "30s"
28+
- "1m"
29+
- "5m"
30+
- "10m"
31+
- "30m"
32+
- "60m"
33+
- "180m"
34+
35+
permissions: {}
36+
37+
jobs:
38+
discover:
39+
if: ${{ github.repository == 'chainguard-dev/malcontent' }}
40+
runs-on: ubuntu-latest
41+
permissions:
42+
contents: read
43+
outputs:
44+
targets: ${{ steps.find.outputs.targets }}
45+
steps:
46+
- name: Checkout code
47+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
48+
with:
49+
persist-credentials: false
50+
51+
- name: Discover fuzz targets
52+
id: find
53+
env:
54+
TARGET_FILTER: ${{ inputs.fuzz_target }}
55+
run: |
56+
# Find all Fuzz* functions in test files and build JSON array
57+
# Format: [{"test": "FuzzName", "package": "./pkg/path/"}]
58+
all_targets=$(grep -r "^func Fuzz" --include="*_test.go" -l pkg/ | while read -r file; do
59+
dir="./$(dirname "${file}")/"
60+
grep -o "^func Fuzz[A-Za-z0-9_]*" "${file}" | sed 's/^func //' | while read -r func; do
61+
echo "{\"test\":\"${func}\",\"package\":\"${dir}\"}"
62+
done
63+
done | jq -s -c '.')
64+
65+
targets="${all_targets}"
66+
67+
# If a specific target is requested, validate and filter
68+
if [ -n "${TARGET_FILTER}" ]; then
69+
# Validate format: must start with "Fuzz" and contain only alphanumeric/underscore
70+
if ! echo "${TARGET_FILTER}" | grep -qE '^Fuzz[A-Za-z0-9_]+$'; then
71+
echo "::error::Invalid fuzz target format: '${TARGET_FILTER}'. Must match pattern 'Fuzz[A-Za-z0-9_]+'"
72+
exit 1
73+
fi
74+
75+
# Filter to the requested target
76+
targets=$(echo "${all_targets}" | jq -c --arg t "${TARGET_FILTER}" '[.[] | select(.test == $t)]')
77+
78+
# Check if target exists
79+
if [ "${targets}" = "[]" ]; then
80+
echo "::error::Fuzz target '${TARGET_FILTER}' not found."
81+
echo "Available targets:"
82+
echo "${all_targets}" | jq -r '.[].test' | sort | sed 's/^/ - /'
83+
exit 1
84+
fi
85+
fi
86+
87+
echo "targets=${targets}" >> "${GITHUB_OUTPUT}"
88+
echo "Discovered targets: ${targets}"
89+
90+
fuzz:
91+
if: ${{ github.repository == 'chainguard-dev/malcontent' && needs.discover.outputs.targets != '[]' }}
92+
needs: discover
93+
runs-on: ubuntu-latest-16-core
94+
permissions:
95+
contents: read
96+
strategy:
97+
fail-fast: false
98+
matrix:
99+
target: ${{ fromJson(needs.discover.outputs.targets) }}
100+
container:
101+
image: cgr.dev/chainguard/wolfi-base:latest # zizmor: ignore[unpinned-images]
102+
options: >-
103+
--cap-add DAC_OVERRIDE
104+
--cap-add SETGID
105+
--cap-add SETUID
106+
--cap-drop ALL
107+
--cgroupns private
108+
--cpu-shares=16384
109+
--memory-swappiness=0
110+
--security-opt no-new-privileges
111+
--ulimit core=0
112+
--ulimit nofile=65535:65535
113+
--ulimit nproc=65535:65535
114+
steps:
115+
- name: Install dependencies
116+
run: |
117+
apk update
118+
apk add curl findutils git go nodejs upx xz yara-x~1.12.0
119+
120+
- name: Checkout code
121+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
122+
with:
123+
persist-credentials: false
124+
125+
- name: Trust repository
126+
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
127+
128+
- name: Clone malcontent samples (required for compile fuzzers)
129+
if: contains(matrix.target.package, 'compile')
130+
run: |
131+
make samples
132+
133+
- name: Run fuzzer - ${{ matrix.target.test }}
134+
env:
135+
FUZZ_TIME: ${{ inputs.fuzz_time || '30s' }}
136+
run: |
137+
go test -timeout 0 -fuzz="${{ matrix.target.test }}" -fuzztime="${FUZZ_TIME}" "${{ matrix.target.package }}"

.github/workflows/go-tests.yaml

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
permissions:
2121
contents: read
2222
container:
23-
image: cgr.dev/chainguard/wolfi-base:latest
23+
image: cgr.dev/chainguard/wolfi-base:latest # zizmor: ignore[unpinned-images]
2424
options: >-
2525
--cap-add DAC_OVERRIDE
2626
--cap-add SETGID
@@ -57,7 +57,7 @@ jobs:
5757
permissions:
5858
contents: read
5959
container:
60-
image: cgr.dev/chainguard/wolfi-base:latest
60+
image: cgr.dev/chainguard/wolfi-base:latest # zizmor: ignore[unpinned-images]
6161
options: >-
6262
--cap-add DAC_OVERRIDE
6363
--cap-add SETGID
@@ -87,44 +87,3 @@ jobs:
8787
- name: Integration tests
8888
run: |
8989
make integration
90-
91-
fuzz:
92-
if: ${{ github.repository == 'chainguard-dev/malcontent' }}
93-
runs-on: ubuntu-latest-16-core
94-
permissions:
95-
contents: read
96-
container:
97-
image: cgr.dev/chainguard/wolfi-base:latest
98-
options: >-
99-
--cap-add DAC_OVERRIDE
100-
--cap-add SETGID
101-
--cap-add SETUID
102-
--cap-drop ALL
103-
--cgroupns private
104-
--cpu-shares=16384
105-
--memory-swappiness=0
106-
--security-opt no-new-privileges
107-
--ulimit core=0
108-
--ulimit nofile=65535:65535
109-
--ulimit nproc=65535:65535
110-
steps:
111-
- name: Install dependencies
112-
run: |
113-
apk update
114-
apk add curl findutils git go nodejs upx xz yara-x~1.12.0
115-
116-
- name: Checkout code
117-
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
118-
with:
119-
persist-credentials: false
120-
121-
- name: Trust repository
122-
run: git config --global --add safe.directory "${GITHUB_WORKSPACE}"
123-
124-
- name: Clone malcontent samples required for Fuzz tests
125-
run: |
126-
make samples
127-
128-
- name: Fuzz tests
129-
run: |
130-
make fuzz

.github/workflows/release.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright 2024 Chainguard, Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
14
name: Cut Release
25

36
on:

.github/workflows/scorecard.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright 2024 Chainguard, Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
14
# This workflow uses actions that are not certified by GitHub. They are provided
25
# by a third-party and are governed by separate terms of service, privacy
36
# policy, and support documentation.

.github/workflows/third-party.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright 2024 Chainguard, Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
14
name: Update third-party rules
25

36
on:

.github/workflows/version.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Copyright 2024 Chainguard, Inc.
2+
# SPDX-License-Identifier: Apache-2.0
3+
14
name: Bump Version
25

36
on:

Makefile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,25 @@ test:
142142
fuzz:
143143
go test -timeout 0 -fuzz=FuzzContainsUnprintable -fuzztime=10s ./pkg/report/
144144
go test -timeout 0 -fuzz=FuzzExtractArchive -fuzztime=10s ./pkg/archive/
145+
go test -timeout 0 -fuzz=FuzzExtractBz2 -fuzztime=10s ./pkg/archive/
146+
go test -timeout 0 -fuzz=FuzzExtractDeb -fuzztime=10s ./pkg/archive/
147+
go test -timeout 0 -fuzz=FuzzExtractGzip -fuzztime=10s ./pkg/archive/
148+
go test -timeout 0 -fuzz=FuzzExtractRPM -fuzztime=10s ./pkg/archive/
145149
go test -timeout 0 -fuzz=FuzzExtractTar -fuzztime=10s ./pkg/archive/
150+
go test -timeout 0 -fuzz=FuzzExtractUPX -fuzztime=10s ./pkg/archive/
146151
go test -timeout 0 -fuzz=FuzzExtractZip -fuzztime=10s ./pkg/archive/
152+
go test -timeout 0 -fuzz=FuzzExtractZlib -fuzztime=10s ./pkg/archive/
153+
go test -timeout 0 -fuzz=FuzzExtractZstd -fuzztime=10s ./pkg/archive/
147154
go test -timeout 0 -fuzz=FuzzFile -fuzztime=30s ./pkg/programkind/
148155
go test -timeout 0 -fuzz=FuzzGetExt -fuzztime=10s ./pkg/programkind/
149156
go test -timeout 0 -fuzz=FuzzIsValidPath -fuzztime=10s ./pkg/archive/
150157
go test -timeout 0 -fuzz=FuzzLongestUnique -fuzztime=10s ./pkg/report/
151158
go test -timeout 0 -fuzz=FuzzMatchToString -fuzztime=10s ./pkg/report/
152159
go test -timeout 0 -fuzz=FuzzPath -fuzztime=10s ./pkg/programkind/
160+
go test -timeout 0 -fuzz=FuzzRecursiveCompile -fuzztime=10s ./pkg/compile/
161+
go test -timeout 0 -fuzz=FuzzRemoveRules -fuzztime=10s ./pkg/compile/
162+
go test -timeout 0 -fuzz=FuzzRenderDifferential -fuzztime=10s ./pkg/render/
163+
go test -timeout 0 -fuzz=FuzzReportLoad -fuzztime=10s ./pkg/report/
153164
go test -timeout 0 -fuzz=FuzzStringPoolAtomic -fuzztime=10s ./pkg/report/
154165
go test -timeout 0 -fuzz=FuzzStringPoolConcurrent -fuzztime=10s ./pkg/report/
155166
go test -timeout 0 -fuzz=FuzzStringPoolIntern -fuzztime=10s ./pkg/report/

pkg/action/archive_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// Copyright 2024 Chainguard, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
14
package action
25

36
import (

pkg/action/diff.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"maps"
1111
"os"
1212
"path/filepath"
13-
"runtime"
1413
"slices"
1514
"sort"
1615
"strings"
@@ -19,7 +18,6 @@ import (
1918
"github.com/chainguard-dev/malcontent/pkg/archive"
2019
"github.com/chainguard-dev/malcontent/pkg/file"
2120
"github.com/chainguard-dev/malcontent/pkg/malcontent"
22-
"github.com/chainguard-dev/malcontent/pkg/pool"
2321
"github.com/chainguard-dev/malcontent/pkg/programkind"
2422
"github.com/chainguard-dev/malcontent/pkg/report"
2523
"github.com/egibs/reconcile/pkg/files"
@@ -222,10 +220,6 @@ func Diff(ctx context.Context, c malcontent.Config, _ *clog.Logger) (*malcontent
222220
isReport bool
223221
)
224222

225-
initReadPool.Do(func() {
226-
readPool = pool.NewBufferPool(runtime.GOMAXPROCS(0))
227-
})
228-
229223
if c.OCI {
230224
srcPath, err = archive.OCI(ctx, srcPath, c.OCIAuth)
231225
if err != nil {

0 commit comments

Comments
 (0)