Chromium Code Reviews| Index: sandbox/win/src/win_utils_unittest.cc |
| diff --git a/sandbox/win/src/win_utils_unittest.cc b/sandbox/win/src/win_utils_unittest.cc |
| index 7500798102a8c76fbb2b7e1bcc8a478880abc825..9ecca28bbb52e6a6aa81c72c1f2a5060ccebe95d 100644 |
| --- a/sandbox/win/src/win_utils_unittest.cc |
| +++ b/sandbox/win/src/win_utils_unittest.cc |
| @@ -3,8 +3,13 @@ |
| // found in the LICENSE file. |
| #include <windows.h> |
| +#include <psapi.h> |
| +#include <vector> |
| + |
| +#include "base/numerics/safe_conversions.h" |
| #include "base/win/scoped_handle.h" |
| +#include "base/win/scoped_process_information.h" |
| #include "sandbox/win/src/nt_internals.h" |
| #include "sandbox/win/src/win_utils.h" |
| #include "sandbox/win/tests/common/test_utils.h" |
| @@ -122,3 +127,83 @@ TEST(WinUtils, NtStatusToWin32Error) { |
| EXPECT_EQ(static_cast<DWORD>(ERROR_ACCESS_DENIED), |
| GetLastErrorFromNtStatus(STATUS_ACCESS_DENIED)); |
| } |
| + |
| +class ScopedTerminateProcess { |
|
Will Harris
2016/09/08 16:54:03
I wonder if this should be in the anonymous namesp
|
| + public: |
| + ScopedTerminateProcess(HANDLE process) : process_(process) {} |
| + |
| + ~ScopedTerminateProcess() { |
| + ::TerminateProcess(process_, 0); |
| + } |
| + |
| + private: |
| + HANDLE process_; |
| +}; |
| + |
| +static bool GetModuleList(HANDLE process, std::vector<HMODULE>* result) { |
| + std::vector<HMODULE> modules(256); |
| + DWORD size_needed = 0; |
| + if (EnumProcessModules( |
| + process, &modules[0], |
| + base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)), |
| + &size_needed)) { |
| + result->assign(modules.begin(), |
| + modules.begin() + (size_needed / sizeof(HMODULE))); |
| + return true; |
| + } |
| + modules.resize(size_needed / sizeof(HMODULE)); |
| + if (EnumProcessModules( |
| + process, &modules[0], |
| + base::checked_cast<DWORD>(modules.size() * sizeof(HMODULE)), |
| + &size_needed)) { |
| + result->assign(modules.begin(), |
| + modules.begin() + (size_needed / sizeof(HMODULE))); |
| + return true; |
| + } |
| + return false; |
| +} |
| + |
| +TEST(WinUtils, GetProcessBaseAddress) { |
| + using sandbox::GetProcessBaseAddress; |
| + STARTUPINFO start_info = {}; |
| + PROCESS_INFORMATION proc_info = {}; |
| + WCHAR command_line[] = L"notepad"; |
| + start_info.cb = sizeof(start_info); |
| + start_info.dwFlags = STARTF_USESHOWWINDOW; |
| + start_info.wShowWindow = SW_HIDE; |
| + EXPECT_TRUE(::CreateProcessW(nullptr, command_line, nullptr, nullptr, FALSE, |
| + CREATE_SUSPENDED, nullptr, nullptr, &start_info, |
| + &proc_info)); |
| + base::win::ScopedProcessInformation scoped_proc_info(proc_info); |
| + ScopedTerminateProcess process_terminate(scoped_proc_info.process_handle()); |
| + void* base_address = GetProcessBaseAddress(scoped_proc_info.process_handle()); |
| + EXPECT_NE(nullptr, base_address); |
| + EXPECT_NE(static_cast<DWORD>(-1), |
| + ::ResumeThread(scoped_proc_info.thread_handle())); |
| + ::WaitForInputIdle(scoped_proc_info.process_handle(), 1000); |
| + EXPECT_NE(static_cast<DWORD>(-1), |
| + ::SuspendThread(scoped_proc_info.thread_handle())); |
| + // Check again, the process will have done some more memory initialization. |
| + EXPECT_EQ(base_address, |
| + GetProcessBaseAddress(scoped_proc_info.process_handle())); |
| + |
| + std::vector<HMODULE> modules; |
| + // Compare against the loader's module list (which should now be initialized). |
| + // GetModuleList could fail if the target process hasn't fully initialized. |
| + // If so skip this check and log it as a warning. |
| + if (GetModuleList(scoped_proc_info.process_handle(), &modules) && |
| + modules.size() > 0) { |
| + // First module should be the main executable. |
| + EXPECT_EQ(base_address, modules[0]); |
| + } else { |
| + LOG(WARNING) << "Couldn't test base address against module list"; |
| + } |
| + // Fill in some of the virtual memory with 10MiB chunks and try again. |
| + for (int count = 0; count < 100; ++count) { |
| + EXPECT_NE(nullptr, |
| + ::VirtualAllocEx(scoped_proc_info.process_handle(), nullptr, |
| + 10 * 1024 * 1024, MEM_RESERVE, PAGE_NOACCESS)); |
| + } |
| + EXPECT_EQ(base_address, |
| + GetProcessBaseAddress(scoped_proc_info.process_handle())); |
| +} |