From ab393862426405b672999eeaa7f418e1d6eeb8e6 Mon Sep 17 00:00:00 2001 From: Daniel Liu <139250065@qq.com> Date: Tue, 27 Jan 2026 11:25:23 +0800 Subject: [PATCH] core/types: fix panic on invalid signature length #33647 (#1979) Replace panic with error return in decodeSignature to prevent crashes on invalid inputs, and update callers to propagate the error. Co-authored-by: DeFi Junkie --- core/types/transaction_signing.go | 30 ++++++++++++++++++-------- core/types/transaction_signing_test.go | 25 +++++++++++++++++++++ core/types/tx_setcode.go | 5 ++++- 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 8ed5bf6f68..1b35765c47 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -217,7 +217,10 @@ func (s pragueSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big if txdata.ChainID.Sign() != 0 && txdata.ChainID.CmpBig(s.chainId) != 0 { return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, txdata.ChainID, s.chainId) } - R, S, _ = decodeSignature(sig) + R, S, _, err = decodeSignature(sig) + if err != nil { + return nil, nil, nil, err + } V = big.NewInt(int64(sig[64])) return R, S, V, nil } @@ -284,7 +287,10 @@ func (s londonSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 { return nil, nil, nil, ErrInvalidChainId } - R, S, _ = decodeSignature(sig) + R, S, _, err = decodeSignature(sig) + if err != nil { + return nil, nil, nil, err + } V = big.NewInt(int64(sig[64])) return R, S, V, nil } @@ -355,7 +361,10 @@ func (s eip2930Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *bi if txdata.ChainID.Sign() != 0 && txdata.ChainID.Cmp(s.chainId) != 0 { return nil, nil, nil, ErrInvalidChainId } - R, S, _ = decodeSignature(sig) + R, S, _, err = decodeSignature(sig) + if err != nil { + return nil, nil, nil, err + } V = big.NewInt(int64(sig[64])) default: return nil, nil, nil, ErrTxTypeNotSupported @@ -440,7 +449,10 @@ func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big if tx.Type() != LegacyTxType { return nil, nil, nil, ErrTxTypeNotSupported } - R, S, V = decodeSignature(sig) + R, S, V, err = decodeSignature(sig) + if err != nil { + return nil, nil, nil, err + } if s.chainId.Sign() != 0 { V = big.NewInt(int64(sig[64] + 35)) V.Add(V, s.chainIdMul) @@ -514,8 +526,8 @@ func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v * if tx.Type() != LegacyTxType { return nil, nil, nil, ErrTxTypeNotSupported } - r, s, v = decodeSignature(sig) - return r, s, v, nil + r, s, v, err = decodeSignature(sig) + return r, s, v, err } // Hash returns the hash to be signed by the sender. @@ -531,14 +543,14 @@ func (fs FrontierSigner) Hash(tx *Transaction) common.Hash { }) } -func decodeSignature(sig []byte) (r, s, v *big.Int) { +func decodeSignature(sig []byte) (r, s, v *big.Int, err error) { if len(sig) != crypto.SignatureLength { - panic(fmt.Sprintf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength)) + return nil, nil, nil, fmt.Errorf("wrong size for signature: got %d, want %d", len(sig), crypto.SignatureLength) } r = new(big.Int).SetBytes(sig[:32]) s = new(big.Int).SetBytes(sig[32:64]) v = new(big.Int).SetBytes([]byte{sig[64] + 27}) - return r, s, v + return r, s, v, nil } func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) { diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go index 3c83b1b406..470ef27363 100644 --- a/core/types/transaction_signing_test.go +++ b/core/types/transaction_signing_test.go @@ -135,3 +135,28 @@ func TestChainId(t *testing.T) { t.Error("expected no error") } } + +func TestSignatureValuesError(t *testing.T) { + // 1. Setup a valid transaction + tx := NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), nil) + signer := HomesteadSigner{} + + // 2. Call WithSignature with invalid length sig (not 65 bytes) + invalidSig := make([]byte, 64) + + func() { + defer func() { + if r := recover(); r != nil { + t.Fatalf("Panicked for invalid signature length, expected error: %v", r) + } + }() + _, err := tx.WithSignature(signer, invalidSig) + if err == nil { + t.Fatal("Expected error for invalid signature length, got nil") + } else { + // This is just a sanity check to ensure we got an error, + // the exact error message is verified in unit tests elsewhere if needed. + t.Logf("Got expected error: %v", err) + } + }() +} diff --git a/core/types/tx_setcode.go b/core/types/tx_setcode.go index 8726b1f788..e045b04af8 100644 --- a/core/types/tx_setcode.go +++ b/core/types/tx_setcode.go @@ -94,7 +94,10 @@ func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAutho if err != nil { return SetCodeAuthorization{}, err } - r, s, _ := decodeSignature(sig) + r, s, _, err := decodeSignature(sig) + if err != nil { + return SetCodeAuthorization{}, err + } return SetCodeAuthorization{ ChainID: auth.ChainID, Address: auth.Address,