aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2019-05-14 16:21:19 +0200
committerDmitry Vyukov <dvyukov@google.com>2019-05-14 19:28:01 +0200
commit2376f0f937b8e6b457ef1fdf088b8b7059dcb0e2 (patch)
tree6a66d085190a488475a843ec8a138fd6a3c8e8a1
parent9a4969814ea6a65b306ca7d3192c23381c778ad4 (diff)
pkg/compiler: allow to refer to syscall arguments in len paths
This allows to use len[syscall:arg] expressions.
-rw-r--r--docs/syscall_descriptions_syntax.md14
-rw-r--r--executor/defs.h2
-rw-r--r--pkg/compiler/check.go34
-rw-r--r--pkg/compiler/testdata/all.txt3
-rw-r--r--pkg/compiler/testdata/errors2.txt2
-rw-r--r--prog/size.go17
-rw-r--r--prog/size_test.go4
-rw-r--r--sys/test/gen/64.go6
-rw-r--r--sys/test/test.txt1
9 files changed, 53 insertions, 30 deletions
diff --git a/docs/syscall_descriptions_syntax.md b/docs/syscall_descriptions_syntax.md
index e3318d300..25b0e0e65 100644
--- a/docs/syscall_descriptions_syntax.md
+++ b/docs/syscall_descriptions_syntax.md
@@ -252,7 +252,9 @@ s2 {
`len` argument can also be a path expression which allows more complex
addressing. Path expressions are similar to C field references, but also allow
-referencing parent and sibling elements. For example:
+referencing parent and sibling elements. A special reference `syscall` used
+in the beginning of the path allows to refer directly to the syscall arguments.
+For example:
```
s1 {
@@ -271,13 +273,17 @@ s3 {
# This refers to the array d in the sibling s2.
f len[s1:a:d, int32]
# This refers to the array k in the child s4.
- g len[h:i, int32]
- h ptr[in, s4]
+ g len[i:j, int32]
+# This refers to syscall argument l.
+ h len[syscall:l, int32]
+ i ptr[in, s4]
}
s4 {
- i array[int8]
+ j array[int8]
}
+
+foo(k ptr[in, s1], l ptr[in, array[int8]])
```
## Proc
diff --git a/executor/defs.h b/executor/defs.h
index cd8cfae38..eae412e55 100644
--- a/executor/defs.h
+++ b/executor/defs.h
@@ -165,7 +165,7 @@
#if GOARCH_64
#define GOARCH "64"
-#define SYZ_REVISION "3218225be4c9aad40c39be2b8bcb3008fd76ff1e"
+#define SYZ_REVISION "596ee9bf31191a84ff800056cadc632de17b3b28"
#define SYZ_EXECUTOR_USES_FORK_SERVER 0
#define SYZ_EXECUTOR_USES_SHMEM 0
#define SYZ_PAGE_SIZE 4096
diff --git a/pkg/compiler/check.go b/pkg/compiler/check.go
index 8442f70ec..0b296e2ea 100644
--- a/pkg/compiler/check.go
+++ b/pkg/compiler/check.go
@@ -179,7 +179,7 @@ func (comp *compiler) checkFieldGroup(fields []*ast.Field, what, ctx string) {
existing := make(map[string]bool)
for _, f := range fields {
fn := f.Name.Name
- if fn == prog.ParentRef {
+ if fn == prog.ParentRef || fn == prog.SyscallRef {
comp.error(f.Pos, "reserved %v name %v in %v", what, fn, ctx)
}
if existing[fn] {
@@ -347,10 +347,18 @@ func (comp *compiler) checkLenType(t0, t *ast.Type, parents []parentDesc,
func (comp *compiler) checkLenTarget(arg, t0, t *ast.Type, parents []parentDesc, warned map[string]bool) {
targets := append([]*ast.Type{arg}, arg.Colon...)
- if len(targets) != 1 {
- for _, target := range targets {
- if target.Ident == prog.ParentRef {
- comp.error(target.Pos, "%v can't be part of path expressions", prog.ParentRef)
+ for i, target := range targets {
+ if target.Ident == prog.ParentRef && len(targets) != 1 {
+ comp.error(target.Pos, "%v can't be part of path expressions", prog.ParentRef)
+ return
+ }
+ if target.Ident == prog.SyscallRef {
+ if i != 0 {
+ comp.error(target.Pos, "syscall can't be in the middle of path expressions")
+ return
+ }
+ if len(targets) == 1 {
+ comp.error(targets[0].Pos, "no argument name after syscall reference")
return
}
}
@@ -405,15 +413,15 @@ func (comp *compiler) checkLenTargetRec(t0, t *ast.Type, targets []*ast.Type,
}
for pi := len(parents) - 1; pi >= 0; pi-- {
parent := parents[pi]
- if parent.name == "" || parent.name != target.Ident && target.Ident != prog.ParentRef {
- continue
- }
- if len(targets) != 0 {
- parents1 := make([]parentDesc, pi+1)
- copy(parents1, parents[:pi+1])
- comp.checkLenTargetRec(t0, t, targets, parents1, warned)
+ if parent.name != "" && (parent.name == target.Ident || target.Ident == prog.ParentRef) ||
+ parent.name == "" && target.Ident == prog.SyscallRef {
+ if len(targets) != 0 {
+ parents1 := make([]parentDesc, pi+1)
+ copy(parents1, parents[:pi+1])
+ comp.checkLenTargetRec(t0, t, targets, parents1, warned)
+ }
+ return
}
- return
}
comp.error(target.Pos, "%v target %v does not exist", t.Ident, target.Ident)
}
diff --git a/pkg/compiler/testdata/all.txt b/pkg/compiler/testdata/all.txt
index 7acb47743..25461ff9a 100644
--- a/pkg/compiler/testdata/all.txt
+++ b/pkg/compiler/testdata/all.txt
@@ -72,6 +72,7 @@ foo$len_var1(a ptr[in, array[string]], b ptr[in, len[a, int32]])
len_expr1 {
f11 len_expr2
+ f12 bytesize[syscall:b, int32]
}
len_expr2 {
@@ -95,7 +96,7 @@ len_expr4 {
f41 int32
}
-foo$len_expr(a ptr[in, len_expr1])
+foo$len_expr(a ptr[in, len_expr1], b ptr[in, array[int8, 3]])
# Pointer type.
diff --git a/pkg/compiler/testdata/errors2.txt b/pkg/compiler/testdata/errors2.txt
index 6b7737ef5..311be3ea9 100644
--- a/pkg/compiler/testdata/errors2.txt
+++ b/pkg/compiler/testdata/errors2.txt
@@ -145,6 +145,8 @@ slen1 {
f3 len[f0:parent, int32] ### parent can't be part of path expressions
f4 len[slen2:f, int32] ### len path slen2 does not refer to a struct
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
slen2 ptr[in, array[slen2]]
slen21 slen2
slen22 array[slen2]
diff --git a/prog/size.go b/prog/size.go
index ab8e69292..5586d0da5 100644
--- a/prog/size.go
+++ b/prog/size.go
@@ -11,9 +11,11 @@ import (
const (
// Special reference to the outer struct used in len targets.
ParentRef = "parent"
+ // Special reference directly to syscall arguments used in len targets.
+ SyscallRef = "syscall"
)
-func (target *Target) assignSizes(args []Arg, parentsMap map[Arg]Arg, autos map[Arg]bool) {
+func (target *Target) assignSizes(args []Arg, parentsMap map[Arg]Arg, syscallArgs []Arg, autos map[Arg]bool) {
for _, arg := range args {
if arg = InnerArg(arg); arg == nil {
continue // Pointer to optional len field, no need to fill in value.
@@ -29,7 +31,11 @@ func (target *Target) assignSizes(args []Arg, parentsMap map[Arg]Arg, autos map[
delete(autos, arg)
}
a := arg.(*ConstArg)
- target.assignSize(a, a, typ.Path, args, parentsMap)
+ if typ.Path[0] == SyscallRef {
+ target.assignSize(a, nil, typ.Path[1:], syscallArgs, parentsMap)
+ } else {
+ target.assignSize(a, a, typ.Path, args, parentsMap)
+ }
}
}
@@ -53,9 +59,6 @@ func (target *Target) assignSize(dst *ConstArg, pos Arg, path []string, args []A
if len(path) == 0 {
dst.Val = target.computeSize(buf, dst.Type().(*LenType))
} else {
- if path[0] == ParentRef {
- buf = parentsMap[buf]
- }
target.assignSize(dst, buf, path, buf.(*GroupArg).Inner, parentsMap)
}
return
@@ -119,11 +122,11 @@ func (target *Target) assignSizesArray(args []Arg, autos map[Arg]bool) {
}
})
}
- target.assignSizes(args, parentsMap, autos)
+ target.assignSizes(args, parentsMap, args, autos)
for _, arg := range args {
ForeachSubArg(arg, func(arg Arg, _ *ArgCtx) {
if _, ok := arg.Type().(*StructType); ok {
- target.assignSizes(arg.(*GroupArg).Inner, parentsMap, autos)
+ target.assignSizes(arg.(*GroupArg).Inner, parentsMap, args, autos)
}
})
}
diff --git a/prog/size_test.go b/prog/size_test.go
index 1962b3fc6..613104bf1 100644
--- a/prog/size_test.go
+++ b/prog/size_test.go
@@ -152,8 +152,8 @@ func TestAssignSize(t *testing.T) {
"test$length29(&(0x7f0000000000)={'./a\\x00', './b/c\\x00', 0xa, 0x14, 0x21})",
},
{
- "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, &(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}}, 0x40, &(0x7f0000000000)=0x18, 0x2)",
+ "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)",
},
}
for i, test := range tests {
diff --git a/sys/test/gen/64.go b/sys/test/gen/64.go
index c07a033db..09797261d 100644
--- a/sys/test/gen/64.go
+++ b/sys/test/gen/64.go
@@ -90,8 +90,10 @@ var structDescs_64 = []*KeyedStruct{
{Key: StructKey{Name: "explicitly_sized_union"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "explicitly_sized_union", TypeSize: 42}, Fields: []Type{
&IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f1", TypeSize: 1}}},
}}},
- {Key: StructKey{Name: "len_expr1"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "len_expr1", TypeSize: 64}, Fields: []Type{
+ {Key: StructKey{Name: "len_expr1"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "len_expr1", TypeSize: 72}, Fields: []Type{
&StructType{Key: StructKey{Name: "len_expr2"}, FldName: "f11"},
+ &LenType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "bytesize", FldName: "f12", TypeSize: 4}}, BitSize: 8, Path: []string{"syscall", "a2"}},
+ &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 4}}, IsPad: true},
}}},
{Key: StructKey{Name: "len_expr2"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "len_expr2", TypeSize: 64}, Fields: []Type{
&StructType{Key: StructKey{Name: "len_expr3"}, FldName: "f21"},
@@ -1003,4 +1005,4 @@ var consts_64 = []ConstValue{
{Name: "SYS_unsupported"},
}
-const revision_64 = "3218225be4c9aad40c39be2b8bcb3008fd76ff1e"
+const revision_64 = "596ee9bf31191a84ff800056cadc632de17b3b28"
diff --git a/sys/test/test.txt b/sys/test/test.txt
index 9fd037bf3..73c43d83d 100644
--- a/sys/test/test.txt
+++ b/sys/test/test.txt
@@ -432,6 +432,7 @@ test$length29(a ptr[in, static_filename])
len_expr1 {
f11 len_expr2
+ f12 bytesize[syscall:a2, int32]
}
len_expr2 {