Skip to content

Commit 91b37dc

Browse files
committed
NewScriptPubkey: fix panic on empty scriptPubKey
If scriptPubKey is empty, we can't get &scriptPubKey[0] from it.
1 parent cbb04bd commit 91b37dc

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

kernel/script_pubkey.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ func newScriptPubkey(ptr *C.btck_ScriptPubkey, fromOwned bool) *ScriptPubkey {
3535
// Parameters:
3636
// - rawScriptPubkey: Serialized script pubkey data
3737
func NewScriptPubkey(rawScriptPubkey []byte) *ScriptPubkey {
38-
ptr := C.btck_script_pubkey_create(unsafe.Pointer(&rawScriptPubkey[0]), C.size_t(len(rawScriptPubkey)))
38+
var buf unsafe.Pointer
39+
if len(rawScriptPubkey) > 0 {
40+
buf = unsafe.Pointer(&rawScriptPubkey[0])
41+
}
42+
ptr := C.btck_script_pubkey_create(buf, C.size_t(len(rawScriptPubkey)))
3943
return newScriptPubkey(check(ptr), true)
4044
}
4145

kernel/script_pubkey_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,53 @@ func TestScriptPubkeyFromRaw(t *testing.T) {
3232
}
3333
}
3434

35+
func TestScriptPubkeyEmpty(t *testing.T) {
36+
tests := []struct {
37+
name string
38+
data []byte
39+
}{
40+
{name: "nil slice", data: nil},
41+
{name: "empty slice", data: []byte{}},
42+
}
43+
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
scriptPubkey := NewScriptPubkey(tt.data)
47+
if scriptPubkey == nil {
48+
t.Fatal("ScriptPubkey is nil")
49+
}
50+
defer scriptPubkey.Destroy()
51+
52+
bytes, err := scriptPubkey.Bytes()
53+
if err != nil {
54+
t.Fatalf("ScriptPubkey.Bytes() error = %v", err)
55+
}
56+
if len(bytes) != 0 {
57+
t.Fatalf("Expected empty script serialization, got %x", bytes)
58+
}
59+
60+
// Minimal coinbase-style transaction with a single empty scriptSig and
61+
// zero-value output; used to trigger verification paths.
62+
txHex := "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff0100000000000000000000000000"
63+
txBytes, err := hex.DecodeString(txHex)
64+
if err != nil {
65+
t.Fatalf("Failed to decode transaction hex: %v", err)
66+
}
67+
tx, err := NewTransaction(txBytes)
68+
if err != nil {
69+
t.Fatalf("Failed to create transaction: %v", err)
70+
}
71+
defer tx.Destroy()
72+
73+
var scriptErr *ScriptVerifyError
74+
err = scriptPubkey.Verify(0, tx, nil, 0, ScriptFlagsVerifyNone)
75+
if err == nil || !errors.As(err, &scriptErr) {
76+
t.Fatalf("Expected script verification error for empty script, got %v", err)
77+
}
78+
})
79+
}
80+
}
81+
3582
func TestScriptPubkeyCopy(t *testing.T) {
3683
scriptHex := "76a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe26158088ac"
3784
scriptBytes, err := hex.DecodeString(scriptHex)

0 commit comments

Comments
 (0)