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 |