Skip to content

Commit aac9b00

Browse files
ccojocarCosmin Cojocar
authored andcommitted
Refactor properly the package error parsing and cover all test cases
Signed-off-by: Cosmin Cojocar <[email protected]>
1 parent 625718d commit aac9b00

File tree

2 files changed

+181
-58
lines changed

2 files changed

+181
-58
lines changed

analyzer.go

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func (gosec *Analyzer) Process(buildTags []string, packagePaths ...string) error
111111
}
112112
for _, pkg := range pkgs {
113113
if pkg.Name != "" {
114-
err := gosec.parseErrors(pkg)
114+
err := gosec.ParseErrors(pkg)
115115
if err != nil {
116116
return fmt.Errorf("parsing errors in pkg %q: %v", pkg.Name, err)
117117
}
@@ -185,39 +185,34 @@ func (gosec *Analyzer) check(pkg *packages.Package) {
185185
}
186186
}
187187

188-
func (gosec *Analyzer) parseErrors(pkg *packages.Package) error {
188+
// ParseErrors parses the errors from given package
189+
func (gosec *Analyzer) ParseErrors(pkg *packages.Package) error {
189190
if len(pkg.Errors) == 0 {
190191
return nil
191192
}
192193
for _, pkgErr := range pkg.Errors {
193-
// infoErr contains information about the error
194-
// at index 0 is the file path
195-
// at index 1 is the line; index 2 is for column
196-
// at index 3 is the actual error
197-
infoErr := strings.Split(pkgErr.Error(), ":")
198-
filePath := infoErr[0]
194+
parts := strings.Split(pkgErr.Pos, ":")
195+
file := parts[0]
199196
var err error
200-
var line, column int
201-
var errorMsg string
202-
if len(infoErr) > 3 {
203-
if line, err = strconv.Atoi(infoErr[1]); err != nil {
197+
var line int
198+
if len(parts) > 1 {
199+
if line, err = strconv.Atoi(parts[1]); err != nil {
204200
return fmt.Errorf("parsing line: %v", err)
205201
}
206-
if column, err = strconv.Atoi(infoErr[2]); err != nil {
202+
}
203+
var column int
204+
if len(parts) > 2 {
205+
if column, err = strconv.Atoi(parts[2]); err != nil {
207206
return fmt.Errorf("parsing column: %v", err)
208207
}
209-
errorMsg = strings.TrimSpace(infoErr[3])
210-
} else if len(infoErr) > 1 {
211-
errorMsg = strings.TrimSpace(infoErr[1])
212-
} else {
213-
return fmt.Errorf("cannot parse error %q", infoErr)
214208
}
215-
newErr := NewError(line, column, errorMsg)
216-
if errSlice, ok := gosec.errors[filePath]; ok {
217-
gosec.errors[filePath] = append(errSlice, *newErr)
209+
msg := strings.TrimSpace(pkgErr.Msg)
210+
newErr := NewError(line, column, msg)
211+
if errSlice, ok := gosec.errors[file]; ok {
212+
gosec.errors[file] = append(errSlice, *newErr)
218213
} else {
219214
errSlice = []Error{}
220-
gosec.errors[filePath] = append(errSlice, *newErr)
215+
gosec.errors[file] = append(errSlice, *newErr)
221216
}
222217
}
223218
return nil

analyzer_test.go

Lines changed: 164 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/securego/gosec"
1010
"github.com/securego/gosec/rules"
11+
"golang.org/x/tools/go/packages"
1112

1213
. "github.com/onsi/ginkgo"
1314
. "github.com/onsi/gomega"
@@ -234,58 +235,185 @@ var _ = Describe("Analyzer", func() {
234235
err = analyzer.Process(buildTags, pkg.Path)
235236
Expect(err).ShouldNot(HaveOccurred())
236237
})
238+
237239
It("should report an error when the package is empty", func() {
238240
analyzer.LoadRules(rules.Generate().Builders())
239241
pkg := testutils.NewTestPackage()
240242
defer pkg.Close()
241243
err := analyzer.Process(buildTags, pkg.Path)
242244
Expect(err).Should(HaveOccurred())
243245
})
244-
})
245246

246-
It("should be possible to overwrite nosec comments, and report issues", func() {
247-
// Rule for MD5 weak crypto usage
248-
sample := testutils.SampleCodeG401[0]
249-
source := sample.Code[0]
250-
251-
// overwrite nosec option
252-
nosecIgnoreConfig := gosec.NewConfig()
253-
nosecIgnoreConfig.SetGlobal(gosec.Nosec, "true")
254-
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, logger)
255-
customAnalyzer.LoadRules(rules.Generate(rules.NewRuleFilter(false, "G401")).Builders())
256-
257-
nosecPackage := testutils.NewTestPackage()
258-
defer nosecPackage.Close()
259-
nosecSource := strings.Replace(source, "h := md5.New()", "h := md5.New() // #nosec", 1)
260-
nosecPackage.AddFile("md5.go", nosecSource)
261-
err := nosecPackage.Build()
262-
Expect(err).ShouldNot(HaveOccurred())
263-
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
264-
Expect(err).ShouldNot(HaveOccurred())
265-
nosecIssues, _, _ := customAnalyzer.Report()
266-
Expect(nosecIssues).Should(HaveLen(sample.Errors))
247+
It("should be possible to overwrite nosec comments, and report issues", func() {
248+
// Rule for MD5 weak crypto usage
249+
sample := testutils.SampleCodeG401[0]
250+
source := sample.Code[0]
267251

268-
})
252+
// overwrite nosec option
253+
nosecIgnoreConfig := gosec.NewConfig()
254+
nosecIgnoreConfig.SetGlobal(gosec.Nosec, "true")
255+
customAnalyzer := gosec.NewAnalyzer(nosecIgnoreConfig, tests, logger)
256+
customAnalyzer.LoadRules(rules.Generate(rules.NewRuleFilter(false, "G401")).Builders())
269257

270-
It("should be able to analyze Go test package", func() {
271-
customAnalyzer := gosec.NewAnalyzer(nil, true, logger)
272-
customAnalyzer.LoadRules(rules.Generate().Builders())
273-
pkg := testutils.NewTestPackage()
274-
defer pkg.Close()
275-
pkg.AddFile("foo.go", `
258+
nosecPackage := testutils.NewTestPackage()
259+
defer nosecPackage.Close()
260+
nosecSource := strings.Replace(source, "h := md5.New()", "h := md5.New() // #nosec", 1)
261+
nosecPackage.AddFile("md5.go", nosecSource)
262+
err := nosecPackage.Build()
263+
Expect(err).ShouldNot(HaveOccurred())
264+
err = customAnalyzer.Process(buildTags, nosecPackage.Path)
265+
Expect(err).ShouldNot(HaveOccurred())
266+
nosecIssues, _, _ := customAnalyzer.Report()
267+
Expect(nosecIssues).Should(HaveLen(sample.Errors))
268+
269+
})
270+
271+
It("should be able to analyze Go test package", func() {
272+
customAnalyzer := gosec.NewAnalyzer(nil, true, logger)
273+
customAnalyzer.LoadRules(rules.Generate().Builders())
274+
pkg := testutils.NewTestPackage()
275+
defer pkg.Close()
276+
pkg.AddFile("foo.go", `
276277
package foo
277278
func foo(){
278279
}`)
279-
pkg.AddFile("foo_test.go", `
280+
pkg.AddFile("foo_test.go", `
280281
package foo_test
281282
import "testing"
282283
func TestFoo(t *testing.T){
283284
}`)
284-
err := pkg.Build()
285-
Expect(err).ShouldNot(HaveOccurred())
286-
err = customAnalyzer.Process(buildTags, pkg.Path)
287-
Expect(err).ShouldNot(HaveOccurred())
288-
_, metrics, _ := customAnalyzer.Report()
289-
Expect(metrics.NumFiles).To(Equal(3))
285+
err := pkg.Build()
286+
Expect(err).ShouldNot(HaveOccurred())
287+
err = customAnalyzer.Process(buildTags, pkg.Path)
288+
Expect(err).ShouldNot(HaveOccurred())
289+
_, metrics, _ := customAnalyzer.Report()
290+
Expect(metrics.NumFiles).To(Equal(3))
291+
})
292+
})
293+
294+
Context("when parsing errors from a package", func() {
295+
296+
It("should return no error when the error list is empty", func() {
297+
pkg := &packages.Package{}
298+
err := analyzer.ParseErrors(pkg)
299+
Expect(err).ShouldNot(HaveOccurred())
300+
})
301+
302+
It("should properly parse the errors", func() {
303+
pkg := &packages.Package{
304+
Errors: []packages.Error{
305+
packages.Error{
306+
Pos: "file:1:2",
307+
Msg: "build error",
308+
},
309+
},
310+
}
311+
err := analyzer.ParseErrors(pkg)
312+
Expect(err).ShouldNot(HaveOccurred())
313+
_, _, errors := analyzer.Report()
314+
Expect(len(errors)).To(Equal(1))
315+
for _, ferr := range errors {
316+
Expect(len(ferr)).To(Equal(1))
317+
Expect(ferr[0].Line).To(Equal(1))
318+
Expect(ferr[0].Column).To(Equal(2))
319+
Expect(ferr[0].Err).Should(MatchRegexp(`build error`))
320+
}
321+
})
322+
323+
It("should properly parse the errors without line and column", func() {
324+
pkg := &packages.Package{
325+
Errors: []packages.Error{
326+
packages.Error{
327+
Pos: "file",
328+
Msg: "build error",
329+
},
330+
},
331+
}
332+
err := analyzer.ParseErrors(pkg)
333+
Expect(err).ShouldNot(HaveOccurred())
334+
_, _, errors := analyzer.Report()
335+
Expect(len(errors)).To(Equal(1))
336+
for _, ferr := range errors {
337+
Expect(len(ferr)).To(Equal(1))
338+
Expect(ferr[0].Line).To(Equal(0))
339+
Expect(ferr[0].Column).To(Equal(0))
340+
Expect(ferr[0].Err).Should(MatchRegexp(`build error`))
341+
}
342+
})
343+
344+
It("should properly parse the errors without column", func() {
345+
pkg := &packages.Package{
346+
Errors: []packages.Error{
347+
packages.Error{
348+
Pos: "file",
349+
Msg: "build error",
350+
},
351+
},
352+
}
353+
err := analyzer.ParseErrors(pkg)
354+
Expect(err).ShouldNot(HaveOccurred())
355+
_, _, errors := analyzer.Report()
356+
Expect(len(errors)).To(Equal(1))
357+
for _, ferr := range errors {
358+
Expect(len(ferr)).To(Equal(1))
359+
Expect(ferr[0].Line).To(Equal(0))
360+
Expect(ferr[0].Column).To(Equal(0))
361+
Expect(ferr[0].Err).Should(MatchRegexp(`build error`))
362+
}
363+
})
364+
365+
It("should return error when line cannot be parsed", func() {
366+
pkg := &packages.Package{
367+
Errors: []packages.Error{
368+
packages.Error{
369+
Pos: "file:line",
370+
Msg: "build error",
371+
},
372+
},
373+
}
374+
err := analyzer.ParseErrors(pkg)
375+
Expect(err).Should(HaveOccurred())
376+
})
377+
378+
It("should return error when column cannot be parsed", func() {
379+
pkg := &packages.Package{
380+
Errors: []packages.Error{
381+
packages.Error{
382+
Pos: "file:1:column",
383+
Msg: "build error",
384+
},
385+
},
386+
}
387+
err := analyzer.ParseErrors(pkg)
388+
Expect(err).Should(HaveOccurred())
389+
})
390+
391+
It("should append error to the same file", func() {
392+
pkg := &packages.Package{
393+
Errors: []packages.Error{
394+
packages.Error{
395+
Pos: "file:1:2",
396+
Msg: "error1",
397+
},
398+
packages.Error{
399+
Pos: "file:3:4",
400+
Msg: "error2",
401+
},
402+
},
403+
}
404+
err := analyzer.ParseErrors(pkg)
405+
Expect(err).ShouldNot(HaveOccurred())
406+
_, _, errors := analyzer.Report()
407+
Expect(len(errors)).To(Equal(1))
408+
for _, ferr := range errors {
409+
Expect(len(ferr)).To(Equal(2))
410+
Expect(ferr[0].Line).To(Equal(1))
411+
Expect(ferr[0].Column).To(Equal(2))
412+
Expect(ferr[0].Err).Should(MatchRegexp(`error1`))
413+
Expect(ferr[1].Line).To(Equal(3))
414+
Expect(ferr[1].Column).To(Equal(4))
415+
Expect(ferr[1].Err).Should(MatchRegexp(`error2`))
416+
}
417+
})
290418
})
291419
})

0 commit comments

Comments
 (0)