Skip to content

Commit

Permalink
Keep methods and fields separate in SourceOrSinkElement
Browse files Browse the repository at this point in the history
This improves performance.
  • Loading branch information
owen-mc committed Nov 11, 2024
1 parent b6a31b1 commit 3986dff
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 18 deletions.
8 changes: 4 additions & 4 deletions go/ql/lib/semmle/go/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,8 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement(
exists(string p | p = interpretPackage(pkg) |
result.hasTypeInfo(p, type, subtypes) and
(
result.asEntity().(Field).hasQualifiedName(p, type, name) or
result.asEntity().(Method).hasQualifiedName(p, type, name)
result.asFieldEntity().hasQualifiedName(p, type, name) or
result.asMethodEntity().hasQualifiedName(p, type, name)
)
or
subtypes = true and
Expand All @@ -488,12 +488,12 @@ SourceSinkInterpretationInput::SourceOrSinkElement interpretElement(
m2.getName() = name and
m2.getReceiverBaseType().hasQualifiedName(pkg2, type2)
|
result.asEntity() = m2 and
result.asMethodEntity() = m2 and
result.hasTypeInfo(pkg2, type2, subtypes)
)
or
type = "" and
exists(Entity e | e.hasQualifiedName(p, name) | result.asEntity() = e)
exists(Entity e | e.hasQualifiedName(p, name) | result.asOtherEntity() = e)
)
}

Expand Down
34 changes: 20 additions & 14 deletions go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,12 @@ module SourceSinkInterpretationInput implements
// Methods having multiple qualified names, a given Method is liable to have
// more than one SourceOrSinkElement, one for each of the names it claims.
private newtype TSourceOrSinkElement =
TMethodOrFieldEntityElement(Entity e, string pkg, string type, boolean subtypes) {
(
e.(Method).hasQualifiedName(pkg, type, _) or
e.(Field).hasQualifiedName(pkg, type, _)
) and
TMethodEntityElement(Method m, string pkg, string type, boolean subtypes) {
m.hasQualifiedName(pkg, type, _) and
subtypes = [true, false]
} or
TFieldEntityElement(Field f, string pkg, string type, boolean subtypes) {
f.hasQualifiedName(pkg, type, _) and
subtypes = [true, false]
} or
TOtherEntityElement(Entity e) {
Expand All @@ -170,10 +171,15 @@ module SourceSinkInterpretationInput implements
class SourceOrSinkElement extends TSourceOrSinkElement {
/** Gets this source or sink element as an entity, if it is one. */
Entity asEntity() {
this = TMethodOrFieldEntityElement(result, _, _, _) or
this = TOtherEntityElement(result)
result = [this.asMethodEntity(), this.asFieldEntity(), this.asOtherEntity()]
}

Method asMethodEntity() { this = TMethodEntityElement(result, _, _, _) }

Field asFieldEntity() { this = TFieldEntityElement(result, _, _, _) }

Entity asOtherEntity() { this = TOtherEntityElement(result) }

/** Gets this source or sink element as an AST node, if it is one. */
AstNode asAstNode() { this = TAstElement(result) }

Expand All @@ -182,7 +188,8 @@ module SourceSinkInterpretationInput implements
* with the given values for `pkg`, `type` and `subtypes`.
*/
predicate hasTypeInfo(string pkg, string type, boolean subtypes) {
this = TMethodOrFieldEntityElement(_, pkg, type, subtypes)
this = TMethodEntityElement(_, pkg, type, subtypes) or
this = TFieldEntityElement(_, pkg, type, subtypes)
}

/** Gets a textual representation of this source or sink element. */
Expand Down Expand Up @@ -239,11 +246,10 @@ module SourceSinkInterpretationInput implements
cn = this.asCall().getNode() and
callTarget = cn.getTarget()
|
result.asEntity() = callTarget and
(
not callTarget instanceof Method
result.asOtherEntity() = callTarget
or
callTarget instanceof Method and
result.asMethodEntity() = callTarget and
elementAppliesToQualifier(result, cn.getReceiver())
)
)
Expand Down Expand Up @@ -302,7 +308,7 @@ module SourceSinkInterpretationInput implements
// `syntacticQualBaseType`'s underlying type might be a struct type and `sse`
// might be a promoted method or field in it.
targetType =
getIntermediateEmbeddedType(sse.asEntity(), syntacticQualBaseType.getUnderlyingType())
getIntermediateEmbeddedType(sse.asMethodEntity(), syntacticQualBaseType.getUnderlyingType())
)
)
}
Expand Down Expand Up @@ -382,7 +388,7 @@ module SourceSinkInterpretationInput implements
or
exists(DataFlow::FieldReadNode frn | frn = n |
c = "" and
frn.getField() = pragma[only_bind_into](e).asEntity() and
frn.getField() = pragma[only_bind_into](e).asFieldEntity() and
elementAppliesToQualifier(pragma[only_bind_into](e), frn.getBase())
)
)
Expand All @@ -400,7 +406,7 @@ module SourceSinkInterpretationInput implements
or
exists(SourceOrSinkElement e, DataFlow::Write fw, DataFlow::Node base, Field f |
e = mid.asElement() and
f = e.asEntity()
f = e.asFieldEntity()
|
c = "" and
fw.writesField(base, f, node.asNode()) and
Expand Down

0 comments on commit 3986dff

Please sign in to comment.