Skip to content

[TEST] Add ASan/LeakSanitizer harness and fix memory bugs it found - #7831

Open
Niz13 wants to merge 4 commits into
mainfrom
niz/asan-leak-check-5029
Open

[TEST] Add ASan/LeakSanitizer harness and fix memory bugs it found#7831
Niz13 wants to merge 4 commits into
mainfrom
niz/asan-leak-check-5029

Conversation

@Niz13

@Niz13 Niz13 commented Aug 24, 2026

Copy link
Copy Markdown

Implements the host-side memory-leak check requested in #5029.

Harness

  • scripts/test-triton.sh --asan runs the host-side C++ (ctest) and MLIR lit suites under LeakSanitizer. Sets ASAN_OPTIONS=allow_user_poisoning=0 to neutralize a false use-after-poison caused by linking ASan-instrumented Triton against the non-instrumented prebuilt LLVM (does not weaken leak/redzone detection), and guards that triton-opt is actually ASan-instrumented.
  • scripts/asan/lsan.supp suppresses only benign LLVM/MLIR globals — nothing under third_party/intel.

Bugs found & fixed

  1. Heap-use-after-free in StrideVersioning — the pass called forOp.erase() inside a pre-order walk(), so the walker then dereferenced the freed op. Fixed with collect-then-mutate: gather candidate loops during the walk, version them afterwards (safe — only non-nested top-level loops are candidates).
  2. Six orphaned-ModuleOp leaks in Analysis unit-test fixtures — ModuleOp::create() returned raw and was never freed. Fixed by owning modules in a SmallVector<OwningOpRef<ModuleOp>> member declared after the MLIRContext.

Result (under LeakSanitizer)

Phase Before After
ctest 116 failing (leaks) 453/453, 0 leaks
lit 1 failing (UAF) 446/446, 0 UAF

🤖 Generated with Claude Code

Implements the host-side memory-leak check requested in issue #5029.

- scripts/test-triton.sh gains `--asan`: runs the host-side ctest and
  lit suites under LeakSanitizer. Sets allow_user_poisoning=0 to
  neutralize the false use-after-poison from linking instrumented
  Triton against the non-instrumented prebuilt LLVM, guards that
  triton-opt is ASan-instrumented, and wires in the suppressions file.
- scripts/asan/lsan.supp suppresses only benign LLVM/MLIR globals
  (never anything under third_party/intel).

Fixes found by the harness:
- StrideVersioning erased a loop from inside a pre-order walk(), so the
  walker dereferenced the freed op (heap-use-after-free). Switch to
  collect-then-mutate: gather candidate loops during the walk, version
  them afterwards.
- Six Analysis unit-test fixtures returned a raw ModuleOp from
  ModuleOp::create() and never freed it. Own each module in a
  SmallVector<OwningOpRef<ModuleOp>> member declared after the
  MLIRContext.

Host-side ctest (453) and lit (446) run clean under LeakSanitizer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread third_party/intel/unittest/Analysis/TemporalReuseAnalysisTest.cpp Outdated
@vlad-penkin vlad-penkin linked an issue Aug 31, 2026 that may be closed by this pull request
Niz13 and others added 2 commits August 31, 2026 16:45
Address review feedback: instead of a SmallVector<OwningOpRef<ModuleOp>>
member managing module lifetimes, the buildModule()/createModule()
fixture helpers now return OwningOpRef<ModuleOp> so each test owns its
module locally (as in OptimizePartitionWarps.cpp).

Applied across all six Analysis fixtures. Still leak-free under
LeakSanitizer (118 host-side tests pass).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TEST_F(AliasAnalysisTest, TwoLoadsSameArgDifferentOffsets) {
auto module = createModule();
OwningOpRef<ModuleOp> moduleRef = createModule();
ModuleOp module = *moduleRef;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's use module directly from OwningOpRef without unpacking into a separate variable. Here and elsewhere.
This way should be safer.

Otherwise LGTM!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done, but please take a look at DPAS.h, It had to be changed for this to be uniform across.
if you prefer not to change, I can make exceptions for when it doesn't work.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will const ModuleOp &mod work?

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds an AddressSanitizer/LeakSanitizer testing mode to the repo’s test runner and fixes memory-safety issues uncovered by sanitizer runs (including a walk-time erase UAF in a Triton/MLIR transform and MLIR ModuleOp ownership leaks in Intel backend unit tests).

Changes:

  • Add scripts/test-triton.sh --asan to run host-only ctest + lit under ASan/LSan with a suppression file and instrumentation guardrails.
  • Fix a heap-use-after-free in TritonIntelStrideVersioning by collecting candidate scf.for loops first and versioning them after the walk.
  • Fix ModuleOp::create() ownership leaks in multiple Analysis unit tests by returning/holding OwningOpRef<ModuleOp>.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
third_party/intel/unittest/Analysis/TemporalReuseAnalysisTest.cpp Switch module construction to OwningOpRef<ModuleOp> to prevent leaked ModuleOps in test fixtures.
third_party/intel/unittest/Analysis/StrideInfoTest.cpp Same OwningOpRef<ModuleOp> lifetime ownership fix for stride-analysis unit tests.
third_party/intel/unittest/Analysis/SpatialReuseAnalysisTest.cpp Same OwningOpRef<ModuleOp> lifetime ownership fix for spatial-reuse unit tests.
third_party/intel/unittest/Analysis/ReuseAnalysisTest.cpp Same OwningOpRef<ModuleOp> lifetime ownership fix for reuse-analysis unit tests.
third_party/intel/unittest/Analysis/DPASAnalysisTest.cpp Same OwningOpRef<ModuleOp> lifetime ownership fix for DPAS-analysis unit tests.
third_party/intel/unittest/Analysis/AliasAnalysisTest.cpp Same OwningOpRef<ModuleOp> lifetime ownership fix for alias-analysis unit tests.
third_party/intel/lib/Dialect/Triton/Transforms/StrideVersioning.cpp Avoid IR mutation during a pre-order walk by collecting loops first, then versioning, preventing walk iterator UAF.
scripts/test-triton.sh Add --asan option to run only host-side unit + LIT tests under ASan/LSan with env configuration and instrumentation checks.
scripts/asan/lsan.supp Add LSan suppression list for known benign LLVM/MLIR process-lifetime allocations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/test-triton.sh Outdated
@whitneywhtsang

Copy link
Copy Markdown
Contributor

What's the plan to prevent regressions going forward? Without regular execution, new code could reintroduce leaks/UAFs and we wouldn't catch them until someone manually runs --asan.

@januszjah

Copy link
Copy Markdown
Contributor

What's the plan to prevent regressions going forward? Without regular execution, new code could reintroduce leaks/UAFs and we wouldn't catch them until someone manually runs --asan.

@Niz13 we may create new issue/pr as follow-up to incorporate new feature in CI runs

… variable

Address review feedback: name the OwningOpRef `module` and dereference it
as `*module` at use sites, rather than unpacking into a second `ModuleOp`
variable. Applied across all six Analysis test fixtures.

Since OwningOpRef::operator* yields an rvalue ModuleOp, relax
DPASAnalysisFactory::createDPASAnalysis to take ModuleOp by value (it never
mutates the module); the handle is lightweight and existing lvalue callers
still bind.

Also compose ASAN_OPTIONS/LSAN_OPTIONS so the harness-critical settings are
appended last (last-wins parser) and avoid a stray trailing colon when the
inherited variable is empty.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check memory leaks with address sanitizer

5 participants