| Index: base/process/process_metrics_mac.cc | 
| diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc | 
| index be4107e22322cd0f37bd1927649169e070c38271..9e214b0c1e4deffea6a1fb84256182d4f0cef3d8 100644 | 
| --- a/base/process/process_metrics_mac.cc | 
| +++ b/base/process/process_metrics_mac.cc | 
| @@ -17,6 +17,7 @@ | 
| #include "base/mac/scoped_mach_port.h" | 
| #include "base/memory/ptr_util.h" | 
| #include "base/numerics/safe_conversions.h" | 
| +#include "base/numerics/safe_math.h" | 
| #include "base/sys_info.h" | 
|  | 
| namespace base { | 
| @@ -62,54 +63,14 @@ bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) { | 
| } | 
| } | 
|  | 
| -enum MachVMRegionResult { Finished, Error, Success }; | 
| - | 
| -// Both |size| and |address| are in-out parameters. | 
| -// |info| is an output parameter, only valid on Success. | 
| -MachVMRegionResult GetTopInfo(mach_port_t task, | 
| -                              mach_vm_size_t* size, | 
| -                              mach_vm_address_t* address, | 
| -                              vm_region_top_info_data_t* info) { | 
| -  mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; | 
| -  mach_port_t object_name; | 
| -  kern_return_t kr = mach_vm_region(task, address, size, VM_REGION_TOP_INFO, | 
| -                                    reinterpret_cast<vm_region_info_t>(info), | 
| -                                    &info_count, &object_name); | 
| -  // We're at the end of the address space. | 
| -  if (kr == KERN_INVALID_ADDRESS) | 
| -    return Finished; | 
| - | 
| -  if (kr != KERN_SUCCESS) | 
| -    return Error; | 
| - | 
| -  // The kernel always returns a null object for VM_REGION_TOP_INFO, but | 
| -  // balance it with a deallocate in case this ever changes. See 10.9.2 | 
| -  // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. | 
| -  mach_port_deallocate(task, object_name); | 
| -  return Success; | 
| -} | 
| - | 
| -MachVMRegionResult GetBasicInfo(mach_port_t task, | 
| -                                mach_vm_size_t* size, | 
| -                                mach_vm_address_t* address, | 
| -                                vm_region_basic_info_64* info) { | 
| -  mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; | 
| -  mach_port_t object_name; | 
| -  kern_return_t kr = mach_vm_region( | 
| -      task, address, size, VM_REGION_BASIC_INFO_64, | 
| -      reinterpret_cast<vm_region_info_t>(info), &info_count, &object_name); | 
| +MachVMRegionResult ParseOutputFromMachVMRegion(kern_return_t kr) { | 
| if (kr == KERN_INVALID_ADDRESS) { | 
| // We're at the end of the address space. | 
| -    return Finished; | 
| +    return MachVMRegionResult::Finished; | 
| } else if (kr != KERN_SUCCESS) { | 
| -    return Error; | 
| +    return MachVMRegionResult::Error; | 
| } | 
| - | 
| -  // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but | 
| -  // balance it with a deallocate in case this ever changes. See 10.9.2 | 
| -  // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. | 
| -  mach_port_deallocate(task, object_name); | 
| -  return Success; | 
| +  return MachVMRegionResult::Success; | 
| } | 
|  | 
| }  // namespace | 
| @@ -191,26 +152,30 @@ bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, | 
| // See libtop_update_vm_regions in | 
| // http://www.opensource.apple.com/source/top/top-67/libtop.c | 
| mach_vm_size_t size = 0; | 
| -  for (mach_vm_address_t address = MACH_VM_MIN_ADDRESS;; address += size) { | 
| -    mach_vm_size_t size_copy = size; | 
| -    mach_vm_address_t address_copy = address; | 
| +  mach_vm_address_t address = MACH_VM_MIN_ADDRESS; | 
| +  while (true) { | 
| +    base::CheckedNumeric<mach_vm_address_t> next_address(address); | 
| +    next_address += size; | 
| +    if (!next_address.IsValid()) | 
| +      return false; | 
| +    address = next_address.ValueOrDie(); | 
|  | 
| +    mach_vm_address_t address_copy = address; | 
| vm_region_top_info_data_t info; | 
| MachVMRegionResult result = GetTopInfo(task, &size, &address, &info); | 
| -    if (result == Error) | 
| +    if (result == MachVMRegionResult::Error) | 
| return false; | 
| -    if (result == Finished) | 
| +    if (result == MachVMRegionResult::Finished) | 
| break; | 
|  | 
| vm_region_basic_info_64 basic_info; | 
| -    result = GetBasicInfo(task, &size_copy, &address_copy, &basic_info); | 
| -    switch (result) { | 
| -      case Finished: | 
| -      case Error: | 
| -        return false; | 
| -      case Success: | 
| -        break; | 
| -    } | 
| +    mach_vm_size_t dummy_size = 0; | 
| +    result = GetBasicInfo(task, &dummy_size, &address_copy, &basic_info); | 
| +    if (result == MachVMRegionResult::Error) | 
| +      return false; | 
| +    if (result == MachVMRegionResult::Finished) | 
| +      break; | 
| + | 
| bool is_wired = basic_info.user_wired_count > 0; | 
|  | 
| if (IsAddressInSharedRegion(address, cpu_type) && | 
| @@ -456,4 +421,38 @@ bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { | 
| return true; | 
| } | 
|  | 
| +// Both |size| and |address| are in-out parameters. | 
| +// |info| is an output parameter, only valid on Success. | 
| +MachVMRegionResult GetTopInfo(mach_port_t task, | 
| +                              mach_vm_size_t* size, | 
| +                              mach_vm_address_t* address, | 
| +                              vm_region_top_info_data_t* info) { | 
| +  mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; | 
| +  mach_port_t object_name; | 
| +  kern_return_t kr = mach_vm_region(task, address, size, VM_REGION_TOP_INFO, | 
| +                                    reinterpret_cast<vm_region_info_t>(info), | 
| +                                    &info_count, &object_name); | 
| +  // The kernel always returns a null object for VM_REGION_TOP_INFO, but | 
| +  // balance it with a deallocate in case this ever changes. See 10.9.2 | 
| +  // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. | 
| +  mach_port_deallocate(task, object_name); | 
| +  return ParseOutputFromMachVMRegion(kr); | 
| +} | 
| + | 
| +MachVMRegionResult GetBasicInfo(mach_port_t task, | 
| +                                mach_vm_size_t* size, | 
| +                                mach_vm_address_t* address, | 
| +                                vm_region_basic_info_64* info) { | 
| +  mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64; | 
| +  mach_port_t object_name; | 
| +  kern_return_t kr = mach_vm_region( | 
| +      task, address, size, VM_REGION_BASIC_INFO_64, | 
| +      reinterpret_cast<vm_region_info_t>(info), &info_count, &object_name); | 
| +  // The kernel always returns a null object for VM_REGION_BASIC_INFO_64, but | 
| +  // balance it with a deallocate in case this ever changes. See 10.9.2 | 
| +  // xnu-2422.90.20/osfmk/vm/vm_map.c vm_map_region. | 
| +  mach_port_deallocate(task, object_name); | 
| +  return ParseOutputFromMachVMRegion(kr); | 
| +} | 
| + | 
| }  // namespace base | 
|  |