diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp --- a/compiler-rt/lib/interception/interception_win.cpp +++ b/compiler-rt/lib/interception/interception_win.cpp @@ -143,6 +143,8 @@ static void InterceptionFailed() { // Do we have a good way to abort with an error message here? + // This acts like an abort when no debugger is attached. According to an old + // comment, calling abort() leads to an infinite recursion in CheckFailed. __debugbreak(); } @@ -658,9 +660,9 @@ // Unknown instruction! // FIXME: Unknown instruction failures might happen when we add a new // interceptor or a new compiler version. In either case, they should result - // in visible and readable error messages. However, merely calling abort() - // leads to an infinite recursion in CheckFailed. - InterceptionFailed(); + // in visible and readable error messages. + if (::IsDebuggerPresent()) + __debugbreak(); return 0; } @@ -681,6 +683,8 @@ while (cursor != size) { size_t rel_offset = 0; size_t instruction_size = GetInstructionSize(from + cursor, &rel_offset); + if (!instruction_size) + return false; _memcpy((void*)(to + cursor), (void*)(from + cursor), (size_t)instruction_size); if (rel_offset) { diff --git a/compiler-rt/lib/interception/tests/interception_win_test.cpp b/compiler-rt/lib/interception/tests/interception_win_test.cpp --- a/compiler-rt/lib/interception/tests/interception_win_test.cpp +++ b/compiler-rt/lib/interception/tests/interception_win_test.cpp @@ -307,6 +307,13 @@ 0x56, // push esi }; +const u8 kUnsupportedCode1[] = { + 0x0f, 0x0b, // ud2 + 0x0f, 0x0b, // ud2 + 0x0f, 0x0b, // ud2 + 0x0f, 0x0b, // ud2 +}; + // A buffer holding the dynamically generated code under test. u8* ActiveCode; const size_t ActiveCodeLength = 4096; @@ -717,6 +724,13 @@ EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix)); } +TEST(Interception, UnsupportedInstructionWithTrampoline) { + TestOverrideFunction override = OverrideFunctionWithTrampoline; + FunctionPrefixKind prefix = FunctionPrefixPadding; + + EXPECT_FALSE(TestFunctionPatching(kUnsupportedCode1, override, prefix)); +} + TEST(Interception, PatchableFunctionPadding) { TestOverrideFunction override = OverrideFunction; FunctionPrefixKind prefix = FunctionPrefixPadding;