Skip to content

Re-enabling ASAN tests - #1617

Merged
AnHeuermann merged 8 commits into
OpenModelica:masterfrom
AnHeuermann:fix-asan-ci
Jul 31, 2026
Merged

Re-enabling ASAN tests#1617
AnHeuermann merged 8 commits into
OpenModelica:masterfrom
AnHeuermann:fix-asan-ci

Conversation

@AnHeuermann

@AnHeuermann AnHeuermann commented Jul 30, 2026

Copy link
Copy Markdown
Member

Related Issues

Fixes #1615.

Purpose

  • Enable ASAN again
  • Updated testsuite to enable ASAN everywhere possible
    • Fix memory issues that popped up while it was disabled or never discoverd
    • Disabled ASAN tests still leak memory
  • Update Build configuration to be more strict on all used compiler

Approach

Bugs fixed in OMSimulator

Heap-buffer-overflow in SystemSC (b917d7b)

callEventUpdate and terminateSimulation were allocated in a default member initializer, new bool[fmus.size()](). That runs in the constructor, where fmus is still empty — initialize() only fills it later — so both arrays were always zero length. Every ME step then wrote one flag per FMU past the end of them. The arrays are now std::unique_ptr<bool[]> sized in initialize() once fmus is known. unique_ptr also closes two related problems: terminate() delete[]-ed the arrays without clearing the pointers while initialize() never re-allocated them (dangling pointer on re-initialize), and ~SystemSC() freed nothing at all (leak when terminate() is never called).

KINSOL solver leaked per algebraic loop (01dcf3f)

AlgLoop owned KinsolSolver* as a raw pointer and never deleted it, leaking the KINSOL memory block, five N_Vectors, the dense matrix, the linear solver and the user-data struct for every algebraic loop. kinsolData was also left uninitialized when the fixed-point solver was selected, and the ~12 error returns in NewKinsolSolver() leaked the half-built object. Now a unique_ptr member, with the factory holding one until the object is complete.

Build configuration

  • ASAN now works with Clang, not only GCC (4e5e02f). The flags used to sit inside a GNU-only branch, so -DASAN=ON on a Clang build silently produced an uninstrumented library — it still reported leaks through the preloaded libasan
    interceptors, but detected no overflow or use-after-free at all. A FATAL_ERROR now rejects compilers too old to support the sanitizer.
  • MSVC equivalents of the -Werror= memory warnings (2193adb): C4700, C4701, C4703, C4715, C4716 and C4172 are raised to the default warning level and turned into errors.

Testsuite

  • New testsuite/lsan-suppressions.txt, wired into runtest.py via LSAN_OPTIONS. It covers only non-OMSimulator modules: the uutils coreutils processes the OMSimulatorPython3 wrapper starts, CPython's own interpreter state, and lxml/libxml2/libxslt. print_suppressions=0 keeps the reports out of the compared test output. The file documents why matching on module paths is safe here and why fast_unwind_on_malloc=0 must not be set.
  • asan: yes on 82 test cases, asan: no with an explanatory line on 23 (774f903, ab681d0) — see the limitation below.
  • Dropped the unused from numpy import uint64 from the two FeedthroughSetValue tests and python3-numpy from the coverage workflow (8cfb221). numpy leaks ~683 bytes registering its ufuncs at import, in stacks too shallow to suppress by interpreter frame.

Known limitation

23 tests are marked asan: no. All of them fail on leaks — and in the two embrace cases a use-after-free — that occur inside the FMU binaries, not in OMSimulator: OpenModelica-generated FMUs leak in <Model>_function_initSynchronous, FMU_16_aero_interface.so leaks ~82 kB during fmi2Instantiate, and Dymola's
ECS_HW.so reads the pointer returned by setlocale() after a later call has freed it. All of these tests do call terminate() and delete(), so fmi2FreeInstance is issued correctly. Suppressions cannot help: once the FMU is
dlclosed the stacks are #0 malloc / #1 <unknown module> with nothing left to
match on. Each disabled test carries a one-line comment naming the reason.

* Suppress leaks from Python wrapper / interpreter
* New suppressions file testsuite/lsan-suppressions.txt
* Enabeling ASAN tests on Jenkins
@AnHeuermann AnHeuermann self-assigned this Jul 30, 2026
@AnHeuermann

Copy link
Copy Markdown
Member Author

We have a few real memory issues:

What Reports Where
Leaks under fmi2_instantiate 565 all reachable from oms_instantiate → oms::ComponentFMUCS::instantiate() (ComponentFMUCS.cpp:631)
SUNDIALS leaks (N_VNewEmpty, N_VClone_Serial, SUNDenseMatrix, SUNLinSol_Dense) ~50 oms::KinsolSolver::NewKinsolSolver, under oms_initialize
heap-use-after-free 2 inside the FMU binary ECS_HW.so, in sscanfCx2_underscore — AircraftVehicleDemonstrator.embrace1/embrace2

@AnHeuermann

Copy link
Copy Markdown
Member Author

The remaining issues are basically FMUs leaking memory. We should check if updating the OpenModelica ones improves the situation.

Not sure if we can update the remaining FMUs. For those disabling ASAN might be the only option.

@AnHeuermann

Copy link
Copy Markdown
Member Author

Looks like I need to finally do OpenModelica/OpenModelica#14638....
The old multiarch/crossbuild image isn't compatible with OpenModelica v1.27.

* The issues are caused by the FMU binaries
* fmu.size() can't be used before `fmus` is filled
* Use unique pointer to clarify ownership
* Equivalent of -Werror flags for GCC/Clang
* It was unused and leaking memory
@AnHeuermann
AnHeuermann merged commit 6287cf4 into OpenModelica:master Jul 31, 2026
4 checks passed
@AnHeuermann
AnHeuermann deleted the fix-asan-ci branch July 31, 2026 10:41
@codecov-commenter

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

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.

Fix ASAN tests and memory leaks

2 participants