Windows native build with ASan - Claude AI notes: ASan found a heap-use-after-free bug

Building SWI-Prolog for Windows using CMake and MSVC with Address Sanitizer.

In running some test designed to look at BFR which fail with an Address Sanitizer error, Claude in looking at the output notes

ASan found a heap-use-after-free bug

Is this a plausible bug? Is this such a rare bug that it is not worth hunting down?

Asking because this bug or something like it seems to be lurking in the garbage collector or some rare sequence and with lack of more details, Claude has to try reason how the code should work, and the code is not easy to understand with the VM instructions, C macros and garbage collection so want to make sure it is a plausible bug before I spend the time, which could be days, to hopefully find the root cause and fix it.

Also since it would take me days to understand the details of the code at that level to manually work on the bug, relying on Claude for help but Claude is not good at realizing that sometimes the tools being used to solve a problem are not enough and does not know which tools would help. Also tried to use Visual Studio IDE but with all of the C macros, Claude can not give me proper commands to look at memory locations or instructions as it is can not reason correctly through all of the C macros. Even tried to generate *.i files using CMake with MSVC and that was not working as expected as the *.i files were not created.


EDIT

Claude thinks this is the fix


EDIT

FYI

Claude created a Minimal reproduction

File name: test_asan_debug_bug.pl

% Minimal reproduction for ASan heap-use-after-free bug
% Bug: callCleanupHandler uses freed memory after stack reallocation
%
% To reproduce:
%   swipl -g "test_bug, halt" test_asan_debug_bug.pl
%
% Expected with ASan: heap-use-after-free in callCleanupHandler at pl-wam.c:847

test_bug :-
    % This simple sequence triggers the bug:
    % 1. set_prolog_flag(debug, true) causes stack growth
    % 2. Stack growth reallocates memory
    % 3. setup_call_cleanup has cleanup handlers that reference old memory
    current_prolog_flag(debug, Old),
    set_prolog_flag(debug, true),
    setup_call_cleanup(true, true, true),
    set_prolog_flag(debug, Old).

The CMake commands used to build the code that generated the bug

cmake .. -G "Visual Studio 18 2026" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_C_FLAGS="/fsanitize=address" -DCMAKE_CXX_FLAGS="/fsanitize=address" -DINSTALL_DOCUMENTATION=OFF -DSWIPL_PACKAGES=OFF

cmake --build . --config Debug  

I have not tried this yet, as in the middle of other builds and testing and only have one machine.

heap-use-after-free is always a bug. It is a bit weird that it does not show up using gcc or clang. Well, it could be Windows specific and I never used AddressSanitizer with the Windows version as far as I remember. Using MSVC we need to do a few things differently because MSVC cannot handle empty structs or empty arrays and on Windows long is 32 bits. These could explain different behaviour.

The suggested patch is wrong. The fr = (LocalFrame)valTermRef(fref); below takes care of getting the correct frame reference in case PL_open_foreign_frame() forced a stack shift.

At least the gcc/clang versions give a detailed trace on when and where the memory was allocated, where it was freed and where it was accessed after the free. If you have that, please share it. It is often enough to figure out what went wrong.

And yes, I’m not entirely happy with the LDFUNC macros. It is nice that it allows using the same code efficiently for the single threaded and multi-threaded versions, but it is easy to make mistakes writing this while mistakes typically lead to hard to read compiler errors :frowning: It also complicates navigation and find-definition typically jumps to the macro rather than the function :frowning:

1 Like

Thanks.
Often I have to tell Claude it is wrong but in this case needed your expert advice.


I have not used gcc/clang to build the native Windows version. Visual Studio IDE might be able to supply such, however I have only just started using Visual Studio IDE again after decades of non use to work on some of these ASAN bugs. Will take a look at using GCC/Clang/VS IDE to see what I can find. If anything of value is found will share. Can’t say when I will get a chance at this, could be minutes, could be days or weeks; however the bug is on a list that I plan to try and fix all of them.


Good to know it is not just me. :slightly_smiling_face:

Using the gcc/clang version just run the binary in a console and it will print a detailed report of the problem in case asan finds an issue.

1 Like

I tried to reproduce it on MSYS2/clang64, but there seem to be more issues. That is the output from the above little program:

