From c2f6e92abc1a18b9edf377a180b768d0d4eff76c Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Thu, 21 May 2026 11:26:37 -0500 Subject: [PATCH 1/2] protect DF pooled objects from being deleted --- docs/changelog.txt | 1 + library/include/DataDefs.h | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index 113fc16ba9..735ddddf4e 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -61,6 +61,7 @@ Template for new versions: ## Fixes ## Misc Improvements +- Core: attempts to delete a pool-allocated DF object will now throw an exception instead of corrupting the heap ## Documentation diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index 88c4a93651..aabcfdd9db 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -24,14 +24,15 @@ distribution. #pragma once +#include #include #include #include +#include #include #include #include #include -#include #include "BitArray.h" #include "Export.h" @@ -572,15 +573,21 @@ namespace df * */ + template concept pooled_object = requires () { { T::pool_id } -> std::convertible_to; }; + template concept copy_assignable = std::assignable_from && std::assignable_from; template void *allocator_fn(void *out, const void *in) { - if (out) + // unerase type + T* _out = out ? reinterpret_cast(out) : nullptr; + const T* _in = in ? reinterpret_cast(in) : nullptr; + + if (_out) { if constexpr (copy_assignable) { - *(T*)out = *(const T*)in; + *_out = *_in; return out; } else @@ -588,13 +595,20 @@ namespace df return nullptr; } } - else if (in) + else if (_in) { + if constexpr (pooled_object) + { + if (_in->pool_id != -1) + { + throw std::runtime_error("Pool-allocated type cannot be deallocated with allocator_fn"); + } + } #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor" - delete (T*)in; + delete _in; #pragma GCC diagnostic pop - return (T*)in; + return const_cast(in); } else return new T(); From ab59c374923cba0ccba5c0a32154d37cf49f6c4f Mon Sep 17 00:00:00 2001 From: Kelly Kinkade Date: Thu, 21 May 2026 11:39:03 -0500 Subject: [PATCH 2/2] `pool_id`s are `size_t` --- library/include/DataDefs.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/include/DataDefs.h b/library/include/DataDefs.h index aabcfdd9db..37892391a4 100644 --- a/library/include/DataDefs.h +++ b/library/include/DataDefs.h @@ -573,12 +573,14 @@ namespace df * */ - template concept pooled_object = requires () { { T::pool_id } -> std::convertible_to; }; + using df_pool_id_t = size_t; + template concept pooled_object = requires () { { T::pool_id } -> std::convertible_to; }; template concept copy_assignable = std::assignable_from && std::assignable_from; template void *allocator_fn(void *out, const void *in) { + constexpr df_pool_id_t invalid_pool_id = static_cast(-1); // unerase type T* _out = out ? reinterpret_cast(out) : nullptr; const T* _in = in ? reinterpret_cast(in) : nullptr; @@ -599,7 +601,7 @@ namespace df { if constexpr (pooled_object) { - if (_in->pool_id != -1) + if (_in->pool_id != invalid_pool_id) { throw std::runtime_error("Pool-allocated type cannot be deallocated with allocator_fn"); }