Skip to content

Commit 43b095a

Browse files
jholdstockjrick
authored andcommitted
jsonrpc: Avoid nil pointer dereference.
This avoids a number of nil pointer dereferences by adding !nil checks before dereferencing. These checks are required for fields that are tagged with "jsonrpcdefault" because those fields will only have their default value if they have been omitted from the json string, not if they are explicitly set to "null".
1 parent e23864f commit 43b095a

1 file changed

Lines changed: 115 additions & 24 deletions

File tree

internal/rpc/jsonrpc/methods.go

Lines changed: 115 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Copyright (c) 2013-2016 The btcsuite developers
2-
// Copyright (c) 2015-2025 The Decred developers
2+
// Copyright (c) 2015-2026 The Decred developers
33
// Use of this source code is governed by an ISC
44
// license that can be found in the LICENSE file.
55

@@ -1046,7 +1046,10 @@ func (s *Server) getBalance(ctx context.Context, icmd any) (any, error) {
10461046
return nil, errUnloadedWallet
10471047
}
10481048

1049-
minConf := int32(*cmd.MinConf)
1049+
minConf := int32(1)
1050+
if cmd.MinConf != nil {
1051+
minConf = int32(*cmd.MinConf)
1052+
}
10501053
if minConf < 0 {
10511054
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "minconf must be non-negative")
10521055
}
@@ -1062,7 +1065,7 @@ func (s *Server) getBalance(ctx context.Context, icmd any) (any, error) {
10621065
}
10631066

