Fix copy / move behaviour of Maps object.

Currently, moving or copying a Maps object leads to double free of MapInfo.

Even moving a Maps object  did not prevent this, as after a move
the object only has to be in an "unspecified but valid state", which can
be the original state for a vector of raw pointers (but not for a vector
of unique_ptrs).

Changing to unique_ptrs is the most failsafe way to make sure we never
accidentally destruct MapInfo.

Test: atest libuwindstack_test
      Failed LocalUnwinderTest#unwind_after_dlopen which also fails at master.

Change-Id: Id1c9739b334da5c1ba532fd55366e115940a66d3
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 1e4f72e..5da73e4 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -47,9 +47,9 @@
   size_t last = maps_.size();
   while (first < last) {
     size_t index = (first + last) / 2;
-    MapInfo* cur = maps_[index];
+    const auto& cur = maps_[index];
     if (pc >= cur->start && pc < cur->end) {
-      return cur;
+      return cur.get();
     } else if (pc < cur->start) {
       last = index;
     } else {
@@ -67,34 +67,31 @@
         if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
         }
-        maps_.push_back(
-            new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
+        maps_.emplace_back(
+            new MapInfo(maps_.empty() ? nullptr : maps_.back().get(), start, end, pgoff,
+                        flags, name));
       });
 }
 
 void Maps::Add(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags,
                const std::string& name, uint64_t load_bias) {
-  MapInfo* map_info =
-      new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, offset, flags, name);
+  auto map_info =
+      std::make_unique<MapInfo>(maps_.empty() ? nullptr : maps_.back().get(), start, end, offset,
+                                flags, name);
   map_info->load_bias = load_bias;
-  maps_.push_back(map_info);
+  maps_.emplace_back(std::move(map_info));
 }
 
 void Maps::Sort() {
   std::sort(maps_.begin(), maps_.end(),
-            [](const MapInfo* a, const MapInfo* b) { return a->start < b->start; });
+            [](const std::unique_ptr<MapInfo>& a, const std::unique_ptr<MapInfo>& b) {
+              return a->start < b->start; });
 
   // Set the prev_map values on the info objects.
   MapInfo* prev_map = nullptr;
-  for (MapInfo* map_info : maps_) {
+  for (const auto& map_info : maps_) {
     map_info->prev_map = prev_map;
-    prev_map = map_info;
-  }
-}
-
-Maps::~Maps() {
-  for (auto& map : maps_) {
-    delete map;
+    prev_map = map_info.get();
   }
 }
 
@@ -107,8 +104,9 @@
         if (strncmp(name, "/dev/", 5) == 0 && strncmp(name + 5, "ashmem/", 7) != 0) {
           flags |= unwindstack::MAPS_FLAGS_DEVICE_MAP;
         }
-        maps_.push_back(
-            new MapInfo(maps_.empty() ? nullptr : maps_.back(), start, end, pgoff, flags, name));
+        maps_.emplace_back(
+            new MapInfo(maps_.empty() ? nullptr : maps_.back().get(), start, end, pgoff,
+                        flags, name));
       });
 }
 
@@ -124,10 +122,6 @@
   // New maps will be added at the end without deleting the old ones.
   size_t last_map_idx = maps_.size();
   if (!Parse()) {
-    // Delete any maps added by the Parse call.
-    for (size_t i = last_map_idx; i < maps_.size(); i++) {
-      delete maps_[i];
-    }
     maps_.resize(last_map_idx);
     return false;
   }
@@ -135,17 +129,16 @@
   size_t total_entries = maps_.size();
   size_t search_map_idx = 0;
   for (size_t new_map_idx = last_map_idx; new_map_idx < maps_.size(); new_map_idx++) {
-    MapInfo* new_map_info = maps_[new_map_idx];
+    auto& new_map_info = maps_[new_map_idx];
     uint64_t start = new_map_info->start;
     uint64_t end = new_map_info->end;
     uint64_t flags = new_map_info->flags;
     std::string* name = &new_map_info->name;
     for (size_t old_map_idx = search_map_idx; old_map_idx < last_map_idx; old_map_idx++) {
-      MapInfo* info = maps_[old_map_idx];
+      auto& info = maps_[old_map_idx];
       if (start == info->start && end == info->end && flags == info->flags && *name == info->name) {
         // No need to check
         search_map_idx = old_map_idx + 1;
-        delete new_map_info;
         maps_[new_map_idx] = nullptr;
         total_entries--;
         break;
@@ -158,7 +151,7 @@
       // Never delete these maps, they may be in use. The assumption is
       // that there will only every be a handfull of these so waiting
       // to destroy them is not too expensive.
-      saved_maps_.push_back(info);
+      saved_maps_.emplace_back(std::move(info));
       maps_[old_map_idx] = nullptr;
       total_entries--;
     }
@@ -169,14 +162,14 @@
 
   // Now move out any of the maps that never were found.
   for (size_t i = search_map_idx; i < last_map_idx; i++) {
-    saved_maps_.push_back(maps_[i]);
+    saved_maps_.emplace_back(std::move(maps_[i]));
     maps_[i] = nullptr;
     total_entries--;
   }
 
   // Sort all of the values such that the nullptrs wind up at the end, then
   // resize them away.
-  std::sort(maps_.begin(), maps_.end(), [](const auto* a, const auto* b) {
+  std::sort(maps_.begin(), maps_.end(), [](const auto& a, const auto& b) {
     if (a == nullptr) {
       return false;
     } else if (b == nullptr) {
@@ -189,10 +182,4 @@
   return true;
 }
 
-LocalUpdatableMaps::~LocalUpdatableMaps() {
-  for (auto map_info : saved_maps_) {
-    delete map_info;
-  }
-}
-
 }  // namespace unwindstack