Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only encode reference static type in legacy format if it was decoded as such #3199

Merged
merged 1 commit into from
Mar 27, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions migrations/entitlements/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3124,6 +3124,7 @@ func TestRehash(t *testing.T) {
interpreter.UnauthorizedAccess,
newCompositeType(),
)
refType.HasLegacyIsAuthorized = true
refType.LegacyIsAuthorized = true

legacyRefType := &migrations.LegacyReferenceType{
Expand Down
13 changes: 13 additions & 0 deletions migrations/legacy_reference_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ type LegacyReferenceType struct {
var _ interpreter.StaticType = &LegacyReferenceType{}

func (t *LegacyReferenceType) ID() common.TypeID {
if !t.HasLegacyIsAuthorized {
// Encode as a regular reference type
return t.ReferenceStaticType.ID()
}

borrowedType := t.ReferencedType
return common.TypeID(
formatReferenceType(
Expand All @@ -58,6 +63,14 @@ func formatReferenceType(
}

func (t *LegacyReferenceType) Encode(e *cbor.StreamEncoder) error {
if !t.HasLegacyIsAuthorized {
// Encode as a regular reference type
return t.ReferenceStaticType.Encode(e)
}

// Has legacy isAuthorized flag,
// encode as a legacy reference type

// Encode tag number and array head
err := e.EncodeRawBytes([]byte{
// tag number
Expand Down
168 changes: 168 additions & 0 deletions migrations/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
package migrations

import (
"bytes"
"errors"
"fmt"
"testing"

"github.com/fxamacker/cbor/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -2297,3 +2299,169 @@ func TestDomainsMigration(t *testing.T) {
})
})
}

func TestLegacyReferenceType(t *testing.T) {

t.Parallel()

test := func(
t *testing.T,
refType *interpreter.ReferenceStaticType,
expectedTypeID common.TypeID,
expectedEncoding []byte,
) {

legacyRefType := &LegacyReferenceType{
ReferenceStaticType: refType,
}

assert.Equal(t,
expectedTypeID,
legacyRefType.ID(),
)

var buf bytes.Buffer

encoder := cbor.NewStreamEncoder(&buf)
err := legacyRefType.Encode(encoder)
require.NoError(t, err)

err = encoder.Flush()
require.NoError(t, err)

assert.Equal(t, expectedEncoding, buf.Bytes())
}

t.Run("has legacy authorized, unauthorized", func(t *testing.T) {

t.Parallel()

refType := interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.PrimitiveStaticTypeAnyStruct,
)
refType.HasLegacyIsAuthorized = true
refType.LegacyIsAuthorized = false

test(t,
refType,
"&AnyStruct",
[]byte{
// tag
0xd8, interpreter.CBORTagReferenceStaticType,
// array, 2 items follow
0x82,
// authorized = false
0xf4,
// tag
0xd8, interpreter.CBORTagPrimitiveStaticType,
// AnyStruct,
byte(interpreter.PrimitiveStaticTypeAnyStruct),
},
)
})

t.Run("has legacy authorized, authorized", func(t *testing.T) {

t.Parallel()

refType := interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.PrimitiveStaticTypeAnyStruct,
)
refType.HasLegacyIsAuthorized = true
refType.LegacyIsAuthorized = true

test(t,
refType,
"auth&AnyStruct",
[]byte{
// tag
0xd8, interpreter.CBORTagReferenceStaticType,
// array, 2 items follow
0x82,
// authorized = true
0xf5,
// tag
0xd8, interpreter.CBORTagPrimitiveStaticType,
// AnyStruct,
byte(interpreter.PrimitiveStaticTypeAnyStruct),
},
)
})

t.Run("new authorization, unauthorized", func(t *testing.T) {
t.Parallel()

refType := interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.PrimitiveStaticTypeAnyStruct,
)

test(t,
refType,
"&AnyStruct",
[]byte{
// tag
0xd8, interpreter.CBORTagReferenceStaticType,
// array, 2 items follow
0x82,
// tag
0xd8, interpreter.CBORTagUnauthorizedStaticAuthorization,
// nil
0xf6,
// tag
0xd8, interpreter.CBORTagPrimitiveStaticType,
// AnyStruct,
byte(interpreter.PrimitiveStaticTypeAnyStruct),
},
)

})

t.Run("new authorization, authorized", func(t *testing.T) {
t.Parallel()

refType := interpreter.NewReferenceStaticType(
nil,
interpreter.NewEntitlementSetAuthorization(
nil,
func() []common.TypeID {
return []common.TypeID{"Foo"}
},
1,
sema.Conjunction,
),
interpreter.PrimitiveStaticTypeAnyStruct,
)

test(t,
refType,
"auth(Foo)&AnyStruct",
[]byte{
// tag
0xd8, interpreter.CBORTagReferenceStaticType,
// array, 2 items follow
0x82,
// tag
0xd8, interpreter.CBORTagEntitlementSetStaticAuthorization,
// array, 2 items follow
0x82,
0x0,
// array, 1 items follow
0x81,
// UTF-8 string, 3 bytes follow
0x63,
// F, o, o
0x46, 0x6f, 0x6f,
// tag
0xd8, interpreter.CBORTagPrimitiveStaticType,
// AnyStruct,
byte(interpreter.PrimitiveStaticTypeAnyStruct),
},
)
})
}
11 changes: 7 additions & 4 deletions runtime/interpreter/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1772,16 +1772,18 @@ func (d TypeDecoder) decodeReferenceStaticType() (StaticType, error) {
return nil, err
}

var isAuthorized bool
var hasLegacyIsAuthorized bool
var legacyIsAuthorized bool

if t == cbor.BoolType {
// if we saw a bool here, this is a reference encoded in the old format
isAuthorized, err = d.decoder.DecodeBool()
hasLegacyIsAuthorized = true

legacyIsAuthorized, err = d.decoder.DecodeBool()
if err != nil {
return nil, err
}

// TODO: better decoding for old values to compute new, sensible authorizations for them.
authorization = UnauthorizedAccess
} else {
// Decode authorized at array index encodedReferenceStaticTypeAuthorizationFieldKey
Expand Down Expand Up @@ -1812,7 +1814,8 @@ func (d TypeDecoder) decodeReferenceStaticType() (StaticType, error) {
staticType,
)

referenceType.LegacyIsAuthorized = isAuthorized
referenceType.HasLegacyIsAuthorized = hasLegacyIsAuthorized
referenceType.LegacyIsAuthorized = legacyIsAuthorized

return referenceType, nil
}
Expand Down
5 changes: 3 additions & 2 deletions runtime/interpreter/statictype.go
Original file line number Diff line number Diff line change
Expand Up @@ -799,8 +799,9 @@ func (a EntitlementMapAuthorization) Equal(other Authorization) bool {
type ReferenceStaticType struct {
Authorization Authorization
// ReferencedType is type of the referenced value (the type of the target)
ReferencedType StaticType
LegacyIsAuthorized bool
ReferencedType StaticType
HasLegacyIsAuthorized bool
LegacyIsAuthorized bool
}

var _ StaticType = &ReferenceStaticType{}
Expand Down