Files
ObsidianDragon/src/wallet/lite_owned_string.cpp
T
dan_sandClaude Opus 4.8 27d11ebe6d refactor(lite): extract owned-string core, drop dead bridge-runtime scaffold
lite_bridge_runtime.{cpp,h} was ~25k lines of dry-dispatch / dynamic-loader
scaffolding that the shipping wallet never used: 0 of its 122 public types
reached the app binary. The only live code on the bridge path was the
owned-string memory-safety helper — LiteClientBridge::linkedSdxl() already
loads the backend via direct litelib_* externs in lite_client_bridge.cpp.

- Extract LiteBridgeOwnedString + liteBridgeRuntimeTakeOwnedString into
  src/wallet/lite_owned_string.{h,cpp} (the copy-before-free / free-once /
  wipe / "Error:"-classify boundary), with the runtime-friend coupling removed.
- Point lite_client_bridge.cpp at the new header.
- Delete lite_bridge_runtime.{cpp,h} and the 16 runtime-only tests +
  their fixtures/aliases in test_phase4.cpp; keep the 5 owned-string tests
  (retargeted) and restore testGeneratedResourceBehavior, which had been
  caught in the runtime-test line range.
- Swap the CMake source/header references.

Both variants build; full test suite passes; source-hygiene check clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 08:56:55 -05:00

124 lines
3.2 KiB
C++

// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
#include "lite_owned_string.h"
#include <algorithm>
#include <utility>
namespace dragonx {
namespace wallet {
namespace {
// A backend response is a failure when it is prefixed with "Error:" (the litelib_* convention).
bool looksLikeError(const std::string& value)
{
return value.rfind("Error:", 0) == 0;
}
// Best-effort scrub of a copied secret-ish payload before the string is released.
void wipeString(std::string& value)
{
std::fill(value.begin(), value.end(), '\0');
value.clear();
}
} // namespace
LiteBridgeOwnedString::LiteBridgeOwnedString(char* rawValue, FreeStringFn freeString)
: rawValue_(rawValue),
freeString_(freeString),
rawPointerReceived_(rawValue != nullptr)
{
}
LiteBridgeOwnedString::LiteBridgeOwnedString(LiteBridgeOwnedString&& other) noexcept
{
moveFrom(std::move(other));
}
LiteBridgeOwnedString& LiteBridgeOwnedString::operator=(LiteBridgeOwnedString&& other) noexcept
{
if (this == &other) return *this;
copyValueBeforeFree();
releaseRawValue();
wipeString(copiedValue_);
moveFrom(std::move(other));
return *this;
}
LiteBridgeOwnedString::~LiteBridgeOwnedString()
{
copyValueBeforeFree();
releaseRawValue();
wipeString(copiedValue_);
}
LiteBridgeStringResult LiteBridgeOwnedString::intoResult()
{
if (resultTaken_) return {false, {}, "lite bridge string result already consumed"};
resultTaken_ = true;
if (!rawPointerReceived_) return {false, {}, "lite bridge returned a null string"};
if (!rawValue_) return {false, {}, "lite bridge string was already released"};
if (!freeString_) {
rawValue_ = nullptr;
return {false, {}, "lite bridge freeString function is unavailable"};
}
copyValueBeforeFree();
releaseRawValue();
const std::string resultValue = copiedValue_;
wipeString(copiedValue_);
if (looksLikeError(resultValue)) return {false, {}, resultValue};
return {true, resultValue, {}};
}
void LiteBridgeOwnedString::copyValueBeforeFree()
{
if (!rawValue_ || copiedBeforeFree_) return;
copiedValue_ = rawValue_;
copiedBeforeFree_ = true;
}
void LiteBridgeOwnedString::releaseRawValue()
{
if (!rawValue_) return;
if (freeString_) {
freeString_(rawValue_);
freed_ = true;
}
rawValue_ = nullptr;
}
void LiteBridgeOwnedString::moveFrom(LiteBridgeOwnedString&& other) noexcept
{
rawValue_ = other.rawValue_;
freeString_ = other.freeString_;
rawPointerReceived_ = other.rawPointerReceived_;
copiedBeforeFree_ = other.copiedBeforeFree_;
freed_ = other.freed_;
resultTaken_ = other.resultTaken_;
copiedValue_ = std::move(other.copiedValue_);
other.rawValue_ = nullptr;
other.freeString_ = nullptr;
other.rawPointerReceived_ = false;
other.copiedBeforeFree_ = false;
other.freed_ = false;
other.resultTaken_ = true;
wipeString(other.copiedValue_);
}
LiteBridgeStringResult liteBridgeRuntimeTakeOwnedString(
char* rawValue,
LiteClientBridgeApi::FreeStringFn freeString)
{
LiteBridgeOwnedString ownedString(rawValue, freeString);
return ownedString.intoResult();
}
} // namespace wallet
} // namespace dragonx