matth@hp CLANG64 ~/swipl-devel/build.clang.asan
$ gdb src/swipl
...
(gdb) run -g "test_bug, halt" test_asan_debug_bug.pl
Starting program: C:\msys64\home\matth\swipl-devel\build.clang.asan\src\swipl.exe -g "test_bug, halt" test_asan_debug_bug.pl
[New Thread 1960.0x3210]
[New Thread 1960.0x2614]
[New Thread 1960.0x6f38]

Thread 1 received signal SIGSEGV, Segmentation fault.
0x00007ffea7660ea9 in ucrtbase!_local_unwind () from C:\windows\System32\ucrtbase.dll
(gdb) bt
#0  0x00007ffea7660ea9 in ucrtbase!_local_unwind () from C:\windows\System32\ucrtbase.dll
#1  0x00007ffe4fcf3076 in __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >::PopulateFreeArray(__sanitizer::AllocatorStats*, unsigned long long, __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >::RegionInfo*, unsigned long long) () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#2  0x00007ffe4fcf2ef7 in __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >::GetFromAllocator(__sanitizer::AllocatorStats*, unsigned long long, unsigned int*, unsigned long long) () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#3  0x00007ffe4fcf2b0a in __sanitizer::SizeClassAllocator64LocalCache<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> > >::Refill(__sanitizer::SizeClassAllocator64LocalCache<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> > >::PerClass*, __sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >*, unsigned long long) ()
   from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#4  0x00007ffe4fcf2712 in __sanitizer::CombinedAllocator<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> >, __sanitizer::LargeMmapAllocatorPtrArrayDynamic>::Allocate(__sanitizer::SizeClassAllocator64LocalCache<__sanitizer::SizeClassAllocator64<__asan::AP64<__sanitizer::LocalAddressSpaceView> > >*, unsigned long long, unsigned long long) ()
   from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#5  0x00007ffe4fced551 in __asan::Allocator::Allocate(unsigned long long, unsigned long long, __sanitizer::BufferedStackTrace*, __asan::AllocType, bool) ()
   from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#6  0x00007ffe4fcedcda in __asan::asan_realloc(void*, unsigned long long, __sanitizer::BufferedStackTrace*) () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#7  0x00007ffe4fd0ba68 in realloc () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#8  0x00007ffea7620d76 in ucrtbase!.stdio_common_vswprintf_s () from C:\windows\System32\ucrtbase.dll
#9  0x00007ffea76638cf in ucrtbase!.sys_nerr () from C:\windows\System32\ucrtbase.dll
#10 0x00007ffea76344c6 in ucrtbase!_register_onexit_function () from C:\windows\System32\ucrtbase.dll
#11 0x00007ffea7634478 in ucrtbase!_register_onexit_function () from C:\windows\System32\ucrtbase.dll
#12 0x00007ffe4fcd9bf9 in __sanitizer::InitializeCoverage(bool, char const*) () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#13 0x00007ffe4fd16e01 in __asan::AsanInitFromRtl() () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#14 0x00007ffe4fd17655 in __asan_version_mismatch_check_v8 () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#15 0x00007ffe4fd1fe3b in __main () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#16 0x00007ffe4fcc11c1 in _CRT_INIT () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#17 0x00007ffe4fcc121d in DllMainCRTStartup () from C:\msys64\clang64\bin\libclang_rt.asan_dynamic-x86_64.dll
#18 0x00007ffea9fd8bcf in ntdll!RtlActivateActivationContextUnsafeFast () from C:\windows\SYSTEM32\ntdll.dll
#19 0x00007ffeaa01d67d in ntdll!RtlEnumerateEntryHashTable () from C:\windows\SYSTEM32\ntdll.dll
#20 0x00007ffeaa01d42e in ntdll!RtlEnumerateEntryHashTable () from C:\windows\SYSTEM32\ntdll.dll
#21 0x00007ffeaa01d4a0 in ntdll!RtlEnumerateEntryHashTable () from C:\windows\SYSTEM32\ntdll.dll
#22 0x00007ffeaa08f8b9 in ntdll!LdrInitShimEngineDynamic () from C:\windows\SYSTEM32\ntdll.dll
#23 0x00007ffeaa07b54c in ntdll!EtwLogTraceEvent () from C:\windows\SYSTEM32\ntdll.dll
#24 0x00007ffeaa024563 in ntdll!LdrInitializeThunk () from C:\windows\SYSTEM32\ntdll.dll
#25 0x00007ffeaa02448e in ntdll!LdrInitializeThunk () from C:\windows\SYSTEM32\ntdll.dll
#26 0x0000000000000000 in ?? ()

