diff options
author | Marcos Pividori <mpividori@google.com> | 2017-01-22 02:14:57 +0000 |
---|---|---|
committer | Marcos Pividori <mpividori@google.com> | 2017-01-22 02:14:57 +0000 |
commit | aeb1a33bd275591107388eac49a44c82d27f85d1 (patch) | |
tree | a305e08b2d429e83ffe14c0b7726b08222e1f929 | |
parent | a7e63fe63564f09a4c01b83984264f22a9078652 (diff) | |
download | compiler-rt-aeb1a33bd275591107388eac49a44c82d27f85d1.tar.gz |
[interception] Check for export table's size before referring to its elements.
This fix a bug, when calling InternalGetProcAddress() for an executable that
doesn't export any symbol. So the table is empty.
If we don't check for this condition, the program fails with Error 0xc0000142.
Also, I add a regression test for Windows.
Differential Revision: https://reviews.llvm.org/D28502
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@292747 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/interception/interception_win.cc | 2 | ||||
-rw-r--r-- | test/interception/CMakeLists.txt | 25 | ||||
-rw-r--r-- | test/interception/TestCases/Windows/empty_export_table.cc | 17 | ||||
-rw-r--r-- | test/interception/TestCases/Windows/lit.local.cfg | 9 | ||||
-rw-r--r-- | test/interception/lit.cfg | 28 | ||||
-rw-r--r-- | test/interception/lit.site.cfg.in | 15 |
6 files changed, 96 insertions, 0 deletions
diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc index 91abecf6d..e4f3d358f 100644 --- a/lib/interception/interception_win.cc +++ b/lib/interception/interception_win.cc @@ -878,6 +878,8 @@ uptr InternalGetProcAddress(void *module, const char *func_name) { IMAGE_DATA_DIRECTORY *export_directory = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; + if (export_directory->Size == 0) + return 0; RVAPtr<IMAGE_EXPORT_DIRECTORY> exports(module, export_directory->VirtualAddress); RVAPtr<DWORD> functions(module, exports->AddressOfFunctions); diff --git a/test/interception/CMakeLists.txt b/test/interception/CMakeLists.txt index ff9e4b0ad..9ea811a7c 100644 --- a/test/interception/CMakeLists.txt +++ b/test/interception/CMakeLists.txt @@ -1,5 +1,30 @@ set(INTERCEPTION_TEST_DEPS ${SANITIZER_COMMON_LIT_TEST_DEPS}) set(INTERCEPTION_TESTSUITES) +set(INTERCEPTION_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +foreach(arch ${SANITIZER_COMMON_SUPPORTED_ARCH}) + set(INTERCEPTION_TEST_TARGET_ARCH ${arch}) + set(CONFIG_NAME ${arch}-${OS_NAME}) + + get_test_cc_for_arch(${arch} INTERCEPTION_TEST_TARGET_CC + INTERCEPTION_TEST_TARGET_CFLAGS) + + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + set(INTERCEPTION_TEST_TARGET_LIB RTInterception.test.${arch}) + + get_property(INTERCEPTION_TEST_TARGET_LIB_DIR TARGET + ${INTERCEPTION_TEST_TARGET_LIB} PROPERTY ARCHIVE_OUTPUT_DIRECTORY) + + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg + ) + + list(APPEND INTERCEPTION_TESTSUITES + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + list(APPEND INTERCEPTION_TEST_DEPS RTInterception.test.${arch}) +endforeach() # Unit tests. There are currently no unit tests capable to running on Apple or # Android targets. diff --git a/test/interception/TestCases/Windows/empty_export_table.cc b/test/interception/TestCases/Windows/empty_export_table.cc new file mode 100644 index 000000000..6bce149f0 --- /dev/null +++ b/test/interception/TestCases/Windows/empty_export_table.cc @@ -0,0 +1,17 @@ +// RUN: %clang_cl %s %inter_lib -o %t +// RUN: %run %t 2>&1 | FileCheck %s +// CHECK: OK + +#include "interception/interception.h" +#include <stdio.h> +#include <windows.h> + +// We try to get a pointer to a function from an executable that doesn't export +// any symbol (empty export table). +int main() { + __sanitizer::uptr FunPtr = __interception::InternalGetProcAddress( + (void *)GetModuleHandleA(0), "exampleFun"); + if (FunPtr == 0) + printf("OK"); + return 0; +} diff --git a/test/interception/TestCases/Windows/lit.local.cfg b/test/interception/TestCases/Windows/lit.local.cfg new file mode 100644 index 000000000..e924d91c4 --- /dev/null +++ b/test/interception/TestCases/Windows/lit.local.cfg @@ -0,0 +1,9 @@ +def getRoot(config): + if not config.parent: + return config + return getRoot(config.parent) + +root = getRoot(config) + +if root.host_os not in ['Windows']: + config.unsupported = True diff --git a/test/interception/lit.cfg b/test/interception/lit.cfg new file mode 100644 index 000000000..5846eb3b2 --- /dev/null +++ b/test/interception/lit.cfg @@ -0,0 +1,28 @@ +# -*- Python -*- + +# Setup source root. +config.test_source_root = os.path.join(os.path.dirname(__file__), "TestCases") + +# Setup config name. +config.name = "Interception" + +# Add library sustitutions. +if config.host_os == 'Windows': + libpath = os.path.join(config.target_lib_dir, config.target_lib + ".lib") + config.substitutions.append( ("%inter_lib", libpath)) +else: + libpath = os.path.join(config.target_lib_dir, "lib" + config.target_lib + ".a") + config.substitutions.append( ("%inter_lib", libpath)) + +# Add clang substitutions. +config.substitutions.append( ("%clang ", " ".join([config.clang, + config.target_cflags, "-I"+config.sources_dir, ""]) )) + +# Configure clang_cl for Windows. +if config.host_os == 'Windows': + clang_cl_invocation = config.clang.replace("clang.exe","clang-cl.exe") + config.substitutions.append( ("%clang_cl ", " ".join([clang_cl_invocation, + config.target_cflags, "/I"+config.sources_dir, ""]) )) + +# Files to be considered for tests. +config.suffixes = ['.c', '.cc', '.cpp'] diff --git a/test/interception/lit.site.cfg.in b/test/interception/lit.site.cfg.in new file mode 100644 index 000000000..8e873d34a --- /dev/null +++ b/test/interception/lit.site.cfg.in @@ -0,0 +1,15 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Tool-specific config options. +config.target_cflags = "@INTERCEPTION_TEST_TARGET_CFLAGS@" +config.clang = "@INTERCEPTION_TEST_TARGET_CC@" +config.target_arch = "@INTERCEPTION_TEST_TARGET_ARCH@" +config.target_lib = "@INTERCEPTION_TEST_TARGET_LIB@" +config.target_lib_dir = "@INTERCEPTION_TEST_TARGET_LIB_DIR@" +config.sources_dir = os.path.join("@COMPILER_RT_SOURCE_DIR@", "lib") + +# Load common config for all compiler-rt lit tests. +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@INTERCEPTION_LIT_SOURCE_DIR@/lit.cfg") |