diff --git a/src/rpc/rpc_client.cpp b/src/rpc/rpc_client.cpp index 9add4db..87f93a7 100644 --- a/src/rpc/rpc_client.cpp +++ b/src/rpc/rpc_client.cpp @@ -451,8 +451,8 @@ json RPCClient::parseRpcResult(long httpCode, const std::string& body, bool scru throw RpcError(errCode, "RPC error: " + err_msg, httpCode); } - json result = response["result"]; // a COPY of the subobject (operator[] yields an lvalue ref) - if (scrubSource) scrubJsonSecrets(response); // zero the discarded tree's secret before it frees (B7) + json result = std::move(response["result"]); // move the subtree out: the secret now lives only here + if (scrubSource) scrubJsonSecrets(response); // response["result"] is now moved-from (null); harmless (B7) return result; } diff --git a/src/rpc/rpc_client.h b/src/rpc/rpc_client.h index bb3ba06..4939953 100644 --- a/src/rpc/rpc_client.h +++ b/src/rpc/rpc_client.h @@ -285,9 +285,9 @@ private: // hold curl_mutex_ and have verified impl_->curl. std::string performCall(const std::string& method, const json& params, long& httpCodeOut); // Centralizes the HTTP-code check and JSON error->RpcError extraction, returning - // response["result"] on success. When scrubSource is true (secret-bearing calls), the intermediate - // parse tree's string values are zeroed before it is discarded — parseRpcResult returns a COPY of - // the result node, so its own tree would otherwise free the secret un-wiped (B7). + // response["result"] on success. The result subtree is moved out of the parse tree, so a secret lives + // only in the returned node (which callSecret/callSecretString callers wipe). When scrubSource is true + // (secret-bearing calls), any remaining parse-tree string values are zeroed before it is discarded (B7). static json parseRpcResult(long httpCode, const std::string& body, bool scrubSource = false); // A non-200 reply: RpcError when the body carries a JSON-RPC error, else RpcTransportError classified // from the status and plain-text body. hideBody keeps the body out of the message (secret calls).