github / github/codeql

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

Đang mở
#9,308 7 bình luận 0 reaction 0 người được giao Xem trên GitHub
Go
Ngôn ngữ chính
CodeQL
Star
10.1k
Fork
2.1k
Merge trung bình
2 ngày 15 giờ
Pull request đã merge (30 ngày)
141

Mô tả

## 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)

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.