Skip to content

Commit

Permalink
Check duplicate SlabID in inlined slabs in tests
Browse files Browse the repository at this point in the history
This commit adds an extra check in exported validation functions
that are only used for tests in Atree but can also be used by Cadence.
  • Loading branch information
fxamacker committed Oct 3, 2023
1 parent 4b3c26c commit 3f87ec5
Show file tree
Hide file tree
Showing 5 changed files with 440 additions and 408 deletions.
24 changes: 19 additions & 5 deletions array_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ func DumpArraySlabs(a *Array) ([]string, error) {
type TypeInfoComparator func(TypeInfo, TypeInfo) bool

func VerifyArray(a *Array, address Address, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider, inlineEnabled bool) error {
return verifyArray(a, address, typeInfo, tic, hip, inlineEnabled, map[SlabID]struct{}{})
}

func verifyArray(a *Array, address Address, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider, inlineEnabled bool, slabIDs map[SlabID]struct{}) error {
// Verify array address (independent of array inlined status)
if address != a.Address() {
return NewFatalError(fmt.Errorf("array address %v, got %v", address, a.Address()))
Expand Down Expand Up @@ -210,7 +214,7 @@ func VerifyArray(a *Array, address Address, typeInfo TypeInfo, tic TypeInfoCompa
}

// Verify array slabs
computedCount, dataSlabIDs, nextDataSlabIDs, err := v.verifySlab(a.root, 0, nil, []SlabID{}, []SlabID{})
computedCount, dataSlabIDs, nextDataSlabIDs, err := v.verifySlab(a.root, 0, nil, []SlabID{}, []SlabID{}, slabIDs)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by verifySlab().
return err
Expand Down Expand Up @@ -245,6 +249,7 @@ func (v *arrayVerifier) verifySlab(
headerFromParentSlab *ArraySlabHeader,
dataSlabIDs []SlabID,
nextDataSlabIDs []SlabID,
slabIDs map[SlabID]struct{},
) (
elementCount uint32,
_dataSlabIDs []SlabID,
Expand All @@ -253,6 +258,13 @@ func (v *arrayVerifier) verifySlab(
) {
id := slab.Header().slabID

// Verify SlabID is unique
if _, exist := slabIDs[id]; exist {
return 0, nil, nil, NewFatalError(fmt.Errorf("found duplicate slab ID %s", id))
}

slabIDs[id] = struct{}{}

// Verify slab address (independent of array inlined status)
if v.address != id.address {
return 0, nil, nil, NewFatalError(fmt.Errorf("array slab address %v, got %v", v.address, id.address))
Expand Down Expand Up @@ -298,10 +310,10 @@ func (v *arrayVerifier) verifySlab(

switch slab := slab.(type) {
case *ArrayDataSlab:
return v.verifyDataSlab(slab, level, dataSlabIDs, nextDataSlabIDs)
return v.verifyDataSlab(slab, level, dataSlabIDs, nextDataSlabIDs, slabIDs)

case *ArrayMetaDataSlab:
return v.verifyMetaDataSlab(slab, level, dataSlabIDs, nextDataSlabIDs)
return v.verifyMetaDataSlab(slab, level, dataSlabIDs, nextDataSlabIDs, slabIDs)

default:
return 0, nil, nil, NewFatalError(fmt.Errorf("ArraySlab is either *ArrayDataSlab or *ArrayMetaDataSlab, got %T", slab))
Expand All @@ -313,6 +325,7 @@ func (v *arrayVerifier) verifyDataSlab(
level int,
dataSlabIDs []SlabID,
nextDataSlabIDs []SlabID,
slabIDs map[SlabID]struct{},
) (
elementCount uint32,
_dataSlabIDs []SlabID,
Expand Down Expand Up @@ -402,7 +415,7 @@ func (v *arrayVerifier) verifyDataSlab(
}

// Verify element
err = verifyValue(value, v.address, nil, v.tic, v.hip, v.inlineEnabled)
err = verifyValue(value, v.address, nil, v.tic, v.hip, v.inlineEnabled, slabIDs)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by verifyValue().
return 0, nil, nil, fmt.Errorf(
Expand All @@ -420,6 +433,7 @@ func (v *arrayVerifier) verifyMetaDataSlab(
level int,
dataSlabIDs []SlabID,
nextDataSlabIDs []SlabID,
slabIDs map[SlabID]struct{},
) (
elementCount uint32,
_dataSlabIDs []SlabID,
Expand Down Expand Up @@ -467,7 +481,7 @@ func (v *arrayVerifier) verifyMetaDataSlab(
// Verify child slabs
var count uint32
count, dataSlabIDs, nextDataSlabIDs, err =
v.verifySlab(childSlab, level+1, &h, dataSlabIDs, nextDataSlabIDs)
v.verifySlab(childSlab, level+1, &h, dataSlabIDs, nextDataSlabIDs, slabIDs)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by verifySlab().
return 0, nil, nil, err
Expand Down
Loading

0 comments on commit 3f87ec5

Please sign in to comment.