From 8473ed0d81342e7ca541cbe8e61ca9b791750ddf Mon Sep 17 00:00:00 2001 From: Slavomir Date: Tue, 30 Jun 2020 11:31:24 +0300 Subject: [PATCH] Add tests --- .../{Unsafe.ql => WrongUsageOfUnsafe.ql} | 8 + .../Unsafe/WrongUsageOfUnsafe.expected | 90 +++++++ .../experimental/Unsafe/WrongUsageOfUnsafe.go | 240 ++++++++++++++++++ .../Unsafe/WrongUsageOfUnsafe.qlref | 1 + 4 files changed, 339 insertions(+) rename ql/src/experimental/Unsafe/{Unsafe.ql => WrongUsageOfUnsafe.ql} (93%) create mode 100644 ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected create mode 100644 ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go create mode 100644 ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref diff --git a/ql/src/experimental/Unsafe/Unsafe.ql b/ql/src/experimental/Unsafe/WrongUsageOfUnsafe.ql similarity index 93% rename from ql/src/experimental/Unsafe/Unsafe.ql rename to ql/src/experimental/Unsafe/WrongUsageOfUnsafe.ql index e38042f2315..d035b92cbad 100644 --- a/ql/src/experimental/Unsafe/Unsafe.ql +++ b/ql/src/experimental/Unsafe/WrongUsageOfUnsafe.ql @@ -1,5 +1,13 @@ /** + * @name Wrong usage of package unsafe + * @description Casting between variables with different memory sizes can produce reads to + * memory locations that are after the target buffer, and/or unexpected values. * @kind path-problem + * @problem.severity error + * @id go/wrong-usage-of-unsafe + * @tags security + * external/cwe/cwe-119 + * external/cwe/cwe-126 */ import go diff --git a/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected new file mode 100644 index 00000000000..89653a6c089 --- /dev/null +++ b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected @@ -0,0 +1,90 @@ +edges +| WrongUsageOfUnsafe.go:17:27:17:51 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:17:16:17:52 | type conversion | +| WrongUsageOfUnsafe.go:17:27:17:51 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:17:16:17:52 | type conversion | +| WrongUsageOfUnsafe.go:33:23:33:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:33:16:33:48 | type conversion | +| WrongUsageOfUnsafe.go:33:23:33:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:33:16:33:48 | type conversion | +| WrongUsageOfUnsafe.go:51:31:51:58 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | +| WrongUsageOfUnsafe.go:51:31:51:58 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | +| WrongUsageOfUnsafe.go:69:31:69:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | +| WrongUsageOfUnsafe.go:69:31:69:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | +| WrongUsageOfUnsafe.go:89:31:89:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | +| WrongUsageOfUnsafe.go:89:31:89:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | +| WrongUsageOfUnsafe.go:106:33:106:57 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | +| WrongUsageOfUnsafe.go:106:33:106:57 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | +| WrongUsageOfUnsafe.go:151:31:151:60 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | +| WrongUsageOfUnsafe.go:151:31:151:60 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | +| WrongUsageOfUnsafe.go:167:31:167:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | +| WrongUsageOfUnsafe.go:167:31:167:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | +| WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | +| WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | +| WrongUsageOfUnsafe.go:196:28:196:52 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | +| WrongUsageOfUnsafe.go:196:28:196:52 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | +| WrongUsageOfUnsafe.go:214:25:214:49 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | +| WrongUsageOfUnsafe.go:214:25:214:49 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | +| WrongUsageOfUnsafe.go:232:23:232:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | +| WrongUsageOfUnsafe.go:232:23:232:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | +nodes +| WrongUsageOfUnsafe.go:17:16:17:52 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:17:16:17:52 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:17:27:17:51 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:17:27:17:51 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:33:16:33:48 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:33:16:33:48 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:33:23:33:47 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:33:23:33:47 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:51:31:51:58 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:51:31:51:58 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:69:31:69:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:69:31:69:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:89:31:89:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:89:31:89:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:106:33:106:57 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:106:33:106:57 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:151:31:151:60 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:151:31:151:60 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:167:31:167:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:167:31:167:55 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | semmle.label | definition of req : unsafe.Pointer | +| WrongUsageOfUnsafe.go:176:21:176:23 | definition of req : unsafe.Pointer | semmle.label | definition of req : unsafe.Pointer | +| WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:196:28:196:52 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:196:28:196:52 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:214:25:214:49 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:214:25:214:49 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | semmle.label | type conversion | +| WrongUsageOfUnsafe.go:232:23:232:47 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +| WrongUsageOfUnsafe.go:232:23:232:47 | type conversion : unsafe.Pointer | semmle.label | type conversion : unsafe.Pointer | +#select +| WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | WrongUsageOfUnsafe.go:51:31:51:58 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:51:16:51:59 | type conversion | $@. | WrongUsageOfUnsafe.go:51:31:51:58 | type conversion | Dangerous type up-casting to [17]uint8 from uint8 | +| WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | WrongUsageOfUnsafe.go:69:31:69:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:69:16:69:56 | type conversion | $@. | WrongUsageOfUnsafe.go:69:31:69:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | WrongUsageOfUnsafe.go:89:31:89:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:89:16:89:56 | type conversion | $@. | WrongUsageOfUnsafe.go:89:31:89:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | WrongUsageOfUnsafe.go:106:33:106:57 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:106:16:106:58 | type conversion | $@. | WrongUsageOfUnsafe.go:106:33:106:57 | type conversion | Dangerous array type casting to [17]string from [8]string | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous type up-casting to [17]uint8 from harmlessType | +| WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:129:16:129:56 | type conversion | $@. | WrongUsageOfUnsafe.go:129:31:129:55 | type conversion | Dangerous type up-casting to [17]uint8 from struct type | +| WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | WrongUsageOfUnsafe.go:151:31:151:60 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:151:16:151:61 | type conversion | $@. | WrongUsageOfUnsafe.go:151:31:151:60 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | WrongUsageOfUnsafe.go:167:31:167:55 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:183:9:183:27 | type conversion | $@. | WrongUsageOfUnsafe.go:167:31:167:55 | type conversion | Dangerous array type casting to [17]uint8 from [8]uint8 | +| WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | WrongUsageOfUnsafe.go:196:28:196:52 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:196:16:196:53 | type conversion | $@. | WrongUsageOfUnsafe.go:196:28:196:52 | type conversion | Dangerous array type casting to [4]int64 from [1]int64 | +| WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | WrongUsageOfUnsafe.go:214:25:214:49 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:214:16:214:50 | type conversion | $@. | WrongUsageOfUnsafe.go:214:25:214:49 | type conversion | Dangerous numeric type casting to int64 from int8 | +| WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | WrongUsageOfUnsafe.go:232:23:232:47 | type conversion : unsafe.Pointer | WrongUsageOfUnsafe.go:232:16:232:48 | type conversion | $@. | WrongUsageOfUnsafe.go:232:23:232:47 | type conversion | Dangerous numeric type casting to int from int8 | diff --git a/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go new file mode 100644 index 00000000000..e265a758a0b --- /dev/null +++ b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.go @@ -0,0 +1,240 @@ +package main + +import ( + "fmt" + "unsafe" +) + +func main() {} + +func good0() { + // A harmless piece of data: + harmless := [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret without overflowing to secret: + var leaking = (*[8]byte)(unsafe.Pointer(&harmless)) // OK + + fmt.Println(string((*leaking)[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func good1() { + // A harmless piece of data: + harmless := uint(123) + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret: + var leaking = (*int)(unsafe.Pointer(&harmless)) // TODO: is this really OK? + + fmt.Println(*leaking) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} + +func bad00() { + // A harmless piece of data: + harmless := [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we get the pointer to the first byte of harmless) + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless[0])) // BAD + + fmt.Println(string((*leaking)[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} + +func bad0() { + // A harmless piece of data: + harmless := [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless) + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(string((*leaking)[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} + +type Harmless [8]byte + +func bad1() { + // A harmless piece of data: + harmless := Harmless{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless) + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(string((*leaking)[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func bad2() { + // A harmless piece of data: + harmless := [8]string{"A", "A", "A", "A", "A", "A", "A", "A"} + // Something secret: + secret := [9]string{"s", "e", "n", "s", "i", "t", "i", "v", "e"} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless) + var leaking = (*[8 + 9]string)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(*leaking) + fmt.Println([17]string((*leaking))) + + // Avoid optimization: + if secret[0] == "42" { + fmt.Println("hello world") + } +} +func bad3() { + type harmlessType struct { + Data [8]byte + } + // A harmless piece of data: + harmless := harmlessType{ + Data: [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, + } + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless) + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(string((*leaking)[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func bad4() { + type harmlessType struct { + Data [8]byte + } + // A harmless piece of data: + harmless := harmlessType{ + Data: [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'}, + } + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless) + var leaking = (*[8 + 9]byte)(unsafe.Pointer(&harmless.Data)) // BAD + + fmt.Println(string(leaking[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func bad5() { + // A harmless piece of data: + harmless := [8]byte{'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret: + var leaking = buffer_request(unsafe.Pointer(&harmless)) // BAD (see inside buffer_request func) + + fmt.Println((string)(leaking[:])) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func buffer_request(req unsafe.Pointer) [8 + 9]byte { + // The length of req is 8 bytes, + // but we cast it to a longer array, + // which means that when the resulting array + // will be read, the read will also contain pieces of + // data from `secret`. + var buf [8 + 9]byte + buf = *(*[8 + 9]byte)(req) + return buf +} +func bad6() { + // A harmless piece of data: + harmless := [1]int64{23} + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless); + // the leaking array will not contain letters, + // but integers representing bytes from `secret`. + var leaking = (*[4]int64)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(*leaking) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func bad7() { + // A harmless piece of data: + harmless := int8(123) + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless); + // the leaking data will contain some bits from `secret`. + var leaking = (*int64)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(*leaking) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} +func bad8() { + // A harmless piece of data: + harmless := int8(123) + // Something secret: + secret := [9]byte{'s', 'e', 'n', 's', 'i', 't', 'i', 'v', 'e'} + + // Read before secret, overflowing into secret + // (notice we read more than the length of harmless); + // the leaking data will contain some bits from `secret`. + var leaking = (*int)(unsafe.Pointer(&harmless)) // BAD + + fmt.Println(*leaking) + + // Avoid optimization: + if secret[0] == 123 { + fmt.Println("hello world") + } +} diff --git a/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref new file mode 100644 index 00000000000..2f5c54707c7 --- /dev/null +++ b/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.qlref @@ -0,0 +1 @@ +experimental/Unsafe/WrongUsageOfUnsafe.ql