Skip to content

Commit 606a127

Browse files
committed
Fix concurrency issues for parser
Signed-off-by: Quoc Trung Hoang <quoc-trung.hoang@etu.utc.fr>
1 parent 6db51d4 commit 606a127

File tree

5 files changed

+55
-36
lines changed

5 files changed

+55
-36
lines changed

go.sum

-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
257257
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
258258
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
259259
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
260-
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
261260
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
262261
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
263262
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/model/parser_ctx_kv.go

+18-23
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ type pair struct {
2626
// <equal>: '='
2727
// <value>: \S*
2828
type kvParser struct {
29-
pairs map[string]pair
3029
keyBag *[]string
3130
threshold float32
3231
matcher *regexp.Regexp
@@ -39,12 +38,12 @@ func newKVParser(keyRegexp, equal, valRegexp, varRegexp string, bag *[]string) *
3938
matcher: regexp.MustCompile(keyRegexp + equal + valRegexp),
4039
varMatcher: regexp.MustCompile(varRegexp),
4140
keyBag: bag,
42-
pairs: make(map[string]pair),
4341
}
4442
}
4543

4644
// Parse reads file line by line to scan the KV file
4745
func (k *kvParser) Parse(reader io.Reader, leakChan chan Leak, file string, rule *CtxParserRule) {
46+
pairs := make(map[string]pair)
4847
lineNum := 0
4948
buf := bufio.NewScanner(reader)
5049
for buf.Scan() {
@@ -58,29 +57,41 @@ func (k *kvParser) Parse(reader io.Reader, leakChan chan Leak, file string, rule
5857
if len(value) == 0 {
5958
continue
6059
}
61-
k.pairs[string(match[1])] = pair{
60+
pairs[string(match[1])] = pair{
6261
value: match[2],
6362
line: lineNum,
6463
affected: line,
6564
}
6665
}
67-
for key, pair := range k.pairs {
66+
for key, pair := range pairs {
6867
for _, keyword := range *k.keyBag {
6968
if strings.Contains(
7069
strings.ToLower(key),
7170
keyword,
7271
) {
7372
npair := &pair
74-
npair.threats = k.parseVariable(pair.value)
73+
matches := k.varMatcher.FindAllSubmatch(pair.value, -1)
74+
innerCalls := 0
75+
for _, match := range matches {
76+
if len(match) >= 2 {
77+
for key := range pairs {
78+
if strings.Compare(key, string(match[2])) == 0 {
79+
innerCalls++
80+
break
81+
}
82+
}
83+
}
84+
}
85+
npair.threats = innerCalls
7586
if npair.threats == 0 {
7687
npair.threats = 1
7788
}
78-
k.pairs[key] = *npair
89+
pairs[key] = *npair
7990
break
8091
}
8192
}
8293
}
83-
for _, pair := range k.pairs {
94+
for _, pair := range pairs {
8495
if pair.threats != 0 {
8596
leakChan <- FileLeak{
8697
File: file,
@@ -93,22 +104,6 @@ func (k *kvParser) Parse(reader io.Reader, leakChan chan Leak, file string, rule
93104
}
94105
}
95106

96-
func (k *kvParser) parseVariable(value []byte) int {
97-
matches := k.varMatcher.FindAllSubmatch(value, -1)
98-
innerCalls := 0
99-
for _, match := range matches {
100-
if len(match) >= 2 {
101-
for key := range k.pairs {
102-
if strings.Compare(key, string(match[2])) == 0 {
103-
innerCalls++
104-
break
105-
}
106-
}
107-
}
108-
}
109-
return innerCalls
110-
}
111-
112107
// NewEnvParser returns a new environ file leak parser
113108
func newEnvParser(keyBag *[]string) *kvParser {
114109
return newKVParser(

pkg/model/parser_yaml.go

+23-11
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"fmt"
66
"io"
7+
"strconv"
78
"strings"
89

910
"github.com/rs/zerolog/log"
@@ -17,21 +18,32 @@ type yamlParser struct {
1718
func (y *yamlParser) Parse(reader io.Reader, leakChan chan Leak, file string, rule *CtxParserRule) {
1819
buf := &bytes.Buffer{}
1920
buf.ReadFrom(reader)
20-
var root map[string]interface{}
21+
var data interface{}
2122

22-
if err := yaml.Unmarshal(buf.Bytes(), &root); err != nil {
23-
log.Error().
23+
if err := yaml.Unmarshal(buf.Bytes(), &data); err != nil {
24+
log.Trace().
2425
Err(err).
2526
Str("file", file).
2627
Msg("Failed to unmarshal")
28+
return
2729
}
2830

29-
// flatten yaml to a single map to search for potential leaks
30-
// this method does not allow for identifying line numbers
3131
flattened := map[string]string{}
32-
for k, v := range root {
33-
flatten(k, v, flattened)
32+
switch root := data.(type) {
33+
// !!map document node type
34+
case map[string]interface{}:
35+
for k, v := range root {
36+
flattenMap(k, v, flattened)
37+
}
38+
break
39+
// !!seq document node type
40+
case []interface{}:
41+
for k, v := range root {
42+
flattenMap(strconv.Itoa(k), v, flattened)
43+
}
44+
break
3445
}
46+
3547
for k, v := range flattened {
3648
for _, key := range *y.keyBag {
3749
last := k
@@ -54,21 +66,21 @@ func (y *yamlParser) Parse(reader io.Reader, leakChan chan Leak, file string, ru
5466
}
5567
}
5668

57-
func flatten(prefix string, value interface{}, res map[string]string) {
69+
func flattenMap(prefix string, value interface{}, res map[string]string) {
5870
switch submap := value.(type) {
5971
case map[interface{}]interface{}:
6072
for k, v := range submap {
61-
flatten(fmt.Sprintf("%s.%v", prefix, k), v, res)
73+
flattenMap(fmt.Sprintf("%s.%v", prefix, k), v, res)
6274
}
6375
return
6476
case []interface{}:
6577
for i, v := range submap {
66-
flatten(fmt.Sprintf("%s[%d]", prefix, i), v, res)
78+
flattenMap(fmt.Sprintf("%s[%d]", prefix, i), v, res)
6779
}
6880
return
6981
case map[string]interface{}:
7082
for k, v := range submap {
71-
flatten(prefix+"."+k, v, res)
83+
flattenMap(prefix+"."+k, v, res)
7284
}
7385
return
7486
default:

pkg/model/ruleset.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,11 @@ func (r *RuleSet) ParsePatch(patch *object.Patch, commit *object.Commit, repo *R
150150
func (r *RuleSet) ParseFile(file string, leakChan chan Leak) {
151151
fd, err := os.Open(file)
152152
if err != nil {
153-
log.Error().
153+
log.Trace().
154154
Str("file", file).
155155
Err(err).
156156
Msg("Failed to read")
157+
return
157158
}
158159
defer fd.Close()
159160

pkg/scan/fs_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,22 @@
11
package scan
22

33
import (
4+
"fmt"
45
"testing"
56
)
67

78
func TestFsClient(t *testing.T) {
89
f := NewFsScanner(".", "../../resources/rules.yaml", &HTMLReport{}, false)
910
f.Scan(5)
1011
}
12+
func BenchmarkFSScan(b *testing.B) {
13+
conccurrent := []int{50}
14+
for _, i := range conccurrent {
15+
b.Run(fmt.Sprintf("fsscan_%d", i), func(b *testing.B) {
16+
b.StartTimer()
17+
g := NewFsScanner("../..", "../../resources/rules.yaml", &HTMLReport{}, false)
18+
g.Scan(i)
19+
b.ResetTimer()
20+
})
21+
}
22+
}

0 commit comments

Comments
 (0)