소스 검색

ethclient: ensure tx json is not nil before accessing it (#19653)

TransactionInBlock crashed if json was nil and there was an error
because it tried to access fields `From` and `BlockHash` of the nil object.
Dmitry Shulyak 6 년 전
부모
커밋
15f24ff189
2개의 변경된 파일25개의 추가작업 그리고 6개의 파일을 삭제
  1. 7 6
      ethclient/ethclient.go
  2. 18 0
      ethclient/ethclient_test.go

+ 7 - 6
ethclient/ethclient.go

@@ -241,12 +241,13 @@ func (ec *Client) TransactionCount(ctx context.Context, blockHash common.Hash) (
 func (ec *Client) TransactionInBlock(ctx context.Context, blockHash common.Hash, index uint) (*types.Transaction, error) {
 	var json *rpcTransaction
 	err := ec.c.CallContext(ctx, &json, "eth_getTransactionByBlockHashAndIndex", blockHash, hexutil.Uint64(index))
-	if err == nil {
-		if json == nil {
-			return nil, ethereum.NotFound
-		} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
-			return nil, fmt.Errorf("server returned transaction without signature")
-		}
+	if err != nil {
+		return nil, err
+	}
+	if json == nil {
+		return nil, ethereum.NotFound
+	} else if _, r, _ := json.tx.RawSignatureValues(); r == nil {
+		return nil, fmt.Errorf("server returned transaction without signature")
 	}
 	if json.From != nil && json.BlockHash != nil {
 		setSenderFromServer(json.tx, *json.From, *json.BlockHash)

+ 18 - 0
ethclient/ethclient_test.go

@@ -301,3 +301,21 @@ func TestBalanceAt(t *testing.T) {
 		})
 	}
 }
+
+func TestTransactionInBlockInterrupted(t *testing.T) {
+	backend, _ := newTestBackend(t)
+	client, _ := backend.Attach()
+	defer backend.Stop()
+	defer client.Close()
+
+	ec := NewClient(client)
+	ctx, cancel := context.WithCancel(context.Background())
+	cancel()
+	tx, err := ec.TransactionInBlock(ctx, common.Hash{1}, 1)
+	if tx != nil {
+		t.Fatal("transaction should be nil")
+	}
+	if err == nil {
+		t.Fatal("error should not be nil")
+	}
+}