But the same errors appear if I remove set_prolog_flag from the code above. test_installation/0 fails, as well.

To reproduce: install MSYS2, invoke its clang64 system, then pacman -S mingw-w64-clang-x86_64-swi-prolog-full, then swipl, then test_installation.

The sanitizer build is done in the standard way, just don’t omit -DMSYS2=1 as part of the cmake line.

1 Like

From what I read it crashes while initializing the Asan stuff. This looks very much like a broken Asan installation.

Do not take the following as fact, still have to do more research/investigating.
Currently learning how to do the GCC build on Windows 11.


For the MSVC build, with this variation of the command which adds /DNDEBUG

cmake .. -G "Visual Studio 18 2026" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_C_FLAGS="/fsanitize=address /DNDEBUG" -DCMAKE_CXX_FLAGS="/fsanitize=address /DNDEBUG"  -DINSTALL_DOCUMENTATION=OFF -DSWIPL_PACKAGES=OFF 

running just the cpp test from the created CTest, the ASan output is created for the test that causes a SegFault.

% Start unit: cpp
% [1/256] cpp:unwrap ................................ passed (0.062 sec)
% [2/256] cpp:hello ................................. passed (0.000 sec)
% [3/256] cpp:hello ................................. passed (0.000 sec)
% [4/256] cpp:hello ................................. passed (0.000 sec)
% [5/256] cpp:hello2 ................................ passed (0.000 sec)
% [6/256] cpp:hello3 ................................ passed (0.000 sec)
% [7/256] cpp:hello4 ................................ passed (0.000 sec)
% [8/256] cpp:call_cpp .............................. passed (0.000 sec)
% [9/256] cpp:call_cpp .............................. passed (0.001 sec)
% [10/256] cpp:call_cpp ............................. passed (0.000 sec)
% [11/256] cpp:call_cpp ............................. passed (0.000 sec)
% [12/256] cpp:call_cpp ............................. passed (0.000 sec)
% [13/256] cpp:call_cpp ..=================================================================
==165912==ERROR: AddressSanitizer: access-violation on unknown address 0x000000000028 (pc 0x7ffc5b6caecb bp 0x000000000000 sp 0x0066c8ef7160 T0)
==165912==The signal is caused by a READ memory access.
==165912==Hint: address points to the zero page.
    #0 0x7ffc5b6caeca in instr_I_EXITCLEANUP C:\dev\swipl-devel\src\pl-vmi.c:4779
    #1 0x7ffc5b708d58 in PL_next_solution_guarded___LD C:\dev\swipl-devel\src\pl-wam.c:3768
    #2 0x7ffc5b675183 in PL_next_solution___LD C:\dev\swipl-devel\src\pl-wam.c:3578
    #3 0x7ffc5b822fac in callProlog C:\dev\swipl-devel\src\pl-pro.c:529
    #4 0x7ffc5babb50b in pl_with_output_to2_va C:\dev\swipl-devel\src\os\pl-file.c:1814
    #5 0x7ffc5b6c38d8 in instr_I_FCALLDETVA C:\dev\swipl-devel\src\pl-vmi.c:4343
    #6 0x7ffc5b708d58 in PL_next_solution_guarded___LD C:\dev\swipl-devel\src\pl-wam.c:3768
    #7 0x7ffc5b675183 in PL_next_solution___LD C:\dev\swipl-devel\src\pl-wam.c:3578
    #8 0x7ffc5b822fac in callProlog C:\dev\swipl-devel\src\pl-pro.c:529
    #9 0x7ffc5ba2ce8d in pl_with_mutex C:\dev\swipl-devel\src\pl-mutex.c:769
    #10 0x7ffc5b6c48b1 in instr_I_FCALLDET2 C:\dev\swipl-devel\src\pl-vmi.c:4378
    #11 0x7ffc5b708d58 in PL_next_solution_guarded___LD C:\dev\swipl-devel\src\pl-wam.c:3768
    #12 0x7ffc5b675183 in PL_next_solution___LD C:\dev\swipl-devel\src\pl-wam.c:3578
    #13 0x7ffc5b823a73 in query_loop C:\dev\swipl-devel\src\pl-pro.c:171
    #14 0x7ffc5b82385c in prologToplevel C:\dev\swipl-devel\src\pl-pro.c:661
    #15 0x7ffc5b9580f9 in PL_initialise C:\dev\swipl-devel\src\pl-init.c:1524
    #16 0x7ffc5b95896b in PL_winitialise C:\dev\swipl-devel\src\pl-init.c:1295
    #17 0x7ff64b0010cd in wmain C:\dev\swipl-devel\src\pl-main.c:139
    #18 0x7ff64b002898 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:90
    #19 0x7ff64b0027b1 in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #20 0x7ff64b00266d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
    #21 0x7ff64b00290d in wmainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wmain.cpp:16
    #22 0x7ffd0339e8d6  (C:\WINDOWS\System32\KERNEL32.DLL+0x18002e8d6)
    #23 0x7ffd0448c53b  (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18008c53b)

