Merge "fs_mgr: Fix return in error case"
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 0f5af14..2da0103 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -606,17 +606,17 @@
 std::ostream& operator<<(std::ostream& os, Request request) {
     switch (request) {
         case Request::LOCK_SHARED:
-            return os << "LOCK_SHARED";
+            return os << "Shared";
         case Request::LOCK_EXCLUSIVE:
-            return os << "LOCK_EXCLUSIVE";
+            return os << "Exclusive";
         case Request::UNLOCK:
-            return os << "UNLOCK";
+            return os << "Unlock";
         case Request::EXIT:
-            return os << "EXIT";
+            return os << "Exit";
         case Request::UNKNOWN:
             [[fallthrough]];
         default:
-            return os << "UNKNOWN";
+            return os << "Unknown";
     }
 }
 
@@ -746,7 +746,7 @@
                         LockTestParam{Request::LOCK_SHARED, Request::LOCK_EXCLUSIVE}),
         [](const testing::TestParamInfo<LockTestP::ParamType>& info) {
             std::stringstream ss;
-            ss << info.param.first << "_" << info.param.second;
+            ss << info.param.first << info.param.second;
             return ss.str();
         });
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 5ca1fee..225bc9c 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -834,7 +834,7 @@
 }
 
 static void HandleUserspaceReboot() {
-    if (!android::sysprop::InitProperties::userspace_reboot_in_progress().value_or(false)) {
+    if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) {
         LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it";
         return;
     }
diff --git a/init/service.cpp b/init/service.cpp
index a97935e..0e27ff1 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -325,8 +325,8 @@
                     LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
                                << (boot_completed ? "in 4 minutes" : "before boot completed");
                     // Notifies update_verifier and apexd
-                    SetProperty("sys.init.updatable_crashing", "1");
                     SetProperty("sys.init.updatable_crashing_process_name", name_);
+                    SetProperty("sys.init.updatable_crashing", "1");
                 }
             }
         } else {
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 7676289..341275d 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -78,10 +78,31 @@
   CrcGenerateTable();
   Crc64GenerateTable();
 
-  std::vector<uint8_t> src(gnu_debugdata_size_);
-  if (!memory_->ReadFully(gnu_debugdata_offset_, src.data(), gnu_debugdata_size_)) {
-    gnu_debugdata_offset_ = 0;
-    gnu_debugdata_size_ = static_cast<uint64_t>(-1);
+  // Verify the request is not larger than the max size_t value.
+  if (gnu_debugdata_size_ > SIZE_MAX) {
+    return nullptr;
+  }
+  size_t initial_buffer_size;
+  if (__builtin_mul_overflow(5, gnu_debugdata_size_, &initial_buffer_size)) {
+    return nullptr;
+  }
+
+  size_t buffer_increment;
+  if (__builtin_mul_overflow(2, gnu_debugdata_size_, &buffer_increment)) {
+    return nullptr;
+  }
+
+  std::unique_ptr<uint8_t[]> src(new (std::nothrow) uint8_t[gnu_debugdata_size_]);
+  if (src.get() == nullptr) {
+    return nullptr;
+  }
+
+  std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
+  if (!dst->Resize(initial_buffer_size)) {
+    return nullptr;
+  }
+
+  if (!memory_->ReadFully(gnu_debugdata_offset_, src.get(), gnu_debugdata_size_)) {
     return nullptr;
   }
 
@@ -89,21 +110,23 @@
   CXzUnpacker state;
   alloc.Alloc = [](ISzAllocPtr, size_t size) { return malloc(size); };
   alloc.Free = [](ISzAllocPtr, void* ptr) { return free(ptr); };
-
   XzUnpacker_Construct(&state, &alloc);
 
-  std::unique_ptr<MemoryBuffer> dst(new MemoryBuffer);
   int return_val;
   size_t src_offset = 0;
   size_t dst_offset = 0;
   ECoderStatus status;
-  dst->Resize(5 * gnu_debugdata_size_);
   do {
-    size_t src_remaining = src.size() - src_offset;
+    size_t src_remaining = gnu_debugdata_size_ - src_offset;
     size_t dst_remaining = dst->Size() - dst_offset;
-    if (dst_remaining < 2 * gnu_debugdata_size_) {
-      dst->Resize(dst->Size() + 2 * gnu_debugdata_size_);
-      dst_remaining += 2 * gnu_debugdata_size_;
+    if (dst_remaining < buffer_increment) {
+      size_t new_size;
+      if (__builtin_add_overflow(dst->Size(), buffer_increment, &new_size) ||
+          !dst->Resize(new_size)) {
+        XzUnpacker_Free(&state);
+        return nullptr;
+      }
+      dst_remaining += buffer_increment;
     }
     return_val = XzUnpacker_Code(&state, dst->GetPtr(dst_offset), &dst_remaining, &src[src_offset],
                                  &src_remaining, true, CODER_FINISH_ANY, &status);
@@ -112,13 +135,13 @@
   } while (return_val == SZ_OK && status == CODER_STATUS_NOT_FINISHED);
   XzUnpacker_Free(&state);
   if (return_val != SZ_OK || !XzUnpacker_IsStreamWasFinished(&state)) {
-    gnu_debugdata_offset_ = 0;
-    gnu_debugdata_size_ = static_cast<uint64_t>(-1);
     return nullptr;
   }
 
   // Shrink back down to the exact size.
-  dst->Resize(dst_offset);
+  if (!dst->Resize(dst_offset)) {
+    return nullptr;
+  }
 
   return dst.release();
 }
diff --git a/libunwindstack/Memory.cpp b/libunwindstack/Memory.cpp
index a66cd5b..8de3d98 100644
--- a/libunwindstack/Memory.cpp
+++ b/libunwindstack/Memory.cpp
@@ -206,12 +206,12 @@
 }
 
 size_t MemoryBuffer::Read(uint64_t addr, void* dst, size_t size) {
-  if (addr >= raw_.size()) {
+  if (addr >= size_) {
     return 0;
   }
 
-  size_t bytes_left = raw_.size() - static_cast<size_t>(addr);
-  const unsigned char* actual_base = static_cast<const unsigned char*>(raw_.data()) + addr;
+  size_t bytes_left = size_ - static_cast<size_t>(addr);
+  const unsigned char* actual_base = static_cast<const unsigned char*>(raw_) + addr;
   size_t actual_len = std::min(bytes_left, size);
 
   memcpy(dst, actual_base, actual_len);
@@ -219,7 +219,7 @@
 }
 
 uint8_t* MemoryBuffer::GetPtr(size_t offset) {
-  if (offset < raw_.size()) {
+  if (offset < size_) {
     return &raw_[offset];
   }
   return nullptr;
diff --git a/libunwindstack/MemoryBuffer.h b/libunwindstack/MemoryBuffer.h
index 3fe4bbb..a91e59f 100644
--- a/libunwindstack/MemoryBuffer.h
+++ b/libunwindstack/MemoryBuffer.h
@@ -29,18 +29,27 @@
 class MemoryBuffer : public Memory {
  public:
   MemoryBuffer() = default;
-  virtual ~MemoryBuffer() = default;
+  virtual ~MemoryBuffer() { free(raw_); }
 
   size_t Read(uint64_t addr, void* dst, size_t size) override;
 
   uint8_t* GetPtr(size_t offset);
 
-  void Resize(size_t size) { raw_.resize(size); }
+  bool Resize(size_t size) {
+    raw_ = reinterpret_cast<uint8_t*>(realloc(raw_, size));
+    if (raw_ == nullptr) {
+      size_ = 0;
+      return false;
+    }
+    size_ = size;
+    return true;
+  }
 
-  uint64_t Size() { return raw_.size(); }
+  uint64_t Size() { return size_; }
 
  private:
-  std::vector<uint8_t> raw_;
+  uint8_t* raw_ = nullptr;
+  size_t size_ = 0;
 };
 
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index c33908d..fc90dab 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -105,6 +105,9 @@
   void FakeSetDynamicVaddrStart(uint64_t vaddr) { dynamic_vaddr_start_ = vaddr; }
   void FakeSetDynamicVaddrEnd(uint64_t vaddr) { dynamic_vaddr_end_ = vaddr; }
 
+  void FakeSetGnuDebugdataOffset(uint64_t offset) { gnu_debugdata_offset_ = offset; }
+  void FakeSetGnuDebugdataSize(uint64_t size) { gnu_debugdata_size_ = size; }
+
  private:
   std::unordered_map<std::string, uint64_t> globals_;
   std::string fake_build_id_;
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index ea27e3e..3cf90fe 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -1944,4 +1944,23 @@
   CheckLoadBiasInFirstExecPhdr<Elf64_Ehdr, Elf64_Phdr, ElfInterface64>(0x5000, 0x1000, -0x4000);
 }
 
+TEST_F(ElfInterfaceTest, huge_gnu_debugdata_size) {
+  ElfInterfaceFake interface(nullptr);
+
+  interface.FakeSetGnuDebugdataOffset(0x1000);
+  interface.FakeSetGnuDebugdataSize(0xffffffffffffffffUL);
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+
+  interface.FakeSetGnuDebugdataSize(0x4000000000000UL);
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+
+  // This should exceed the size_t value of the first allocation.
+#if defined(__LP64__)
+  interface.FakeSetGnuDebugdataSize(0x3333333333333334ULL);
+#else
+  interface.FakeSetGnuDebugdataSize(0x33333334);
+#endif
+  ASSERT_TRUE(interface.CreateGnuDebugdataMemory() == nullptr);
+}
+
 }  // namespace unwindstack
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 42c6efb..89f048d 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -455,6 +455,7 @@
 };
 
 #undef COMPARE_WEAK
+#undef COMPARE_WEAK_FUNCTIONAL
 
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 07dd3f1..100e507 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -134,7 +134,8 @@
 void sp_report_race();
 void sp_report_stack_pointer();
 
-#undef COMPARE
+#undef COMPARE_STRONG
+#undef COMPARE_STRONG_FUNCTIONAL
 
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 9cf11a4..fdfcde8 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -978,9 +978,11 @@
 
 on userspace-reboot-requested
   # TODO(b/135984674): reset all necessary properties here.
-  setprop sys.boot_completed 0
-  setprop sys.init.updatable_crashing 0
+  setprop sys.boot_completed ""
+  setprop sys.init.updatable_crashing ""
+  setprop sys.init.updatable_crashing_process_name ""
   setprop apexd.status ""
+  setprop sys.user.0.ce_available ""
 
 on userspace-reboot-fs-remount
   # Make sure that vold is running.