Merge bitcoin/bitcoin#36054: test: add script_tests cases covering interpreter mutants

4a12773f26 test: cover DERSIG rejects a non-compound signature type (ViniciusCestarii)
86c7fb910d test: cover OP_16 does not count towards the opcode limit (ViniciusCestarii)
331bf79881 test: cover OP_WITHIN must pop all 3 elements (ViniciusCestarii)
3bb87bc61b test: cover OP_FROMALTSTACK must pop the altstack (ViniciusCestarii)

Pull request description:

  Kills some live mutants on interpreter.cpp that affect consensus found by https://bitcoincore.space. They are:

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3951">interpreter.cpp#3951</a>: <code>OP_FROMALTSTACK</code>: removed <code>popstack(altstack)</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..68265d20b5 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -698,7 +698,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
                       if (altstack.size() < 1)
                           return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION);
                       stack.push_back(altstacktop(-1));
  -                    popstack(altstack);
  +
                   }
                   break;
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#4084">interpreter.cpp#4084</a>: <code>OP_WITHIN</code>: removed one <code>popstack(stack)</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..874cf5e1cf 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -1018,7 +1018,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
                       CScriptNum bn2(stacktop(-2), fRequireMinimal);
                       CScriptNum bn3(stacktop(-1), fRequireMinimal);
                       bool fValue = (bn2 <= bn1 && bn1 < bn3);
  -                    popstack(stack);
  +
                       popstack(stack);
                       popstack(stack);
                       stack.push_back(fValue ? vchTrue : vchFalse);
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3883">interpreter.cpp#3883</a>: opcode limit: <code>opcode > OP_16</code> → <code>opcode >= OP_16</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..e985643606 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -459,7 +459,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&

               if (sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0) {
                   // Note how OP_RESERVED does not count towards the opcode limit.
  -                if (opcode > OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
  +                if (opcode >= OP_16 && ++nOpCount > MAX_OPS_PER_SCRIPT) {
                       return set_error(serror, SCRIPT_ERR_OP_COUNT);
                   }
               }
  ```

  </details>

  <details>
  <summary><a href="https://bitcoincore.space/src/script/interpreter.cpp#3808">interpreter.cpp#3808</a>: <code>IsValidSignatureEncoding</code>: compound type check returns <code>true</code></summary>

  ```diff
  diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
  index 98b16eca6b..b613a6ac19 100644
  --- a/src/script/interpreter.cpp
  +++ b/src/script/interpreter.cpp
  @@ -133,7 +133,7 @@ bool static IsValidSignatureEncoding(const std::vector<unsigned char> &sig) {
       if (sig.size() > 73) return false;

       // A signature is of type 0x30 (compound).
  -    if (sig[0] != 0x30) return false;
  +    if (sig[0] != 0x30) return true;

       // Make sure the length covers the entire signature.
       if (sig[1] != sig.size() - 3) return false;
  ```

  </details>

  Recommend reviewing per commit.

ACKs for top commit:
  instagibbs:
    ACK 4a12773f26
  brunoerg:
    ACK 4a12773f26
  jeanpablojp:
    tACK 4a12773f26

Tree-SHA512: 5f53c733d11cb5d645f420d90ab626f894ef0bb155d01b9de0cae502109b2eaa46c072797d08df115da7a8738f01f31212a207a4d0e6f782128beb37332cf46e
This commit is contained in:
merge-script
2026-08-31 10:01:42 +01:00

View File

@@ -221,6 +221,7 @@
["11 -100 100", "WITHIN", "P2SH,STRICTENC", "OK"],
["-2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
["2147483647 -100 100", "WITHIN NOT", "P2SH,STRICTENC", "OK"],
["0 0 1", "WITHIN DEPTH 1 EQUALVERIFY", "P2SH,STRICTENC", "OK", "WITHIN must pop all 3 elements"],
["2147483647 2147483647 SUB", "0 EQUAL", "P2SH,STRICTENC", "OK"],
["2147483647 DUP ADD", "4294967294 EQUAL", "P2SH,STRICTENC", "OK", ">32 bit EQUAL is valid"],
@@ -332,6 +333,10 @@
"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161",
"P2SH,STRICTENC", "OK",
"201 opcodes executed. 0x61 is NOP"],
["1",
"0x60606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060606060",
"P2SH,STRICTENC", "OK",
"202 OP_16 do not count towards the 201 opcode limit."],
["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f",
"P2SH,STRICTENC", "OK",
@@ -1042,6 +1047,7 @@
["NOP", "TOALTSTACK 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION", "but, hey, more is always better, right?"],
["1", "FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION"],
["1", "2 TOALTSTACK FROMALTSTACK FROMALTSTACK", "P2SH,STRICTENC", "INVALID_ALTSTACK_OPERATION", "FROMALTSTACK must pop the altstack"],
["1", "2DROP 1", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
["1", "2DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
["1 1", "3DUP", "P2SH,STRICTENC", "INVALID_STACK_OPERATION"],
@@ -1286,6 +1292,7 @@
["0x17 0x3014020002107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length R is incorrectly encoded for DERSIG"],
["0x17 0x3014021077777777777777777777777777777777020001", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Zero-length S is incorrectly encoded for DERSIG"],
["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Negative S is incorrectly encoded for DERSIG"],
["0x27 0x312402107777777777777777777777777777777702107777777777777777777777777777777701", "0 CHECKSIG NOT", "DERSIG", "SIG_DER", "Non-compound type is incorrectly encoded for DERSIG"],
["Some basic segwit checks"],
[["00", 0.00000000 ], "", "0 0x206e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "P2SH,WITNESS", "EVAL_FALSE", "Invalid witness script"],