mirror of
https://github.com/securego/gosec.git
synced 2024-12-24 11:35:52 +00:00
fix: G602 support for nested conditionals with bounds check (#1201)
* Recursive fix * Add some more test cases * Fix formatting * Add depth check
This commit is contained in:
parent
11d69032b0
commit
ea5b2766bb
2 changed files with 133 additions and 32 deletions
|
@ -118,32 +118,45 @@ func runSliceBounds(pass *analysis.Pass) (interface{}, error) {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
bound = invBound(bound)
|
bound = invBound(bound)
|
||||||
}
|
}
|
||||||
for _, instr := range block.Instrs {
|
var processBlock func(block *ssa.BasicBlock, depth int)
|
||||||
if _, ok := issues[instr]; ok {
|
processBlock = func(block *ssa.BasicBlock, depth int) {
|
||||||
switch bound {
|
if depth == maxDepth {
|
||||||
case lowerUnbounded:
|
return
|
||||||
break
|
}
|
||||||
case upperUnbounded, unbounded:
|
depth++
|
||||||
delete(issues, instr)
|
for _, instr := range block.Instrs {
|
||||||
case upperBounded:
|
if _, ok := issues[instr]; ok {
|
||||||
switch tinstr := instr.(type) {
|
switch bound {
|
||||||
case *ssa.Slice:
|
case lowerUnbounded:
|
||||||
lower, upper := extractSliceBounds(tinstr)
|
break
|
||||||
if isSliceInsideBounds(0, value, lower, upper) {
|
case upperUnbounded, unbounded:
|
||||||
delete(issues, instr)
|
delete(issues, instr)
|
||||||
}
|
case upperBounded:
|
||||||
case *ssa.IndexAddr:
|
switch tinstr := instr.(type) {
|
||||||
indexValue, err := extractIntValue(tinstr.Index.String())
|
case *ssa.Slice:
|
||||||
if err != nil {
|
lower, upper := extractSliceBounds(tinstr)
|
||||||
break
|
if isSliceInsideBounds(0, value, lower, upper) {
|
||||||
}
|
delete(issues, instr)
|
||||||
if isSliceIndexInsideBounds(0, value, indexValue) {
|
}
|
||||||
delete(issues, instr)
|
case *ssa.IndexAddr:
|
||||||
|
indexValue, err := extractIntValue(tinstr.Index.String())
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if isSliceIndexInsideBounds(0, value, indexValue) {
|
||||||
|
delete(issues, instr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if nestedIfInstr, ok := instr.(*ssa.If); ok {
|
||||||
|
for _, nestedBlock := range nestedIfInstr.Block().Succs {
|
||||||
|
processBlock(nestedBlock, depth)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processBlock(block, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -195,13 +195,13 @@ package main
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
testMap := make(map[string]any, 0)
|
testMap := make(map[string]any, 0)
|
||||||
testMap["test1"] = map[string]interface{}{
|
testMap["test1"] = map[string]interface{}{
|
||||||
"test2": map[string]interface{}{
|
"test2": map[string]interface{}{
|
||||||
"value": 0,
|
"value": 0,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
fmt.Println(testMap)
|
fmt.Println(testMap)
|
||||||
}
|
}
|
||||||
`}, 0, gosec.NewConfig()},
|
`}, 0, gosec.NewConfig()},
|
||||||
{[]string{`
|
{[]string{`
|
||||||
|
@ -210,10 +210,10 @@ package main
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
s := make([]byte, 0)
|
s := make([]byte, 0)
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
fmt.Println(s[0])
|
fmt.Println(s[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`}, 0, gosec.NewConfig()},
|
`}, 0, gosec.NewConfig()},
|
||||||
{[]string{`
|
{[]string{`
|
||||||
|
@ -221,6 +221,93 @@ package main
|
||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := make([]byte, 0)
|
||||||
|
if len(s) > 0 {
|
||||||
|
switch s[0] {
|
||||||
|
case 0:
|
||||||
|
fmt.Println("zero")
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
fmt.Println(s[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}, 0, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := make([]byte, 0)
|
||||||
|
if len(s) > 0 {
|
||||||
|
switch s[0] {
|
||||||
|
case 0:
|
||||||
|
b := true
|
||||||
|
if b == true {
|
||||||
|
// Should work for many-levels of nesting when the condition is not on the target slice
|
||||||
|
fmt.Println(s[0])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
fmt.Println(s[0])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}, 0, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := make([]byte, 0)
|
||||||
|
if len(s) > 0 {
|
||||||
|
if len(s) > 1 {
|
||||||
|
fmt.Println(s[1])
|
||||||
|
}
|
||||||
|
fmt.Println(s[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}, 0, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := make([]byte, 2)
|
||||||
|
fmt.Println(s[1])
|
||||||
|
s = make([]byte, 0)
|
||||||
|
fmt.Println(s[1])
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
s := make([]byte, 0)
|
||||||
|
if len(s) > 0 {
|
||||||
|
if len(s) > 4 {
|
||||||
|
fmt.Println(s[3])
|
||||||
|
} else {
|
||||||
|
// Should error
|
||||||
|
fmt.Println(s[2])
|
||||||
|
}
|
||||||
|
fmt.Println(s[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}, 1, gosec.NewConfig()},
|
||||||
|
{[]string{`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
s := make([]byte, 0)
|
s := make([]byte, 0)
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
|
@ -249,5 +336,6 @@ func main() {
|
||||||
fmt.Println(s[i])
|
fmt.Println(s[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
`}, 0, gosec.NewConfig()},
|
`}, 0, gosec.NewConfig()},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue