Skip to content

test(#2293): screen every generated tool log for sanitizer findings - #2299

Merged
xsscx merged 1 commit into
masterfrom
fix/issue-2293-screen-every-tool-log
Aug 24, 2026
Merged

test(#2293): screen every generated tool log for sanitizer findings#2299
xsscx merged 1 commit into
masterfrom
fix/issue-2293-screen-every-tool-log

Conversation

@colourbill-ctrl

Copy link
Copy Markdown
Contributor

Closes #2293.

The regression added in #2292 screened only the two iccApplyToLink logs. The two iccFromXml logs and the six iccDumpProfile logs were never passed to sanitizer_check, and the iccDumpProfile calls had no exit-status check at all.

ICCDEV_TEST_ENV sets halt_on_error=0 for both sanitizers, so a UBSan report is printed while the tool still exits zero — an exit status cannot see it. All twelve invocations now go through one choke point rather than five more sanitizer_check calls, since an omitted call at a new call site is how the gap arrived.

Red/green

Measured with tool shims modelling each case (clang 21.1.3, ASan+UBSan):

case before after
iccFromXml finding, exit 0 PASS FAIL
iccDumpProfile finding, exit 0 PASS FAIL
iccDumpProfile UBSan runtime error: PASS FAIL
iccDumpProfile LeakSanitizer, exit 23 PASS FAIL
iccDumpProfile SUMMARY: line only PASS FAIL
iccDumpProfile exit 1 (arg path) PASS FAIL
iccDumpProfile exit 253 (write failure) PASS FAIL
iccDumpProfile exit 139 (SIGSEGV) PASS FAIL
iccDumpProfile exit 255 (bad invocation) PASS FAIL
iccApplyToLink exits 0, writes nothing PASS FAIL
iccApplyToLink writes an unparseable link PASS FAIL
ASan report + abort (real ASan) FAIL, misnamed FAIL, named
iccDumpProfile exit 255 (verdict) PASS PASS
iccDumpProfile exit 254 (unknown) PASS PASS
iccApplyToLink finding FAIL FAIL

The last three are the point of the dump_tool split: with -v, iccDumpProfile returns the validation verdict, not a success flag. The device links this test generates already validate as noncompliant — the last severity mapping to exit 0 — so a plain || fail would turn a future validation tightening into a phantom #1982 regression. Same asymmetry documented at iccdev-qa-profile-manifest.sh:197-207.

Anti-regression: with the two CIccXform::Create conditions reverted to their pre-fix form the test still fails (exit 2), so the #1982 assertion is unweakened. shellcheck and bash -n clean; CTest #149 passes.

On CI coverage — please read before trusting the checks

I dispatched ci-pr-action before opening this PR per the playbook (run 32772831218, ci_scope=fast-lane, ctest_recent_limit=0). It concluded success, but every build and CTest lane was skipped, so that green is not evidence for this change and I am not citing it as such.

The reason is structural, not a misdispatch: a .github/scripts/-only diff sets ci_changed and nothing else, native_changed is set only by C/C++ extensions (ci-pr-action.yml:473), and tool-tests gates on native_changed == true (:866). No ci_scope value changes that — run_full=true from fast-lane does not reach this gate. Noting it as a fact rather than filing it: a change to a CTest harness script currently gets no CTest coverage, so the evidence here is the local matrix above.

Scope

The same unscreened-log pattern exists in iccdev-issue-1781-applytolink-qa-matrix.sh (plus four exit 0 skip paths with no SKIP_RETURN_CODE). Filed separately as #2298 rather than folded in — different harness, different CTest.

The dual-PCS regression from #2292 passed only the two iccApplyToLink logs
through sanitizer_check().  The two iccFromXml logs and the six
iccDumpProfile logs were never screened, and the iccDumpProfile calls had no
status check at all, so a finding in the tools that build this test's
fixtures and produce the output its assertions read went unreported.

All twelve invocations now go through one choke point rather than five more
sanitizer_check() calls, since an omitted call at a new call site is exactly
how the gap arrived.  The sibling harness already uses this idiom
(iccdev-issue-1781-applytolink-qa-matrix.sh:118).

The log is screened BEFORE the status is judged.  halt_on_error=0 only keeps
a tool alive where the build can recover, and nothing here passes
-fsanitize-recover=address: Build/Cmake/CMakeLists.txt:977 adds
-fno-sanitize-recover= for UBSan/integer/float only and SANITIZER_RECOVER
defaults OFF (:584).  So an ASan finding always aborts and arrives WITH a
non-zero status, and only UBSan can report while still exiting zero, in the
lane that sets SANITIZER_RECOVER=ON (ci-iccdev-tool-tests.yml:434).  Judging
the status first leaves the run red but reports every ASan abort as a plain
tool failure.  The stale comment that described the opposite ordering is
rewritten rather than left to contradict this.

iccDumpProfile gets its own variant, because with -v its exit code is a
VALIDATION VERDICT and not a success flag: it ends "return nValid".  The
device links this test generates already validate as noncompliant -- the last
severity that still maps to 0 -- so a plain status gate would turn a future
validation tightening into a phantom #1982 regression while the D2B/B2D
selection this test guards was intact.  Same asymmetry documented in
iccdev-qa-profile-manifest.sh:197-207 and
Build/Cmake/Testing/CMakeLists.txt:6538.

That tolerance is an ALLOW-list (0, 254, 255), not a blacklist, because the
tool has more non-verdict exits than verdicts: 1 from the QA-flag argument
paths (iccDumpProfile.cpp:582, :604), 253 from a failed dump write (:1010,
:1053), and any signal.  253 truncates the log, which matters most in Part 2
where the assertion is that the two normalized chain dumps DIFFER: a
truncation hitting one arm only would make them differ for a reason unrelated
to tag selection.

255 needs two log pins on top of that, because three different things produce
it: icValidateCriticalError, an unparseable profile (:703-706 forces the same
verdict), and a bad invocation (:617, :632, :664).  A bad invocation prints
"Usage:" and returns before the version banner at :703, so requiring the
banner catches it; an unparseable profile prints the banner and then "Unable
to parse".  Part 1 also gains the link-exists guard Part 2 already had.  All
three keep a tool-output failure from surfacing as fixture drift.

The "-v 100" on the dumps is deliberate and is what makes that tolerance
necessary: no grep pin reads the validation report, so dropping -v would let
every dump use run_tool() and delete the variant entirely.  It is kept because
this test carries the "asan" label and CIccProfile::Validate() walks every tag
-- measured, that is the only difference between the 165-line -v dump and the
160-line plain one -- so dropping it would shrink the code executed under the
sanitizer, which is the coverage this change exists to protect.

sanitizer_check's alternation gains LeakSanitizer, MemorySanitizer and
DEADLYSIGNAL: dump_tool has to tolerate 254 and 255, so for those logs the
regex is the only thing that can catch a finding which still exits with one
of those codes.  ICCDEV_TEST_ENV sets detect_leaks=0, but this script is
runnable standalone against an ASan build where LSan is on by default.

Measured with tool shims modelling each case, clang 21.1.3 ASan+UBSan:

  case                                      before  after
  iccFromXml finding, exit 0                PASS    FAIL
  iccDumpProfile finding, exit 0            PASS    FAIL
  iccDumpProfile UBSan runtime error        PASS    FAIL
  iccDumpProfile LeakSanitizer, exit 23     PASS    FAIL
  iccDumpProfile SUMMARY: line only         PASS    FAIL
  iccDumpProfile exit 1 (arg path)          PASS    FAIL
  iccDumpProfile exit 253 (write fail)      PASS    FAIL
  iccDumpProfile exit 139 (SIGSEGV)         PASS    FAIL
  iccDumpProfile exit 255 (bad invocation)  PASS    FAIL
  iccApplyToLink exits 0, writes nothing    PASS    FAIL
  iccApplyToLink writes unparseable link    PASS    FAIL
  ASan report + abort (real ASan)           FAIL*   FAIL   (*named a tool failure)
  iccDumpProfile exit 255 (verdict)         PASS    PASS
  iccDumpProfile exit 254 (unknown)         PASS    PASS
  iccApplyToLink finding                    FAIL    FAIL

Anti-regression: with the two CIccXform::Create conditions reverted to their
pre-fix form the test still fails (exit 2) at the first opt-out chain, so the
#1982 assertion is unweakened.  shellcheck and bash -n clean; CTest #149
passes.

A sanitizer report also survives normalize() into the two files Part 2
compares, carrying a per-process PID that differs between arms; screening
before the comparison removes that interaction.  It is a latent ordering
hazard only, not a demonstrated false pass: on both regression shapes tried
-- both conditions reverted, and the destination condition alone --
iccApplyToLink fails closed and Part 2 is never reached.
@github-actions github-actions Bot added Scripts Shell, PowerShell, or repository automation scripts Unix Linux, macOS, Bash, or POSIX shell scope pending CI checks still running labels Aug 24, 2026

@xsscx xsscx left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2026-08-24 20:22:23 UTC

@xsscx xsscx self-assigned this Aug 24, 2026
@xsscx
xsscx enabled auto-merge (squash) August 24, 2026 20:22
@xsscx
xsscx merged commit e95eac0 into master Aug 24, 2026
30 checks passed
@xsscx
xsscx deleted the fix/issue-2293-screen-every-tool-log branch August 24, 2026 22:56
@xsscx xsscx added this to the v2.3.2.4 milestone Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pending CI checks still running Scripts Shell, PowerShell, or repository automation scripts Unix Linux, macOS, Bash, or POSIX shell scope

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TODO: Punch List #2292 - log is never passed to sanitizer_check

2 participants