==165912==Register values:
rax = 28  rbx = 0  rcx = 1bf81da3530  rdx = cd91dee79  
rdi = 0  rsi = 0  rbp = 0  rsp = 66c8ef7160  
r8  = 66c8ef73b0  r9  = 66c8ef73c8  r10 = 66c8ef7233  r11 = 6600000000  
r12 = 0  r13 = 0  r14 = 0  r15 = 0  
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: access-violation C:\dev\swipl-devel\src\pl-vmi.c:4779 in instr_I_EXITCLEANUP
==165912==ABORTING

I’ll investigate it in more depth next week.

If I count correctly, that is

test(call_cpp) :-
    call_cpp_ex(unknown_pred(hello(世界四)), Ex),
    assertion(subsumes_term(error(existence_error(procedure, unknown_pred/1), _), Ex)).

That should indeed work fine. Some of the C++ tests test out-of-memory conditions. They suffer from portability issues. This one not. This is the second hint that something is wrong with BFR, the choicepoint associated with a goal. Doesn’t reproduce on Linux (neither on the normal Windows release build).

1 Like

At this point, I have several possible paths forward:

  1. Investigate the bug in more depth.
  2. Address the warnings reported during the build, such as type-related warnings.
  3. Verify that my current fixes work across other targets (Linux, MSYS2, WASM), adding appropriate #ifdefs where necessary.
  4. Build on Windows using GCC.
  5. Learn more about using ASan with MSVC. At the moment this is largely hidden behind CMake, and I do not fully understand what it is doing or what additional options might be available.
  6. Temporarily disable the failing cpp test so that the remaining tests can run, potentially revealing additional issues.

These options are not mutually exclusive; most of them will need to be done eventually. The main question is the order in which they make the most sense.

Right now, I am leaning toward postponing the cpp bug that causes the access violation. Instead, I would first submit the fixes I already have as a pull request so they can be reviewed. That way, when I return to the access violation, I can be more confident that my earlier changes did not obscure or alter the underlying issue.

Now that I know how to obtain ASan output by adding the appropriate option, I am also questioning whether it is worth doing a GCC build at this stage.

My thinking for a plan is:

  1. Disable the failing cpp test so that as many tests as possible can run.
  2. Fix the build warnings, particularly type-related ones.
  3. Ensure that these fixes do not break other builds (MSYS2, Linux, WASM), using #ifdefs where required. (Note, I can not test for MacOS as I do not have a Mac)
  4. Submit a pull request with these fixes.

The ASan-related bug can then be revisited using the updated production code.

Curious as to what @jan and @mgondan1 think. Suggestions welcome.

First of all, at least from the commandline, ctest continues with the other tests after a failing test. The SWI-Prolog test suite is split in about 90 ctest tests. Each of these runs (often) many Prolog tests. If one ctest test crashes hard, the remaining Prolog tests are skipped, but other ctest tests should run.

I think it is wise to share what you have already. Please make sure to pull the latest version as @mgondan1 and I did quite a few type changes. None of these relate to serious bugs though. AFAIK the MSVC compilation was silent except for one invalid shift. That is probably fixed already. That was using an older MSVC version though.

1 Like

Yes, you are correct.

It will take me some time as I really horrible with Git and do not usually do PRs.

Will pull the latest dev version then apply the bug fixes and rerun the CTest.

Do you want them as one large PR or as individual PRs?
If you prefer individual do you want them as I get them ready to submit or wait and send them all at once?

To reproduce eventual problems in MSYS2 (without ASAN): install MSYS2, invoke its clang64 system, then pacman -S mingw-w64-clang-x86_64-swi-prolog-full (this also installs the necessary dependencies for the git version).

