Make MethodCallNode char pred more accurate

When a function is assigned to a variable and called through that
variable then we previously didn't realise it was a function. With
this change we try use local flow to determine if the function being
called is a method.
This commit is contained in:
Owen Mansel-Chan
2023-07-19 10:24:27 +01:00
parent d41d2bc29e
commit de8794e9ba
3 changed files with 12 additions and 8 deletions

View File

@@ -0,0 +1,4 @@
---
category: fix
---
* The definition of `DataFlow::MethodCallNode` has been expanded to include `DataFlow::CallNode`s where what is being called is a variable that has a method assigned to it within the calling function. This means we can now follow data flow into the receiver of such a method call.

View File

@@ -631,9 +631,9 @@ module Public {
/** A data flow node that represents a call to a method. */
class MethodCallNode extends CallNode {
MethodCallNode() { expr.getTarget() instanceof Method }
MethodCallNode() { getACalleeSource(this) instanceof MethodReadNode }
override Method getTarget() { result = expr.getTarget() }
override Method getTarget() { result = getACalleeSource(this).(MethodReadNode).getMethod() }
override MethodDecl getACallee() { result = super.getACallee() }
}

View File

@@ -51,7 +51,7 @@ func main() {
gs1 := GenericStruct1[string]{""}
gs1.Field = source()
f := gs1.Getter
sink(f()) // $ MISSING: hasValueFlow="call to f"
sink(f()) // $ hasValueFlow="call to f"
}
{
gs1 := GenericStruct1[string]{""}
@@ -62,7 +62,7 @@ func main() {
gs1 := GenericStruct1[string]{""}
f := gs1.Setter
f(source())
sink(gs1.Field) // $ MISSING: hasValueFlow="selection of Field"
sink(gs1.Field) // $ hasValueFlow="selection of Field"
}
{
@@ -87,7 +87,7 @@ func main() {
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field1 = source()
f := gs2.Getter1
sink(f()) // $ MISSING: hasValueFlow="call to f"
sink(f()) // $ hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
@@ -98,7 +98,7 @@ func main() {
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Setter1
f(source())
sink(gs2.Field1) // $ MISSING: hasValueFlow="selection of Field1"
sink(gs2.Field1) // $ hasValueFlow="selection of Field1"
}
{
@@ -123,7 +123,7 @@ func main() {
gs2 := GenericStruct2[string, string]{"", ""}
gs2.Field2 = source()
f := gs2.Getter2
sink(f()) // $ MISSING: hasValueFlow="call to f"
sink(f()) // $ hasValueFlow="call to f"
}
{
gs2 := GenericStruct2[string, string]{"", ""}
@@ -134,6 +134,6 @@ func main() {
gs2 := GenericStruct2[string, string]{"", ""}
f := gs2.Setter2
f(source())
sink(gs2.Field2) // $ MISSING: hasValueFlow="selection of Field2"
sink(gs2.Field2) // $ hasValueFlow="selection of Field2"
}
}