Skip to content

Commit 184371f

Browse files
committed
Swift: Implement 'interpretElement0'.
1 parent ace00c3 commit 184371f

File tree

2 files changed

+83
-4
lines changed

2 files changed

+83
-4
lines changed

swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ private import internal.FlowSummaryImplSpecific
7878
* ensuring that they are visible to the taint tracking / data flow library.
7979
*/
8080
private module Frameworks {
81-
/* TODO */
81+
private import codeql.swift.frameworks.StandardLibrary.String
8282
}
8383

8484
/**
@@ -344,11 +344,86 @@ private predicate elementSpec(
344344
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
345345
}
346346

347+
private string paramsStringPart(AbstractFunctionDecl c, int i) {
348+
i = -1 and result = "(" and exists(c)
349+
or
350+
exists(int n, string p | c.getParam(n).getType().toString() = p |
351+
i = 2 * n and result = p
352+
or
353+
i = 2 * n - 1 and result = "," and n != 0
354+
)
355+
or
356+
i = 2 * c.getNumberOfParams() and result = ")"
357+
}
358+
359+
/**
360+
* Gets a parenthesized string containing all parameter types of this callable, separated by a comma.
361+
*
362+
* Returns the empty string if the callable has no parameters.
363+
* Parameter types are represented by their type erasure.
364+
*/
365+
cached
366+
string paramsString(AbstractFunctionDecl c) {
367+
result = concat(int i | | paramsStringPart(c, i) order by i)
368+
}
369+
370+
bindingset[func]
371+
predicate matchesSignature(AbstractFunctionDecl func, string signature) {
372+
signature = "" or
373+
paramsString(func) = signature
374+
}
375+
376+
private NominalType getDeclType(IterableDeclContext decl) {
377+
result = decl.(ClassDecl).getType()
378+
or
379+
result = decl.(StructDecl).getType()
380+
or
381+
result = getDeclType(decl.(ExtensionDecl).getExtendedTypeDecl())
382+
or
383+
result = decl.(EnumDecl).getType()
384+
or
385+
result = decl.(ProtocolDecl).getType()
386+
}
387+
388+
/**
389+
* Gets the element in module `namespace` that satisfies the following properties:
390+
* 1. If the element is a member of a class-like type, then the class-like type has name `type`
391+
* 2. If `subtypes = true` and the element is a member of a class-like type, then overrides of the element
392+
* are also returned.
393+
* 3. The element has name `name`
394+
* 4. If `signature` is non-empty, then the element has a list of parameter types described by `signature`.
395+
*
396+
* NOTE: `namespace` is currently not used (since we don't properly extract modules yet).
397+
*/
347398
pragma[nomagic]
348399
private Element interpretElement0(
349400
string namespace, string type, boolean subtypes, string name, string signature
350401
) {
351-
none() // TODO
402+
namespace = "" and // TODO: Fill out when we properly extract modules.
403+
(
404+
exists(AbstractFunctionDecl func |
405+
func.getName() = name and
406+
type = "" and
407+
matchesSignature(func, signature) and
408+
subtypes = false and
409+
not result instanceof MethodDecl and
410+
result = func
411+
)
412+
or
413+
exists(NominalType nomType, IterableDeclContext decl, MethodDecl method |
414+
method.getName() = name and
415+
method = decl.getAMember() and
416+
nomType.getName() = type and
417+
matchesSignature(method, signature) and
418+
result = method
419+
|
420+
subtypes = true and
421+
getDeclType(decl) = nomType.getADerivedType*()
422+
or
423+
subtypes = false and
424+
getDeclType(decl) = nomType
425+
)
426+
)
352427
}
353428

354429
/** Gets the source/sink/summary element corresponding to the supplied parameters. */
Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
21
private import codeql.swift.generated.type.NominalType
2+
private import codeql.swift.elements.decl.NominalTypeDecl
33

4-
class NominalType extends NominalTypeBase { }
4+
class NominalType extends NominalTypeBase {
5+
NominalType getABaseType() { result = this.getDeclaration().(NominalTypeDecl).getABaseType() }
6+
7+
NominalType getADerivedType() { result.getABaseType() = this }
8+
}

0 commit comments

Comments
 (0)