Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
- name: Install vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgGitCommitId: c82f74667287d3dc386bce81e44964370c91a289
vcpkgGitCommitId: 66c0373dc7fca549e5803087b9487edfe3aca0a1
runVcpkgInstall: true
- name: create $ACE_ROOT/ace/config.h
run: |
Expand All @@ -123,7 +123,7 @@ jobs:
- name: create $ACE_ROOT/bin/MakeProjectCreator/config/default.features
run: |
echo "ipv6=1" | out-file -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
echo "xerces3=1" | out-file -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
echo "xerces3=1" | out-file -append -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
echo "ssl=1" | out-file -append -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
echo "openssl11=1" | out-file -append -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
echo "versioned_namespace=1" | out-file -append -encoding ASCII ${env:ACE_ROOT}/bin/MakeProjectCreator/config/default.features
Expand Down
102 changes: 102 additions & 0 deletions ACE/tests/Compiler_Features_43_Test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* Test runtime behavior when throwing a plain C++ pointer in recursion
*/

#include "test_config.h"
#include <cstdio>
#include <vector>
#include <memory>

namespace DynamicAny {
struct DynAny { virtual ~DynAny() = default; };
struct DynValue : virtual DynAny {};
struct DynValueCommon : virtual DynAny {};
}

struct TAO_DynCommon : virtual DynamicAny::DynAny {
virtual ~TAO_DynCommon()
{
ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynCommon %@\n"), this));
}
};
struct TAO_DynAny_i : virtual TAO_DynCommon, virtual DynamicAny::DynAny {
virtual ~TAO_DynAny_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynAny_i %@\n"), this)); }
};
struct TAO_DynValueCommon_i : virtual TAO_DynAny_i, virtual DynamicAny::DynValueCommon {
virtual ~TAO_DynValueCommon_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynValueCommon_i %@\n"), this)); }
};
// ============================================================
// CreateDynAnyUtils<T>
// ============================================================
template<typename DA_IMPL>
struct CreateDynAnyUtils {
static DA_IMPL* create(bool trigger, int depth = 0) {
ACE_DEBUG ((LM_DEBUG, ACE_TEXT("[Create depth=%d] new DA_IMPL\n"), depth));
DA_IMPL* p = new DA_IMPL();
std::unique_ptr<DA_IMPL> guard(p);
try {
p->from_inputCDR(trigger, depth);
}
catch (DA_IMPL* original) {
ACE_DEBUG ((LM_DEBUG, ACE_TEXT("!!! CAUGHT pointer %@ at depth %d (destroying blank %@) !!!\n"),
original, depth, p));
return original;
}
return guard.release();
}
};
// ============================================================
// TAO_DynValue_i
// ============================================================
struct TAO_DynValue_i : virtual DynamicAny::DynValue, virtual TAO_DynValueCommon_i {
TAO_DynValue_i() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("TAO_DynValue_i ctor %@\n"), this)); }
~TAO_DynValue_i() override { ACE_DEBUG ((LM_DEBUG, ACE_TEXT("~TAO_DynValue_i dtor %@\n"), this)); }
static TAO_DynValue_i* cached ;
std::vector<void*> da_members_;
void from_inputCDR(bool trigger_indirection, int depth) {
ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" from_inputCDR depth=%d this=%@\n"), depth, this));
// Simulates deep recursion of ACE_TAO (exactly like in the real DynValue_i)
if (depth < 3) {
ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" Creating nested member at depth %d\n"), depth + 1));
try {
auto* member = CreateDynAnyUtils<TAO_DynValue_i>::create(trigger_indirection, depth + 1);
da_members_.push_back(member);
}
catch (TAO_DynValue_i* orig) {
ACE_DEBUG ((LM_DEBUG,ACE_TEXT(" Nested member threw indirection %@\n"), orig));
da_members_.push_back(orig);
}
Comment on lines +55 to +68
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

da_members_ stores raw void with no cleanup — p1 and p3 are leaked.*

When p0 is deleted in run_main, p0->da_members_ (holding p1 as void*) is destroyed without deleting the pointed-to object, because std::vector<void*> has no element destructor. p1 itself is therefore never freed, and p1->da_members_ (holding p3) leaks transitively. This is a simplified stand-in for the real TAO refcounting, but the stubs provide no _remove_ref/delete path, so LeakSanitizer/Valgrind will flag these as definite leaks.

If this is intentional, a comment noting the deliberate omission of cleanup would prevent false alarms and clarify intent for future readers.

🧰 Tools
🪛 Cppcheck (2.19.0)

[error] 61-61: #error ACE/TAO require C++17 compliance, please upgrade your compiler and/or fix the platform configuration for your environment

(preprocessorErrorDirective)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ACE/tests/Compiler_Features_43_Test.cpp` around lines 55 - 68, da_members_
currently holds raw void* (in from_inputCDR where
CreateDynAnyUtils<TAO_DynValue_i>::create stores members), causing leaked
objects when owners like p0 are destroyed (p1/p3 leaked); fix by making
ownership explicit: change da_members_ to store TAO_DynValue_i* (or better
std::unique_ptr<TAO_DynValue_i>), and ensure the owning class (where
from_inputCDR is defined) deletes or lets unique_ptr clean up members in its
destructor, or if non-owning pointers are intended, add a clear comment above
da_members_ and in run_main explaining deliberate omission so leak detectors
won’t be confused.

}
if (trigger_indirection && cached && depth >= 2) {
ACE_DEBUG ((LM_DEBUG,ACE_TEXT("*** INDIRECTION - THROWING CACHED POINTER %@ ***\n"), cached));
cached->_add_ref();
throw cached; // throw of the raw pointer
}
if (!cached) cached = this;
}
void _add_ref() { ACE_DEBUG ((LM_DEBUG, ACE_TEXT(" _add_ref on %@\n"), this)); }
};
TAO_DynValue_i* TAO_DynValue_i::cached = nullptr;

int run_main (int, ACE_TCHAR*[])
{
ACE_START_TEST (ACE_TEXT ("Compiler_Features_43_Test"));

int res = {};

TAO_DynValue_i::cached = nullptr;
try
{
auto* result = CreateDynAnyUtils<TAO_DynValue_i>::create(true, 0);
ACE_DEBUG ((LM_DEBUG, ACE_TEXT("Success - returned %@\n"), result));
delete result;
}
catch (...) {
ACE_ERROR ((LM_ERROR, ACE_TEXT("In outer catch\n")));
res = -1;
}

ACE_END_TEST;

return res;
}
1 change: 1 addition & 0 deletions ACE/tests/run_test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ Compiler_Features_39_Test
Compiler_Features_40_Test
Compiler_Features_41_Test
Compiler_Features_42_Test
Compiler_Features_43_Test
Config_Test: !LynxOS !VxWorks !ACE_FOR_TAO
Conn_Test: !ACE_FOR_TAO
DLL_Test: !STATIC
Expand Down
7 changes: 7 additions & 0 deletions ACE/tests/tests.mpc
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,13 @@ project(Compiler_Features_42_Test) : acetest {
}
}

project(Compiler_Features_43_Test) : acetest {
exename = Compiler_Features_43_Test
Source_Files {
Compiler_Features_43_Test.cpp
}
}

project(Config Test) : acetest {
avoids += ace_for_tao
exename = Config_Test
Expand Down
Loading