AI-generated analysisPublished automatically and not human-verified. Validated context appears in community notes below.
← Watch feed
Informational 12 Bitcoin

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

Public commit record

What the developer wrote

Authored by merge-script

96/100 · Strong
Merge bitcoin/bitcoin#36054: test: add script_tests cases covering interpreter mutants

4a12773f269742d2c655beb1b3f5ffe98e9beadb test: cover DERSIG rejects a non-compound signature type (ViniciusCestarii)
86c7fb910d674c757c4829cd006b3732d3a5e78b test: cover OP_16 does not count towards the opcode limit (ViniciusCestarii)
331bf798819ca4f2815450ba50d5920e2d2c2aa6 test: cover OP_WITHIN must pop all 3 elements (ViniciusCestarii)
3bb87bc61b489911cf36e50f74ac8b6ee201b82b 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 4a12773f269742d2c655beb1b3f5ffe98e9beadb
brunoerg:
ACK 4a12773f269742d2c655beb1b3f5ffe98e9beadb
jeanpablojp:
tACK 4a12773f269742d2c655beb1b3f5ffe98e9beadb

Tree-SHA512: 5f53c733d11cb5d645f420d90ab626f894ef0bb155d01b9de0cae502109b2eaa46c072797d08df115da7a8738f01f31212a207a4d0e6f782128beb37332cf46e
✓ Specific, descriptive subject✓ Names a concrete action or component✓ Provides detailed explanatory context✓ Mentions testing or verification✓ Links an issue, advisory, or supporting reference✓ Names security-relevant behavior explicitly
The short version

What changed, and why it matters

This commit only adds new test cases to Bitcoin Core's script test suite. It does not change any production code. The tests are designed to catch accidental code changes ('mutants') in the script interpreter that could affect consensus rules, but the commit itself is a defensive test addition with no active vulnerability being fixed.

Recommended action

No immediate action required. Treat as routine hardening of consensus test coverage. Reviewers may verify the new test vectors correctly fail against the described mutants.

Security signals we found

01

Adds consensus-relevant regression tests for script interpreter mutants

02

References externally discovered live mutants on bitcoincore.space

03

Targets DERSIG, opcode counting, OP_WITHIN, and OP_FROMALTSTACK behavior

04

No production code changes; purely test coverage

Risk score

Why this scored 12/100

Our methodology →
Potential impact 0/30
Exploitability 0/25
Stealth signal 0/15
Affected reach 0/15
Confidence 8/10
Evidence quality 4/5
Human-validated context

Community notes

Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.

No validated notes yet.

The AI analysis stands alone for now. Submit a note if you can add evidence or important context.