Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions proof.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
23 changes: 23 additions & 0 deletions proof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading