mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-27 05:10:43 +00:00
pkg/compiler: add offsetof type
Similar to C offsetof gives offset of a field from the beginning of the parent struct. We have several TODOs in descriptions asking for this.
This commit is contained in:
parent
f59a9cb554
commit
76fc461b55
@ -50,6 +50,8 @@ rest of the type-options are type-specific:
|
||||
argname of the object
|
||||
"bitsize": similar to "len", but always denotes the size in bits, type-options:
|
||||
argname of the object
|
||||
"offsetof": offset of the field from the beginning of the parent struct, type-options:
|
||||
field
|
||||
"vma"/"vma64": a pointer to a set of pages (used as input for mmap/munmap/mremap/madvise), type-options:
|
||||
optional number of pages (e.g. vma[7]), or a range of pages (e.g. vma[2-4])
|
||||
vma64 has size of 8 bytes regardless of target pointer size
|
||||
|
@ -165,7 +165,7 @@
|
||||
|
||||
#if GOARCH_64
|
||||
#define GOARCH "64"
|
||||
#define SYZ_REVISION "e07c8657b55348a9385e59d435ee7ad303ccc728"
|
||||
#define SYZ_REVISION "74c87d08a1f72c38c85e889813b60823a1e5755c"
|
||||
#define SYZ_EXECUTOR_USES_FORK_SERVER 0
|
||||
#define SYZ_EXECUTOR_USES_SHMEM 0
|
||||
#define SYZ_PAGE_SIZE 4096
|
||||
|
@ -15509,6 +15509,7 @@ const call_t syscalls[] = {
|
||||
{"test$length9", 0},
|
||||
{"test$missing_resource", 0},
|
||||
{"test$missing_struct", 0},
|
||||
{"test$offsetof0", 0},
|
||||
{"test$opt0", 0},
|
||||
{"test$opt1", 0},
|
||||
{"test$opt2", 0},
|
||||
|
@ -415,7 +415,12 @@ func (comp *compiler) checkLenTargetRec(t0, t *ast.Type, targets []*ast.Type,
|
||||
parent := parents[pi]
|
||||
if parent.name != "" && (parent.name == target.Ident || target.Ident == prog.ParentRef) ||
|
||||
parent.name == "" && target.Ident == prog.SyscallRef {
|
||||
if len(targets) != 0 {
|
||||
if len(targets) == 0 {
|
||||
if t.Ident == "offsetof" {
|
||||
comp.error(target.Pos, "%v must refer to fields", t.Ident)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
parents1 := make([]parentDesc, pi+1)
|
||||
copy(parents1, parents[:pi+1])
|
||||
comp.checkLenTargetRec(t0, t, targets, parents1, warned)
|
||||
|
2
pkg/compiler/testdata/all.txt
vendored
2
pkg/compiler/testdata/all.txt
vendored
@ -90,6 +90,8 @@ len_expr3 {
|
||||
f34 bytesize[len_expr1:f11:f22:f41, int32]
|
||||
f35 bytesize[len_expr2:f23:f41, int32]
|
||||
f36 bytesize[len_expr2:f24:f41, int32]
|
||||
f37 offsetof[f32, int32]
|
||||
f38 offsetof[len_expr2:f21, int32]
|
||||
}
|
||||
|
||||
len_expr4 {
|
||||
|
2
pkg/compiler/testdata/errors2.txt
vendored
2
pkg/compiler/testdata/errors2.txt
vendored
@ -147,6 +147,8 @@ slen1 {
|
||||
f5 len[slen22:f, int32] ### len path slen22 does not refer to a struct
|
||||
f6 len[syscall, int32] ### no argument name after syscall reference
|
||||
f7 len[syscall:b, int32] ### len target b does not exist
|
||||
f8 offsetof[parent, int32] ### offsetof must refer to fields
|
||||
f9 offsetof[slen1, int32] ### offsetof must refer to fields
|
||||
slen2 ptr[in, array[slen2]]
|
||||
slen21 slen2
|
||||
slen22 array[slen2]
|
||||
|
@ -204,13 +204,14 @@ var typeArray = &typeDesc{
|
||||
}
|
||||
|
||||
var typeLen = &typeDesc{
|
||||
Names: []string{"len", "bytesize", "bytesize2", "bytesize4", "bytesize8", "bitsize"},
|
||||
Names: []string{"len", "bytesize", "bytesize2", "bytesize4", "bytesize8", "bitsize", "offsetof"},
|
||||
CanBeArgRet: canBeArg,
|
||||
CantBeOpt: true,
|
||||
NeedBase: true,
|
||||
Args: []namedArg{{Name: "len target", Type: typeArgLenTarget}},
|
||||
Gen: func(comp *compiler, t *ast.Type, args []*ast.Type, base prog.IntTypeCommon) prog.Type {
|
||||
var bitSize uint64
|
||||
var offset bool
|
||||
switch t.Ident {
|
||||
case "bytesize":
|
||||
bitSize = 8
|
||||
@ -219,6 +220,9 @@ var typeLen = &typeDesc{
|
||||
bitSize = byteSize * 8
|
||||
case "bitsize":
|
||||
bitSize = 1
|
||||
case "offsetof":
|
||||
bitSize = 8
|
||||
offset = true
|
||||
}
|
||||
path := []string{args[0].Ident}
|
||||
for _, col := range args[0].Colon {
|
||||
@ -228,6 +232,7 @@ var typeLen = &typeDesc{
|
||||
IntTypeCommon: base,
|
||||
Path: path,
|
||||
BitSize: bitSize,
|
||||
Offset: offset,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
22
prog/size.go
22
prog/size.go
@ -42,8 +42,12 @@ func (target *Target) assignSizes(args []Arg, parentsMap map[Arg]Arg, syscallArg
|
||||
func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []Arg, parentsMap map[Arg]Arg) {
|
||||
elem := path[0]
|
||||
path = path[1:]
|
||||
var offset uint64
|
||||
for _, buf := range args {
|
||||
if elem != buf.Type().FieldName() {
|
||||
if !buf.Type().BitfieldMiddle() {
|
||||
offset += buf.Size()
|
||||
}
|
||||
continue
|
||||
}
|
||||
buf = InnerArg(buf)
|
||||
@ -52,7 +56,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
|
||||
return
|
||||
}
|
||||
if len(path) == 0 {
|
||||
dst.Val = target.computeSize(buf, dst.Type().(*LenType))
|
||||
dst.Val = target.computeSize(buf, offset, dst.Type().(*LenType))
|
||||
} else {
|
||||
target.assignSize(dst, buf, path, buf.(*GroupArg).Inner, parentsMap)
|
||||
}
|
||||
@ -61,7 +65,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
|
||||
if elem == ParentRef {
|
||||
buf := parentsMap[pos]
|
||||
if len(path) == 0 {
|
||||
dst.Val = target.computeSize(buf, dst.Type().(*LenType))
|
||||
dst.Val = target.computeSize(buf, noOffset, dst.Type().(*LenType))
|
||||
} else {
|
||||
target.assignSize(dst, buf, path, buf.(*GroupArg).Inner, parentsMap)
|
||||
}
|
||||
@ -77,7 +81,7 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
|
||||
continue
|
||||
}
|
||||
if len(path) == 0 {
|
||||
dst.Val = target.computeSize(buf, dst.Type().(*LenType))
|
||||
dst.Val = target.computeSize(buf, noOffset, dst.Type().(*LenType))
|
||||
} else {
|
||||
target.assignSize(dst, buf, path, buf.(*GroupArg).Inner, parentsMap)
|
||||
}
|
||||
@ -91,10 +95,14 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
|
||||
dst.Type().FieldName(), elem, pos.Type().Name(), pos.Type().FieldName(), argNames))
|
||||
}
|
||||
|
||||
func (target *Target) computeSize(arg Arg, lenType *LenType) uint64 {
|
||||
if arg == nil {
|
||||
// Arg is an optional pointer, set size to 0.
|
||||
return 0
|
||||
const noOffset = ^uint64(0)
|
||||
|
||||
func (target *Target) computeSize(arg Arg, offset uint64, lenType *LenType) uint64 {
|
||||
if lenType.Offset {
|
||||
if offset == noOffset {
|
||||
panic("offset of a non-field")
|
||||
}
|
||||
return offset * 8 / lenType.BitSize
|
||||
}
|
||||
bitSize := lenType.BitSize
|
||||
if bitSize == 0 {
|
||||
|
@ -155,6 +155,10 @@ func TestAssignSize(t *testing.T) {
|
||||
"test$length30(&(0x7f0000000000)={{{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, {'a', 'aaa', 'aaaaa', 'aaaaaa'}, &(0x7f0000000000)={'a', 'aaa', 'aaaaa', 'aaaaaa'}, &(0x7f0000000000)=&(0x7f0000000000)={'a', 'aaa', 'aaaaa', 'aaaaaa'}, 0x0}, 0x0}, 0x0, &(0x7f0000000000)=0x0, 0x0)",
|
||||
"test$length30(&(0x7f0000000000)={{{0x0, 0x18, 0x1, 0x3, 0x5, 0x6}, {'a', 'aaa', 'aaaaa', 'aaaaaa'}, &(0x7f0000000000)={'a', 'aaa', 'aaaaa', 'aaaaaa'}, &(0x7f0000000000)=&(0x7f0000000000)={'a', 'aaa', 'aaaaa', 'aaaaaa'}, 0x2}, 0x4}, 0x40, &(0x7f0000000000)=0x18, 0x2)",
|
||||
},
|
||||
{
|
||||
"test$offsetof0(&(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0})",
|
||||
"test$offsetof0(&(0x7f0000000000)={0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x6, 0x8, 0x10, 0x18, 0x18, 0x20})",
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
p, err := target.Deserialize([]byte(test.unsizedProg), Strict)
|
||||
|
@ -255,6 +255,7 @@ func (t *FlagsType) isDefaultArg(arg Arg) bool {
|
||||
type LenType struct {
|
||||
IntTypeCommon
|
||||
BitSize uint64 // want size in multiple of bits instead of array size
|
||||
Offset bool // offset from the beginning of the parent struct or base object
|
||||
Path []string
|
||||
}
|
||||
|
||||
|
@ -152,6 +152,27 @@ var structDescs_64 = []*KeyedStruct{
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f2", TypeSize: 1}}},
|
||||
&ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 3}}, IsPad: true},
|
||||
}}},
|
||||
{Key: StructKey{Name: "offsetof0"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "offsetof0", TypeSize: 72}, Fields: []Type{
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "f0", TypeSize: 4}}},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f1", TypeSize: 1}}},
|
||||
&ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 1}}, IsPad: true},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f2", TypeSize: 2}}},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f3", TypeSize: 1}}},
|
||||
&ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 7}}, IsPad: true},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int64", FldName: "f4", TypeSize: 8}}},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "f5", TypeSize: 4}, BitfieldLen: 5, BitfieldMdl: true}},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int32", FldName: "f6", TypeSize: 4}, BitfieldOff: 5, BitfieldLen: 10}},
|
||||
&ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 4}}, IsPad: true},
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int64", FldName: "f7", TypeSize: 8}}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o0", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f0"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o1", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f1"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o2", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f2"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o3", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f3"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o4", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f4"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o5", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f5"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o6", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f6"}},
|
||||
&LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "offsetof", FldName: "o7", TypeSize: 4}}, BitSize: 8, Offset: true, Path: []string{"f7"}},
|
||||
}}},
|
||||
{Key: StructKey{Name: "serialize0_struct"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "serialize0_struct", TypeSize: 15}, Fields: []Type{
|
||||
&BufferType{TypeCommon: TypeCommon{TypeName: "string", FldName: "a", TypeSize: 10}, Kind: 2, SubKind: "serialize_strings", Values: []string{"aaa\x00\x00\x00\x00\x00\x00\x00", "bbb\x00\x00\x00\x00\x00\x00\x00"}},
|
||||
&BufferType{TypeCommon: TypeCommon{TypeName: "string", FldName: "b", TypeSize: 5}, Kind: 2, SubKind: "serialize_strings", Values: []string{"aaa\x00\x00", "bbb\x00\x00"}},
|
||||
@ -896,6 +917,9 @@ var syscalls_64 = []*Syscall{
|
||||
{Name: "test$missing_struct", CallName: "test", MissingArgs: 5, Args: []Type{
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "a", TypeSize: 8}, Type: &StructType{Key: StructKey{Name: "syz_use_missing"}}},
|
||||
}},
|
||||
{Name: "test$offsetof0", CallName: "test", MissingArgs: 5, Args: []Type{
|
||||
&PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "a0", TypeSize: 8}, Type: &StructType{Key: StructKey{Name: "offsetof0"}}},
|
||||
}},
|
||||
{Name: "test$opt0", CallName: "test", MissingArgs: 5, Args: []Type{
|
||||
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "intptr", FldName: "a0", TypeSize: 8, IsOptional: true}}},
|
||||
}},
|
||||
@ -1010,4 +1034,4 @@ var consts_64 = []ConstValue{
|
||||
{Name: "SYS_unsupported"},
|
||||
}
|
||||
|
||||
const revision_64 = "e07c8657b55348a9385e59d435ee7ad303ccc728"
|
||||
const revision_64 = "74c87d08a1f72c38c85e889813b60823a1e5755c"
|
||||
|
@ -461,6 +461,27 @@ len_expr4 {
|
||||
|
||||
test$length30(a0 ptr[in, len_expr1], a1 bytesize[a0:f11], a2 ptr[in, bytesize[a0:f11:f21, int32]], a3 bytesize[a0:f11:f21:f31])
|
||||
|
||||
test$offsetof0(a0 ptr[in, offsetof0])
|
||||
|
||||
offsetof0 {
|
||||
f0 int32
|
||||
f1 int8
|
||||
f2 int16
|
||||
f3 int8
|
||||
f4 int64
|
||||
f5 int32:5
|
||||
f6 int32:10
|
||||
f7 int64
|
||||
o0 offsetof[f0, int32]
|
||||
o1 offsetof[f1, int32]
|
||||
o2 offsetof[f2, int32]
|
||||
o3 offsetof[f3, int32]
|
||||
o4 offsetof[f4, int32]
|
||||
o5 offsetof[f5, int32]
|
||||
o6 offsetof[f6, int32]
|
||||
o7 offsetof[f7, int32]
|
||||
}
|
||||
|
||||
# Big endian
|
||||
|
||||
test$end0(a0 ptr[in, syz_end_int_struct])
|
||||
|
Loading…
Reference in New Issue
Block a user