Fix nil pointer dereference when WitnessHash is called before HasWitness

Issue: btcsuite/btcd#1543
Related PR: btcsuite/btcutil#156
This commit is contained in:
Anirudha Bose 2020-05-03 20:44:25 +05:30
parent b2bf7f89d6
commit 29af078e7b
No known key found for this signature in database
GPG key ID: F4AED71D3784186A
3 changed files with 48 additions and 5 deletions

View file

@ -145,10 +145,10 @@ func TestBlock(t *testing.T) {
// Transaction offsets and length for the transaction in Block100000. // Transaction offsets and length for the transaction in Block100000.
wantTxLocs := []wire.TxLoc{ wantTxLocs := []wire.TxLoc{
{TxStart: 81, TxLen: 135}, {TxStart: 81, TxLen: 144},
{TxStart: 216, TxLen: 259}, {TxStart: 225, TxLen: 259},
{TxStart: 475, TxLen: 257}, {TxStart: 484, TxLen: 257},
{TxStart: 732, TxLen: 225}, {TxStart: 741, TxLen: 225},
} }
// Ensure the transaction location information is accurate. // Ensure the transaction location information is accurate.
@ -333,6 +333,10 @@ var Block100000 = wire.MsgBlock{
0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02, 0x04, 0x4c, 0x86, 0x04, 0x1b, 0x02, 0x06, 0x02,
}, },
Sequence: 0xffffffff, Sequence: 0xffffffff,
Witness: [][]byte{
{0x04, 0x31},
{0x01, 0x43},
},
}, },
}, },
TxOut: []*wire.TxOut{ TxOut: []*wire.TxOut{

2
tx.go
View file

@ -70,7 +70,7 @@ func (t *Tx) WitnessHash() *chainhash.Hash {
// HasWitness on the underlying wire.MsgTx, however it caches the result so // HasWitness on the underlying wire.MsgTx, however it caches the result so
// subsequent calls are more efficient. // subsequent calls are more efficient.
func (t *Tx) HasWitness() bool { func (t *Tx) HasWitness() bool {
if t.txHashWitness != nil { if t.txHasWitness != nil {
return *t.txHasWitness return *t.txHasWitness
} }

View file

@ -95,3 +95,42 @@ func TestTxErrors(t *testing.T) {
"got %v, want %v", err, io.EOF) "got %v, want %v", err, io.EOF)
} }
} }
// TestTxHasWitness tests the HasWitness() method.
func TestTxHasWitness(t *testing.T) {
msgTx := Block100000.Transactions[0] // contains witness data
tx := btcutil.NewTx(msgTx)
tx.WitnessHash() // Populate the witness hash cache
tx.HasWitness() // Should not fail (see btcsuite/btcd#1543)
if !tx.HasWitness() {
t.Errorf("HasWitness: got false, want true")
}
for _, msgTxWithoutWitness := range Block100000.Transactions[1:] {
txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness)
if txWithoutWitness.HasWitness() {
t.Errorf("HasWitness: got false, want true")
}
}
}
// TestTxWitnessHash tests the WitnessHash() method.
func TestTxWitnessHash(t *testing.T) {
msgTx := Block100000.Transactions[0] // contains witness data
tx := btcutil.NewTx(msgTx)
if tx.WitnessHash().IsEqual(tx.Hash()) {
t.Errorf("WitnessHash: witness hash and tx id must NOT be same - "+
"got %v, want %v", tx.WitnessHash(), tx.Hash())
}
for _, msgTxWithoutWitness := range Block100000.Transactions[1:] {
txWithoutWitness := btcutil.NewTx(msgTxWithoutWitness)
if !txWithoutWitness.WitnessHash().IsEqual(txWithoutWitness.Hash()) {
t.Errorf("WitnessHash: witness hash and tx id must be same - "+
"got %v, want %v", txWithoutWitness.WitnessHash(), txWithoutWitness.Hash())
}
}
}