Learn how easy it is to sync an existing GitHub or Google Code repo to a SourceForge project! See Demo

Close

#1928 CRT calls TlsFree before TlsGetValue, leading to racy accesses and leaks

WSL
assigned
Earnie Boyd
Bug
none
Waiting_User_Response
False
2014-07-03
2013-02-20
Derek Bruening
No

Running Dr. Memory (http://code.google.com/p/drmemory/) on this simple
program:

#include <iostream>
int main() 
{
    try {
        std::cout << "throwing exception" << std::endl;
        throw std::exception();
    } catch (std::exception&) {
        std::cout << "caught exception" << std::endl;
    }
    return 0;
}

Results in two error reports, one "UNADDRESSABLE ACCESS" and one memory
leak. These are detailed in these two Dr. Memory issue tracker entries:

http://code.google.com/p/drmemory/issues/detail?id=1043
http://code.google.com/p/drmemory/issues/detail?id=1134

I tried with the latest mingw and the same errors are present.

% /c/mingw/bin/g++ -v
Using built-in specs.
COLLECT_GCC=C:\mingw\bin\g++.exe
COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.7.2/lto-wrapper.exe
Target: mingw32
Configured with: ../gcc-4.7.2/configure --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --disable-build-poststage1-with-cxx --enable-version-specific-runtime-libs --build=mingw32 --prefix=/mingw
Thread model: win32
gcc version 4.7.2 (GCC)
% /c/mingw/bin/ld -v
GNU ld (GNU Binutils) 2.23.1
% uname -a
CYGWIN_NT-6.1-WOW64 kraken 1.7.16(0.262/5/3) 2012-07-20 22:55 i686 Cygwin

I'm on Windows 7 Ultimate 6.1.7601 Service Pack 1 Build 7601

I built like this:
% /c/mingw/bin/g++ -static-libgcc -static-libstdc++ -ggdb -mthreads -o cppexcept-mingw.exe cppexcept.cpp

I ran Dr. Memory like this:
% ~/drmemory/releases/DrMemory-Windows-1.5.0-5/bin/drmemory.exe -batch -- ./cppexcept-mingw.exe

The -mthreads makes no difference in whether the bugs are reported.

At the Dr. Memory team we believe, after looking at the mingw and gcc sources, that these two errors both stem from the TlsFree being called too early. See the two Dr. Memory issue links above for further information.

Discussion

  • Derek Bruening
    Derek Bruening
    2013-02-20

    I'm pasting in the Dr. Memory errors here for easier reference:

    Error #1: UNADDRESSABLE ACCESS: reading 0x7efdde1c-0x7efdde20 4 byte(s)
    # 0 KERNELBASE.dll!TlsGetValue   
    # 1 __mingwthr_run_key_dtors               [/usr/src/mingw-runtime/mingw-runtime-3.20-1/src/mingwrt-3.20-mingw32/tlsthrd.c:108]
    # 2 __mingw_TLScallback                    [/usr/src/mingw-runtime/mingw-runtime-3.20-1/src/mingwrt-3.20-mingw32/tlsthrd.c:133]
    # 3 __dyn_tls_dtor@12                      [/usr/src/mingw-runtime/mingw-runtime-3.20-1/src/mingwrt-3.20-mingw32/tlssup.c:170]
    # 4 ntdll.dll!LdrpCallInitRoutine
    # 5 ntdll.dll!LdrpCallTlsInitializers
    # 6 ntdll.dll!LdrShutdownProcess
    # 7 ntdll.dll!RtlExitUserProcess
    # 8 KERNEL32.dll!ExitProcessStub
    # 9 __mingw_CRTStartup                     [/usr/src/mingw-runtime/mingw-runtime-3.20-1/src/mingwrt-3.20-mingw32/crt1.c:252]
    #10 mainCRTStartup                         [/usr/src/mingw-runtime/mingw-runtime-3.20-1/src/mingwrt-3.20-mingw32/crt1.c:264]
    #11 KERNEL32.dll!BaseThreadInitThunk
    Note: @0:00:00.577 in thread 6616
    Note: instruction: mov    0x00000e10(%eax,%ecx,4) -> %eax
    
    Error #2: LEAK 8 direct bytes 0x003420b8-0x003420c0 + 0 indirect bytes
    # 0 __cxa_get_globals                      [/usr/src/packages/mingw-gcc/mingw-gcc-4.5.2-1/src/gcc-4.5.2/libstdc++-v3/libsupc++/eh_globals.cc:132]
    # 1 __cxa_allocate_exception               [/usr/src/packages/mingw-gcc/mingw-gcc-4.5.2-1/src/gcc-4.5.2/libstdc++-v3/libsupc++/eh_alloc.cc:132]
    # 2 test_exception()                       [/d/derek/dr/test/cppexcept.cpp:30]
    # 3 main                                   [/d/derek/dr/test/cppexcept.cpp:38]
    
    ERRORS FOUND:
          1 unique,     1 total unaddressable access(es)
          0 unique,     0 total uninitialized access(es)
          0 unique,     0 total invalid heap argument(s)
          0 unique,     0 total GDI usage error(s)
          0 unique,     0 total warning(s)
          1 unique,     1 total,      8 byte(s) of leak(s)
          0 unique,     0 total,      0 byte(s) of possible leak(s)
    
     
  • Earnie Boyd
    Earnie Boyd
    2013-02-20

    • labels: --> duplicate?, tls
    • status: unread --> assigned
    • assigned_to: Earnie Boyd
    • category: Unknown --> Waiting_User_Response
     
  • Earnie Boyd
    Earnie Boyd
    2013-02-20

    Can you run your tests on the current repository 4.0-dev branch code please?

     
    Last edit: Earnie Boyd 2013-02-20
  • Derek Bruening
    Derek Bruening
    2013-02-20

    Can you run your tests on the current repository 4.0-dev branch code please?

    Hmmm, I've been using binary releases of mingw. I can try to make some time to build mingw from the latest sources.

    Note that it may be simpler and faster, if you have the latest mingw already built, to grab Dr. Memory from http://code.google.com/p/drmemory/downloads/list and run it on the tiny app in the original entry above. We have built-in DWARF2 mingw symbol support and perhaps our tool could be useful to your project (it's essentially "Valgrind Memcheck for Windows").

     
  • Derek Bruening
    Derek Bruening
    2013-02-20

    Sorry, I just discovered that the g++ 4.7.2 was failing to compile (the installation BIN was not on the path so it failed to find
    libgmp-10.dll, etc., with a silent error in a non-cmd window) and I was running the 4.5.2-built executable while verifying it also happened w/ 4.7.2.

    g++ 4.5.2 is where we observed this bug. It is not present on 4.7.2.

    This can be resolved.