github / github/codeql

TaintTracking: copy inside range on map produces multiple (incomplete) path variants if struct or field are a pointer

Abierto
#9,308 7 comentarios 0 reacciones 0 asignados Ver en GitHub
Go
Lenguaje dominante
CodeQL
Estrellas
10.1k
Forks
2.1k
Merge medio
2 d 15 h
PR fusionados (30 d)
141

Descripción

## Summary

When a transfer of taint happens in a `range` loop, and the domain is a pointer to a struct and the field is a map, then the results will contain multiple paths.

## Preamble code

```golang
package main

func main() {}

func source() interface{} { return nil }

func sink(v interface{}) {}
func link(in interface{}, out interface{}) {}

type StructWithPointerField struct {
Params *map[string]string
}
type StructWithValueField struct {
Params map[string]string
}
```

## Cases with domain = a field of a struct (spoiler: most produce unexpected results)

```golang
func range_2A() {
src := source().(StructWithValueField)

{
data := make(map[string]interface{})
for key, value := range src.Params {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361815-734c3500-8cdc-11eb-9cb4-310fc1931589.png)

---

```golang
func range_2B() {
src := source().(*StructWithValueField)

{
data := make(map[string]interface{})
for key, value := range src.Params {
data[key] = value
}
sink(data)
}
}
```

nets the following result (multiple paths, which is **UNexpected**):

![image](https://user-images.githubusercontent.com/15271561/112362020-a7bff100-8cdc-11eb-95f2-53af130f276e.png)

---

```golang
func range_2C() {
src := source().(StructWithPointerField)

{
data := make(map[string]interface{})
for key, value := range *src.Params {
data[key] = value
}
sink(data)
}
}
```

nets the following result (multiple paths, which is **UNexpected**):

![image](https://user-images.githubusercontent.com/15271561/112362108-c2926580-8cdc-11eb-8136-84ec7b03a7f7.png)

---

```golang
func range_2D() {
src := source().(*StructWithPointerField)

{
data := make(map[string]interface{})
for key, value := range *src.Params {
data[key] = value
}
sink(data)
}
}
```

nets the following result (multiple paths, which is **UNexpected**):

![image](https://user-images.githubusercontent.com/15271561/112362217-e2298e00-8cdc-11eb-8581-555f2244e844.png)

## Cases with domain = map (spoiler: all satisfy expectations)

```golang
func range_1A() {
src := source().(map[string]string)

{
data := make(map[string]interface{})
for key, value := range src {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112360900-7d216880-8cdb-11eb-89b6-886256eed183.png)

---

```golang
func range_1B() {
src := source().(*map[string]string)

{
data := make(map[string]interface{})
for key, value := range *src {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361042-a510cc00-8cdb-11eb-8903-59fd4edefa16.png)

---

```golang
func range_1C() {
src := source().(*map[*string]string)

{
data := make(map[string]interface{})
for key, value := range *src {
data[*key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361146-bfe34080-8cdb-11eb-84c3-c087ef6f0d18.png)

---

```golang
func range_1D() {
src := source().(*map[string]*string)

{
data := make(map[string]interface{})
for key, value := range *src {
data[key] = *value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361233-d8ebf180-8cdb-11eb-9535-e2c230066d3c.png)

---

```golang
func range_1E() {
src := source().(*map[*string]*string)

{
data := make(map[string]interface{})
for key, value := range *src {
data[*key] = *value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361336-f02adf00-8cdb-11eb-957e-063f31b8eff0.png)

---

```golang
func range_1F() {
src := source().(string)

var (
Map map[string]string
)
link([]byte(src), &Map)

{
data := make(map[string]interface{})
for key, value := range Map {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361430-0afd5380-8cdc-11eb-9e76-053ccf6edad1.png)

---

```golang
func range_1G() {
src := source().(string)

Map := new(map[string]string)
link([]byte(src), Map)

{
data := make(map[string]interface{})
for key, value := range *Map {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361507-21a3aa80-8cdc-11eb-8bd3-00d6eafc31ea.png)

---

```golang
func range_1H() {
src := source().(string)

Map := make(map[string]string)
link([]byte(src), &Map)

{
data := make(map[string]interface{})
for key, value := range Map {
data[key] = value
}
sink(data)
}
}
```

nets the following result (one path, which is expected):

![image](https://user-images.githubusercontent.com/15271561/112361586-3aac5b80-8cdc-11eb-9103-5149e5dbb6f8.png)

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.