Conversation
The parameter is optional and typed *bool, so a client may send an explicit JSON null for it. The declared jsonrpcdefault is only applied when the field is absent, which leaves the pointer nil, and the handler dereferenced it as its first effective statement. The handler runs on a goroutine with no recover, so the result is a process crash rather than a failed request, and the limited tier of RPC credential is enough to trigger it. Nil-guard the dereference the same way the other optional pointer parameters in this command set are guarded at their dereference sites. Absent and explicit false then behave identically, which is what the declared default already implies: a request that does not opt in to high fees declines them. No signature or wire change, so clients are unaffected. The existing table test missed this because every case constructs the command with a non-nil pointer, as one naturally does. The nil state is only reachable through a parsed request. The new case is first in the table so the panic is the first thing exercised, and it fails on the unfixed handler with a SIGSEGV at this line before the guard is added. Fixes decred#3813
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
sendrawtransactiontakes an optionalAllowHighFees *boolwith ajsonrpcdefault:"false"tag. The parser applies that declared default only when the field is absent, so a client that sends an explicit JSONnullfor it arrives with a nil pointer. The handler dereferenced it as its first effective statement:The handler runs on a goroutine with no
recover, so this is a process crash rather than a failed request. The limited tier of RPC credential is enough to trigger it, and the same request with the parameter omitted works correctly.Why it went unnoticed: every case in the existing
TestHandleSendRawTransactionconstructs the command with a non-nil pointer, because that is the natural way to write the test literal. The nil state is only reachable through a parsed request, not a constructed one.Fix
Nil-guard the dereference, matching the idiom already used throughout this command set (
if c.Verbose != nil && !*c.Verbose, and the other optional pointer parameters the report counts):Absent and explicit-
falsethen behave identically, which is what the declared default already implies: a request that does not opt in to high fees is treated as one that declines them. No signature or wire change, so clients are unaffected.Test
One case added to the existing table, placed first so the panic is the first thing exercised. It fails on the unfixed handler:
and passes with the guard. The mock sync manager is set to return a processing error so the case asserts the handler reaches the deserialization path and returns the existing error code, rather than merely not panicking.
Verification
Run in a clean
golang:1.25container againstmaster(6f6cf21):go test ./internal/rpcserver/ -run TestHandleSendRawTransactionokaftergo test ./internal/rpcserver/... -count=1go vet ./internal/rpcserver/...gofmt -lon both touched filesA note on the class, not just this instance
If the parser skips a declared default for an explicit null, then every optional pointer parameter in the command set carries this hazard, and the ones that are currently safe are safe only because each dereference site is guarded by hand. Twenty-odd hand-written guards is a lot of places to keep in step.
Normalising the parser so an explicit null takes the declared default would remove the class entirely. That changes parsing behaviour for every command in the set, so it is a wider decision than a crash fix and I have deliberately not folded it in here. Raising it in case it is worth doing on its own.