Merge bitcoin/bitcoin#22278: Add LIFETIMEBOUND to CScript where needed

fa7e6c56f5 Add LIFETIMEBOUND to InitializeChainstate (MarcoFalke)
fa5c896724 Add LIFETIMEBOUND to CScript where needed (MarcoFalke)

Pull request description:

  Without this, stack-use-after-scope can only be detected at runtime with ASan or code review, both of which are expensive.

  Use `LIFETIMEBOUND` to turn this error into a compile warning.

  See https://releases.llvm.org/12.0.0/tools/clang/docs/AttributeReference.html#lifetimebound

  Example:

  ```cpp
  const CScript a{WITH_LOCK(::cs_main, return CScript{} << OP_0 << OP_1)};
  ```

  Before: (no warning)
  After:

  ```
  warning: returning reference to local temporary object [-Wreturn-stack-address]
      const CScript a{WITH_LOCK(::cs_main, return CScript{} << OP_0 << OP_1)};
                                                  ^~~~~~~~~
  ./sync.h:276:65: note: expanded from macro 'WITH_LOCK'
  #define WITH_LOCK(cs, code) [&]() -> decltype(auto) { LOCK(cs); code; }()
                                                                  ^~~~

ACKs for top commit:
  theuni:
    utACK fa7e6c56f5.
  jonatack:
    Light ACK fa7e6c56f5 debug build with clang 13, reproduced the example compiler warning in the pull description, and briefly looked at `clang::lifetimebound` support in earlier versions of clang; it is in clang 7 (https://releases.llvm.org/7.0.0/tools/clang/docs/AttributeReference.html#lifetimebound-clang-lifetimebound), did not see references to it in earlier docs

Tree-SHA512: e915acdc4532445205b7703fab61a5d682231ace78ecfb274cb8523ca2bddefd85828f50ac047cfb1afaff92a331f5f7b5a1472539f999e30f7cf8ac8c3222f3
pull/826/head
fanquake 3 years ago
commit f4e12fd50c
No known key found for this signature in database
GPG Key ID: 2EEB9F5CC09526C1

@ -6,6 +6,7 @@
#ifndef BITCOIN_SCRIPT_SCRIPT_H
#define BITCOIN_SCRIPT_SCRIPT_H
#include <attributes.h>
#include <crypto/common.h>
#include <prevector.h>
#include <serialize.h>
@ -438,9 +439,9 @@ public:
/** Delete non-existent operator to defend against future introduction */
CScript& operator<<(const CScript& b) = delete;
CScript& operator<<(int64_t b) { return push_int64(b); }
CScript& operator<<(int64_t b) LIFETIMEBOUND { return push_int64(b); }
CScript& operator<<(opcodetype opcode)
CScript& operator<<(opcodetype opcode) LIFETIMEBOUND
{
if (opcode < 0 || opcode > 0xff)
throw std::runtime_error("CScript::operator<<(): invalid opcode");
@ -448,13 +449,13 @@ public:
return *this;
}
CScript& operator<<(const CScriptNum& b)
CScript& operator<<(const CScriptNum& b) LIFETIMEBOUND
{
*this << b.getvch();
return *this;
}
CScript& operator<<(const std::vector<unsigned char>& b)
CScript& operator<<(const std::vector<unsigned char>& b) LIFETIMEBOUND
{
if (b.size() < OP_PUSHDATA1)
{

@ -929,7 +929,7 @@ public:
CChainState& InitializeChainstate(
CTxMemPool* mempool,
const std::optional<uint256>& snapshot_blockhash = std::nullopt)
EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
LIFETIMEBOUND EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
//! Get all chainstates currently being used.
std::vector<CChainState*> GetAll();

Loading…
Cancel
Save