Skip to content

Commit 70f24be

Browse files
committed
CI: enforce UBSan strict on ASan+UBSan workflow after clean baseline
Follow-up to b9777c8 (the ASan+UBSan workflow). Run #1 of the new job came back clean: zero distinct UBSan diagnostics across the --help and --features smoke invocations. https://github.com/libretro/RetroArch/actions/runs/25056073385 * .github/workflows/Linux-asan-ubsan.yml - Flip UBSAN_OPTIONS=halt_on_error=0 to halt_on_error=1 in both smoke steps. A future change that introduces signed-overflow / alignment / shift-too-large UB along the option-parsing or print paths will now fail the run instead of being silently logged in a discovery summary. - Add a parallel grep -q "runtime error:" check after each timeout invocation so the failure is visible at exit code level even if a future sanitizer release changes the default abort semantics, mirroring the existing "AddressSanitizer:" check. - Drop the "Summarize UBSan baseline" step. Its job was to surface diagnostics during the discovery phase; with strict enforcement above it any non-zero count would have already aborted the run, so the summary is dead weight that suggested the workflow was still in soft-fail mode. - Step name updates: "ASan strict, UBSan soft-fail" -> "ASan + UBSan strict" on both smoke runs. Honest scoping note unchanged from b9777c8: --help and --features both exit(0) directly without going through the normal shutdown path, so this enforces UBSan-cleanliness only for libc init / main / frontend bootstrap / option parsing / the print functions. Audio resampling, color math, parsers, and full-lifecycle cleanup still aren't covered. The follow-up step running with --max-frames=N against a noop core (deferred from b9777c8) will extend coverage, and that step's first run will start in soft-fail mode the same way this one did.
1 parent 60c7e39 commit 70f24be

1 file changed

Lines changed: 26 additions & 30 deletions

File tree

.github/workflows/Linux-asan-ubsan.yml

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,25 @@ jobs:
8585
test -x retroarch
8686
file retroarch
8787
88-
- name: Smoke run --help (ASan strict, UBSan soft-fail)
88+
- name: Smoke run --help (ASan + UBSan strict)
8989
# `--help` exits cleanly via exit(0) after printing the usage
9090
# banner. Coverage scope: libc init, main(), frontend
9191
# driver bootstrap, argv duplication, the getopt walk over
9292
# the full option table, and retroarch_print_help() itself.
9393
# Doesn't reach into core loading / video init / cleanup-on-
9494
# shutdown -- a follow-up step running with --max-frames=N
9595
# against a noop core will extend coverage to the full
96-
# lifecycle. ASan runs in abort-on-error mode so any heap
97-
# corruption fails the job; UBSan reports stacktraces but
98-
# does not fail (first iteration -- we want to see the
99-
# baseline before deciding which UBSan classes to enforce).
96+
# lifecycle. ASan and UBSan both run in halt-on-error mode:
97+
# the first run of this workflow (Apr 28 2026, run #1)
98+
# reported zero distinct UBSan diagnostics across both
99+
# smoke invocations, so the baseline for these two surfaces
100+
# is clean and we enforce it. If a future change introduces
101+
# signed-overflow / alignment / shift-too-large UB along
102+
# the option-parsing or print paths, this step will fail
103+
# and the diagnostic line will be in the captured stderr.
100104
env:
101105
ASAN_OPTIONS: abort_on_error=1:detect_leaks=0:print_stacktrace=1:strict_string_checks=1
102-
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=0
106+
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
103107
# Avoid noise from libGL / Mesa / Wayland symbol-resolution
104108
# leaks at process shutdown; those are not RetroArch bugs.
105109
LSAN_OPTIONS: exitcode=0
@@ -113,14 +117,21 @@ jobs:
113117
cat /tmp/help.err
114118
# ASan abort_on_error sends the process to exit code 1 + a
115119
# SUMMARY: line on stderr. Treat any "AddressSanitizer:"
116-
# marker as fatal regardless of exit code.
120+
# or UBSan "runtime error:" marker as fatal regardless of
121+
# exit code -- belt-and-suspenders to the runtime options
122+
# in case a future sanitizer release changes its default
123+
# exit semantics.
117124
if grep -q "AddressSanitizer:" /tmp/help.err; then
118125
echo "[FAIL] AddressSanitizer reported a finding"
119126
exit 1
120127
fi
128+
if grep -q "runtime error:" /tmp/help.err; then
129+
echo "[FAIL] UBSan reported a finding"
130+
exit 1
131+
fi
121132
echo "[pass] retroarch --help under ASan+UBSan"
122133
123-
- name: Smoke run --features (ASan strict, UBSan soft-fail)
134+
- name: Smoke run --features (ASan + UBSan strict)
124135
# `--features` exits cleanly via exit(0) after printing the
125136
# compile-time feature list. Coverage scope is the same as
126137
# --help (libc init / main / frontend bootstrap / arg parse)
@@ -130,10 +141,11 @@ jobs:
130141
# such walk reads pointers into a static-string table -- low
131142
# corruption surface but a useful sanity check that the link-
132143
# time feature flags resolve consistently. Doesn't reach
133-
# core loading or cleanup-on-shutdown.
144+
# core loading or cleanup-on-shutdown. Like the --help step
145+
# this enforces UBSan strict because the baseline is clean.
134146
env:
135147
ASAN_OPTIONS: abort_on_error=1:detect_leaks=0:print_stacktrace=1:strict_string_checks=1
136-
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=0
148+
UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1
137149
LSAN_OPTIONS: exitcode=0
138150
run: |
139151
set -eu
@@ -147,24 +159,8 @@ jobs:
147159
echo "[FAIL] AddressSanitizer reported a finding"
148160
exit 1
149161
fi
150-
echo "[pass] retroarch --features under ASan+UBSan"
151-
152-
- name: Summarize UBSan baseline
153-
# Both runtime steps are non-fatal on UBSan diagnostics. This
154-
# step prints a count of distinct UBSan messages observed so
155-
# follow-up patches have a numerical target to drive to zero.
156-
# If this step ever shows zero, flip
157-
# UBSAN_OPTIONS=halt_on_error=1 in the runtime steps above to
158-
# enforce the clean baseline.
159-
if: always()
160-
run: |
161-
set +e
162-
ub_count=$( {
163-
grep -h "runtime error:" /tmp/help.err /tmp/features.err 2>/dev/null
164-
} | sort -u | wc -l)
165-
echo "UBSan distinct diagnostics: ${ub_count}"
166-
if [ "${ub_count}" != "0" ]; then
167-
echo "=== unique UBSan diagnostics ==="
168-
grep -h "runtime error:" /tmp/help.err /tmp/features.err 2>/dev/null \
169-
| sort -u
162+
if grep -q "runtime error:" /tmp/features.err; then
163+
echo "[FAIL] UBSan reported a finding"
164+
exit 1
170165
fi
166+
echo "[pass] retroarch --features under ASan+UBSan"

0 commit comments

Comments
 (0)