10641067
if accountName == "*" {
1065-
balances, err := w.AccountBalances(ctx, int32(*cmd.MinConf))
1068+
balances, err := w.AccountBalances(ctx, minConf)
10661069
if err != nil {
10671070
return nil, err
10681071
}
@@ -1128,7 +1131,7 @@ func (s *Server) getBalance(ctx context.Context, icmd any) (any, error) {
11281131
return nil, err
11291132
}
11301133

1131-
bal, err := w.AccountBalance(ctx, account, int32(*cmd.MinConf))
1134+
bal, err := w.AccountBalance(ctx, account, minConf)
11321135
if err != nil {
11331136
// Expect account lookup to succeed
11341137
if errors.Is(err, errors.NotExist) {
@@ -2392,10 +2395,15 @@ func (s *Server) getReceivedByAccount(ctx context.Context, icmd any) (any, error
23922395
return 0.0, nil
23932396
}
23942397

2398+
minConf := int32(1)
2399+
if cmd.MinConf != nil {
2400+
minConf = int32(*cmd.MinConf)
2401+
}
2402+
23952403
// TODO: This is more inefficient that it could be, but the entire
23962404
// algorithm is already dominated by reading every transaction in the
23972405
// wallet's history.
2398-
results, err := w.TotalReceivedForAccounts(ctx, int32(*cmd.MinConf))
2406+
results, err := w.TotalReceivedForAccounts(ctx, minConf)
23992407
if err != nil {
24002408
return nil, err
24012409
}
@@ -2419,7 +2427,13 @@ func (s *Server) getReceivedByAddress(ctx context.Context, icmd any) (any, error
24192427
if err != nil {
24202428
return nil, err
24212429
}
2422-
total, err := w.TotalReceivedForAddr(ctx, addr, int32(*cmd.MinConf))
2430+
2431+
minConf := int32(1)
2432+
if cmd.MinConf != nil {
2433+
minConf = int32(*cmd.MinConf)
2434+
}
2435+
2436+
total, err := w.TotalReceivedForAddr(ctx, addr, minConf)
24232437
if err != nil {
24242438
if errors.Is(err, errors.NotExist) {
24252439
return nil, errAddressNotInWallet
@@ -2726,7 +2740,11 @@ func (s *Server) getTxOut(ctx context.Context, icmd any) (any, error) {
27262740

27272741
// Attempt to read the unspent txout info from wallet.
27282742
outpoint := wire.OutPoint{Hash: *txHash, Index: cmd.Vout, Tree: cmd.Tree}
2729-
utxo, err := w.UnspentOutput(ctx, outpoint, *cmd.IncludeMempool)
2743+
includeMempool := true
2744+
if cmd.IncludeMempool != nil {
2745+
includeMempool = *cmd.IncludeMempool
2746+
}
2747+
utxo, err := w.UnspentOutput(ctx, outpoint, includeMempool)
27302748
if err != nil && !errors.Is(err, errors.NotExist) {
27312749
return nil, err
27322750
}
@@ -2922,8 +2940,13 @@ func (s *Server) listAccounts(ctx context.Context, icmd any) (any, error) {
29222940
return nil, errUnloadedWallet
29232941
}
29242942

2943+
minConf := int32(1)
2944+
if cmd.MinConf != nil {
2945+
minConf = int32(*cmd.MinConf)
2946+
}
2947+
29252948
accountBalances := map[string]float64{}
2926-
results, err := w.AccountBalances(ctx, int32(*cmd.MinConf))
2949+
results, err := w.AccountBalances(ctx, minConf)
29272950
if err != nil {
29282951
return nil, err
29292952
}
@@ -2978,7 +3001,12 @@ func (s *Server) listReceivedByAccount(ctx context.Context, icmd any) (any, erro
29783001
return nil, errUnloadedWallet
29793002
}
29803003

2981-
results, err := w.TotalReceivedForAccounts(ctx, int32(*cmd.MinConf))
3004+
minConf := int32(1)
3005+
if cmd.MinConf != nil {
3006+
minConf = int32(*cmd.MinConf)
3007+
}
3008+
3009+
results, err := w.TotalReceivedForAccounts(ctx, minConf)
29823010
if err != nil {
29833011
return nil, err
29843012
}
@@ -3040,7 +3068,11 @@ func (s *Server) listReceivedByAddress(ctx context.Context, icmd any) (any, erro
30403068
allAddrData[address] = AddrData{}
30413069
}
30423070

3043-
minConf := *cmd.MinConf
3071+
minConf := int32(1)
3072+
if cmd.MinConf != nil {
3073+
minConf = int32(*cmd.MinConf)
3074+
}
3075+
30443076
var endHeight int32
30453077
if minConf == 0 {
30463078
endHeight = -1
@@ -3103,7 +3135,11 @@ func (s *Server) listSinceBlock(ctx context.Context, icmd any) (any, error) {
31033135
return nil, errUnloadedWallet
31043136
}
31053137

3106-
targetConf := int32(*cmd.TargetConfirmations)
3138+
targetConf := int32(1)
3139+
if cmd.TargetConfirmations != nil {
3140+
targetConf = int32(*cmd.TargetConfirmations)
3141+
}
3142+
31073143
if targetConf < 1 {
31083144
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "target_confirmations must be positive")
31093145
}
@@ -3169,7 +3205,16 @@ func (s *Server) listTransactions(ctx context.Context, icmd any) (any, error) {
31693205
`Use "*" to reference all accounts.`)
31703206
}
31713207

3172-
return w.ListTransactions(ctx, *cmd.From, *cmd.Count)
3208+
count := 10
3209+
if cmd.Count != nil {
3210+
count = *cmd.Count
3211+
}
3212+
from := 0
3213+
if cmd.From != nil {
3214+
from = *cmd.From
3215+
}
3216+
3217+
return w.ListTransactions(ctx, from, count)
31733218
}
31743219

31753220
// listAddressTransactions handles a listaddresstransactions request by
@@ -3252,7 +3297,18 @@ func (s *Server) listUnspent(ctx context.Context, icmd any) (any, error) {
32523297
if cmd.Account != nil {
32533298
account = *cmd.Account
32543299
}
3255-
result, err := w.ListUnspent(ctx, int32(*cmd.MinConf), int32(*cmd.MaxConf), addresses, account)
3300+
3301+
minConf := int32(1)
3302+
if cmd.MinConf != nil {
3303+
minConf = int32(*cmd.MinConf)
3304+
}
3305+
3306+
maxConf := int32(9999999)
3307+
if cmd.MaxConf != nil {
3308+
maxConf = int32(*cmd.MaxConf)
3309+
}
3310+
3311+
result, err := w.ListUnspent(ctx, minConf, maxConf, addresses, account)
32563312
if err != nil {
32573313
if errors.Is(err, errors.NotExist) {
32583314
return nil, errAddressNotInWallet
@@ -4171,7 +4227,12 @@ func (s *Server) rescanWallet(ctx context.Context, icmd any) (any, error) {
41714227
return nil, errNoNetwork
41724228
}
41734229

4174-
err := w.RescanFromHeight(ctx, n, int32(*cmd.BeginHeight))
4230+
beginHeight := int32(0)
4231+
if cmd.BeginHeight != nil {
4232+
beginHeight = int32(*cmd.BeginHeight)
4233+
}
4234+
4235+
err := w.RescanFromHeight(ctx, n, beginHeight)
41754236
return nil, err
41764237
}
41774238

@@ -4342,7 +4403,12 @@ func (s *Server) ticketInfo(ctx context.Context, icmd any) (any, error) {
43424403

43434404
res := make([]types.TicketInfoResult, 0)
43444405

4345-
start := wallet.NewBlockIdentifierFromHeight(*cmd.StartHeight)
4406+
startHeight := int32(0)
4407+
if cmd.StartHeight != nil {
4408+
startHeight = int32(*cmd.StartHeight)
4409+
}
4410+
4411+
start := wallet.NewBlockIdentifierFromHeight(startHeight)
43464412
end := wallet.NewBlockIdentifierFromHeight(-1)
43474413
tmptx := new(wire.MsgTx)
43484414
err := w.GetTickets(ctx, func(ts []*wallet.TicketSummary, h *wire.BlockHeader) (bool, error) {
@@ -4441,7 +4507,10 @@ func (s *Server) sendFrom(ctx context.Context, icmd any) (any, error) {
44414507
if cmd.Amount < 0 {
44424508
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "negative amount")
44434509
}
4444-
minConf := int32(*cmd.MinConf)
4510+
minConf := int32(1)
4511+
if cmd.MinConf != nil {
4512+
minConf = int32(*cmd.MinConf)
4513+
}
44454514
if minConf < 0 {
44464515
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "negative minconf")
44474516
}
@@ -4481,7 +4550,10 @@ func (s *Server) sendMany(ctx context.Context, icmd any) (any, error) {
44814550
}
44824551

44834552
// Check that minconf is positive.
4484-
minConf := int32(*cmd.MinConf)
4553+
minConf := int32(1)
4554+
if cmd.MinConf != nil {
4555+
minConf = int32(*cmd.MinConf)
4556+
}
44854557
if minConf < 0 {
44864558
return nil, rpcErrorf(dcrjson.ErrRPCInvalidParameter, "negative minconf")
44874559
}
@@ -4559,16 +4631,23 @@ func (s *Server) sendToMultiSig(ctx context.Context, icmd any) (any, error) {
45594631
if err != nil {
45604632
return nil, rpcError(dcrjson.ErrRPCInvalidParameter, err)
45614633
}
4562-
nrequired := int8(*cmd.NRequired)
4563-
minconf := int32(*cmd.MinConf)
4634+
nrequired := int8(1)
4635+
if cmd.NRequired != nil {
4636+
nrequired = int8(*cmd.NRequired)
4637+
}
4638+
4639+
minConf := int32(1)
4640+
if cmd.MinConf != nil {
4641+
minConf = int32(*cmd.MinConf)
4642+
}
45644643

45654644
pubKeys, err := walletPubKeys(ctx, w, cmd.Pubkeys)
45664645
if err != nil {
45674646
return nil, err
45684647
}
45694648

45704649
tx, addr, script, err :=
4571-
w.CreateMultisigTx(ctx, account, amount, pubKeys, nrequired, minconf)
4650+
w.CreateMultisigTx(ctx, account, amount, pubKeys, nrequired, minConf)
45724651
if err != nil {
45734652
return nil, err
45744653
}
@@ -4605,7 +4684,11 @@ func (s *Server) sendRawTransaction(ctx context.Context, icmd any) (any, error)
46054684
return nil, rpcError(dcrjson.ErrRPCDeserialization, err)
46064685
}
46074686

4608-
if !*cmd.AllowHighFees {
4687+
allowHighFees := false
4688+
if cmd.AllowHighFees != nil {
4689+
allowHighFees = *cmd.AllowHighFees
4690+
}
4691+
if !allowHighFees {
46094692
highFees, err := txrules.TxPaysHighFees(msgtx)
46104693
if err != nil {
46114694
return nil, err
@@ -4823,7 +4906,11 @@ func (s *Server) signRawTransaction(ctx context.Context, icmd any) (any, error)
48234906
}
48244907

48254908
var hashType txscript.SigHashType
4826-
switch *cmd.Flags {
4909+
flags := "ALL"
4910+
if cmd.Flags != nil {
4911+
flags = *cmd.Flags
4912+
}
4913+
switch flags {
48274914
case "ALL":
48284915
hashType = txscript.SigHashAll
48294916
case "NONE":
@@ -4906,7 +4993,7 @@ func (s *Server) signRawTransaction(ctx context.Context, icmd any) (any, error)
49064993
for i, txIn := range tx.TxIn {
49074994
// We don't need the first input of a stakebase tx, as it's garbage
49084995
// anyway.
4909-
if i == 0 && *cmd.Flags == "ssgen" {
4996+
if i == 0 && flags == "ssgen" {
49104997
continue
49114998
}
49124999

@@ -5053,7 +5140,11 @@ func (s *Server) signRawTransactions(ctx context.Context, icmd any) (any, error)
50535140
// do that now. Otherwise, construct the slice and return it.
50545141
toReturn := make([]types.SignedTransaction, len(cmd.RawTxs))
50555142

5056-
if *cmd.Send {
5143+
send := true
5144+
if cmd.Send != nil {
5145+
send = *cmd.Send
5146+
}
5147+
if send {
50575148
n, ok := s.walletLoader.NetworkBackend()
50585149
if !ok {
50595150
return nil, errNoNetwork

0 commit comments

Comments
 (0)