Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 60 additions & 50 deletions cpp/ql/lib/semmle/code/cpp/dataflow/ExternalFlow.qll
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,32 @@ private string getSignatureParameterName(string signature, string type, string n
)
}

/**
* Gets a `Function` identified by the `(namespace, type, name)` components.
*
* If `subtypes` is `true` then the result may be an override of the function
* identified by the components.
*/
bindingset[type, name]
private Function getFunction(string namespace, string type, boolean subtypes, string name) {
funcHasQualifiedName(result, namespace, name) and
subtypes = false and
type = ""
or
exists(Class namedClass, Class classWithMethod |
hasClassAndName(classWithMethod, result, name) and
classHasQualifiedName(namedClass, namespace, type)
|
// member declared in the named type or a subtype of it
subtypes = true and
classWithMethod = namedClass.getADerivedClass*()
or
// member declared directly in the named type
subtypes = false and
classWithMethod = namedClass
)
}

/**
* Holds if the suffix containing the entries in `signature` starting at entry
* `i` matches the suffix containing the parameters of `func` starting at entry `i`.
Expand All @@ -812,13 +838,16 @@ private string getSignatureParameterName(string signature, string type, string n
* is `func:n` then the signature name is compared with the `n`'th name
* in `name`.
*/
private predicate signatureMatches(Function func, string signature, string type, string name, int i) {
private predicate signatureMatches(
Function func, string namespace, string signature, string type, string name, int i
) {
func = getFunction(namespace, type, _, name) and
exists(string s |
s = getSignatureParameterName(signature, type, name, i) and
s = getParameterTypeName(func, i)
) and
if exists(getParameterTypeName(func, i + 1))
then signatureMatches(func, signature, type, name, i + 1)
then signatureMatches(func, namespace, signature, type, name, i + 1)
else i = count(signature.indexOf(","))
}

Expand All @@ -833,7 +862,7 @@ module ExternalFlowDebug {
*
* Exposed for testing purposes.
*/
predicate signatureMatches_debug = signatureMatches/5;
predicate signatureMatches_debug = signatureMatches/6;

/**
* INTERNAL: Do not use.
Expand Down Expand Up @@ -909,7 +938,7 @@ private predicate elementSpecMatchesSignature(
) {
elementSpec(namespace, pragma[only_bind_into](type), subtypes, pragma[only_bind_into](name),
pragma[only_bind_into](signature), _) and
signatureMatches(func, signature, type, name, 0)
signatureMatches(func, namespace, signature, type, name, 0)
}

/**
Expand Down Expand Up @@ -953,7 +982,7 @@ private predicate funcHasQualifiedName(Function func, string namespace, string n
* Holds if `namedClass` is in namespace `namespace` and has
* name `type` (excluding any template parameters).
*/
bindingset[type, namespace]
bindingset[type]
pragma[inline_late]
private predicate classHasQualifiedName(Class namedClass, string namespace, string type) {
exists(string typeWithoutArgs |
Expand All @@ -969,17 +998,14 @@ private predicate classHasQualifiedName(Class namedClass, string namespace, stri
* are also returned.
* 3. The element has name `name`
* 4. If `signature` is non-empty, then the element has a list of parameter types described by `signature`.
*
* NOTE: `namespace` is currently not used (since we don't properly extract modules yet).
*/
pragma[nomagic]
private Element interpretElement0(
string namespace, string type, boolean subtypes, string name, string signature
) {
result = getFunction(namespace, type, subtypes, name) and
(
// Non-member functions
funcHasQualifiedName(result, namespace, name) and
subtypes = false and
type = "" and
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
Expand All @@ -989,52 +1015,36 @@ private Element interpretElement0(
)
or
// Member functions
exists(Class namedClass, Class classWithMethod |
hasClassAndName(classWithMethod, result, name) and
classHasQualifiedName(namedClass, namespace, type)
|
(
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
signature = "" and
elementSpec(namespace, type, subtypes, name, "", _)
) and
(
// member declared in the named type or a subtype of it
subtypes = true and
classWithMethod = namedClass.getADerivedClass*()
or
// member declared directly in the named type
subtypes = false and
classWithMethod = namedClass
)
)
elementSpecMatchesSignature(result, namespace, type, subtypes, name, signature)
or
elementSpec(namespace, type, subtypes, name, signature, _) and
// Member variables
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
member.getName() = name and
member = classWithMember.getAMember() and
namedClass.hasQualifiedName(namespace, type) and
result = member
|
// field declared in the named type or a subtype of it (or an extension of any)
subtypes = true and
classWithMember = namedClass.getADerivedClass*()
or
// field declared directly in the named type (or an extension of it)
subtypes = false and
classWithMember = namedClass
)
elementSpec(namespace, type, subtypes, name, signature, _)
)
or
// Member variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
exists(Class namedClass, Class classWithMember, MemberVariable member |
member.getName() = name and
member = classWithMember.getAMember() and
namedClass.hasQualifiedName(namespace, type) and
result = member
|
// field declared in the named type or a subtype of it (or an extension of any)
subtypes = true and
classWithMember = namedClass.getADerivedClass*()
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
// field declared directly in the named type (or an extension of it)
subtypes = false and
result = any(GlobalOrNamespaceVariable v | v.hasQualifiedName(namespace, name))
classWithMember = namedClass
)
or
// Global or namespace variables
elementSpec(namespace, type, subtypes, name, signature, _) and
signature = "" and
type = "" and
subtypes = false and
result = any(GlobalOrNamespaceVariable v | v.hasQualifiedName(namespace, name))
}

cached
Expand Down
Loading