diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-03-17 14:32:13 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-03-17 21:19:13 +0100 |
| commit | 2e9037c55f6a3308190ab4eb0ce110dddc7a6f2b (patch) | |
| tree | 7f97740e9d496a53a990d88a41405e67b8d4af44 /pkg/compiler/gen.go | |
| parent | 0bcbb36f9fff81ac0bff9ec0959b9ea4c444a700 (diff) | |
pkg/compiler: check that const values fit into base type
const[0x12345678, int8] is always an error, detect these cases.
Found some bugs in mptcp, socket proto and fuchsia fidl descriptions.
Diffstat (limited to 'pkg/compiler/gen.go')
| -rw-r--r-- | pkg/compiler/gen.go | 66 |
1 files changed, 24 insertions, 42 deletions
diff --git a/pkg/compiler/gen.go b/pkg/compiler/gen.go index 30080f56a..5a658ce15 100644 --- a/pkg/compiler/gen.go +++ b/pkg/compiler/gen.go @@ -60,10 +60,10 @@ func (comp *compiler) collectCallArgSizes() map[string][]uint64 { argSizes := callArgSizes[n.CallName] for i, arg := range n.Args { if len(argSizes) <= i { - argSizes = append(argSizes, 0) + argSizes = append(argSizes, comp.ptrSize) } desc, _, _ := comp.getArgsBase(arg.Type, arg.Name.Name, prog.DirIn, true) - typ := comp.genField(arg, prog.DirIn, true) + typ := comp.genField(arg, prog.DirIn, comp.ptrSize) // Ignore all types with base (const, flags). We don't have base in syscall args. // Also ignore resources and pointers because fd can be 32-bits and pointer 64-bits, // and then there is no way to fix this. @@ -76,7 +76,7 @@ func (comp *compiler) collectCallArgSizes() map[string][]uint64 { continue } argID := fmt.Sprintf("%v|%v", n.CallName, i) - if argSizes[i] == 0 { + if _, ok := argPos[argID]; !ok { argSizes[i] = typ.Size() argPos[argID] = arg.Pos continue @@ -109,45 +109,18 @@ func (comp *compiler) genSyscalls() []*prog.Syscall { func (comp *compiler) genSyscall(n *ast.Call, argSizes []uint64) *prog.Syscall { var ret prog.Type if n.Ret != nil { - ret = comp.genType(n.Ret, "ret", prog.DirOut, true) - } - args := comp.genFieldArray(n.Args, prog.DirIn, true) - for i, arg := range args { - // Now that we know a more precise size, patch the type. - // This is somewhat hacky. Ideally we figure out the size earlier, - // store it somewhere and use during generation of the arg base type. - if argSizes[i] != 0 { - patchArgBaseSize(arg, argSizes[i]) - } + ret = comp.genType(n.Ret, "ret", prog.DirOut, comp.ptrSize) } return &prog.Syscall{ Name: n.Name.Name, CallName: n.CallName, NR: n.NR, MissingArgs: len(argSizes) - len(n.Args), - Args: args, + Args: comp.genFieldArray(n.Args, prog.DirIn, argSizes), Ret: ret, } } -func patchArgBaseSize(t0 prog.Type, size uint64) { - // We only need types that (1) can be arg, (2) have base type. - switch t := t0.(type) { - case *prog.ConstType: - t.TypeSize = size - case *prog.LenType: - t.TypeSize = size - case *prog.FlagsType: - t.TypeSize = size - case *prog.ProcType: - t.TypeSize = size - case *prog.IntType, *prog.ResourceType, *prog.PtrType, *prog.VmaType, *prog.UnionType: - // These don't have base. - default: - panic(fmt.Sprintf("type %#v can't be an arg", t)) - } -} - func (comp *compiler) genStructDescs(syscalls []*prog.Syscall) []*prog.KeyedStruct { // Calculate struct/union/array sizes, add padding to structs and detach // StructDesc's from StructType's. StructType's can be recursive so it's @@ -321,7 +294,7 @@ func (comp *compiler) genStructDesc(res *prog.StructDesc, n *ast.Struct, dir pro common.IsVarlen = varlen *res = prog.StructDesc{ TypeCommon: common, - Fields: comp.genFieldArray(n.Fields, dir, false), + Fields: comp.genFieldArray(n.Fields, dir, make([]uint64, len(n.Fields))), } } @@ -517,23 +490,32 @@ func genPad(size uint64) prog.Type { } } -func (comp *compiler) genField(f *ast.Field, dir prog.Dir, isArg bool) prog.Type { - return comp.genType(f.Type, f.Name.Name, dir, isArg) -} - -func (comp *compiler) genFieldArray(fields []*ast.Field, dir prog.Dir, isArg bool) []prog.Type { +func (comp *compiler) genFieldArray(fields []*ast.Field, dir prog.Dir, argSizes []uint64) []prog.Type { var res []prog.Type - for _, f := range fields { - res = append(res, comp.genField(f, dir, isArg)) + for i, f := range fields { + res = append(res, comp.genField(f, dir, argSizes[i])) } return res } -func (comp *compiler) genType(t *ast.Type, field string, dir prog.Dir, isArg bool) prog.Type { - desc, args, base := comp.getArgsBase(t, field, dir, isArg) +func (comp *compiler) genField(f *ast.Field, dir prog.Dir, argSize uint64) prog.Type { + return comp.genType(f.Type, f.Name.Name, dir, argSize) +} + +func (comp *compiler) genType(t *ast.Type, field string, dir prog.Dir, argSize uint64) prog.Type { + desc, args, base := comp.getArgsBase(t, field, dir, argSize != 0) if desc.Gen == nil { panic(fmt.Sprintf("no gen for %v %#v", field, t)) } + if argSize != 0 { + // Now that we know a more precise size, patch the type. + // This is somewhat hacky. Ideally we figure out the size earlier, + // store it somewhere and use during generation of the arg base type. + base.TypeSize = argSize + if desc.CheckConsts != nil { + desc.CheckConsts(comp, t, args, base) + } + } base.IsVarlen = desc.Varlen != nil && desc.Varlen(comp, t, args) return desc.Gen(comp, t, args, base) } |
