]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os: Page class: disable move operations and improve custom delete operator for proper... 64957/head
authorEdwin Rodriguez <edwin.rodriguez1@ibm.com>
Fri, 1 Aug 2025 18:20:36 +0000 (14:20 -0400)
committerEdwin Rodriguez <edwin.rodriguez1@ibm.com>
Mon, 25 Aug 2025 17:20:07 +0000 (13:20 -0400)
Fix UB in Page 'operator delete' to eliminate uninitialized memory access

Fixes: https://tracker.ceph.com/issues/72404
Signed-off-by: Edwin Rodriguez <edwin.rodriguez1@ibm.com>
src/os/memstore/PageSet.h

index 71954e57464267ae0065430aba3492aa3ab3aa28..b7e7e7304a4f32e7f712b32da0c96c274edc3c5a 100644 (file)
@@ -75,12 +75,24 @@ struct Page {
   // copy disabled
   Page(const Page&) = delete;
   const Page& operator=(const Page&) = delete;
+  Page(Page&&) = delete;
+  Page& operator=(Page&&) = delete;
 
  private: // private constructor, use create() instead
   Page(char *data, uint64_t offset) : data(data), offset(offset), nrefs(1) {}
 
-  static void operator delete(void *p) {
-    delete[] reinterpret_cast<Page*>(p)->data;
+  // Custom delete operator that uses std::destroying_delete_t to ensure proper cleanup
+  // of the buffer-Page layout. Since Page is placed at the end of a larger allocated buffer
+  // containing both the data array and the Page object itself, we need to:
+  // 1. Store the buffer pointer before destroying the Page object
+  // 2. Call the Page destructor explicitly to destroy the object in-place
+  // 3. Delete the entire buffer containing both data and Page
+  // Without std::destroying_delete_t, the compiler would call the destructor
+  // before our delete operator, leading to unitialized memory access.
+  static void operator delete(Page *p, std::destroying_delete_t) {
+    auto* buffer = p->data;
+    p->~Page();
+    delete[] buffer;
   }
 };