Coverage Report

Created: 2026-10-07 20:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/test/fuzz/script_flags.cpp
Line
Count
Source
1
// Copyright (c) 2009-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <consensus/amount.h>
6
#include <primitives/transaction.h>
7
#include <script/interpreter.h>
8
#include <serialize.h>
9
#include <streams.h>
10
#include <test/fuzz/fuzz.h>
11
#include <test/util/script.h>
12
13
#include <cassert>
14
#include <ios>
15
#include <utility>
16
#include <vector>
17
18
static SpanReader& operator>>(SpanReader& ds, script_verify_flags& f)
19
0
{
20
0
    script_verify_flags::value_type n{0};
21
0
    ds >> n;
22
0
    f = script_verify_flags::from_int(n);
23
0
    assert(n == f.as_int());
  Branch (23:5): [True: 0, False: 0]
24
0
    return ds;
25
0
}
26
27
FUZZ_TARGET(script_flags)
28
0
{
29
0
    if (buffer.size() > 100'000) return;
  Branch (29:9): [True: 0, False: 0]
30
0
    SpanReader ds{buffer};
31
0
    try {
32
0
        const CTransaction tx(deserialize, TX_WITH_WITNESS, ds);
33
34
0
        script_verify_flags verify_flags;
35
0
        ds >> verify_flags;
36
37
0
        assert(verify_flags == script_verify_flags::from_int(verify_flags.as_int()));
  Branch (37:9): [True: 0, False: 0]
38
39
0
        if (!IsValidFlagCombination(verify_flags)) return;
  Branch (39:13): [True: 0, False: 0]
40
41
0
        script_verify_flags fuzzed_flags;
42
0
        ds >> fuzzed_flags;
43
44
0
        std::vector<CTxOut> spent_outputs;
45
0
        for (unsigned i = 0; i < tx.vin.size(); ++i) {
  Branch (45:30): [True: 0, False: 0]
46
0
            CTxOut prevout;
47
0
            ds >> prevout;
48
0
            if (!MoneyRange(prevout.nValue)) {
  Branch (48:17): [True: 0, False: 0]
49
                // prevouts should be consensus-valid
50
0
                prevout.nValue = 1;
51
0
            }
52
0
            spent_outputs.push_back(prevout);
53
0
        }
54
0
        PrecomputedTransactionData txdata;
55
0
        txdata.Init(tx, std::move(spent_outputs));
56
57
0
        for (unsigned i = 0; i < tx.vin.size(); ++i) {
  Branch (57:30): [True: 0, False: 0]
58
0
            const CTxOut& prevout = txdata.m_spent_outputs.at(i);
59
0
            const TransactionSignatureChecker checker{&tx, i, prevout.nValue, txdata, MissingDataBehavior::ASSERT_FAIL};
60
61
0
            ScriptError serror;
62
0
            const bool ret = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror);
63
0
            assert(ret == (serror == SCRIPT_ERR_OK));
  Branch (63:13): [True: 0, False: 0]
64
65
            // Verify that removing flags from a passing test or adding flags to a failing test does not change the result
66
0
            if (ret) {
  Branch (66:17): [True: 0, False: 0]
67
0
                verify_flags &= ~fuzzed_flags;
68
0
            } else {
69
0
                verify_flags |= fuzzed_flags;
70
0
            }
71
0
            if (!IsValidFlagCombination(verify_flags)) return;
  Branch (71:17): [True: 0, False: 0]
72
73
0
            ScriptError serror_fuzzed;
74
0
            const bool ret_fuzzed = VerifyScript(tx.vin.at(i).scriptSig, prevout.scriptPubKey, &tx.vin.at(i).scriptWitness, verify_flags, checker, &serror_fuzzed);
75
0
            assert(ret_fuzzed == (serror_fuzzed == SCRIPT_ERR_OK));
  Branch (75:13): [True: 0, False: 0]
76
77
0
            assert(ret_fuzzed == ret);
  Branch (77:13): [True: 0, False: 0]
78
0
        }
79
0
    } catch (const std::ios_base::failure&) {
80
0
        return;
81
0
    }
82
0
}