From c7918378631992d874c99736272ed342d5d77b2c Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Sat, 8 Dec 2018 19:03:09 +0100 Subject: executor: fix handling of big-endian bitfields Currently we apply big-endian-ness and bitfield-ness in the wrong order in copyin. This leads to totally bogus result. Fix this. --- pkg/compiler/check.go | 3 ++- pkg/compiler/testdata/errors.txt | 1 + pkg/compiler/types.go | 18 ++++++++++++++---- 3 files changed, 17 insertions(+), 5 deletions(-) (limited to 'pkg/compiler') diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go index 6ec2fa9e2..cc0535449 100644 --- a/pkg/compiler/check.go +++ b/pkg/compiler/check.go @@ -751,7 +751,8 @@ func (comp *compiler) checkTypeBasic(t *ast.Type, desc *typeDesc, flags checkFla comp.error(t.Pos, "%v can't be type alias target", t.Ident) return } - if flags&checkIsResourceBase != 0 && !desc.ResourceBase { + if flags&checkIsResourceBase != 0 && + (desc.CanBeResourceBase == nil || !desc.CanBeResourceBase(comp, t)) { comp.error(t.Pos, "%v can't be resource base (int types can)", t.Ident) return } diff --git a/pkg/compiler/testdata/errors.txt b/pkg/compiler/testdata/errors.txt index fed520e6e..55ec40901 100644 --- a/pkg/compiler/testdata/errors.txt +++ b/pkg/compiler/testdata/errors.txt @@ -65,6 +65,7 @@ resource r2[r0]: 2 resource r3[int32:1] ### unexpected ':', only struct fields can be bitfields resource r4[int32[opt]] ### resource base can't be marked as opt resource r5[non_existent] ### unknown type non_existent +resource r6[int64be] ### int64be can't be resource base (int types can) resource r9["foo"] ### unexpected string "foo", expect type foo$7(a r0, a1 r2[opt]) diff --git a/pkg/compiler/types.go b/pkg/compiler/types.go index 98edc9d74..30ff8884a 100644 --- a/pkg/compiler/types.go +++ b/pkg/compiler/types.go @@ -18,11 +18,12 @@ type typeDesc struct { CantBeOpt bool // can't be marked as opt? NeedBase bool // needs base type when used as field? AllowColon bool // allow colon (int8:2) on fields? - ResourceBase bool // can be resource base type? OptArgs int // number of optional arguments in Args array Args []namedArg // type arguments // CanBeArgRet returns if this type can be syscall argument/return (false if nil). CanBeArgRet func(comp *compiler, t *ast.Type) (bool, bool) + // CanBeResourceBase returns if this type can be a resource base type (false if nil. + CanBeResourceBase func(comp *compiler, t *ast.Type) bool // Check does custom verification of the type (optional, consts are not patched yet). Check func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) // CheckConsts does custom verification of the type (optional, consts are patched). @@ -67,9 +68,16 @@ var typeInt = &typeDesc{ CanBeArgRet: canBeArg, CanBeTypedef: true, AllowColon: true, - ResourceBase: true, OptArgs: 1, Args: []namedArg{{Name: "range", Type: typeArgIntRange}}, + CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { + // Big-endian resources can always be converted to non-big-endian, + // since we will always revert bytes during copyout and during copyin, + // so the result is the same as not reverting at all. + // Big-endian resources are also not implemented and don't have tests. + _, be := comp.parseIntType(t.Ident) + return !be + }, Check: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) { typeArgBase.Type.Check(comp, t) }, @@ -653,8 +661,10 @@ var typeArgType = &typeArg{} var typeResource = &typeDesc{ // No Names, but getTypeDesc knows how to match it. - CanBeArgRet: canBeArgRet, - ResourceBase: true, + CanBeArgRet: canBeArgRet, + CanBeResourceBase: func(comp *compiler, t *ast.Type) bool { + return true + }, // Gen is assigned below to avoid initialization loop. } -- cgit mrf-deployment