From 08cbc8f33fe8d1ecdd01787329703c1bb03f0d01 Mon Sep 17 00:00:00 2001 From: Matt Liberty Date: Wed, 22 May 2024 13:35:19 -0700 Subject: [PATCH] odb: carefully preserve the object ids across recycling Currently the code assumes that placement new won't change the oid but that doesn't appear to be true in newer compilers. Fixes #5142 Signed-off-by: Matt Liberty --- src/odb/src/db/dbArrayTable.hpp | 8 +++++--- src/odb/src/db/dbTable.hpp | 11 +++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/odb/src/db/dbArrayTable.hpp b/src/odb/src/db/dbArrayTable.hpp index d1a048b913b..a9d2de558be 100644 --- a/src/odb/src/db/dbArrayTable.hpp +++ b/src/odb/src/db/dbArrayTable.hpp @@ -248,9 +248,10 @@ T* dbArrayTable::create() } _dbFreeObject* o = popQ(_free_list); - o->_oid |= DB_ALLOC_BIT; + const uint oid = o->_oid; new (o) T(_db); T* t = (T*) o; + t->_oid = oid | DB_ALLOC_BIT; dbArrayTablePage* page = (dbArrayTablePage*) t->getObjectPage(); page->_alloccnt++; @@ -302,8 +303,9 @@ void dbArrayTable::destroy(T* t) _dbFreeObject* o = (_dbFreeObject*) t; page->_alloccnt--; + const uint oid = t->_oid; t->~T(); // call destructor - o->_oid &= ~DB_ALLOC_BIT; + o->_oid = oid & ~DB_ALLOC_BIT; // Add to freelist pushQ(_free_list, o); @@ -395,8 +397,8 @@ void dbArrayTable::copy_page(uint page_id, dbArrayTablePage* page) for (; t < e; t++, o++) { if (t->_oid & DB_ALLOC_BIT) { - o->_oid = t->_oid; new (o) T(_db, *t); + o->_oid = t->_oid; } else { *((_dbFreeObject*) o) = *((_dbFreeObject*) t); } diff --git a/src/odb/src/db/dbTable.hpp b/src/odb/src/db/dbTable.hpp index a9073a04139..2800fb5d1af 100644 --- a/src/odb/src/db/dbTable.hpp +++ b/src/odb/src/db/dbTable.hpp @@ -249,9 +249,10 @@ T* dbTable::create() } _dbFreeObject* o = popQ(_free_list); + const uint oid = o->_oid; new (o) T(_db); - o->_oid |= DB_ALLOC_BIT; T* t = (T*) o; + t->_oid = oid | DB_ALLOC_BIT; dbTablePage* page = (dbTablePage*) t->getObjectPage(); page->_alloccnt++; @@ -279,9 +280,10 @@ T* dbTable::duplicate(T* c) } _dbFreeObject* o = popQ(_free_list); - o->_oid |= DB_ALLOC_BIT; + uint oid = o->_oid; new (o) T(_db, *c); T* t = (T*) o; + t->_oid = oid | DB_ALLOC_BIT; dbTablePage* page = (dbTablePage*) t->getObjectPage(); page->_alloccnt++; @@ -422,8 +424,9 @@ void dbTable::destroy(T* t) _dbFreeObject* o = (_dbFreeObject*) t; page->_alloccnt--; + const uint oid = t->_oid; t->~T(); // call destructor - o->_oid &= ~DB_ALLOC_BIT; + o->_oid = oid & ~DB_ALLOC_BIT; uint offset = t - (T*) page->_objects; uint id = page->_page_addr + offset; @@ -613,8 +616,8 @@ void dbTable::copy_page(uint page_id, dbTablePage* page) for (; t < e; t++, o++) { if (t->_oid & DB_ALLOC_BIT) { - o->_oid = t->_oid; new (o) T(_db, *t); + o->_oid = t->_oid; } else { *((_dbFreeObject*) o) = *((_dbFreeObject*) t); }