2016-11-17 18:38:10 +01:00
|
|
|
// Copyright 2016 syzkaller project authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
|
|
|
|
|
2017-09-14 19:25:01 +02:00
|
|
|
package prog
|
2016-11-17 18:38:10 +01:00
|
|
|
|
|
|
|
import (
|
prog: introduce more readable format for data args
Fixes #460
File names, crypto algorithm names, etc in programs are completely unreadable:
bind$alg(r0, &(0x7f0000408000)={0x26, "6861736800000000000000000000",
0x0, 0x0, "6d6435000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
00000000000"}, 0x58)
Introduce another format for printable strings.
New args are denoted by '' ("" for old args).
New format is enabled for printable chars, \x00
and \t, \r, \n.
Example:
`serialize(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
vs:
`serialize(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
2017-12-13 19:18:07 +01:00
|
|
|
"bytes"
|
2016-11-17 18:38:10 +01:00
|
|
|
"fmt"
|
prog: introduce more readable format for data args
Fixes #460
File names, crypto algorithm names, etc in programs are completely unreadable:
bind$alg(r0, &(0x7f0000408000)={0x26, "6861736800000000000000000000",
0x0, 0x0, "6d6435000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
00000000000"}, 0x58)
Introduce another format for printable strings.
New args are denoted by '' ("" for old args).
New format is enabled for printable chars, \x00
and \t, \r, \n.
Example:
`serialize(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
vs:
`serialize(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
2017-12-13 19:18:07 +01:00
|
|
|
"math/rand"
|
2016-11-17 18:38:10 +01:00
|
|
|
"reflect"
|
2017-07-24 15:05:08 +02:00
|
|
|
"regexp"
|
2016-11-17 18:38:10 +01:00
|
|
|
"sort"
|
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func setToArray(s map[string]struct{}) []string {
|
|
|
|
a := make([]string, 0, len(s))
|
|
|
|
for c := range s {
|
|
|
|
a = append(a, c)
|
|
|
|
}
|
|
|
|
sort.Strings(a)
|
|
|
|
return a
|
|
|
|
}
|
|
|
|
|
prog: introduce more readable format for data args
Fixes #460
File names, crypto algorithm names, etc in programs are completely unreadable:
bind$alg(r0, &(0x7f0000408000)={0x26, "6861736800000000000000000000",
0x0, 0x0, "6d6435000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
00000000000"}, 0x58)
Introduce another format for printable strings.
New args are denoted by '' ("" for old args).
New format is enabled for printable chars, \x00
and \t, \r, \n.
Example:
`serialize(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
vs:
`serialize(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
2017-12-13 19:18:07 +01:00
|
|
|
func TestSerializeData(t *testing.T) {
|
|
|
|
t.Parallel()
|
|
|
|
r := rand.New(rand.NewSource(0))
|
|
|
|
for i := 0; i < 1e4; i++ {
|
|
|
|
data := make([]byte, r.Intn(4))
|
|
|
|
for i := range data {
|
|
|
|
data[i] = byte(r.Intn(256))
|
|
|
|
}
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
serializeData(buf, data)
|
|
|
|
p := newParser(buf.Bytes())
|
|
|
|
if !p.Scan() {
|
|
|
|
t.Fatalf("parser does not scan")
|
|
|
|
}
|
|
|
|
data1, err := deserializeData(p)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("failed to deserialize %q -> %s: %v", data, buf.Bytes(), err)
|
|
|
|
}
|
|
|
|
if !bytes.Equal(data, data1) {
|
|
|
|
t.Fatalf("corrupted data %q -> %s -> %q", data, buf.Bytes(), data1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-17 18:38:10 +01:00
|
|
|
func TestCallSet(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
prog string
|
|
|
|
ok bool
|
|
|
|
calls []string
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"",
|
|
|
|
false,
|
|
|
|
[]string{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"r0 = (foo)",
|
|
|
|
false,
|
|
|
|
[]string{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"getpid()",
|
|
|
|
true,
|
|
|
|
[]string{"getpid"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"r11 = getpid()",
|
|
|
|
true,
|
|
|
|
[]string{"getpid"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"getpid()\n" +
|
|
|
|
"open(0x1, something that this package may not understand)\n" +
|
|
|
|
"getpid()\n" +
|
|
|
|
"#read()\n" +
|
|
|
|
"\n" +
|
|
|
|
"close$foo(&(0x0000) = {})\n",
|
|
|
|
true,
|
|
|
|
[]string{"getpid", "open", "close$foo"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for i, test := range tests {
|
|
|
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
|
|
|
calls, err := CallSet([]byte(test.prog))
|
|
|
|
if err != nil && test.ok {
|
|
|
|
t.Fatalf("parsing failed: %v", err)
|
|
|
|
}
|
|
|
|
if err == nil && !test.ok {
|
|
|
|
t.Fatalf("parsing did not fail")
|
|
|
|
}
|
|
|
|
callArray := setToArray(calls)
|
|
|
|
sort.Strings(test.calls)
|
|
|
|
if !reflect.DeepEqual(callArray, test.calls) {
|
|
|
|
t.Fatalf("got call set %+v, expect %+v", callArray, test.calls)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCallSetRandom(t *testing.T) {
|
2017-09-14 19:25:01 +02:00
|
|
|
target, rs, iters := initTest(t)
|
2016-11-17 18:38:10 +01:00
|
|
|
for i := 0; i < iters; i++ {
|
2017-09-14 19:25:01 +02:00
|
|
|
p := target.Generate(rs, 10, nil)
|
2016-11-17 18:38:10 +01:00
|
|
|
calls0 := make(map[string]struct{})
|
|
|
|
for _, c := range p.Calls {
|
|
|
|
calls0[c.Meta.Name] = struct{}{}
|
|
|
|
}
|
|
|
|
calls1, err := CallSet(p.Serialize())
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("CallSet failed: %v", err)
|
|
|
|
}
|
|
|
|
callArray0 := setToArray(calls0)
|
|
|
|
callArray1 := setToArray(calls1)
|
|
|
|
if !reflect.DeepEqual(callArray0, callArray1) {
|
|
|
|
t.Fatalf("got call set:\n%+v\nexpect:\n%+v", callArray1, callArray0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-07-24 15:05:08 +02:00
|
|
|
|
|
|
|
func TestDeserialize(t *testing.T) {
|
2017-12-13 13:49:08 +01:00
|
|
|
target := initTargetTest(t, "test", "64")
|
2017-07-24 15:05:08 +02:00
|
|
|
tests := []struct {
|
|
|
|
data string
|
|
|
|
err *regexp.Regexp
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"syz_test$struct(&(0x7f0000000000)={0x0, {0x0}})",
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"syz_test$struct(&(0x7f0000000000)=0x0)",
|
|
|
|
regexp.MustCompile(`bad const type.*`),
|
|
|
|
},
|
2017-11-28 16:25:45 +01:00
|
|
|
{
|
|
|
|
`syz_test$regression1(&(0x7f0000000000)=[{"000000"}, {"0000000000"}])`,
|
|
|
|
nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`syz_test$regression2(&(0x7f0000000000)=[0x1, 0x2, 0x3, 0x4, 0x5, 0x6])`,
|
|
|
|
nil,
|
|
|
|
},
|
2017-07-24 15:05:08 +02:00
|
|
|
}
|
2017-11-28 16:25:45 +01:00
|
|
|
buf := make([]byte, ExecBufferSize)
|
2017-07-24 15:05:08 +02:00
|
|
|
for _, test := range tests {
|
2017-11-28 16:25:45 +01:00
|
|
|
p, err := target.Deserialize([]byte(test.data))
|
2017-07-24 15:05:08 +02:00
|
|
|
if err != nil {
|
|
|
|
if test.err == nil {
|
|
|
|
t.Fatalf("deserialization failed with\n%s\ndata:\n%s\n", err, test.data)
|
|
|
|
}
|
|
|
|
if !test.err.MatchString(err.Error()) {
|
|
|
|
t.Fatalf("deserialization failed with\n%s\nwhich doesn't match\n%s\ndata:\n%s\n", err, test.err, test.data)
|
|
|
|
}
|
2017-11-28 16:25:45 +01:00
|
|
|
} else {
|
|
|
|
if test.err != nil {
|
|
|
|
t.Fatalf("deserialization should have failed with:\n%s\ndata:\n%s\n",
|
|
|
|
test.err, test.data)
|
|
|
|
}
|
2017-12-22 11:47:04 +01:00
|
|
|
p.SerializeForExec(buf)
|
2017-07-24 15:05:08 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
prog: introduce more readable format for data args
Fixes #460
File names, crypto algorithm names, etc in programs are completely unreadable:
bind$alg(r0, &(0x7f0000408000)={0x26, "6861736800000000000000000000",
0x0, 0x0, "6d6435000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
00000000000"}, 0x58)
Introduce another format for printable strings.
New args are denoted by '' ("" for old args).
New format is enabled for printable chars, \x00
and \t, \r, \n.
Example:
`serialize(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
vs:
`serialize(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
2017-12-13 19:18:07 +01:00
|
|
|
|
|
|
|
func TestSerializeDeserialize(t *testing.T) {
|
|
|
|
target := initTargetTest(t, "test", "64")
|
|
|
|
tests := [][2]string{
|
|
|
|
{
|
2017-12-13 20:12:13 +01:00
|
|
|
`serialize0(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
|
|
|
|
`serialize0(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
`serialize1(&(0x7f0000000000)="0000000000000000", 0x8)`,
|
|
|
|
`serialize1(&(0x7f0000000000)=""/8, 0x8)`,
|
prog: introduce more readable format for data args
Fixes #460
File names, crypto algorithm names, etc in programs are completely unreadable:
bind$alg(r0, &(0x7f0000408000)={0x26, "6861736800000000000000000000",
0x0, 0x0, "6d6435000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000
00000000000"}, 0x58)
Introduce another format for printable strings.
New args are denoted by '' ("" for old args).
New format is enabled for printable chars, \x00
and \t, \r, \n.
Example:
`serialize(&(0x7f0000408000)={"6861736800000000000000000000", "4849000000"})`,
vs:
`serialize(&(0x7f0000408000)={'hash\x00', 'HI\x00'})`,
2017-12-13 19:18:07 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
p, err := target.Deserialize([]byte(test[0]))
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
data := p.Serialize()
|
|
|
|
test[1] += "\n"
|
|
|
|
if string(data) != test[1] {
|
|
|
|
t.Fatalf("\ngot : %s\nwant: %s", data, test[1])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|