mobile: don't retain transient []byte in CallMsg.SetData (#14804)
* mobile: don't retain transient []byte in CallMsg.SetData Go mobile doesn't copy []byte parameters, for performance and to allow writes to the byte array be reflected in the native byte array. Unfortunately, that means []byte arguments are only valid during the call it is being passed into. CallMsg.SetData retains such a byte array. Copy it instead Fixes #14675 * mobile: copy all []byte arguments from gomobile To avoid subtle errors when accidentially retaining an otherwise transient byte slice coming from gomobile, copy all byte slices before use. * mobile: replace copySlice with common.CopyBytes
This commit is contained in:
parent
cf5d4b5541
commit
23c6fcdbe8
@ -25,6 +25,7 @@ import (
|
|||||||
|
|
||||||
"github.com/ethereum/go-ethereum/accounts"
|
"github.com/ethereum/go-ethereum/accounts"
|
||||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -111,7 +112,7 @@ func (ks *KeyStore) DeleteAccount(account *Account, passphrase string) error {
|
|||||||
// SignHash calculates a ECDSA signature for the given hash. The produced signature
|
// SignHash calculates a ECDSA signature for the given hash. The produced signature
|
||||||
// is in the [R || S || V] format where V is 0 or 1.
|
// is in the [R || S || V] format where V is 0 or 1.
|
||||||
func (ks *KeyStore) SignHash(address *Address, hash []byte) (signature []byte, _ error) {
|
func (ks *KeyStore) SignHash(address *Address, hash []byte) (signature []byte, _ error) {
|
||||||
return ks.keystore.SignHash(accounts.Account{Address: address.address}, hash)
|
return ks.keystore.SignHash(accounts.Account{Address: address.address}, common.CopyBytes(hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTx signs the given transaction with the requested account.
|
// SignTx signs the given transaction with the requested account.
|
||||||
@ -130,7 +131,7 @@ func (ks *KeyStore) SignTx(account *Account, tx *Transaction, chainID *BigInt) (
|
|||||||
// be decrypted with the given passphrase. The produced signature is in the
|
// be decrypted with the given passphrase. The produced signature is in the
|
||||||
// [R || S || V] format where V is 0 or 1.
|
// [R || S || V] format where V is 0 or 1.
|
||||||
func (ks *KeyStore) SignHashPassphrase(account *Account, passphrase string, hash []byte) (signature []byte, _ error) {
|
func (ks *KeyStore) SignHashPassphrase(account *Account, passphrase string, hash []byte) (signature []byte, _ error) {
|
||||||
return ks.keystore.SignHashWithPassphrase(account.account, passphrase, hash)
|
return ks.keystore.SignHashWithPassphrase(account.account, passphrase, common.CopyBytes(hash))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignTxPassphrase signs the transaction if the private key matching the
|
// SignTxPassphrase signs the transaction if the private key matching the
|
||||||
@ -189,7 +190,7 @@ func (ks *KeyStore) ExportKey(account *Account, passphrase, newPassphrase string
|
|||||||
|
|
||||||
// ImportKey stores the given encrypted JSON key into the key directory.
|
// ImportKey stores the given encrypted JSON key into the key directory.
|
||||||
func (ks *KeyStore) ImportKey(keyJSON []byte, passphrase, newPassphrase string) (account *Account, _ error) {
|
func (ks *KeyStore) ImportKey(keyJSON []byte, passphrase, newPassphrase string) (account *Account, _ error) {
|
||||||
acc, err := ks.keystore.Import(keyJSON, passphrase, newPassphrase)
|
acc, err := ks.keystore.Import(common.CopyBytes(keyJSON), passphrase, newPassphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -198,7 +199,7 @@ func (ks *KeyStore) ImportKey(keyJSON []byte, passphrase, newPassphrase string)
|
|||||||
|
|
||||||
// ImportECDSAKey stores the given encrypted JSON key into the key directory.
|
// ImportECDSAKey stores the given encrypted JSON key into the key directory.
|
||||||
func (ks *KeyStore) ImportECDSAKey(key []byte, passphrase string) (account *Account, _ error) {
|
func (ks *KeyStore) ImportECDSAKey(key []byte, passphrase string) (account *Account, _ error) {
|
||||||
privkey, err := crypto.ToECDSA(key)
|
privkey, err := crypto.ToECDSA(common.CopyBytes(key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -212,7 +213,7 @@ func (ks *KeyStore) ImportECDSAKey(key []byte, passphrase string) (account *Acco
|
|||||||
// ImportPreSaleKey decrypts the given Ethereum presale wallet and stores
|
// ImportPreSaleKey decrypts the given Ethereum presale wallet and stores
|
||||||
// a key file in the key directory. The key file is encrypted with the same passphrase.
|
// a key file in the key directory. The key file is encrypted with the same passphrase.
|
||||||
func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (ccount *Account, _ error) {
|
func (ks *KeyStore) ImportPreSaleKey(keyJSON []byte, passphrase string) (ccount *Account, _ error) {
|
||||||
account, err := ks.keystore.ImportPreSaleKey(keyJSON, passphrase)
|
account, err := ks.keystore.ImportPreSaleKey(common.CopyBytes(keyJSON), passphrase)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,8 @@ package geth
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A BigInt represents a signed multi-precision integer.
|
// A BigInt represents a signed multi-precision integer.
|
||||||
@ -52,7 +54,7 @@ func (bi *BigInt) GetInt64() int64 {
|
|||||||
// SetBytes interprets buf as the bytes of a big-endian unsigned integer and sets
|
// SetBytes interprets buf as the bytes of a big-endian unsigned integer and sets
|
||||||
// the big int to that value.
|
// the big int to that value.
|
||||||
func (bi *BigInt) SetBytes(buf []byte) {
|
func (bi *BigInt) SetBytes(buf []byte) {
|
||||||
bi.bigint.SetBytes(buf)
|
bi.bigint.SetBytes(common.CopyBytes(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetInt64 sets the big int to x.
|
// SetInt64 sets the big int to x.
|
||||||
|
@ -119,7 +119,7 @@ func DeployContract(opts *TransactOpts, abiJSON string, bytecode []byte, client
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
addr, tx, bound, err := bind.DeployContract(&opts.opts, parsed, bytecode, client.client, args.objects...)
|
addr, tx, bound, err := bind.DeployContract(&opts.opts, parsed, common.CopyBytes(bytecode), client.client, args.objects...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ type Hash struct {
|
|||||||
// NewHashFromBytes converts a slice of bytes to a hash value.
|
// NewHashFromBytes converts a slice of bytes to a hash value.
|
||||||
func NewHashFromBytes(binary []byte) (hash *Hash, _ error) {
|
func NewHashFromBytes(binary []byte) (hash *Hash, _ error) {
|
||||||
h := new(Hash)
|
h := new(Hash)
|
||||||
if err := h.SetBytes(binary); err != nil {
|
if err := h.SetBytes(common.CopyBytes(binary)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return h, nil
|
return h, nil
|
||||||
@ -136,7 +136,7 @@ type Address struct {
|
|||||||
// NewAddressFromBytes converts a slice of bytes to a hash value.
|
// NewAddressFromBytes converts a slice of bytes to a hash value.
|
||||||
func NewAddressFromBytes(binary []byte) (address *Address, _ error) {
|
func NewAddressFromBytes(binary []byte) (address *Address, _ error) {
|
||||||
a := new(Address)
|
a := new(Address)
|
||||||
if err := a.SetBytes(binary); err != nil {
|
if err := a.SetBytes(common.CopyBytes(binary)); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return a, nil
|
return a, nil
|
||||||
|
@ -64,7 +64,7 @@ func (msg *CallMsg) SetFrom(address *Address) { msg.msg.From = address.address
|
|||||||
func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = big.NewInt(gas) }
|
func (msg *CallMsg) SetGas(gas int64) { msg.msg.Gas = big.NewInt(gas) }
|
||||||
func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint }
|
func (msg *CallMsg) SetGasPrice(price *BigInt) { msg.msg.GasPrice = price.bigint }
|
||||||
func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint }
|
func (msg *CallMsg) SetValue(value *BigInt) { msg.msg.Value = value.bigint }
|
||||||
func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = data }
|
func (msg *CallMsg) SetData(data []byte) { msg.msg.Data = common.CopyBytes(data) }
|
||||||
func (msg *CallMsg) SetTo(address *Address) {
|
func (msg *CallMsg) SetTo(address *Address) {
|
||||||
if address == nil {
|
if address == nil {
|
||||||
msg.msg.To = nil
|
msg.msg.To = nil
|
||||||
|
@ -46,7 +46,7 @@ func (i *Interface) SetBool(b bool) { i.object = &b }
|
|||||||
func (i *Interface) SetBools(bs []bool) { i.object = &bs }
|
func (i *Interface) SetBools(bs []bool) { i.object = &bs }
|
||||||
func (i *Interface) SetString(str string) { i.object = &str }
|
func (i *Interface) SetString(str string) { i.object = &str }
|
||||||
func (i *Interface) SetStrings(strs *Strings) { i.object = &strs.strs }
|
func (i *Interface) SetStrings(strs *Strings) { i.object = &strs.strs }
|
||||||
func (i *Interface) SetBinary(binary []byte) { i.object = &binary }
|
func (i *Interface) SetBinary(binary []byte) { b := common.CopyBytes(binary); i.object = &b }
|
||||||
func (i *Interface) SetBinaries(binaries [][]byte) { i.object = &binaries }
|
func (i *Interface) SetBinaries(binaries [][]byte) { i.object = &binaries }
|
||||||
func (i *Interface) SetAddress(address *Address) { i.object = &address.address }
|
func (i *Interface) SetAddress(address *Address) { i.object = &address.address }
|
||||||
func (i *Interface) SetAddresses(addrs *Addresses) { i.object = &addrs.addresses }
|
func (i *Interface) SetAddresses(addrs *Addresses) { i.object = &addrs.addresses }
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
@ -68,7 +69,7 @@ func NewHeaderFromRLP(data []byte) (*Header, error) {
|
|||||||
h := &Header{
|
h := &Header{
|
||||||
header: new(types.Header),
|
header: new(types.Header),
|
||||||
}
|
}
|
||||||
if err := rlp.DecodeBytes(data, h.header); err != nil {
|
if err := rlp.DecodeBytes(common.CopyBytes(data), h.header); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return h, nil
|
return h, nil
|
||||||
@ -145,7 +146,7 @@ func NewBlockFromRLP(data []byte) (*Block, error) {
|
|||||||
b := &Block{
|
b := &Block{
|
||||||
block: new(types.Block),
|
block: new(types.Block),
|
||||||
}
|
}
|
||||||
if err := rlp.DecodeBytes(data, b.block); err != nil {
|
if err := rlp.DecodeBytes(common.CopyBytes(data), b.block); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return b, nil
|
return b, nil
|
||||||
@ -212,7 +213,7 @@ type Transaction struct {
|
|||||||
|
|
||||||
// NewTransaction creates a new transaction with the given properties.
|
// NewTransaction creates a new transaction with the given properties.
|
||||||
func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction {
|
func NewTransaction(nonce int64, to *Address, amount, gasLimit, gasPrice *BigInt, data []byte) *Transaction {
|
||||||
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, data)}
|
return &Transaction{types.NewTransaction(uint64(nonce), to.address, amount.bigint, gasLimit.bigint, gasPrice.bigint, common.CopyBytes(data))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTransactionFromRLP parses a transaction from an RLP data dump.
|
// NewTransactionFromRLP parses a transaction from an RLP data dump.
|
||||||
@ -220,7 +221,7 @@ func NewTransactionFromRLP(data []byte) (*Transaction, error) {
|
|||||||
tx := &Transaction{
|
tx := &Transaction{
|
||||||
tx: new(types.Transaction),
|
tx: new(types.Transaction),
|
||||||
}
|
}
|
||||||
if err := rlp.DecodeBytes(data, tx.tx); err != nil {
|
if err := rlp.DecodeBytes(common.CopyBytes(data), tx.tx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return tx, nil
|
return tx, nil
|
||||||
@ -285,7 +286,7 @@ func (tx *Transaction) WithSignature(sig []byte, chainID *BigInt) (signedTx *Tra
|
|||||||
if chainID != nil {
|
if chainID != nil {
|
||||||
signer = types.NewEIP155Signer(chainID.bigint)
|
signer = types.NewEIP155Signer(chainID.bigint)
|
||||||
}
|
}
|
||||||
rawTx, err := tx.tx.WithSignature(signer, sig)
|
rawTx, err := tx.tx.WithSignature(signer, common.CopyBytes(sig))
|
||||||
return &Transaction{rawTx}, err
|
return &Transaction{rawTx}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +316,7 @@ func NewReceiptFromRLP(data []byte) (*Receipt, error) {
|
|||||||
r := &Receipt{
|
r := &Receipt{
|
||||||
receipt: new(types.Receipt),
|
receipt: new(types.Receipt),
|
||||||
}
|
}
|
||||||
if err := rlp.DecodeBytes(data, r.receipt); err != nil {
|
if err := rlp.DecodeBytes(common.CopyBytes(data), r.receipt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return r, nil
|
return r, nil
|
||||||
|
Loading…
Reference in New Issue
Block a user