To test that version (10.0.0), just invoke swipl and then test_installation. I’ve seen some problems there yesterday.

To test the current git, use cmake -DMSYS2=1 .. and whichever other switches you want. Note that ASAN version only works in the clang64 flavor of MSYS2.

Here are two markdown tables I have been using to keep track of my progress, they were not originally created for others but they will give you a heads up. The first table was bugs originally found without ASan then added ASan to get more details, some are ASan in that list. The second table was created for more bugs that turhed up with ASan.

File Test Suite Test Name Line Modification Type Fixed Fix Order Fix Appendix
tests/thread/test_shared_dynamic.pl N/A N/A N/A File removed from directory :white_check_mark: - Fixed race condition in assertDefinition() - generation values now set before index update. AH
tests/core/test_arith.pl bigint bf_trig_alloc 602 Option: blocked :white_check_mark: - Fixed: malloc/free for BFNTTState, off-by-one in mp_realloc. M
tests/core/test_format.pl format large_float_1 82 Option: blocked :white_check_mark: - Fixed ms_snprintf null-termination bug. AE
tests/core/test_hash.pl term_hash2 simple_3 130 Option: blocked :white_check_mark: - Fixed incorrect pointer arithmetic for indirect data. AF
tests/db/test_db.pl assert cyclic_head 67 Option: blocked :white_check_mark: - Fixed Windows-specific cycle detection threshold. AG
tests/GC/test_agc_copyterm.pl agc_copyterm copy 47 Option: blocked :white_check_mark: - Fixed: test logic bug in check_term (used wrong variable). AD
tests/GC/test_ch_shift.pl N/A N/A N/A File removed from directory :white_check_mark: - Changed Windows depth 5000→1300. Q
tests/library/test_pio.pl read_pending_input utf8 216 Option: blocked :white_check_mark: - Fixed by reducing test chars 1000→500. V
tests/library/test_pio.pl read_pending_input utf16be 218 Option: blocked :white_check_mark: - Fixed by reducing test chars 1000→500. V
tests/library/test_pio.pl read_pending_input utf16le 220 Option: blocked :white_check_mark: - Fixed by reducing test chars 1000→500. V
tests/library/test_pio.pl read_pending_input wchar_t 222 Option: blocked :white_check_mark: - Fixed by reducing test chars 1000→500. V
tests/xsb/sub_tests/xsb_test_sub.pl xsb_sub rrtc8 79 Commented out :white_check_mark: - Fixed uninitialized variable in src/pl-trie.c:2245. R
tests/xsb/sub_tests/xsb_test_sub.pl xsb_sub drtc8 88 Commented out :white_check_mark: - Fixed uninitialized variable in src/pl-trie.c:2245. R
Test # File Test Suite Test Name Line Modification Type Failure Type Root Cause Hypothesis Fix Appendix
2 tests/test.pl testset(term_atom) term_atom 1886 - SEGFAULT Stack overflow in term_atom test set. ASan max depth: 584. Fix: add ASan-aware depth 500 via term_atom_depth/1. :white_check_mark: W
5 tests/db/test_db.pl assert cyclic_head 67 - SEGFAULT Stack overflow in cyclic_head test. Windows CYCLE_CHECK_AT=2700 too high for ASan. Fix: add Windows+ASan specific CYCLE_CHECK_AT=550 in pl-comp.c. :white_check_mark: X
8 tests/tabling/test_tabling.pl tabling_clpfd fib_error 970 - Heap-overflow Heap-buffer-overflow in trie_lookup_abstract() at pl-trie.c:810. Pointer arithmetic underflow when avm-- decrements past buffer base during attvar handling. Fix: add bounds check after avm-- to set avm = NULL when outside buffer. :white_check_mark: Y
14 tests/GC/test_ch_shift.pl N/A N/A 47 File removed from directory SEGFAULT Stack overflow: ASan depth 1000 too high for MSVC+ASan (max 334). Fix: add Windows+ASan specific depth 300. :white_check_mark: Z
22 tests/xsb/delay_tests/tabsimp_seq.P N/A tabsimp_seq - - SEGFAULT Stack overflow: ASan depth 5000 too high for MSVC+ASan (max 3727). Fix: add Windows+ASan specific depth 3300. :white_check_mark: AA
39 packages/clib/test_uri.pl uri, iri, uri_query, uri_authority, uri_encode, uri_edit - - - SEGFAULT DLL unloading issue. under_valgrind() didn’t detect ASan, causing DLLs to unload while TLS destructors still referenced them. :white_check_mark: AB
49 packages/cpp/test_cpp.pl cpp, cpp_atommap, cpp_map_str_str - - - Failed (ASan: SEGFAULT) Stale frame pointers during exception unwinding. environment_frame pointed above lTop (discarded memory). Fixed: Check frame validity (frame <= lTop) in in_foreign_argv() (pl-fli.c:141) and skip assertions in PL_open_query() (pl-wam.c:2901, 2969). :white_check_mark: AC
49b packages/cpp/test_cpp.pl cpp indexOfWord - - ASan: access-violation Issue #3: Use-after-free in indexOfWord() during exception printing. Word contains freed memory pattern (0x98765xxx). Blocked by assertion failure in discardChoicesAfter() at pl-wam.c:2641 for $c_call_prolog/0 frame. :cross_mark: AC
55 packages/http/test_websocket.pl serialization, http - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
57 packages/nlp/test_nlp.pl stem, metaphone, snowball - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
59 packages/pengines/test_pengines.pl local_pengines, remote_pengines, application - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
62 packages/RDF/test_write.pl rdf_write - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
72 packages/sgml/test_sgml.pl (test suites unknown) - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
75 packages/sgml/test_c14n.pl c14n - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB
78 packages/json/test_json.pl json_read, json_convert, json_http - - - SEGFAULT DLL unloading issue. Fixed by under_valgrind() ASan detection fix. :white_check_mark: AB

