From 72cef849f9de81f483347ae045ac02b3401f9aa2 Mon Sep 17 00:00:00 2001 From: Smertig Date: Wed, 6 Jan 2021 15:25:56 +0300 Subject: [PATCH] Rewrite vtable test to prevent devirtualization (gcc) --- test/test_hooks.cpp | 46 +++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/test/test_hooks.cpp b/test/test_hooks.cpp index 4616909..2d345be 100644 --- a/test/test_hooks.cpp +++ b/test/test_hooks.cpp @@ -273,38 +273,40 @@ TEST_CASE("Pointer-to-member function") { REQUIRE(A_f(&a, 10) == a.f(10)); } -TEST_CASE("vtable hooking") { - struct A { - int b = 5; +struct AV { + int b = 5; - NO_OPTIMIZE - virtual int f(int a) const { - return a + b; - } - }; + NO_OPTIMIZE + virtual int f(int a) const { + return a + b; + } +}; +// prevent devirtualization +NO_OPTIMIZE +int call_f(AV& av, int arg) { + return av.f(arg); +} + +TEST_CASE("vtable hooking") { using vtable_t = std::array; - struct A2 { + struct AV2 { vtable_t* vtable; int b; }; - static_assert(sizeof(A) == sizeof(A2)); + static_assert(sizeof(AV) == sizeof(AV2)); - auto prevent_devirtualization = [](A& a) { - REQUIRE(a.f(10) == 15); + AV av; + REQUIRE(call_f(av, 10) == 15); - auto hook = [](auto original, auto self, int arg) -> int { - return 2 * original(self, arg + 1); - }; - - auto& vtable = *rcmp::bit_cast(&a)->vtable; - rcmp::hook_indirect_function>(&vtable[0], hook); - - REQUIRE(a.f(10) == 32); + auto hook = [](auto original, auto self, int arg) -> int { + return 2 * original(self, arg + 1); }; - A a; - prevent_devirtualization(a); + auto& vtable = *rcmp::bit_cast(&av)->vtable; + rcmp::hook_indirect_function>(&vtable[0], hook); + + REQUIRE(call_f(av, 10) == 32); }