Onyx-Protocol / Onyx

Onyx

Home Page:https://Onyx.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

protocol/validation: nil pointer during ValidateTx

jbowens opened this issue · comments

Fuzz testing found a transaction for which ValidateTx will panic with a nil pointer deference:

Here's an individual test case that can be put into the protocol/validation package to repro: https://gist.github.com/jbowens/5f0fb08beac2eb2a4c33937302c62127

Here's the stack trace:

=== RUN   TestFuzzNilPointer
--- FAIL: TestFuzzNilPointer (0.00s)
panic: runtime error: invalid memory address or nil pointer dereference [recovered]
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x11830e8]

goroutine 5 [running]:
testing.tRunner.func1(0xc42006e8f0)
	/usr/local/go/src/testing/testing.go:622 +0x29d
panic(0x11c3740, 0x12e01d0)
	/usr/local/go/src/runtime/panic.go:489 +0x2cf
chain/protocol/validation.checkValidDest(0xc4200f3b78, 0xc42000b040, 0x0, 0xc42000ade0)
	/Users/jackson/src/chain/protocol/validation/validation.go:394 +0x5b8
chain/protocol/validation.checkValid(0xc4200f4070, 0x12c8980, 0xc4200ec030, 0xc4200c8e08, 0x1)
	/Users/jackson/src/chain/protocol/validation/validation.go:106 +0x1f5c
chain/protocol/validation.checkValidSrc(0xc4200f4e18, 0xc42000aea0, 0x10000c4200c8b60, 0xc4200ba128)
	/Users/jackson/src/chain/protocol/validation/validation.go:313 +0x119
chain/protocol/validation.checkValid(0xc420018d80, 0x12c8a40, 0xc4200ec090, 0xc4200c8e18, 0x20)
	/Users/jackson/src/chain/protocol/validation/validation.go:171 +0x1ba0
chain/protocol/validation.checkValid(0xc4200f5e70, 0x12c8bc0, 0xc42000c0e0, 0x0, 0x8000101)
	/Users/jackson/src/chain/protocol/validation/validation.go:72 +0x41ca
chain/protocol/validation.ValidateTx(0xc4200a6090, 0x50935a092ffad7ec, 0x9fbac4f4486db6c3, 0xb8cd5b9f51cf6972, 0x48584dde286a7220, 0x0, 0xc4200c8b60)
	/Users/jackson/src/chain/protocol/validation/validation.go:478 +0xde
chain/protocol/validation.TestFuzzNilPointer(0xc42006e8f0)
	/Users/jackson/src/chain/protocol/validation/fuzz_test.go:28 +0x22f
testing.tRunner(0xc42006e8f0, 0x12048d0)
	/usr/local/go/src/testing/testing.go:657 +0x96
created by testing.(*T).Run
	/usr/local/go/src/testing/testing.go:697 +0x2ca
exit status 2
FAIL	chain/protocol/validation	0.011s

Should we be using the proto-generated getters to avoid nil panics? Or performing nil checks along the way? It looks like most of the validation code assumes the bc.Tx type is well-formed and omits nil checks.

Any thoughts on collapsing the Body and Witness bc protos into their parent messages? Removing indirection would help get rid of a lot of nil checks.

Instead of an entry.body method we could have a entry.writeBody() method that calls writeForHash for the relevant fields.

I wonder if we should just use protobufs for transport and then define validation in terms of plain Go types. We already talked about maybe changing our protobuf representation of the txgraph so that we reduce some of the bloat. We could optimize the protobufs for a small wire footprint and implement a mapping to Go types that are optimized for convenience.