mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-05-15 12:36:48 +00:00
core/types: fix panic on invalid signature length (#33647)
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:
parent
54ab4e3c7d
commit
8fad02ac63
3 changed files with 42 additions and 8 deletions
|
|
@ -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 {
|
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)
|
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]))
|
V = big.NewInt(int64(sig[64]))
|
||||||
return R, S, V, nil
|
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 {
|
if tx.Type() != LegacyTxType {
|
||||||
return nil, nil, nil, ErrTxTypeNotSupported
|
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 {
|
if s.chainId.Sign() != 0 {
|
||||||
V = big.NewInt(int64(sig[64] + 35))
|
V = big.NewInt(int64(sig[64] + 35))
|
||||||
V.Add(V, s.chainIdMul)
|
V.Add(V, s.chainIdMul)
|
||||||
|
|
@ -442,8 +448,8 @@ func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *
|
||||||
if tx.Type() != LegacyTxType {
|
if tx.Type() != LegacyTxType {
|
||||||
return nil, nil, nil, ErrTxTypeNotSupported
|
return nil, nil, nil, ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
r, s, v = decodeSignature(sig)
|
r, s, v, err = decodeSignature(sig)
|
||||||
return r, s, v, nil
|
return r, s, v, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash returns the hash to be signed by the sender.
|
// 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 {
|
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])
|
r = new(big.Int).SetBytes(sig[:32])
|
||||||
s = new(big.Int).SetBytes(sig[32:64])
|
s = new(big.Int).SetBytes(sig[32:64])
|
||||||
v = new(big.Int).SetBytes([]byte{sig[64] + 27})
|
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) {
|
func recoverPlain(sighash common.Hash, R, S, Vb *big.Int, homestead bool) (common.Address, error) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,10 @@ func SignSetCode(prv *ecdsa.PrivateKey, auth SetCodeAuthorization) (SetCodeAutho
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return SetCodeAuthorization{}, err
|
return SetCodeAuthorization{}, err
|
||||||
}
|
}
|
||||||
r, s, _ := decodeSignature(sig)
|
r, s, _, err := decodeSignature(sig)
|
||||||
|
if err != nil {
|
||||||
|
return SetCodeAuthorization{}, err
|
||||||
|
}
|
||||||
return SetCodeAuthorization{
|
return SetCodeAuthorization{
|
||||||
ChainID: auth.ChainID,
|
ChainID: auth.ChainID,
|
||||||
Address: auth.Address,
|
Address: auth.Address,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue