summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcos Pividori <mpividori@google.com>2017-01-22 02:14:57 +0000
committerMarcos Pividori <mpividori@google.com>2017-01-22 02:14:57 +0000
commitaeb1a33bd275591107388eac49a44c82d27f85d1 (patch)
treea305e08b2d429e83ffe14c0b7726b08222e1f929
parenta7e63fe63564f09a4c01b83984264f22a9078652 (diff)
downloadcompiler-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.cc2
-rw-r--r--test/interception/CMakeLists.txt25
-rw-r--r--test/interception/TestCases/Windows/empty_export_table.cc17
-rw-r--r--test/interception/TestCases/Windows/lit.local.cfg9
-rw-r--r--test/interception/lit.cfg28
-rw-r--r--test/interception/lit.site.cfg.in15
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")