File: fuzzing.yml

package info (click to toggle)
expat 2.7.4-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 133,648 kB
  • sloc: xml: 610,598; ansic: 29,659; sh: 725; makefile: 402; cpp: 376; python: 137
file content (180 lines) | stat: -rw-r--r-- 6,698 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#                          __  __            _
#                       ___\ \/ /_ __   __ _| |_
#                      / _ \\  /| '_ \ / _` | __|
#                     |  __//  \| |_) | (_| | |_
#                      \___/_/\_\ .__/ \__,_|\__|
#                               |_| XML parser
#
# Copyright (c) 2024-2025 Sebastian Pipping <sebastian@pipping.org>
# Licensed under the MIT license:
#
# Permission is  hereby granted,  free of charge,  to any  person obtaining
# a  copy  of  this  software   and  associated  documentation  files  (the
# "Software"),  to  deal in  the  Software  without restriction,  including
# without  limitation the  rights  to use,  copy,  modify, merge,  publish,
# distribute, sublicense, and/or sell copies of the Software, and to permit
# persons  to whom  the Software  is  furnished to  do so,  subject to  the
# following conditions:
#
# The above copyright  notice and this permission notice  shall be included
# in all copies or substantial portions of the Software.
#
# THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
# EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
# NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
# USE OR OTHER DEALINGS IN THE SOFTWARE.

name: Run fuzzing regression tests

on:
  pull_request:
  push:
  schedule:
    - cron: '0 2 * * 5'  # Every Friday at 2am
  workflow_dispatch:

permissions:
  contents: read

jobs:
  run_fuzzers:
    name: Run fuzzing regression tests
    strategy:
      fail-fast: false
      matrix:
        fuzzer:
          - xml_parse_fuzzer_UTF-8
          - xml_parsebuffer_fuzzer_UTF-16LE
    runs-on: ubuntu-24.04
    env:
      fuzzer: ${{ matrix.fuzzer }}
    steps:
    - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd  # v6.0.2

    - name: Install Clang 21
      run: |-
        set -x
        source /etc/os-release
        wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
        sudo add-apt-repository "deb https://apt.llvm.org/${UBUNTU_CODENAME}/ llvm-toolchain-${UBUNTU_CODENAME}-21 main"
        sudo apt-get update  # due to new repository
        sudo apt-get install --yes --no-install-recommends -V \
            clang-21 \
            libclang-rt-21-dev \
            llvm-21
        echo /usr/lib/llvm-21/bin >>"${GITHUB_PATH}"

    - name: Install build dependencies
      run: |-
        set -x
        sudo apt-get install --yes --no-install-recommends -V \
            autoconf \
            automake \
            docbook2x \
            libtool \
            libprotobuf-dev \
            lzip \
            protobuf-compiler

    - name: Turn Git clone into Autotools "make dist" release tarball
      run: |-
        set -x
        pushd expat/
          ./buildconf.sh
          ./configure
          make dist
        popd
        tar xf expat/expat-*.tar.xz
        rm -R expat/
        mv expat-* expat

    - name: Build Expat fuzzers
      run: |
        set -x -o pipefail

        type -P clang clang++
        clang --version | head -n1
        clang++ --version | head -n1

        cd expat/
        args=(
            # Build nothing but fuzzers
            -DEXPAT_BUILD_DOCS=OFF
            -DEXPAT_BUILD_EXAMPLES=OFF
            -DEXPAT_BUILD_FUZZERS=ON
            -DEXPAT_BUILD_PKGCONFIG=OFF
            -DEXPAT_BUILD_TESTS=OFF
            -DEXPAT_BUILD_TOOLS=OFF

            # Tune compilation of fuzzers to use Clang with ASan and UBSan
            -DCMAKE_C_COMPILER=clang
            -DCMAKE_CXX_COMPILER=clang++
            -DCMAKE_{C,CXX}_FLAGS='-Wall -Wextra -pedantic -O1 -g -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common -fprofile-instr-generate -fcoverage-mapping'
            -DCMAKE_{EXE,MODULE,SHARED}_LINKER_FLAGS='-g -fsanitize=address,undefined'
            -DEXPAT_WARNINGS_AS_ERRORS=ON
        )
        cmake "${args[@]}" -S . -B build
        make -C build VERBOSE=1 -j$(nproc)

        ./build/fuzz/xml_lpm_fuzzer -help=1

    - name: Download and extract Expat fuzzing corpora
      run: |-
        set -x
        cd expat/build/
        wget -q -O corpus.zip "https://storage.googleapis.com/expat-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/expat_${fuzzer}/public.zip"
        unzip -q -d corpus/ corpus.zip

    - name: Run fuzzing regression tests (1 to 5 minutes)
      run: |
        fuzz_args=(
            -jobs=$(nproc)
            -print_final_stats=1
            -rss_limit_mb=2560  # from OSS-Fuzz
            -timeout=25         # from OSS-Fuzz
        )

        set -x -o pipefail
        cd expat/build/

        # Configure UBSan to show (non-default) stack traces for runtime errors
        # NOTE: "halt_on_error=1" we don't need to add because of the
        #       -fno-sanitize-recover=all for CFLAGS further up.
        # NOTE: "abort_on_error=1" we don't need here because to CI,
        #       a non-zero exit code is all that matters.
        export UBSAN_OPTIONS='print_stacktrace=1'

        mkdir coverage/
        export LLVM_PROFILE_FILE=coverage/expat-%p.profraw

        find corpus/ -type f | sort | xargs "fuzz/${fuzzer}" "${fuzz_args[@]}"

    - name: Store fuzzing logs of last batch
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f  # v6.0.0
      with:
        name: ${{ matrix.fuzzer }}_${{ github.sha }}_logs_last
        path: expat/build/fuzz-*.log
        if-no-files-found: error

    - name: Render coverage report
      run: |
        set -x -o pipefail
        cd expat/build/

        # Merged and convert to a single indexed profile data file
        llvm-profdata merge -sparse -o coverage/expat.profdata coverage/expat-*.profraw

        # Render report
        llvm-cov show fuzz/${fuzzer} -instr-profile=coverage/expat.profdata -show-branches=count -format=html -output-dir=coverage/html/
        llvm-cov report fuzz/${fuzzer} -instr-profile=coverage/expat.profdata -show-functions -sources ../lib/ | tee coverage/report_functions.txt
        llvm-cov report fuzz/${fuzzer} -instr-profile=coverage/expat.profdata                 -sources ../lib/ | tee coverage/report_files.txt

    - name: Store coverage report
      uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f  # v6.0.0
      with:
        name: ${{ matrix.fuzzer }}_${{ github.sha }}_coverage
        path: expat/build/coverage/
        if-no-files-found: error