diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4a04bf9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "src/chronos"] + path = src/chronos + url = https://github.com/datadiode/chronos diff --git a/README.md b/README.md index 500abb3..8638d46 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Visual Leak Detector (Support Visual Studio 2019 16.7) +# Visual Leak Detector (Support Visual Studio 2022 17.12) ## Introduction @@ -18,6 +18,6 @@ We encourage developers who've added their own features, or fixed bugs they've f * [Source code](https://github.com/oneiric/vld) -Copyright © 2005-2021 VLD Team +Copyright © 2005-2025 VLD Team [1]: https://github.com/oneiric/vld/blob/master/COPYING.txt diff --git a/appveyor.yml b/appveyor.yml index e1621f8..657b8e9 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,43 +11,43 @@ environment: GTEST_REPEAT: 1 matrix: - - VldStackWalkMethod: safe - Toolset: v90 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: safe - Toolset: v100 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: safe - Toolset: v110 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: safe - Toolset: v120_xp - Solution: vld_vs14.sln + # - VldStackWalkMethod: safe + # Toolset: v90 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: safe + # Toolset: v100 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: safe + # Toolset: v110 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: safe + # Toolset: v120_xp + # Solution: vld_vs14.sln - VldStackWalkMethod: safe Toolset: v140_xp - Solution: vld_vs14.sln - - - VldStackWalkMethod: fast - Toolset: v90 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: fast - Toolset: v100 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: fast - Toolset: v110 - Solution: vld_vs14_wo_mfc.sln - GTEST_FILTER: -*.Mfc* - - VldStackWalkMethod: fast - Toolset: v120_xp - Solution: vld_vs14.sln + Solution: vld_vs16.sln + + # - VldStackWalkMethod: fast + # Toolset: v90 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: fast + # Toolset: v100 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: fast + # Toolset: v110 + # Solution: vld_vs14_wo_mfc.sln + # GTEST_FILTER: -*.Mfc* + # - VldStackWalkMethod: fast + # Toolset: v120_xp + # Solution: vld_vs14.sln - VldStackWalkMethod: fast Toolset: v140_xp - Solution: vld_vs14.sln + Solution: vld_vs16.sln platform: - Win32 @@ -55,9 +55,9 @@ platform: configuration: - Debug_VldRelease - - Debug_VldRelease_StaticCrt + # - Debug_VldRelease_StaticCrt - Release - - Release_StaticCrt + # - Release_StaticCrt matrix: fast_finish: false @@ -82,7 +82,7 @@ build_script: return } & .\change_toolset.ps1 $env:Toolset - msbuild /v:m /p:"Configuration=$env:CONFIGURATION" /p:Platform="$env:PLATFORM" "$env:Solution" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + msbuild /v:m /p:"Configuration=$env:CONFIGURATION" /p:Platform="$env:PLATFORM" /p:PlatformToolset=$env:Toolset "$env:Solution" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" test_script: - ps: | diff --git a/lib/cppformat/format.vcxproj b/lib/cppformat/format.vcxproj index 34873a8..e9bdca0 100644 --- a/lib/cppformat/format.vcxproj +++ b/lib/cppformat/format.vcxproj @@ -30,7 +30,7 @@ StaticLibrary MultiByte - v142 + v143 diff --git a/lib/gtest/msvc/gtest.vcxproj b/lib/gtest/msvc/gtest.vcxproj index afa595a..7a88721 100644 --- a/lib/gtest/msvc/gtest.vcxproj +++ b/lib/gtest/msvc/gtest.vcxproj @@ -44,7 +44,7 @@ StaticLibrary - v142 + v143 MultiByte diff --git a/setup/version.h b/setup/version.h index 7babd1b..0cc3220 100644 --- a/setup/version.h +++ b/setup/version.h @@ -1,9 +1,5 @@ -#define VLDVERSION L"2.7.0" -#define VERSION_NUMBER 2,7,0,0 -#define VERSION_STRING "2.7.0.0" -#define VERSION_COPYRIGHT "Copyright (C) 2005-2021" - -#ifndef __FILE__ -!define VLD_VERSION "2.7.0" // NSIS Script -#endif +#define VLDVERSION L"2.8.4" +#define VERSION_NUMBER 2,8,4,0 +#define VERSION_STRING "2.8.4.0" +#define VERSION_COPYRIGHT "Copyright (C) 2005-2025" diff --git a/setup/vld-setup.iss b/setup/vld-setup.iss index b192276..c481688 100644 --- a/setup/vld-setup.iss +++ b/setup/vld-setup.iss @@ -2,9 +2,9 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "Visual Leak Detector" -#define MyAppVersion "2.7.0" +#define MyAppVersion "2.8.4" #define MyAppPublisher "VLD Team" -#define MyAppURL "http://vld.codeplex.com/" +#define MyAppURL "https://github.com/oneiric/vld" #define MyAppRegKey "Software\Visual Leak Detector" [Setup] @@ -25,7 +25,7 @@ LicenseFile=license-free.txt OutputBaseFilename=vld-{#MyAppVersion}-setup Compression=lzma SolidCompression=True -MinVersion=0,6.0 +MinVersion=0,6.1 ; Tell Windows Explorer to reload the environment ChangesEnvironment=yes AllowNoIcons=yes @@ -41,16 +41,19 @@ Name: "english"; MessagesFile: "compiler:Default.isl" Name: "{group}\View Documentation"; Filename: "http://vld.codeplex.com/documentation" [Files] +Source: "..\x64\Release\chronos_x64.exe"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion +Source: "..\Release\chronos_x86.exe"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion +Source: "..\src\chronos\LICENSE"; DestDir: "{app}"; DestName: "LICENSE_chronos.txt"; Flags: ignoreversion Source: "dbghelp\x64\dbghelp.dll"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion Source: "dbghelp\x64\Microsoft.DTfW.DHL.manifest"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion Source: "dbghelp\x86\dbghelp.dll"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion Source: "dbghelp\x86\Microsoft.DTfW.DHL.manifest"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion -Source: "..\src\bin\Win32\Release-v142\vld.lib"; DestDir: "{app}\lib\Win32"; Flags: ignoreversion -Source: "..\src\bin\Win32\Release-v142\vld_x86.dll"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion -Source: "..\src\bin\Win32\Release-v142\vld_x86.pdb"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion -Source: "..\src\bin\x64\Release-v142\vld.lib"; DestDir: "{app}\lib\Win64"; Flags: ignoreversion -Source: "..\src\bin\x64\Release-v142\vld_x64.dll"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion -Source: "..\src\bin\x64\Release-v142\vld_x64.pdb"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion +Source: "..\src\bin\Win32\Release-v143\vld.lib"; DestDir: "{app}\lib\Win32"; Flags: ignoreversion +Source: "..\src\bin\Win32\Release-v143\vld_x86.dll"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion +Source: "..\src\bin\Win32\Release-v143\vld_x86.pdb"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion +Source: "..\src\bin\x64\Release-v143\vld.lib"; DestDir: "{app}\lib\Win64"; Flags: ignoreversion +Source: "..\src\bin\x64\Release-v143\vld_x64.dll"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion +Source: "..\src\bin\x64\Release-v143\vld_x64.pdb"; DestDir: "{app}\bin\Win64"; Flags: ignoreversion Source: "..\src\vld.h"; DestDir: "{app}\include"; Flags: ignoreversion Source: "..\src\vld_def.h"; DestDir: "{app}\include"; Flags: ignoreversion Source: "..\vld.ini"; DestDir: "{app}"; Flags: ignoreversion @@ -61,7 +64,7 @@ Source: "..\COPYING.txt"; DestDir: "{app}"; Flags: ignoreversion [Tasks] Name: "modifypath"; Description: "Add VLD directory to your environmental path" Name: "modifyVS2008Props"; Description: "Add VLD directory to VS 2008" -Name: "modifyVS2010Props"; Description: "Add VLD directory to VS 2010 - VS 2019" +Name: "modifyVS2010Props"; Description: "Add VLD directory to VS 2010 - VS 2022" [ThirdParty] UseRelativePaths=True @@ -318,12 +321,28 @@ var StaticLibraryDirectoriesNode: Variant; AdditionalStaticLibraryDirectories: string; begin - if not FileExists(filename) then - Exit; XMLDocument := CreateOleObject('Msxml2.DOMDocument.3.0'); try XMLDocument.async := False; - XMLDocument.load(filename); + XMLDocument.preserveWhiteSpace := True; + if FileExists(filename) then + XMLDocument.load(filename) + else + XMLDocument.loadXML( + ''#13#10 + ''#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ' '#13#10 + ''#13#10); if (XMLDocument.parseError.errorCode = 0) then begin XMLDocument.setProperty('SelectionLanguage', 'XPath'); @@ -426,7 +445,7 @@ var Path: string; begin Path := GetEnv('LOCALAPPDATA')+'\Microsoft\MSBuild\v4.0\'; - if DirExists(Path) then + if ForceDirectories(Path) then begin ModifyProps(Path + 'Microsoft.Cpp.Win32.user.props', 'Win32'); ModifyProps(Path + 'Microsoft.Cpp.x64.user.props', 'Win64'); diff --git a/src/chronos b/src/chronos new file mode 160000 index 0000000..c22e8ec --- /dev/null +++ b/src/chronos @@ -0,0 +1 @@ +Subproject commit c22e8ec2fc9731ebdf2146511972c9a038c4f53d diff --git a/src/dllspatches.cpp b/src/dllspatches.cpp index a997995..d1160ce 100644 --- a/src/dllspatches.cpp +++ b/src/dllspatches.cpp @@ -769,6 +769,16 @@ patchentry_t VisualLeakDetector::m_ntdllPatch [] = { NULL, NULL, NULL }; +patchentry_t VisualLeakDetector::m_winsockPatch [] = { + "socket", NULL, _socket, + "accept", NULL, _accept, + "connect", NULL, _connect, + "closesocket", NULL, _closesocket, + "WSACreateEvent", NULL, _WSACreateEvent, + "WSACloseEvent", NULL, _WSACloseEvent, + NULL, NULL, NULL +}; + patchentry_t VisualLeakDetector::m_ole32Patch [] = { "CoGetMalloc", NULL, _CoGetMalloc, "CoTaskMemAlloc", NULL, _CoTaskMemAlloc, @@ -776,6 +786,13 @@ patchentry_t VisualLeakDetector::m_ole32Patch [] = { NULL, NULL, NULL }; +SSL_CTX_new_t VisualLeakDetector::m_SSL_CTX_new = NULL; + +patchentry_t VisualLeakDetector::m_opensslPatch [] = { + "SSL_CTX_new", (LPVOID*)&m_SSL_CTX_new, _SSL_CTX_new, + NULL, NULL, NULL +}; + moduleentry_t VisualLeakDetector::m_patchTable [] = { // Win32 heap APIs. "kernel32.dll", FALSE, 0x0, m_kernelbasePatch, // we patch this record on Win7 and higher @@ -842,6 +859,12 @@ moduleentry_t VisualLeakDetector::m_patchTable [] = { // NT APIs. "ntdll.dll", FALSE, 0x0, m_ntdllPatch, + // Winsock APIs. + "ws2_32.dll", FALSE, 0x0, m_winsockPatch, + + // OpenSSL APIs. + "libssl-3-x64.dll", FALSE, 0x0, m_opensslPatch, + // COM heap APIs. "ole32.dll", FALSE, 0x0, m_ole32Patch }; diff --git a/src/stdafx.h b/src/stdafx.h index a968c06..c0055fc 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -3,7 +3,8 @@ #include #include #include -#include +#include +#include #if _WIN32_WINNT < 0x0600 // Windows XP or earlier, no GetProcessIdOfThread() #include #endif diff --git a/src/tests/basics/Allocs.cpp b/src/tests/basics/Allocs.cpp index c5f7f2c..2f81697 100644 --- a/src/tests/basics/Allocs.cpp +++ b/src/tests/basics/Allocs.cpp @@ -31,12 +31,8 @@ #define CRTDLLNAME _T("msvcr110d.dll") #elif _MSC_VER == 1800 // VS 2013 #define CRTDLLNAME _T("msvcr120d.dll") -#elif _MSC_VER == 1900 // VS 2015 +#elif _MSC_VER >= 1900 // VS 2015+ #define CRTDLLNAME _T("ucrtbased.dll") -#elif _MSC_VER == 1924 // VS 2019 16.4 -#define CRTDLLNAME _T("ucrtbased.dll") -#elif _MSC_VER == 1927 // VS 2019 16.7 -#define CRTDLLNAME _T("ucrtbase.dll") #else #error Unsupported compiler #endif @@ -59,11 +55,7 @@ #define CRTDLLNAME _T("msvcr110.dll") #elif _MSC_VER == 1800 // VS 2013 #define CRTDLLNAME _T("msvcr120.dll") -#elif _MSC_VER == 1900 // VS 2015 -#define CRTDLLNAME _T("ucrtbase.dll") -#elif _MSC_VER == 1924 // VS 2019 16.4 -#define CRTDLLNAME _T("ucrtbase.dll") -#elif _MSC_VER == 1927 // VS 2019 16.7 +#elif _MSC_VER >= 1900 // VS 2015+ #define CRTDLLNAME _T("ucrtbase.dll") #else #error Unsupported compiler diff --git a/src/tests/basics/basics.vcxproj b/src/tests/basics/basics.vcxproj index e04dcae..82b6080 100644 --- a/src/tests/basics/basics.vcxproj +++ b/src/tests/basics/basics.vcxproj @@ -61,7 +61,7 @@ Application Unicode - v142 + v143 true diff --git a/src/tests/corruption/corruption.vcxproj b/src/tests/corruption/corruption.vcxproj index 13289ad..3f4b14d 100644 --- a/src/tests/corruption/corruption.vcxproj +++ b/src/tests/corruption/corruption.vcxproj @@ -61,7 +61,7 @@ Application Unicode - v142 + v143 true diff --git a/src/tests/dynamic_app/dynamic_app.vcxproj b/src/tests/dynamic_app/dynamic_app.vcxproj index 412621b..e1a0144 100644 --- a/src/tests/dynamic_app/dynamic_app.vcxproj +++ b/src/tests/dynamic_app/dynamic_app.vcxproj @@ -61,7 +61,7 @@ Application Unicode - v142 + v143 true diff --git a/src/tests/dynamic_dll/dynamic.vcxproj b/src/tests/dynamic_dll/dynamic.vcxproj index 51b1d51..06faf29 100644 --- a/src/tests/dynamic_dll/dynamic.vcxproj +++ b/src/tests/dynamic_dll/dynamic.vcxproj @@ -61,7 +61,7 @@ DynamicLibrary Unicode - v142 + v143 true diff --git a/src/tests/mfc/vldmfc.vcxproj b/src/tests/mfc/vldmfc.vcxproj index c063cb1..0cf9d96 100644 --- a/src/tests/mfc/vldmfc.vcxproj +++ b/src/tests/mfc/vldmfc.vcxproj @@ -45,7 +45,7 @@ Application Unicode - v142 + v143 Dynamic diff --git a/src/tests/mfc_dll/mfc.vcxproj b/src/tests/mfc_dll/mfc.vcxproj index bfccd4f..1fbb869 100644 --- a/src/tests/mfc_dll/mfc.vcxproj +++ b/src/tests/mfc_dll/mfc.vcxproj @@ -61,7 +61,7 @@ DynamicLibrary Unicode - v142 + v143 true diff --git a/src/tests/suite/testsuite.cpp b/src/tests/suite/testsuite.cpp index d87d975..452b56b 100644 --- a/src/tests/suite/testsuite.cpp +++ b/src/tests/suite/testsuite.cpp @@ -69,12 +69,8 @@ enum action_e { #define CRTDLLNAME _T("msvcr110d.dll") #elif _MSC_VER == 1800 // VS 2013 #define CRTDLLNAME _T("msvcr120d.dll") -#elif _MSC_VER == 1900 // VS 2015 +#elif _MSC_VER >= 1900 // VS 2015+ #define CRTDLLNAME _T("ucrtbased.dll") -#elif _MSC_VER == 1924 // VS 2019 -#define CRTDLLNAME _T("ucrtbased.dll") -#elif _MSC_VER == 1927 // VS 2019 16.7 -#define CRTDLLNAME _T("ucrtbase.dll") #else #error Unsupported compiler #endif @@ -97,11 +93,7 @@ enum action_e { #define CRTDLLNAME _T("msvcr110.dll") #elif _MSC_VER == 1800 // VS 2013 #define CRTDLLNAME _T("msvcr120.dll") -#elif _MSC_VER == 1900 // VS 2015 -#define CRTDLLNAME _T("ucrtbase.dll") -#elif _MSC_VER == 1924 // VS 2019 16.4 -#define CRTDLLNAME _T("ucrtbase.dll") -#elif _MSC_VER == 1927 // VS 2019 16.7 +#elif _MSC_VER >= 1900 // VS 2015+ #define CRTDLLNAME _T("ucrtbase.dll") #else #error Unsupported compiler diff --git a/src/tests/suite/testsuite.vcxproj b/src/tests/suite/testsuite.vcxproj index 20d1ae6..8e77d65 100644 --- a/src/tests/suite/testsuite.vcxproj +++ b/src/tests/suite/testsuite.vcxproj @@ -60,7 +60,7 @@ Application NotSet - v142 + v143 diff --git a/src/tests/vld_ComTest/ComTest_vs14.vcxproj b/src/tests/vld_ComTest/ComTest_vs14.vcxproj index 318f01a..88bf2a4 100644 --- a/src/tests/vld_ComTest/ComTest_vs14.vcxproj +++ b/src/tests/vld_ComTest/ComTest_vs14.vcxproj @@ -61,7 +61,7 @@ DynamicLibrary Unicode - v142 + v143 true diff --git a/src/tests/vld_dll1/vld_dll1_vs14.vcxproj b/src/tests/vld_dll1/vld_dll1_vs14.vcxproj index f57ece7..a3af339 100644 --- a/src/tests/vld_dll1/vld_dll1_vs14.vcxproj +++ b/src/tests/vld_dll1/vld_dll1_vs14.vcxproj @@ -60,7 +60,7 @@ DynamicLibrary - v142 + v143 Unicode diff --git a/src/tests/vld_dll2/vld_dll2_vs14.vcxproj b/src/tests/vld_dll2/vld_dll2_vs14.vcxproj index 2110a7a..841df15 100644 --- a/src/tests/vld_dll2/vld_dll2_vs14.vcxproj +++ b/src/tests/vld_dll2/vld_dll2_vs14.vcxproj @@ -60,7 +60,7 @@ DynamicLibrary - v142 + v143 Unicode diff --git a/src/tests/vld_main/vld_main_vs14.vcxproj b/src/tests/vld_main/vld_main_vs14.vcxproj index 3f4b8aa..a1361c3 100644 --- a/src/tests/vld_main/vld_main_vs14.vcxproj +++ b/src/tests/vld_main/vld_main_vs14.vcxproj @@ -60,7 +60,7 @@ Application - v142 + v143 Unicode diff --git a/src/tests/vld_main_test/vld_main_test_vs14.vcxproj b/src/tests/vld_main_test/vld_main_test_vs14.vcxproj index 6bd4efc..f8ab85c 100644 --- a/src/tests/vld_main_test/vld_main_test_vs14.vcxproj +++ b/src/tests/vld_main_test/vld_main_test_vs14.vcxproj @@ -60,7 +60,7 @@ Application - v142 + v143 Unicode diff --git a/src/tests/vld_unload/vld_unload_vs14.vcxproj b/src/tests/vld_unload/vld_unload_vs14.vcxproj index 2078498..a29e886 100644 --- a/src/tests/vld_unload/vld_unload_vs14.vcxproj +++ b/src/tests/vld_unload/vld_unload_vs14.vcxproj @@ -60,7 +60,7 @@ Application - v142 + v143 Unicode diff --git a/src/vld.cpp b/src/vld.cpp index a37d9ce..20733e9 100644 --- a/src/vld.cpp +++ b/src/vld.cpp @@ -349,6 +349,7 @@ VisualLeakDetector::VisualLeakDetector () m_options = 0x0; m_reportFile = NULL; wcsncpy_s(m_reportFilePath, MAX_PATH, VLD_DEFAULT_REPORT_FILE_NAME, _TRUNCATE); + wcsncpy_s(m_sslkeyFilePath, MAX_PATH, VLD_DEFAULT_SSLKEY_FILE_NAME, _TRUNCATE); m_status = 0x0; HMODULE ntdll = GetModuleHandleW(L"ntdll.dll"); @@ -866,19 +867,11 @@ VOID VisualLeakDetector::attachToLoadedModules (ModuleSet *newmodules) { // This module does not import VLD. This means that none of the module's // sources #included vld.h. - if ((m_options & VLD_OPT_MODULE_LIST_INCLUDE) != 0) + const BOOL match = PathMatchSpecW(modulename, m_forcedModuleList); + if ((m_options & VLD_OPT_MODULE_LIST_INCLUDE) != (match ? VLD_OPT_MODULE_LIST_INCLUDE : 0)) { - if (wcsstr(m_forcedModuleList, modulename) == NULL) { - // Exclude this module from leak detection. - moduleFlags |= VLD_MODULE_EXCLUDED; - } - } - else - { - if (wcsstr(m_forcedModuleList, modulename) != NULL) { - // Exclude this module from leak detection. - moduleFlags |= VLD_MODULE_EXCLUDED; - } + // Exclude this module from leak detection. + moduleFlags |= VLD_MODULE_EXCLUDED; } } } @@ -1169,6 +1162,14 @@ VOID VisualLeakDetector::configure () WCHAR* path = _wfullpath(m_reportFilePath, filename, MAX_PATH); assert(path); + // Read the SSL key file location. + LoadStringOption(L"SSLKeyFile", filename, MAX_PATH, inipath); + if (filename[0] == '\0') { + wcsncpy_s(filename, MAX_PATH, VLD_DEFAULT_SSLKEY_FILE_NAME, _TRUNCATE); + } + path = _wfullpath(m_sslkeyFilePath, filename, MAX_PATH); + assert(path); + LoadStringOption(L"ReportTo", buffer, buffersize, inipath); if (_wcsicmp(buffer, L"both") == 0) { m_options |= (VLD_OPT_REPORT_TO_DEBUGGER | VLD_OPT_REPORT_TO_FILE); @@ -1358,6 +1359,7 @@ VOID VisualLeakDetector::mapBlock (HANDLE heap, LPCVOID mem, SIZE_T size, bool d blockinfo->reported = false; blockinfo->debugCrtAlloc = debugcrtalloc; blockinfo->ucrt = ucrt; + blockinfo->resource = IS_INTRESOURCE(heap); if (SIZE_MAX - m_totalAlloc > size) m_totalAlloc += size; @@ -1680,6 +1682,9 @@ VOID VisualLeakDetector::reportConfig () bool VisualLeakDetector::isDebugCrtAlloc( LPCVOID block, blockinfo_t* info ) { + if (info->resource) + return false; + // Autodetection allocations from statically linked CRT if (!info->debugCrtAlloc) { crtdbgblockheader_t* crtheader = (crtdbgblockheader_t*)block; @@ -1916,7 +1921,7 @@ SIZE_T VisualLeakDetector::reportLeaks (heapinfo_t* heapinfo, bool &firstLeak, S info->callStack->dump(m_options & VLD_OPT_TRACE_INTERNAL_FRAMES); // Dump the data in the user data section of the memory block. - if (m_maxDataDump != 0) { + if (m_maxDataDump != 0 && size != 0) { Report(L" Data:\n"); if (m_options & VLD_OPT_UNICODE_REPORT) { DumpMemoryW(address, (m_maxDataDump < size) ? m_maxDataDump : size); @@ -2099,6 +2104,14 @@ BOOL VisualLeakDetector::detachFromModule (PCWSTR /*modulepath*/, DWORD64 module return TRUE; } +void VisualLeakDetector::SSL_CTX_keylog_cb_func(const void* ssl_ctx, const char* line) +{ + if (FILE *sslkeyFile = _wfsopen(g_vld.m_sslkeyFilePath, L"a", _SH_DENYNO)) { + fprintf(sslkeyFile, "%s\n", line); + fclose(sslkeyFile); + } +} + //////////////////////////////////////////////////////////////////////////////// // // Win32 IAT Replacement Functions diff --git a/src/vld.vcxproj b/src/vld.vcxproj index ae0c939..1e375f1 100644 --- a/src/vld.vcxproj +++ b/src/vld.vcxproj @@ -32,7 +32,7 @@ - v142 + v143 @@ -88,7 +88,7 @@ 4201;4229;4091;4302;4311;4312;4127 - psapi.lib;%(AdditionalDependencies) + shlwapi.lib;ws2_32.lib;%(AdditionalDependencies) Windows @@ -107,7 +107,7 @@ false - psapi.lib;%(AdditionalDependencies) + shlwapi.lib;ws2_32.lib;%(AdditionalDependencies) Windows @@ -135,6 +135,7 @@ true true Windows + shlwapi.lib;ws2_32.lib;%(AdditionalDependencies) vld.dll.dependency.x86.manifest @@ -160,6 +161,7 @@ true true Windows + shlwapi.lib;ws2_32.lib;%(AdditionalDependencies) vld.dll.dependency.x64.manifest diff --git a/src/vld_hooks.cpp b/src/vld_hooks.cpp index 314e99c..436f48a 100644 --- a/src/vld_hooks.cpp +++ b/src/vld_hooks.cpp @@ -42,6 +42,11 @@ extern HANDLE g_currentProcess; extern CriticalSection g_heapMapLock; extern DbgHelp g_DbgHelp; +// Heap handles are pointers, hence disjunct from numbers below 65536, which +// hence can serve as pseudo heap handles for tracking non-memory resources. +#define VLD_SOCKET_RESOURCE MAKEINTRESOURCE(1) +#define VLD_WSAEVENT_RESOURCE MAKEINTRESOURCE(2) + //////////////////////////////////////////////////////////////////////////////// // // Debug CRT and MFC IAT Replacement Functions @@ -298,6 +303,198 @@ LPVOID VisualLeakDetector::_HeapReAlloc (HANDLE heap, DWORD flags, LPVOID mem, S return newmem; } +//////////////////////////////////////////////////////////////////////////////// +// +// Winsock IAT Replacement Functions +// +//////////////////////////////////////////////////////////////////////////////// + +// _socket - Calls to socket are patched through to this function. +// This function invokes the real socket and then calls VLD's allocation +// tracking function with a pseudo heap handle of value VLD_SOCKET_RESOURCE. +// +// Return Value: +// +// Returns the return value from socket. +// +SOCKET VisualLeakDetector::_socket (int af, int type, int protocol) +{ + PRINT_HOOKED_FUNCTION2(); + // Allocate the resource. + SOCKET s = socket(af, type, protocol); + + if ((s == INVALID_SOCKET) || !g_vld.enabled()) + return s; + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + CAPTURE_CONTEXT(); + CaptureContext cc(socket, context_); + cc.Set(VLD_SOCKET_RESOURCE, reinterpret_cast(s), NULL, 0); + } + + return s; +} + +// _accept - Calls to accept are patched through to this function. +// This function invokes the real accept and then calls VLD's allocation +// tracking function with a pseudo heap handle of value VLD_SOCKET_RESOURCE. +// +// Return Value: +// +// Returns the return value from accept. +// +SOCKET VisualLeakDetector::_accept (SOCKET s, struct sockaddr *addr, int *addrlen) +{ + PRINT_HOOKED_FUNCTION2(); + // Allocate the resource. + s = accept(s, addr, addrlen); + + if ((s == INVALID_SOCKET) || !g_vld.enabled()) + return s; + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + CAPTURE_CONTEXT(); + CaptureContext cc(accept, context_); + cc.Set(VLD_SOCKET_RESOURCE, reinterpret_cast(s), NULL, 0); + } + + return s; +} + +// _connect - Calls to connect are patched through to this function. +// This function invokes the real connect and then calls VLD's allocation +// tracking function with a pseudo heap handle of value VLD_SOCKET_RESOURCE. +// +// Return Value: +// +// Returns the return value from connect. +// +SOCKET VisualLeakDetector::_connect (SOCKET s, const struct sockaddr *name, int namelen) +{ + PRINT_HOOKED_FUNCTION2(); + // Allocate the resource. + s = connect(s, name, namelen); + + if ((s == INVALID_SOCKET) || !g_vld.enabled()) + return s; + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + CAPTURE_CONTEXT(); + CaptureContext cc(connect, context_); + cc.Set(VLD_SOCKET_RESOURCE, reinterpret_cast(s), NULL, 0); + } + + return s; +} + +// _closesocket - Calls to closesocket are patched through to this function. +// This function calls VLD's free tracking function with a pseudo heap handle +// of value VLD_SOCKET_RESOURCE and then invokes the real closesocket. +// +// Return Value: +// +// Returns the value returned by closesocket. +// +int VisualLeakDetector::_closesocket (SOCKET s) +{ + PRINT_HOOKED_FUNCTION2(); + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + // Record the current frame pointer. + CAPTURE_CONTEXT(); + context_.func = reinterpret_cast(closesocket); + + // Unmap the resource from the specified pseudo heap. + g_vld.unmapBlock(VLD_SOCKET_RESOURCE, reinterpret_cast(s), context_); + } + + return closesocket(s); +} + +// _WSACreateEvent - Calls to WSACreateEvent are patched through to this +// function. This function invokes the real WSACreateEvent and then calls +// VLD's allocation tracking function with a pseudo heap handle of value +// VLD_HANDLE_RESOURCE. +// +// Return Value: +// +// Returns the return value from WSACreateEvent. +// +WSAEVENT VisualLeakDetector::_WSACreateEvent () +{ + PRINT_HOOKED_FUNCTION2(); + // Allocate the resource. + WSAEVENT hEvent = WSACreateEvent(); + + if ((hEvent == WSA_INVALID_EVENT) || !g_vld.enabled()) + return hEvent; + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + CAPTURE_CONTEXT(); + CaptureContext cc(WSACreateEvent, context_); + cc.Set(VLD_WSAEVENT_RESOURCE, hEvent, NULL, 0); + } + + return hEvent; +} + +// _WSACloseEvent - Calls to WSACloseEvent are patched through to this function. +// This function calls VLD's free tracking function with a pseudo heap handle +// of value VLD_HANDLE_RESOURCE and then invokes the real WSACloseEvent. +// +// Return Value: +// +// Returns the value returned by WSACloseEvent. +// +BOOL VisualLeakDetector::_WSACloseEvent (WSAEVENT hEvent) +{ + PRINT_HOOKED_FUNCTION2(); + + if (!g_DbgHelp.IsLockedByCurrentThread()) // skip dbghelp.dll calls + { + // Record the current frame pointer. + CAPTURE_CONTEXT(); + context_.func = reinterpret_cast(WSACloseEvent); + + // Unmap the resource from the specified pseudo heap. + g_vld.unmapBlock(VLD_WSAEVENT_RESOURCE, hEvent, context_); + } + + return WSACloseEvent(hEvent); +} + +// _SSL_CTX_new - Calls to SSL_CTX_new are patched through to this function. +// This function calls the real SSL_CTX_new and then sets a keylog callback. +// +// Return Value: +// +// Returns the value returned by SSL_CTX_new. +// +void* VisualLeakDetector::_SSL_CTX_new (void* ctx) +{ + PRINT_HOOKED_FUNCTION2(); + + static SSL_CTX_set_keylog_callback_t pSSL_CTX_set_keylog_callback = NULL; + + if (pSSL_CTX_set_keylog_callback == NULL) { + // This is the first call to this function. Link to the real SSL_CTX_set_keylog_callback + HMODULE libssl = GetModuleHandleW(L"libssl-3-x64.dll"); + pSSL_CTX_set_keylog_callback = (SSL_CTX_set_keylog_callback_t)g_vld._RGetProcAddress(libssl, "SSL_CTX_set_keylog_callback"); + } + + LPVOID ssl_ctx = m_SSL_CTX_new(ctx); + if (ssl_ctx) + { + pSSL_CTX_set_keylog_callback(ssl_ctx, SSL_CTX_keylog_cb_func); + } + return ssl_ctx; +} + //////////////////////////////////////////////////////////////////////////////// // // COM IAT Replacement Functions diff --git a/src/vldint.h b/src/vldint.h index 05cec20..07e4ef9 100644 --- a/src/vldint.h +++ b/src/vldint.h @@ -68,6 +68,10 @@ typedef BOOL(__stdcall *HeapFree_t) (HANDLE, DWORD, LPVOID); typedef FARPROC(__stdcall *GetProcAddress_t) (HMODULE, LPCSTR); typedef FARPROC(__stdcall *GetProcAddressForCaller_t) (HMODULE, LPCSTR, LPVOID); +typedef void (__cdecl *SSL_CTX_keylog_cb_func_t)(const void *, const char *); +typedef void* (__cdecl *SSL_CTX_new_t) (void*); +typedef void (__cdecl *SSL_CTX_set_keylog_callback_t) (void*, SSL_CTX_keylog_cb_func_t); + typedef void* (__cdecl *_calloc_dbg_t) (size_t, size_t, int, const char*, int); typedef void* (__cdecl *_malloc_dbg_t) (size_t, int, const char *, int); typedef void* (__cdecl *_realloc_dbg_t) (void *, size_t, int, const char *, int); @@ -111,6 +115,7 @@ struct blockinfo_t { bool reported; bool debugCrtAlloc; bool ucrt; + bool resource; }; // BlockMaps map memory blocks (via their addresses) to blockinfo_t structures. @@ -321,6 +326,7 @@ class VisualLeakDetector : public IMalloc // Static functions (callbacks) static BOOL __stdcall addLoadedModule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context); static BOOL __stdcall detachFromModule (PCWSTR modulepath, DWORD64 modulebase, ULONG modulesize, PVOID context); + static void __cdecl SSL_CTX_keylog_cb_func(const void* ssl_ctx, const char* line); // Utils static bool isModuleExcluded (UINT_PTR returnaddress); @@ -353,6 +359,17 @@ class VisualLeakDetector : public IMalloc static BYTE __stdcall _RtlFreeHeap (HANDLE heap, DWORD flags, LPVOID mem); static LPVOID __stdcall _RtlReAllocateHeap (HANDLE heap, DWORD flags, LPVOID mem, SIZE_T size); + // Winsock IAT replacement functions + static SOCKET __stdcall _socket (int af, int type, int protocol); + static SOCKET __stdcall _accept (SOCKET s, struct sockaddr *addr, int *addrlen); + static SOCKET __stdcall _connect (SOCKET s, const struct sockaddr *name, int namelen); + static int __stdcall _closesocket (SOCKET s); + static WSAEVENT __stdcall _WSACreateEvent (); + static BOOL __stdcall _WSACloseEvent (WSAEVENT hEvent); + + // OpenSSL replacement functions + static void* __cdecl _SSL_CTX_new (void*); + // COM IAT replacement functions static HRESULT __stdcall _CoGetMalloc (DWORD context, LPMALLOC *imalloc); static LPVOID __stdcall _CoTaskMemAlloc (SIZE_T size); @@ -379,10 +396,13 @@ class VisualLeakDetector : public IMalloc static patchentry_t m_kernelbasePatch []; static patchentry_t m_kernel32Patch []; static patchentry_t m_ntdllPatch []; + static patchentry_t m_winsockPatch []; + static patchentry_t m_opensslPatch []; static patchentry_t m_ole32Patch []; - static moduleentry_t m_patchTable [58]; // Table of imports patched for attaching VLD to other modules. + static moduleentry_t m_patchTable [60]; // Table of imports patched for attaching VLD to other modules. FILE *m_reportFile; // File where the memory leak report may be sent to. WCHAR m_reportFilePath [MAX_PATH]; // Full path and name of file to send memory leak report to. + WCHAR m_sslkeyFilePath [MAX_PATH]; // Full path and name of sslkeylogfile. const char *m_selfTestFile; // Filename where the memory leak self-test block is leaked. int m_selfTestLine; // Line number where the memory leak self-test block is leaked. UINT32 m_status; // Status flags: @@ -402,6 +422,7 @@ class VisualLeakDetector : public IMalloc static GetProcessHeap_t m_GetProcessHeap; static HeapCreate_t m_HeapCreate; static HeapFree_t m_HeapFree; + static SSL_CTX_new_t m_SSL_CTX_new; }; @@ -409,3 +430,4 @@ class VisualLeakDetector : public IMalloc #define VLD_DEFAULT_MAX_DATA_DUMP 256 #define VLD_DEFAULT_MAX_TRACE_FRAMES 64 #define VLD_DEFAULT_REPORT_FILE_NAME L".\\memory_leak_report.txt" +#define VLD_DEFAULT_SSLKEY_FILE_NAME L".\\sslkeys.log" diff --git a/vld_vs16.sln b/vld_vs16.sln index 0caa557..7216850 100644 --- a/vld_vs16.sln +++ b/vld_vs16.sln @@ -71,6 +71,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vld_main_test", "src\tests\ {8C732490-DC1A-40C0-923F-1555B9141B80} = {8C732490-DC1A-40C0-923F-1555B9141B80} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "chronos", "src\chronos\chronos.vcxproj", "{3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_StaticCrt|Win32 = Debug_StaticCrt|Win32 @@ -472,6 +474,30 @@ Global {BB99EDE9-D039-4169-B26B-6BFD93C6AF8E}.Release|Win32.Build.0 = Release|Win32 {BB99EDE9-D039-4169-B26B-6BFD93C6AF8E}.Release|x64.ActiveCfg = Release|x64 {BB99EDE9-D039-4169-B26B-6BFD93C6AF8E}.Release|x64.Build.0 = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_StaticCrt|Win32.ActiveCfg = Debug|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_StaticCrt|Win32.Build.0 = Debug|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_StaticCrt|x64.ActiveCfg = Debug|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_StaticCrt|x64.Build.0 = Debug|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease_StaticCrt|Win32.ActiveCfg = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease_StaticCrt|Win32.Build.0 = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease_StaticCrt|x64.ActiveCfg = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease_StaticCrt|x64.Build.0 = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease|Win32.ActiveCfg = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease|Win32.Build.0 = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease|x64.ActiveCfg = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug_VldRelease|x64.Build.0 = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug|Win32.ActiveCfg = Debug|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug|Win32.Build.0 = Debug|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug|x64.ActiveCfg = Debug|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Debug|x64.Build.0 = Debug|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release_StaticCrt|Win32.ActiveCfg = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release_StaticCrt|Win32.Build.0 = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release_StaticCrt|x64.ActiveCfg = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release_StaticCrt|x64.Build.0 = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release|Win32.ActiveCfg = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release|Win32.Build.0 = Release|Win32 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release|x64.ActiveCfg = Release|x64 + {3DB94AD0-4960-4D71-B10A-F3A56AEA4C5D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE