core/types: fix panic on invalid signature length (#33647)
Some checks are pending
/ Linux Build (push) Waiting to run
/ Linux Build (arm) (push) Waiting to run
/ Keeper Build (push) Waiting to run
/ Windows Build (push) Waiting to run
/ Docker Image (push) Waiting to run

Replace panic with error return in decodeSignature to prevent crashes on
invalid inputs, and update callers to propagate the error.
This commit is contained in:
DeFi Junkie 2026-01-21 08:57:02 +03:00 committed by GitHub
parent 54ab4e3c7d
commit 8fad02ac63
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 42 additions and 8 deletions

View file

@ -282,7 +282,10 @@ func (s *modernSigner) SignatureValues(tx *Transaction, sig []byte) (R, S, V *bi
if tx.inner.chainID().Sign() != 0 && tx.inner.chainID().Cmp(s.chainID) != 0 {
return nil, nil, nil, fmt.Errorf("%w: have %d want %d", ErrInvalidChainId, tx.inner.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
}
@ -373,7 +376,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)
@ -442,8 +448,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.
@ -459,14 +465,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) {

View file

@ -200,3 +200,28 @@ func Benchmark_modernSigner_Equal(b *testing.B) {
}
}
}
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)
}
}()
}

View file

@ -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,