4040 run-docs : ${{ steps.docs-changes.outputs.run-docs || false }}
4141 run_tests : ${{ steps.check.outputs.run_tests }}
4242 run_hypothesis : ${{ steps.check.outputs.run_hypothesis }}
43+ run_cifuzz : ${{ steps.check.outputs.run_cifuzz }}
4344 config_hash : ${{ steps.config_hash.outputs.hash }}
4445 steps :
4546 - uses : actions/checkout@v4
7677 echo "Run hypothesis tests"
7778 echo "run_hypothesis=true" >> $GITHUB_OUTPUT
7879 fi
80+
81+ # oss-fuzz maintains a configuration for fuzzing the main branch of
82+ # CPython, so CIFuzz should be run only for code that is likely to be
83+ # merged into the main branch; compatibility with older branches may
84+ # be broken.
85+ FUZZ_RELEVANT_FILES='(\.c$|\.h$|\.cpp$|^configure$|^\.github/workflows/build\.yml$|^Modules/_xxtestfuzz)'
86+ if [ "$GITHUB_BASE_REF" = "main" ] && [ "$(git diff --name-only origin/$GITHUB_BASE_REF.. | grep -qE $FUZZ_RELEVANT_FILES; echo $?)" -eq 0 ]; then
87+ # The tests are pretty slow so they are executed only for PRs
88+ # changing relevant files.
89+ echo "Run CIFuzz tests"
90+ echo "run_cifuzz=true" >> $GITHUB_OUTPUT
91+ else
92+ echo "Branch too old for CIFuzz tests; or no C files were changed"
93+ echo "run_cifuzz=false" >> $GITHUB_OUTPUT
94+ fi
7995 - name : Compute hash for config cache key
8096 id : config_hash
8197 run : |
@@ -534,6 +550,46 @@ jobs:
534550 - name : Tests
535551 run : xvfb-run make test
536552
553+ # CIFuzz job based on https://google.github.io/oss-fuzz/getting-started/continuous-integration/
554+ cifuzz :
555+ name : CIFuzz
556+ runs-on : ubuntu-latest
557+ timeout-minutes : 60
558+ needs : check_source
559+ if : needs.check_source.outputs.run_cifuzz == 'true'
560+ permissions :
561+ security-events : write
562+ strategy :
563+ fail-fast : false
564+ matrix :
565+ sanitizer : [address, undefined, memory]
566+ steps :
567+ - name : Build fuzzers (${{ matrix.sanitizer }})
568+ id : build
569+ uses : google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
570+ with :
571+ oss-fuzz-project-name : cpython3
572+ sanitizer : ${{ matrix.sanitizer }}
573+ - name : Run fuzzers (${{ matrix.sanitizer }})
574+ uses : google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
575+ with :
576+ fuzz-seconds : 600
577+ oss-fuzz-project-name : cpython3
578+ output-sarif : true
579+ sanitizer : ${{ matrix.sanitizer }}
580+ - name : Upload crash
581+ uses : actions/upload-artifact@v3
582+ if : failure() && steps.build.outcome == 'success'
583+ with :
584+ name : ${{ matrix.sanitizer }}-artifacts
585+ path : ./out/artifacts
586+ - name : Upload SARIF
587+ if : always() && steps.build.outcome == 'success'
588+ uses : github/codeql-action/upload-sarif@v2
589+ with :
590+ sarif_file : cifuzz-sarif/results.sarif
591+ checkout_path : cifuzz-sarif
592+
537593 all-required-green : # This job does nothing and is only used for the branch protection
538594 name : All required checks pass
539595 if : always()
@@ -550,6 +606,7 @@ jobs:
550606 - build_ubuntu_ssltests
551607 - test_hypothesis
552608 - build_asan
609+ - cifuzz
553610
554611 runs-on : ubuntu-latest
555612
@@ -562,6 +619,7 @@ jobs:
562619 build_ubuntu_ssltests,
563620 build_win32,
564621 build_win_arm64,
622+ cifuzz,
565623 test_hypothesis,
566624 allowed-skips : >-
567625 ${{
@@ -585,6 +643,13 @@ jobs:
585643 '
586644 || ''
587645 }}
646+ ${{
647+ !fromJSON(needs.check_source.outputs.run_cifuzz)
648+ && '
649+ cifuzz,
650+ '
651+ || ''
652+ }}
588653 ${{
589654 !fromJSON(needs.check_source.outputs.run_hypothesis)
590655 && '
0 commit comments