Skip to content

Commit 37bd17f

Browse files
authored
Fix null pointer dereference in weak_ref::get() (#1232)
1 parent d81ec9f commit 37bd17f

File tree

5 files changed

+38
-13
lines changed

5 files changed

+38
-13
lines changed

.github/workflows/ci.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ jobs:
278278
strategy:
279279
matrix:
280280
arch: [i686, x86_64]
281+
config: [Debug, Release]
281282
runs-on: windows-latest
282283
steps:
283284
- uses: actions/checkout@v3
@@ -290,12 +291,21 @@ jobs:
290291
rm llvm-mingw.zip
291292
if (!(Test-Path "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin\clang++.exe")) { return 1 }
292293
Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\bin"
294+
# for the ASAN runtime DLL:
295+
Add-Content $env:GITHUB_PATH "$pwd\llvm-mingw-${llvm_mingw_version}-ucrt-${{ matrix.arch }}\${{ matrix.arch }}-w64-mingw32\bin"
293296
294297
- name: Build cppwinrt
295298
run: |
296299
mkdir build
297300
cd build
298-
cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug -DDOWNLOAD_WINDOWSNUMERICS=TRUE
301+
if ("${{ matrix.config }}" -eq "Debug") {
302+
$sanitizers = "TRUE"
303+
} else {
304+
$sanitizers = "FALSE"
305+
}
306+
cmake ../ -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=${{ matrix.config }} `
307+
-DDOWNLOAD_WINDOWSNUMERICS=TRUE `
308+
-DENABLE_TEST_SANITIZERS=$sanitizers
299309
cmake --build . -j2 --target cppwinrt
300310
301311
- name: Upload cppwinrt.exe
@@ -318,6 +328,7 @@ jobs:
318328
- name: Run tests
319329
run: |
320330
cd build
331+
$env:UBSAN_OPTIONS = "print_stacktrace=1"
321332
ctest --verbose
322333
323334
build-msvc-natvis:

strings/base_weak_ref.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ WINRT_EXPORT namespace winrt
2323
{
2424
impl::com_ref<default_interface<T>> temp;
2525
m_ref->Resolve(guid_of<T>(), put_abi(temp));
26-
void* result = get_self<T>(temp);
27-
detach_abi(temp);
26+
void* result = nullptr;
27+
if (temp) {
28+
result = get_self<T>(temp);
29+
detach_abi(temp);
30+
}
2831
return impl::com_ref<T>{ result, take_ownership_from_abi };
2932
}
3033
else

test/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ add_custom_target(build-cppwinrt-projection
6565
)
6666

6767

68+
set(ENABLE_TEST_SANITIZERS FALSE CACHE BOOL "Enable ASan and UBSan for the tests.")
69+
if(ENABLE_TEST_SANITIZERS)
70+
# Disable the 'vptr' check because it seems to produce false-positives when using COM classes.
71+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,address -fno-sanitize=vptr")
72+
endif()
73+
74+
6875
add_subdirectory(test)
6976
add_subdirectory(test_cpp20)
7077
add_subdirectory(test_win7)

test/catch.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10807,7 +10807,7 @@ namespace Catch {
1080710807
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
1080810808
};
1080910809

10810-
static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
10810+
static LONG CALLBACK topLevelExceptionFilter(PEXCEPTION_POINTERS ExceptionInfo) {
1081110811
for (auto const& def : signalDefs) {
1081210812
if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
1081310813
reportFatal(def.name);
@@ -10821,7 +10821,7 @@ namespace Catch {
1082110821
// Since we do not support multiple instantiations, we put these
1082210822
// into global variables and rely on cleaning them up in outlined
1082310823
// constructors/destructors
10824-
static PVOID exceptionHandlerHandle = nullptr;
10824+
static LPTOP_LEVEL_EXCEPTION_FILTER previousTopLevelExceptionFilter = nullptr;
1082510825

1082610826
// For MSVC, we reserve part of the stack memory for handling
1082710827
// memory overflow structured exception.
@@ -10841,18 +10841,15 @@ namespace Catch {
1084110841
FatalConditionHandler::~FatalConditionHandler() = default;
1084210842

1084310843
void FatalConditionHandler::engage_platform() {
10844-
// Register as first handler in current chain
10845-
exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
10846-
if (!exceptionHandlerHandle) {
10847-
CATCH_RUNTIME_ERROR("Could not register vectored exception handler");
10848-
}
10844+
// Register as a the top level exception filter.
10845+
previousTopLevelExceptionFilter = SetUnhandledExceptionFilter(topLevelExceptionFilter);
1084910846
}
1085010847

1085110848
void FatalConditionHandler::disengage_platform() {
10852-
if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {
10853-
CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");
10849+
if (SetUnhandledExceptionFilter(reinterpret_cast<LPTOP_LEVEL_EXCEPTION_FILTER>(previousTopLevelExceptionFilter)) != topLevelExceptionFilter) {
10850+
CATCH_RUNTIME_ERROR("Could not restore previous top level exception filter");
1085410851
}
10855-
exceptionHandlerHandle = nullptr;
10852+
previousTopLevelExceptionFilter = nullptr;
1085610853
}
1085710854

1085810855
} // end namespace Catch

test/test_cpp20/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ set(CMAKE_CXX_STANDARD 20)
33
# are experimental in libc++ as of Clang 15.
44
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
55

6+
if(ENABLE_TEST_SANITIZERS)
7+
# As of LLVM 15, custom_error.cpp doesn't build with ASAN due to:
8+
# error: cannot make section .ASAN$GL associative with sectionless symbol _ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE4nposE
9+
set_source_files_properties(custom_error.cpp PROPERTIES COMPILE_OPTIONS "-fno-sanitize=address")
10+
set_source_files_properties(custom_error.cpp PROPERTIES SKIP_PRECOMPILE_HEADERS true)
11+
endif()
12+
613
file(GLOB TEST_SRCS
714
LIST_DIRECTORIES false
815
CONFIGURE_DEPENDS

0 commit comments

Comments
 (0)