It depends a little. Surely unrelated patches should be in different commits. I think it is best to just share what you have first. Then we can see. I think one of the problems is that quite a few tests are blocked by the very tight default C stack of Windows. That is normally fixed using some link flag. Maybe that didn’t come through?

A couple of them look serious and worth investigating. I might have a look to see whether Asan works in the cross-compiled version. That might answer whether some problems are Windows or MSVC related. The MSYS-2 version should behave similarly.

edit Asan does not work for GCC on Windows: https://stackoverflow.com/questions/55018627/cannot-find-lasan-using-address-sanitizer-in-mingw-in-windows-mingw

Those tests were unblocked after adjusting the values. If I recall correctly, most—if not all—of them did not expose any real bugs once the value was lowered.

Not that I saw or noticed. It actually took me a few days to realize that the first occurrence of this issue, where the lowered value was used, was not a major error such as a segmentation fault. I initially spent a lot of time checking the code for bugs, only to conclude that the code itself was correct and that the value simply needed to be changed. After that realization, it became much easier to check this first before chasing down potential bugs. A hard lesson to learn, but ultimately worth the effort.


I’m more than happy to help with building, testing, and using ASan—and to use the Visual Studio IDE if that’s helpful in tracking these down. I should note, however, that I don’t have your level of expertise in the low-level details, particularly around the C macros and related internals.


Thanks.


I’m working on that now. Remember, I am horrible with Git, so this will take some time. :slightly_smiling_face:

Ok. It seems the default is not altered. But, MinGW sets the default to 2Mb, while MSVC sets it to 1Mb. That should still be enough to pass the tests (the WASM version also uses 1Mb), but if the system is compiled for debugging and using Asan, the stack frames can be a lot larger. You can verify the stack size using (according to the AI …)

dumpbin /headers swipl.exe

To change, pass -DSWIPL_C_STACK_SIZE=2097152 to CMake for 2Mb (but using debug and Asan it might be better to pass 4 or 8 Mb). Pushed e090099c223d11a4ab1cf699dd84b0603408662e to set the default to 4Mb on Windows if SWIPL_C_STACK_SIZE is not set, regardless of the compiler.

1 Like

The three changes

worked as expected. Most, if not all, of the related adjustments to values that were previously needed to get the tests to pass are no longer required, and the tests are now passing without further value tuning.

The bf_trig_alloc test is still failing. I initially applied a fix, but then noticed that it introduced several additional failures in the table. After removing the fix, those newly introduced failures also disappeared.

Currently building with

cmake .. -G "Visual Studio 18 2026" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake -DSWIPL_PACKAGES_GUI=OFF -DSWIPL_PACKAGES_ARCHIVE=OFF -DSWIPL_PACKAGES_YAML=OFF -DSWIPL_PACKAGES_PYTHON=OFF

and working toward enabling as many packages as possible in order to generate and run the maximum number of CTest cases.