Go language deep copy shallow copy

Recently, when writing code, I found a bug, which is related to deep copy and shallow copy

Earlier we looked at the Go language design and implementation – Faith-oriented programming

I’ve talked about it in great detail, and there are two kinds

The arguments are int and array

func myFunction(i int, arr [2]int) {
	i = 29
	arr[1] = 88
	fmt.Printf("in my_funciton - i=(%d, %p) arr=(%v, %p)\n", i, &i, arr, &arr)
}

$ go run main.go
before calling - i=(30.0xc000072008) arr=([66 77].0xc000072010)
in my_funciton - i=(29.0xc000072028) arr=([66 88].0xc000072040)
after  calling - i=(30.0xc000072008) arr=([66 77].0xc000072010)
Copy the code

The first is that the arguments in the pass are int and array

You can see that there is no change

So go is value pass-through for both integer and array types

The parameters in the pass are structure and structure pointer

type MyStruct struct {
	i int
}

func myFunction(a MyStruct, b *MyStruct) {
	a.i = 31
	b.i = 41
	fmt.Printf("in my_function - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}

func main(a) {
	a := MyStruct{i: 30}
	b := &MyStruct{i: 40}
	fmt.Printf("before calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
	myFunction(a, b)
	fmt.Printf("after calling - a=(%d, %p) b=(%v, %p)\n", a, &a, b, &b)
}

$ go run main.go
before calling - a=({30}, 0xc000018178) b=(&{40}, 0xc00000c028)
in my_function - a=({31}, 0xc000018198) b=(&{41}, 0xc00000c038)
after calling  - a=({30}, 0xc000018178) b=(&{41}, 0xc00000c028)
Copy the code

When a structure and a structure pointer are passed in the argument

You can see that A.I does not change before or after entering the parameter

But B.I changed before and after the entry parameter

And we can see that here

  • When passing a structure: all contents of the structure are copied.
  • When passing structure pointer: Structure pointer will be copied.

This brings me to my problem

The bug

func (sqli *SqlInjection) GenerateTimePayloads(payloadTemplate string, OriginDict interface{}) [][]fakehttp.Request {

So let’s look at my function calls in the code, one of which is string and one of which is value passing

But how does this interface{} get passed in arguments

So regardless of whether you’re passing in a structure or something else, because it’s not a pointer then you’re going to copy what’s in that structure and pass it around

So I wrote newDict := OriginDict.(url.values)

Interface {} may be passed as a pointer, so let’s test it

I’m going to use interface to pass the structure pointer and the structure and see if there’s any problem

Arrays, ints are definitely passed by value, I think there is no problem

type MyStruct struct {
	i int
}

func myFunction(t interface{}, OriginDict interface{}) {
	a := t.(MyStruct)
	a.i = 31
	b := OriginDict.(*MyStruct)
	b.i = 41
	fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}

func main(a) {
	a := MyStruct{i: 40}
	b := &MyStruct{i: 40}
	fmt.Printf("before calling - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
	myFunction(a, b)
	fmt.Printf("after calling - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}

[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "before calling - a=({%! s(int=40)}, 0x140000180f8) b=(&{40}, 0x1400000e028) in my_function - a=({%! s(int=31)}, 0x14000018110) b=(&{41}, 0x1400000e038) after calling - a=({%! s(int=40)}, 0x140000180f8) b=(&{41}, 0x1400000e028)
Copy the code

The result is exactly the same as the previous one, indicating that the structure pointer is passed according to whether or not the structure pointer is passed

Is there something wrong with my thinking

I’m passing a dictionary, so I’m passing a dictionary to try it out

type MyStruct struct {
	i int
}

type test map[string] []string

func myFunction(t interface{}, OriginDict interface{}) {
	a := t.(test)
	a["1"] = []string{"123"}
	b := OriginDict.(MyStruct)
	b.i = 41
	fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}

func main(a) {
	var a test
	a = test{
		"0": []string{"123"},
	}
	b := MyStruct{i: 40}
	fmt.Printf("before calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
	myFunction(a, b)
	fmt.Printf("after calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
}

[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "
before calling - a=(map[0: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
in my_function - a=(map[0: [123] 1: [123]], 0x1400000e038) b=({41}, 0x14000018100)
after calling  - a=(map[0: [123] 1: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
Copy the code

The problem was rectified, so the pointer was copied when the parameter was passed by interface{}, resulting in the change of the original value

What if instead of an interface, instead of a map is passed directly in parameters

type MyStruct struct {
	i int
}

func myFunction(a map[string] []string, OriginDict interface{}) {
	a["1"] = []string{"123"}
	b := OriginDict.(MyStruct)
	b.i = 41
	fmt.Printf("in my_function - a=(%s, %p) b=(%v, %p)\n", a, &a, b, &b)
}

func main(a) {
	a := map[string] []string{
		"0": []string{"123"},
	}
	b := MyStruct{i: 40}
	fmt.Printf("before calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
	myFunction(a, b)
	fmt.Printf("after calling - a=(%v, %p) b=(%v, %p)\n", a, &a, b, &b)
}

[Running] go run "/ Users/apple/Desktop/a lot/scanner/Gondar/scanner/test/tesst. Go." "
before calling - a=(map[0: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
in my_function - a=(map[0: [123] 1: [123]], 0x1400000e038) b=({41}, 0x14000018100)
after calling  - a=(map[0: [123] 1: [123]], 0x1400000e028) b=({40}, 0x140000180f8)
Copy the code

The result is the same as the previous one, indicating that the process of passing the interface{} parameter is still the same as its own type

Note The problem is that the map type, which uses pointer passing in the process of passing, is a shallow copy. If the value changes, the original value will change

To summarize

  • Pass struct, int, string, array: deep copy;
  • Passing structure pointer, map: shallow copy;

Refer to the link

Draveness. Me/golang/docs…