A llvm-mingw built winver.exe with ASan enabled shows below error
when exiting the application.
This seems to be caused by libc++ using register_onexit_function
before ASan has all function hooks in place, therefore allocates
memory with plain calloc function.
On process exit ASan uses in asan_allocator.cpp/Deallocate the
function HeapValidate, which fails if msvcrt does not use the heap
returned by GetProcessHeap().
```
wine64 winver_asan.exe
=================================================================
==292==ERROR: AddressSanitizer: attempting free on address which was not malloc()-ed: 0x7ffffea05a10 in thread T0
0130:fixme:file:server_get_file_info Unsupported info class e
#0 0x6ffffa809fe1 in free .../llvm-mingw/llvm-project/compiler-rt\lib/asan/asan_malloc_win.cpp:71:3
#1 0x6ffffeb048c5 in execute_onexit_table /home/bernhard/wine/dlls/msvcrt\exit.c:141:5
#2 0x6ffffbfb109e in _CRT_INIT .../llvm-mingw/mingw-w64/mingw-w64-crt/build-x86_64\../crt\crtdll.c:130:11
#3 0x6ffffbfb1316 in __DllMainCRTStartup .../llvm-mingw/mingw-w64/mingw-w64-crt/build-x86_64\../crt\crtdll.c:196:6
#4 0x6fffffc6d223 in call_dll_entry_point (C:\windows\system32\ntdll.dll+0x17002d223)
#5 0x6fffffc71fdd in MODULE_InitDLL /home/bernhard/wine/dlls/ntdll\loader.c:1720:16
#6 0x6fffffc72601 in process_detach /home/bernhard/wine/dlls/ntdll\loader.c:1866:13
#7 0x6fffffc726f5 in RtlExitUserProcess /home/bernhard/wine/dlls/ntdll\loader.c:3893:5
#8 0x6fffffa8b899 in ExitProcess /home/bernhard/wine/dlls/kernel32\process.c:207:5
#9 0x6ffffeb054a7 in exit /home/bernhard/wine/dlls/msvcrt\exit.c:383:3
#10 0x000140001338 in mainCRTStartup /home/bernhard/wine/dlls/msvcrt\crt_main.c:60:5
#11 0x6fffffa98d58 in BaseThreadInitThunk /home/bernhard/wine/dlls/kernel32\thread.c:61:5
#12 0x6fffffc95afa in RtlUserThreadStart (C:\windows\system32\ntdll.dll+0x170055afa)
Address 0x7ffffea05a10 is a wild pointer inside of access range of size 0x000000000001.
SUMMARY: AddressSanitizer: bad-free /home/bernhard/wine/dlls/msvcrt\exit.c:141:5 in execute_onexit_table
==292==ABORTING
```
Please provide some guidance if this needs to be separated commits per msvcrt version, and if they are all needed (or more)?
--
v2: msvcrt: Do not create in newer msvcrt versions a separate heap.
https://gitlab.winehq.org/wine/wine/-/merge_requests/6791
This stops GCC from optimizing out a `for` loop inside the `dump_cv_sst_src_module()` function, when tools/winedump is compiled with optimization settings -O1 or higher.
Because the `baseSrcLn` field of the `struct OMFSourceFile` was declared as an array of one element **and it is an interior member** of the structure:
```c
typedef struct OMFSourceFile
{
unsigned short cSeg;
unsigned short reserved;
unsigned int baseSrcLn[1];
unsigned short cFName;
char Name;
} OMFSourceFile;
```
The compiler/optimizer assumes that the `baseSrcLn` array may have only zero or one element. And generates the corresponding code.
The following shows code that GCC 14.2.1 generates before and after this patch.
Before patch:
```
524f: e8 0c ef ff ff call 4160 <printf@plt> # this printf(3)'s "File table: ..."
# r15 stores sourceFile->cSeg; assigned above.
5254: 66 41 83 3c 24 00 cmpw $0x0,(%r12) # r12 is sourceFile
525a: 74 22 je 527e <dump_codeview+0x70e>
525c: 4b 8d 44 bc 04 lea 0x4(%r12,%r15,4),%rax #rax is seg_info_dw
5261: 45 8b 44 24 04 mov 0x4(%r12),%r8d # sourceFile->baseSrcLn[0]
5266: be 01 00 00 00 mov $0x1,%esi
526b: 48 8d 3d fe 02 04 00 lea 0x402fe(%rip),%rdi # 45570
5272: 8b 48 04 mov 0x4(%rax),%ecx
5275: 8b 10 mov (%rax),%edx
5277: 31 c0 xor %eax,%eax
5279: e8 e2 ee ff ff call 4160 <printf@plt>
527e: 41 0f b6 06 movzbl (%r14),%eax # eax = sourceModule + ofs
```
The code checks if the `sourceFile->cSeg` is zero or not, and if not it `printf(3)`s information about the first element in the `baseSrcLn` and first offset pair.
There is no `for` loop there, only its first iteration.
After patch:
```
525c: e8 ff ee ff ff call 4160 <printf@plt> # this printf(3)'s "File table: ..."
# r12 is seg_info_dw and r15 stores integer 1; both assigned above.
# r15 is `i' -- the loop counter.
5261: 66 41 83 3e 00 cmpw $0x0,(%r14) # r14 is sourceFile
5266: 74 37 je 529f <dump_codeview+0x72f>
5268: 0f 1f 84 00 00 00 00 nopl 0x0(%rax,%rax,1)
526f: 00
5270: 43 8b 54 fc f8 mov -0x8(%r12,%r15,8),%edx
5275: 43 8b 4c fc fc mov -0x4(%r12,%r15,8),%ecx
527a: 44 89 fe mov %r15d,%esi
527d: 31 c0 xor %eax,%eax
527f: 47 8b 04 be mov (%r14,%r15,4),%r8d # sourceFile->baseSrcLn[i]
5283: 48 8d 3d e6 02 04 00 lea 0x402e6(%rip),%rdi # 45570
528a: 49 83 c7 01 add $0x1,%r15
528e: e8 cd ee ff ff call 4160 <printf@plt>
5293: 41 0f b7 06 movzwl (%r14),%eax
5297: 41 8d 57 ff lea -0x1(%r15),%edx
529b: 39 c2 cmp %eax,%edx
529d: 7c d1 jl 5270 <dump_codeview+0x700>
529f: 48 8b 44 24 18 mov 0x18(%rsp),%rax # rax = sourceModule + ofs
```
The `for` loop now is where it should be.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/6780
This fixes https://bugs.winehq.org/show_bug.cgi?id=52094.
--
v6: ntdll: Properly track refcount with forwarded exports.
ntdll: Don't re-add a module dependency if it already exists.
ntdll: Remove some NULL checks for current_importer.
ntdll: Set export forwarder DLL as the dynamic importer in LdrGetProcedureAddress().
ntdll: Wrap current_modref variable in a new structure.
https://gitlab.winehq.org/wine/wine/-/merge_requests/7