Skip to content

CRing raw-owned buffer was accidentally copyable

Summary

CRing<T> owns a raw heap buffer and deletes it in its destructor, but the class had compiler-generated copy construction and copy assignment. Any accidental copy would duplicate internal raw pointers and create double-free or stale-pointer risk.

The morning dump detected heap corruption while a CRing<TransferredData> was being destroyed as part of CUpDownClient destruction. That dump did not prove that an accidental CRing copy was the concrete root cause; this item records the hardening because the ownership contract was objectively wrong.

Provenance

The raw-owner, copyable CRing<T> design was not introduced by eMuleBB. It is present in the managed stock/community baseline (community/v0.72a / baseline/community-0.72a) with:

  • raw TYPE* storage,
  • destructor-owned delete[] m_pData,
  • no deleted copy constructor,
  • no deleted copy-assignment operator.

Earlier eMuleBB work in 0d7b0fe fixed pointer-state correctness issues in the ring implementation, but did not create or close this copyability gap.

The workspace does not currently contain a 0.73 stock tag or branch. The newest local/upstream community comparison point observed during the trace was 0.72a-community.

eMuleAI Latest Status

Checked against eMuleAI upstream master at 8e34bdec2b7e4fe9e4307df9d80f691804be99ed (eMuleAIv1.4) on 2026-05-24. eMuleAI latest does not have srchybrid/Ring.h or CRing<T> in the checked tree. Its corresponding rate-history members use CList<TransferredData> instead.

Conclusion: this exact CRing<T> bug is not applicable to eMuleAI latest, because eMuleAI does not carry the CRing<T> implementation.

Resolution

Fixed on eMuleBB main by app commit cdd2243 (BUG-017 make ring buffers single-owner). The fix deletes copy construction and copy assignment for CRing<T>, making the raw-owned buffer explicitly single-owner.

Regression coverage was added in test commit b63382f (BUG-017 cover single-owner ring buffers).

Validation

  • Native Debug parity: passed, 729 passed / 0 failed / 237 skipped.
  • Native Release parity: passed, 726 passed / 0 failed / 237 skipped.
  • x64 Debug app build: passed.
  • x64 Release app build: passed.