diff --git a/proof.go b/proof.go index a02a2b6..67f44ff 100644 --- a/proof.go +++ b/proof.go @@ -151,6 +151,15 @@ func (proof Proof) isValidEmptyRangeProof(nth *NmtHasher, nID namespace.ID, root return true } + // validate the root format before slicing its namespace bounds below. + // Without this check, a root shorter than 2*nID.Size() would cause + // MinNamespace/MaxNamespace to panic with a slice bounds error instead of + // returning a verification failure. The non-empty path performs the + // equivalent validation via nth.ValidateNodeFormat(root) in VerifyLeafHashes. + if err := nth.ValidateNodeFormat(root); err != nil { + return false + } + nIDLen := nID.Size() rootMin := namespace.ID(MinNamespace(root, nIDLen)) rootMax := namespace.ID(MaxNamespace(root, nIDLen)) diff --git a/proof_test.go b/proof_test.go index 4631144..60fa555 100644 --- a/proof_test.go +++ b/proof_test.go @@ -102,6 +102,29 @@ func TestVerifyNamespace_EmptyProof(t *testing.T) { } } +// TestVerifyNamespace_EmptyProofShortRoot is a regression test for a panic in +// the empty-range proof path of VerifyNamespace. An empty range proof combined +// with a root shorter than 2*nID.Size() previously caused +// MinNamespace/MaxNamespace to panic with "slice bounds out of range" because +// the root was sliced without first validating its format. The fix validates +// the root and returns a verification failure instead of panicking. +func TestVerifyNamespace_EmptyProofShortRoot(t *testing.T) { + const nIDLen = 8 + // empty range proof: start == end == 0, no nodes, no leafHash + proof := NewEmptyRangeProof(true) + require.True(t, proof.IsEmptyProof()) + + nID := namespace.ID(bytes.Repeat([]byte{0x01}, nIDLen)) + // root shorter than 2*nID.Size(), which would panic the namespace-bound + // slicing in the empty-range path prior to the fix. + shortRoot := make([]byte, 4) + + require.NotPanics(t, func() { + got := proof.VerifyNamespace(sha256.New(), nID, nil, shortRoot) + require.False(t, got) + }) +} + func TestProof_VerifyNamespace_False(t *testing.T) { const testNidLen = 3