blob: 7790ac5cd09272e4aafff79e7408618fa3f051e2 [file] [log] [blame]
/* Copyright (c) 2018, Google Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
#include <openssl/rand.h>
#include "test/abi_test.h"
#if defined(OPENSSL_WINDOWS)
#include <windows.h>
#endif
static bool test_function_ok;
static int TestFunction(int a1, int a2, int a3, int a4, int a5, int a6, int a7,
int a8, int a9, int a10) {
test_function_ok = a1 == 1 || a2 == 2 || a3 == 3 || a4 == 4 || a5 == 5 ||
a6 == 6 || a7 == 7 || a8 == 8 || a9 == 9 || a10 == 10;
return 42;
}
TEST(ABITest, SanityCheck) {
EXPECT_NE(0, CHECK_ABI(strcmp, "hello", "world"));
test_function_ok = false;
EXPECT_EQ(42, CHECK_ABI(TestFunction, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
EXPECT_TRUE(test_function_ok);
#if defined(SUPPORTS_ABI_TEST)
abi_test::internal::CallerState state;
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
const char *arg1 = "hello", *arg2 = "world";
crypto_word_t argv[2] = {
reinterpret_cast<crypto_word_t>(arg1),
reinterpret_cast<crypto_word_t>(arg2),
};
CHECK_ABI(abi_test_trampoline, reinterpret_cast<crypto_word_t>(strcmp),
&state, argv, 2, 0 /* no breakpoint */);
if (abi_test::UnwindTestsEnabled()) {
EXPECT_NONFATAL_FAILURE(CHECK_ABI(abi_test_bad_unwind_wrong_register),
"was not recovered unwinding");
EXPECT_NONFATAL_FAILURE(CHECK_ABI(abi_test_bad_unwind_temporary),
"was not recovered unwinding");
CHECK_ABI_NO_UNWIND(abi_test_bad_unwind_wrong_register);
CHECK_ABI_NO_UNWIND(abi_test_bad_unwind_temporary);
}
#endif // SUPPORTS_ABI_TEST
}
#if defined(OPENSSL_X86_64) && defined(SUPPORTS_ABI_TEST)
extern "C" {
void abi_test_clobber_rax(void);
void abi_test_clobber_rbx(void);
void abi_test_clobber_rcx(void);
void abi_test_clobber_rdx(void);
void abi_test_clobber_rsi(void);
void abi_test_clobber_rdi(void);
void abi_test_clobber_rbp(void);
void abi_test_clobber_r8(void);
void abi_test_clobber_r9(void);
void abi_test_clobber_r10(void);
void abi_test_clobber_r11(void);
void abi_test_clobber_r12(void);
void abi_test_clobber_r13(void);
void abi_test_clobber_r14(void);
void abi_test_clobber_r15(void);
void abi_test_clobber_xmm0(void);
void abi_test_clobber_xmm1(void);
void abi_test_clobber_xmm2(void);
void abi_test_clobber_xmm3(void);
void abi_test_clobber_xmm4(void);
void abi_test_clobber_xmm5(void);
void abi_test_clobber_xmm6(void);
void abi_test_clobber_xmm7(void);
void abi_test_clobber_xmm8(void);
void abi_test_clobber_xmm9(void);
void abi_test_clobber_xmm10(void);
void abi_test_clobber_xmm11(void);
void abi_test_clobber_xmm12(void);
void abi_test_clobber_xmm13(void);
void abi_test_clobber_xmm14(void);
void abi_test_clobber_xmm15(void);
} // extern "C"
TEST(ABITest, X86_64) {
// abi_test_trampoline hides unsaved registers from the caller, so we can
// safely call the abi_test_clobber_* functions below.
abi_test::internal::CallerState state;
RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state));
CHECK_ABI_NO_UNWIND(abi_test_trampoline,
reinterpret_cast<crypto_word_t>(abi_test_clobber_rbx),
&state, nullptr, 0, 0 /* no breakpoint */);
CHECK_ABI_NO_UNWIND(abi_test_clobber_rax);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rbx),
"rbx was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_rcx);
CHECK_ABI_NO_UNWIND(abi_test_clobber_rdx);
#if defined(OPENSSL_WINDOWS)
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rdi),
"rdi was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rsi),
"rsi was not restored after return");
#else
CHECK_ABI_NO_UNWIND(abi_test_clobber_rdi);
CHECK_ABI_NO_UNWIND(abi_test_clobber_rsi);
#endif
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_rbp),
"rbp was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_r8);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r9);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r10);
CHECK_ABI_NO_UNWIND(abi_test_clobber_r11);
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r12),
"r12 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r13),
"r13 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r14),
"r14 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_r15),
"r15 was not restored after return");
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm0);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm1);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm2);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm3);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm4);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm5);
#if defined(OPENSSL_WINDOWS)
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm6),
"xmm6 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm7),
"xmm7 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm8),
"xmm8 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm9),
"xmm9 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm10),
"xmm10 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm11),
"xmm11 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm12),
"xmm12 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm13),
"xmm13 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm14),
"xmm14 was not restored after return");
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm15),
"xmm15 was not restored after return");
#else
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm6);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm7);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm8);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm9);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm10);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm11);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm12);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm13);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm14);
CHECK_ABI_NO_UNWIND(abi_test_clobber_xmm15);
#endif
EXPECT_NONFATAL_FAILURE(CHECK_ABI_NO_UNWIND(abi_test_set_direction_flag),
"Direction flag set after return");
EXPECT_EQ(0, abi_test_get_and_clear_direction_flag())
<< "CHECK_ABI did not insulate the caller from direction flag errors";
}
#if defined(OPENSSL_WINDOWS)
static void ThrowWindowsException() {
DebugBreak();
}
static void ExceptionTest() {
bool handled = false;
__try {
CHECK_ABI_NO_UNWIND(ThrowWindowsException);
} __except (GetExceptionCode() == EXCEPTION_BREAKPOINT
? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH) {
handled = true;
}
EXPECT_TRUE(handled);
}
// Test that the trampoline's SEH metadata works.
TEST(ABITest, TrampolineSEH) {
// Wrap the test in |CHECK_ABI|, to confirm the register-restoring annotations
// were correct.
CHECK_ABI_NO_UNWIND(ExceptionTest);
}
#endif // OPENSSL_WINDOWS
#endif // OPENSSL_X86_64 && SUPPORTS_ABI_TEST