diff --git a/pkg/core/object/fmt.go b/pkg/core/object/fmt.go index 7d1bfc9f0..5fabb085d 100644 --- a/pkg/core/object/fmt.go +++ b/pkg/core/object/fmt.go @@ -35,6 +35,10 @@ func (v *FormatValidator) Validate(obj *Object) error { return errNilCID } + if err := v.validateContent(obj.GetType(), obj.GetPayload()); err != nil { + return errors.Wrapf(err, "(%T) incorrect content", v) + } + if err := v.validateSignatureKey(obj); err != nil { return errors.Wrapf(err, "(%T) could not validate signature key", v) } @@ -83,3 +87,23 @@ func (v *FormatValidator) checkOwnerKey(id *owner.ID, key []byte) error { return nil } + +func (v *FormatValidator) validateContent(t object.Type, payload []byte) error { + switch t { + case object.TypeTombstone: + if len(payload) == 0 { + return errors.Errorf("(%T) empty payload in tombstone", v) + } + + addr, err := object.AddressFromBytes(payload) + if err != nil { + return errors.Wrapf(err, "(%T) could not parse object address from tombstone", v) + } + + if addr.GetContainerID() == nil || addr.GetObjectID() == nil { + return errors.Errorf("(%T) empty address reference in tombstone", v) + } + } + + return nil +} diff --git a/pkg/core/object/fmt_test.go b/pkg/core/object/fmt_test.go index 995924371..1266cff88 100644 --- a/pkg/core/object/fmt_test.go +++ b/pkg/core/object/fmt_test.go @@ -1,6 +1,7 @@ package object import ( + "crypto/ecdsa" "crypto/rand" "crypto/sha256" "testing" @@ -38,9 +39,25 @@ func testObjectID(t *testing.T) *object.ID { return id } +func blankValidObject(t *testing.T, key *ecdsa.PrivateKey) *RawObject { + wallet, err := owner.NEO3WalletFromPublicKey(&key.PublicKey) + require.NoError(t, err) + + ownerID := owner.NewID() + ownerID.SetNeo3Wallet(wallet) + + obj := NewRaw() + obj.SetContainerID(testContainerID(t)) + obj.SetOwnerID(ownerID) + + return obj +} + func TestFormatValidator_Validate(t *testing.T) { v := NewFormatValidator() + ownerKey := test.DecodeKey(-1) + t.Run("nil input", func(t *testing.T) { require.Error(t, v.Validate(nil)) }) @@ -67,32 +84,53 @@ func TestFormatValidator_Validate(t *testing.T) { }) t.Run("correct w/ session token", func(t *testing.T) { - sessionKey := test.DecodeKey(-1) - tok := token.NewSessionToken() - tok.SetSessionKey(crypto.MarshalPublicKey(&sessionKey.PublicKey)) + tok.SetSessionKey(crypto.MarshalPublicKey(&ownerKey.PublicKey)) obj := NewRaw() obj.SetContainerID(testContainerID(t)) obj.SetSessionToken(tok) - require.NoError(t, object.SetIDWithSignature(sessionKey, obj.SDK())) + require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK())) require.NoError(t, v.Validate(obj.Object())) }) t.Run("correct w/o session token", func(t *testing.T) { - ownerKey := test.DecodeKey(-1) + obj := blankValidObject(t, ownerKey) - wallet, err := owner.NEO3WalletFromPublicKey(&ownerKey.PublicKey) + require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK())) + + require.NoError(t, v.Validate(obj.Object())) + }) + + t.Run("tombstone content", func(t *testing.T) { + obj := blankValidObject(t, ownerKey) + + obj.SetType(object.TypeTombstone) + + require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK())) + + require.Error(t, v.Validate(obj.Object())) + + addr := object.NewAddress() + + data, err := addr.ToV2().StableMarshal(nil) require.NoError(t, err) - ownerID := owner.NewID() - ownerID.SetNeo3Wallet(wallet) + obj.SetPayload(data) - obj := NewRaw() - obj.SetContainerID(testContainerID(t)) - obj.SetOwnerID(ownerID) + require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK())) + + require.Error(t, v.Validate(obj.Object())) + + addr.SetContainerID(testContainerID(t)) + addr.SetObjectID(testObjectID(t)) + + data, err = addr.ToV2().StableMarshal(nil) + require.NoError(t, err) + + obj.SetPayload(data) require.NoError(t, object.SetIDWithSignature(ownerKey, obj.SDK()))