1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
// Copyright 2020 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.
package executor
import (
"bytes"
"io/ioutil"
"path/filepath"
"regexp"
"sort"
"strings"
"testing"
)
func TestExecutorMistakes(t *testing.T) {
checks := []*struct {
pattern string
suppression string
message string
tests []string
commonOnly bool
}{
{
pattern: `\)\n\t*(debug|debug_dump_data)\(`,
message: "debug() calls are stripped from C reproducers, this code will break. Use {} around debug() to fix",
commonOnly: true,
tests: []string{
`
if (foo)
debug("foo failed");
`, `
if (x + y)
debug_dump_data(data, len);
`,
},
},
{
// These are also not properly stripped by pkg/csource.
pattern: `/\*[^{]`,
message: "Don't use /* */ block comments. Use // line comments instead",
tests: []string{
`/* C++ comment */`,
},
},
{
pattern: `//[^\s]`,
suppression: `https?://`,
message: "Add a space after //",
tests: []string{
`//foo`,
},
},
}
for _, check := range checks {
re := regexp.MustCompile(check.pattern)
for _, test := range check.tests {
if !re.MatchString(test) {
t.Fatalf("patter %q does not match test %q", check.pattern, test)
}
}
}
for _, file := range executorFiles(t) {
data, err := ioutil.ReadFile(file)
if err != nil {
t.Fatal(err)
}
for _, check := range checks {
if check.commonOnly && !strings.Contains(file, "common") {
continue
}
re := regexp.MustCompile(check.pattern)
supp := regexp.MustCompile(check.suppression)
for _, match := range re.FindAllIndex(data, -1) {
start, end := match[0], match[1]
for check.pattern[0] != '\n' && start != 0 && data[start-1] != '\n' {
start--
}
for check.pattern[len(check.pattern)-1] != '\n' && end != len(data) && data[end] != '\n' {
end++
}
if check.suppression != "" && supp.Match(data[start:end]) {
continue
}
line := bytes.Count(data[:start], []byte{'\n'}) + 1
t.Errorf("\nexecutor/%v:%v: %v\n%s\n", file, line, check.message, data[start:end])
}
}
}
}
func executorFiles(t *testing.T) []string {
cc, err := filepath.Glob("*.cc")
if err != nil {
t.Fatal(err)
}
h, err := filepath.Glob("*.h")
if err != nil {
t.Fatal(err)
}
if len(cc) == 0 || len(h) == 0 {
t.Fatal("found no executor files")
}
res := append(cc, h...)
sort.Strings(res)
return res
}
|