From b06491125e717856d50d282e2ff6e3aa382328ed Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 13 May 2025 15:48:29 +0100 Subject: [PATCH 1/3] Expand test for Extract Tuple Instruction --- go/ql/test/library-tests/semmle/go/IR/test.expected | 12 ++++++------ go/ql/test/library-tests/semmle/go/IR/test.ql | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/IR/test.expected b/go/ql/test/library-tests/semmle/go/IR/test.expected index df2f83e33931..ce3decd70595 100644 --- a/go/ql/test/library-tests/semmle/go/IR/test.expected +++ b/go/ql/test/library-tests/semmle/go/IR/test.expected @@ -1,6 +1,6 @@ -| test.go:9:2:9:16 | ... := ...[0] | file://:0:0:0:0 | bool | -| test.go:9:2:9:16 | ... := ...[1] | file://:0:0:0:0 | bool | -| test.go:15:2:15:20 | ... := ...[0] | file://:0:0:0:0 | string | -| test.go:15:2:15:20 | ... := ...[1] | file://:0:0:0:0 | bool | -| test.go:21:2:21:22 | ... := ...[0] | file://:0:0:0:0 | string | -| test.go:21:2:21:22 | ... := ...[1] | file://:0:0:0:0 | bool | +| test.go:9:2:9:16 | ... := ...[0] | test.go:9:13:9:16 | <-... | 0 | file://:0:0:0:0 | bool | +| test.go:9:2:9:16 | ... := ...[1] | test.go:9:13:9:16 | <-... | 1 | file://:0:0:0:0 | bool | +| test.go:15:2:15:20 | ... := ...[0] | test.go:15:13:15:20 | index expression | 0 | file://:0:0:0:0 | string | +| test.go:15:2:15:20 | ... := ...[1] | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool | +| test.go:21:2:21:22 | ... := ...[0] | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string | +| test.go:21:2:21:22 | ... := ...[1] | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool | diff --git a/go/ql/test/library-tests/semmle/go/IR/test.ql b/go/ql/test/library-tests/semmle/go/IR/test.ql index 1644bd5b2efe..2c4fa43eac00 100644 --- a/go/ql/test/library-tests/semmle/go/IR/test.ql +++ b/go/ql/test/library-tests/semmle/go/IR/test.ql @@ -1,4 +1,5 @@ import go -from IR::ExtractTupleElementInstruction extract -select extract, extract.getResultType() +from IR::ExtractTupleElementInstruction extract, IR::Instruction base, int idx, Type resultType +where extract.extractsElement(base, idx) and resultType = extract.getResultType() +select extract, base, idx, resultType From 7da1ade83501145fd55bd5b90d9de1dff0951e21 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 13 May 2025 15:54:05 +0100 Subject: [PATCH 2/3] Add tests for extracting tuples in `f(g(...))` --- go/ql/test/library-tests/semmle/go/IR/test.expected | 4 ++++ go/ql/test/library-tests/semmle/go/IR/test.go | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/go/ql/test/library-tests/semmle/go/IR/test.expected b/go/ql/test/library-tests/semmle/go/IR/test.expected index ce3decd70595..c42cdaa9932f 100644 --- a/go/ql/test/library-tests/semmle/go/IR/test.expected +++ b/go/ql/test/library-tests/semmle/go/IR/test.expected @@ -4,3 +4,7 @@ | test.go:15:2:15:20 | ... := ...[1] | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool | | test.go:21:2:21:22 | ... := ...[0] | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string | | test.go:21:2:21:22 | ... := ...[1] | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool | +| test.go:29:2:29:7 | call to f[0] | test.go:29:4:29:6 | call to g | 0 | file://:0:0:0:0 | int | +| test.go:29:2:29:7 | call to f[1] | test.go:29:4:29:6 | call to g | 1 | file://:0:0:0:0 | int | +| test.go:33:2:33:7 | call to f[0] | test.go:33:4:33:6 | call to v | 0 | file://:0:0:0:0 | int | +| test.go:33:2:33:7 | call to f[1] | test.go:33:4:33:6 | call to v | 1 | file://:0:0:0:0 | int | diff --git a/go/ql/test/library-tests/semmle/go/IR/test.go b/go/ql/test/library-tests/semmle/go/IR/test.go index de0d567dc3ad..d048632b95b7 100644 --- a/go/ql/test/library-tests/semmle/go/IR/test.go +++ b/go/ql/test/library-tests/semmle/go/IR/test.go @@ -21,3 +21,14 @@ func testTypeAssert() { got, ok := i.(string) fmt.Printf("%v %v", got, ok) } + +func f(x, y int) {} +func g() (int, int) { return 0, 0 } + +func testNestedFunctionCalls() { + f(g()) + + // Edge case: when we call a function from a variable, `getTarget()` is not defined + v := g + f(v()) +} From 933e01b3d4de4d1adb7d263f219cf67ecfd0d3d5 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 13 May 2025 15:55:20 +0100 Subject: [PATCH 3/3] Remove redundant code The case of a CallExpr is actually covered by the next disjunct. Note that the CallExpr case had a subtle bug: `c.getTarget()` is not defined when we are calling a variable. Better to use `c.getCalleeType()`. But in this case we can just delete the code. --- go/ql/lib/semmle/go/controlflow/IR.qll | 4 ---- 1 file changed, 4 deletions(-) diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index 6c7a0c682b53..1a56dfcf2dc9 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -718,10 +718,6 @@ module IR { predicate extractsElement(Instruction base, int idx) { base = this.getBase() and idx = i } override Type getResultType() { - exists(CallExpr c | this.getBase() = evalExprInstruction(c) | - result = c.getTarget().getResultType(i) - ) - or exists(Expr e | this.getBase() = evalExprInstruction(e) | result = e.getType().(TupleType).getComponentType(pragma[only_bind_into](i)) )