| Index: util/win/process_info_test.cc | 
| diff --git a/util/win/process_info_test.cc b/util/win/process_info_test.cc | 
| index d3d674dd875ad10131145d151731abde57776915..71269a5989b1ed52f587cc4e7f3a4914d5095147 100644 | 
| --- a/util/win/process_info_test.cc | 
| +++ b/util/win/process_info_test.cc | 
| @@ -19,6 +19,7 @@ | 
| #include <wchar.h> | 
|  | 
| #include "base/files/file_path.h" | 
| +#include "base/memory/scoped_ptr.h" | 
| #include "build/build_config.h" | 
| #include "gtest/gtest.h" | 
| #include "test/paths.h" | 
| @@ -228,7 +229,7 @@ TEST(ProcessInfo, AccessibleRangesOneInside) { | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(2, 4), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(2, result[0].base()); | 
| EXPECT_EQ(4, result[0].size()); | 
| } | 
| @@ -251,7 +252,7 @@ TEST(ProcessInfo, AccessibleRangesOneTruncatedSize) { | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(5, result[0].base()); | 
| EXPECT_EQ(5, result[0].size()); | 
| } | 
| @@ -274,7 +275,80 @@ TEST(ProcessInfo, AccessibleRangesOneMovedStart) { | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| +  EXPECT_EQ(10, result[0].base()); | 
| +  EXPECT_EQ(5, result[0].size()); | 
| +} | 
| + | 
| +TEST(ProcessInfo, ReserveIsInaccessible) { | 
| +  std::vector<ProcessInfo::MemoryInfo> memory_info; | 
| +  MEMORY_BASIC_INFORMATION mbi = {0}; | 
| + | 
| +  mbi.BaseAddress = 0; | 
| +  mbi.RegionSize = 10; | 
| +  mbi.State = MEM_RESERVE; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  mbi.BaseAddress = reinterpret_cast<void*>(10); | 
| +  mbi.RegionSize = 20; | 
| +  mbi.State = MEM_COMMIT; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = | 
| +      GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| +                                   memory_info); | 
| + | 
| +  ASSERT_EQ(1u, result.size()); | 
| +  EXPECT_EQ(10, result[0].base()); | 
| +  EXPECT_EQ(5, result[0].size()); | 
| +} | 
| + | 
| +TEST(ProcessInfo, PageGuardIsInaccessible) { | 
| +  std::vector<ProcessInfo::MemoryInfo> memory_info; | 
| +  MEMORY_BASIC_INFORMATION mbi = {0}; | 
| + | 
| +  mbi.BaseAddress = 0; | 
| +  mbi.RegionSize = 10; | 
| +  mbi.State = MEM_COMMIT; | 
| +  mbi.Protect = PAGE_GUARD; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  mbi.BaseAddress = reinterpret_cast<void*>(10); | 
| +  mbi.RegionSize = 20; | 
| +  mbi.State = MEM_COMMIT; | 
| +  mbi.Protect = 0; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = | 
| +      GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| +                                   memory_info); | 
| + | 
| +  ASSERT_EQ(1u, result.size()); | 
| +  EXPECT_EQ(10, result[0].base()); | 
| +  EXPECT_EQ(5, result[0].size()); | 
| +} | 
| + | 
| +TEST(ProcessInfo, PageNoAccessIsInaccessible) { | 
| +  std::vector<ProcessInfo::MemoryInfo> memory_info; | 
| +  MEMORY_BASIC_INFORMATION mbi = {0}; | 
| + | 
| +  mbi.BaseAddress = 0; | 
| +  mbi.RegionSize = 10; | 
| +  mbi.State = MEM_COMMIT; | 
| +  mbi.Protect = PAGE_NOACCESS; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  mbi.BaseAddress = reinterpret_cast<void*>(10); | 
| +  mbi.RegionSize = 20; | 
| +  mbi.State = MEM_COMMIT; | 
| +  mbi.Protect = 0; | 
| +  memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
| + | 
| +  std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = | 
| +      GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| +                                   memory_info); | 
| + | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(10, result[0].base()); | 
| EXPECT_EQ(5, result[0].size()); | 
| } | 
| @@ -295,14 +369,14 @@ TEST(ProcessInfo, AccessibleRangesCoalesced) { | 
|  | 
| mbi.BaseAddress = reinterpret_cast<void*>(12); | 
| mbi.RegionSize = 5; | 
| -  mbi.State = MEM_RESERVE; | 
| +  mbi.State = MEM_COMMIT; | 
| memory_info.push_back(ProcessInfo::MemoryInfo(mbi)); | 
|  | 
| std::vector<CheckedRange<WinVMAddress, WinVMSize>> result = | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(11, 4), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(11, result[0].base()); | 
| EXPECT_EQ(4, result[0].size()); | 
| } | 
| @@ -330,7 +404,7 @@ TEST(ProcessInfo, AccessibleRangesMiddleUnavailable) { | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 45), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 2u); | 
| +  ASSERT_EQ(2u, result.size()); | 
| EXPECT_EQ(5, result[0].base()); | 
| EXPECT_EQ(5, result[0].size()); | 
| EXPECT_EQ(15, result[1].base()); | 
| @@ -350,7 +424,7 @@ TEST(ProcessInfo, RequestedBeforeMap) { | 
| GetReadableRangesOfMemoryMap(CheckedRange<WinVMAddress, WinVMSize>(5, 10), | 
| memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(10, result[0].base()); | 
| EXPECT_EQ(5, result[0].size()); | 
| } | 
| @@ -368,11 +442,83 @@ TEST(ProcessInfo, RequestedAfterMap) { | 
| GetReadableRangesOfMemoryMap( | 
| CheckedRange<WinVMAddress, WinVMSize>(15, 100), memory_info); | 
|  | 
| -  ASSERT_EQ(result.size(), 1u); | 
| +  ASSERT_EQ(1u, result.size()); | 
| EXPECT_EQ(15, result[0].base()); | 
| EXPECT_EQ(5, result[0].size()); | 
| } | 
|  | 
| +TEST(ProcessInfo, ReadableRanges) { | 
| +  SYSTEM_INFO system_info; | 
| +  GetSystemInfo(&system_info); | 
| + | 
| +  const size_t kBlockSize = system_info.dwPageSize; | 
| + | 
| +  // Allocate 6 pages, and then commit the second, fourth, and fifth, and mark | 
| +  // two as committed, but PAGE_NOACCESS, so we have a setup like this: | 
| +  // 0       1       2       3       4       5 | 
| +  // +-----------------------------------------------+ | 
| +  // | ????? |       | xxxxx |       |       | ????? | | 
| +  // +-----------------------------------------------+ | 
| +  void* reserve_region = | 
| +      VirtualAlloc(nullptr, kBlockSize * 6, MEM_RESERVE, PAGE_READWRITE); | 
| +  ASSERT_TRUE(reserve_region); | 
| +  uintptr_t reserved_as_int = reinterpret_cast<uintptr_t>(reserve_region); | 
| +  void* readable1 = | 
| +      VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + kBlockSize), | 
| +                   kBlockSize, | 
| +                   MEM_COMMIT, | 
| +                   PAGE_READWRITE); | 
| +  ASSERT_TRUE(readable1); | 
| +  void* readable2 = | 
| +      VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 3)), | 
| +                   kBlockSize * 2, | 
| +                   MEM_COMMIT, | 
| +                   PAGE_READWRITE); | 
| +  ASSERT_TRUE(readable2); | 
| + | 
| +  void* no_access = | 
| +      VirtualAlloc(reinterpret_cast<void*>(reserved_as_int + (kBlockSize * 2)), | 
| +                   kBlockSize, | 
| +                   MEM_COMMIT, | 
| +                   PAGE_NOACCESS); | 
| +  ASSERT_TRUE(no_access); | 
| + | 
| +  HANDLE current_process = GetCurrentProcess(); | 
| +  ProcessInfo info; | 
| +  info.Initialize(current_process); | 
| +  auto ranges = info.GetReadableRanges( | 
| +      CheckedRange<WinVMAddress, WinVMSize>(reserved_as_int, kBlockSize * 6)); | 
| + | 
| +  ASSERT_EQ(2u, ranges.size()); | 
| +  EXPECT_EQ(reserved_as_int + kBlockSize, ranges[0].base()); | 
| +  EXPECT_EQ(kBlockSize, ranges[0].size()); | 
| +  EXPECT_EQ(reserved_as_int + (kBlockSize * 3), ranges[1].base()); | 
| +  EXPECT_EQ(kBlockSize * 2, ranges[1].size()); | 
| + | 
| +  // Also make sure what we think we can read corresponds with what we can | 
| +  // actually read. | 
| +  scoped_ptr<unsigned char[]> into(new unsigned char[kBlockSize * 6]); | 
| +  SIZE_T bytes_read; | 
| + | 
| +  EXPECT_TRUE(ReadProcessMemory( | 
| +      current_process, readable1, into.get(), kBlockSize, &bytes_read)); | 
| +  EXPECT_EQ(kBlockSize, bytes_read); | 
| + | 
| +  EXPECT_TRUE(ReadProcessMemory( | 
| +      current_process, readable2, into.get(), kBlockSize * 2, &bytes_read)); | 
| +  EXPECT_EQ(kBlockSize * 2, bytes_read); | 
| + | 
| +  EXPECT_FALSE(ReadProcessMemory( | 
| +      current_process, no_access, into.get(), kBlockSize, &bytes_read)); | 
| +  EXPECT_FALSE(ReadProcessMemory( | 
| +      current_process, reserve_region, into.get(), kBlockSize, &bytes_read)); | 
| +  EXPECT_FALSE(ReadProcessMemory(current_process, | 
| +                                 reserve_region, | 
| +                                 into.get(), | 
| +                                 kBlockSize * 6, | 
| +                                 &bytes_read)); | 
| +} | 
| + | 
| }  // namespace | 
| }  // namespace test | 
| }  // namespace crashpad | 
|  |