Swift: some expression extractions

This commit is contained in:
Paolo Tranquilli
2022-06-21 17:31:40 +02:00
parent 091299668a
commit 1e4ac44362
28 changed files with 159 additions and 57 deletions

View File

@@ -380,6 +380,7 @@ EnumIsCaseExpr:
ErrorExpr:
_extends: Expr
_tags: [ no_qltest ] # unexpected emission
ExplicitCastExpr:
_extends: Expr
@@ -454,6 +455,7 @@ ObjCSelectorExpr:
_children:
sub_expr: Expr
method: AbstractFunctionDecl
_tags: [ no_qltest ] # to be tested in integration tests
OneWayExpr:
_extends: Expr
@@ -493,6 +495,9 @@ RebindSelfInConstructorExpr:
SequenceExpr:
_extends: Expr
_children:
elements: Expr*
_tags: [ no_qltest ] # we should really never extract these, as these should be resolved to trees of operations
SuperRefExpr:
_extends: Expr
@@ -523,18 +528,28 @@ TypeExpr:
UnresolvedDeclRefExpr:
_extends: Expr
name: string?
_tags: [ no_qltest ] # we should really never extract these
UnresolvedDotExpr:
_extends: Expr
_children:
base: Expr
name: string
_tags: [ no_qltest ] # we should really never extract these
UnresolvedMemberExpr:
_extends: Expr
name: string
_tags: [ no_qltest ] # we should really never extract these
UnresolvedPatternExpr:
_extends: Expr
_tags: [ no_qltest ] # we should really never extract these
UnresolvedSpecializeExpr:
_extends: Expr
_tags: [ no_qltest ] # we should really never extract these
VarargExpansionExpr:
_extends: Expr
@@ -808,9 +823,11 @@ ArrayToPointerExpr:
BridgeFromObjCExpr:
_extends: ImplicitConversionExpr
_tags: [ no_qltest ] # to be tested in integration tests
BridgeToObjCExpr:
_extends: ImplicitConversionExpr
_tags: [ no_qltest ] # to be tested in integration tests
ClassMetatypeToObjectExpr:
_extends: ImplicitConversionExpr
@@ -820,6 +837,7 @@ CollectionUpcastConversionExpr:
ConditionalBridgeFromObjCExpr:
_extends: ImplicitConversionExpr
_tags: [ no_qltest ] # to be tested in integration tests
CovariantFunctionConversionExpr:
_extends: ImplicitConversionExpr

View File

@@ -64,6 +64,7 @@ class SwiftDispatcher {
// visitor (see `visit(T *)` methods below).
template <typename E>
TrapLabelOf<E> fetchLabel(E* e) {
assert(e && "trying to fetch a label on nullptr, maybe fetchOptionalLabel is to be used?");
// this is required so we avoid any recursive loop: a `fetchLabel` during the visit of `e` might
// end up calling `fetchLabel` on `e` itself, so we want the visit of `e` to call `fetchLabel`
// only after having called `assignNewLabel` on `e`.

View File

@@ -280,10 +280,10 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
}
}
void visitParenExpr(swift::ParenExpr* expr) {
auto label = dispatcher_.assignNewLabel(expr);
dispatcher_.emit(ParenExprsTrap{label});
emitIdentityExpr(expr, label);
codeql::ParenExpr translateParenExpr(const swift::ParenExpr& expr) {
ParenExpr entry{dispatcher_.assignNewLabel(expr)};
fillIdentityExpr(expr, entry);
return entry;
}
void visitLoadExpr(swift::LoadExpr* expr) {
@@ -535,6 +535,62 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
dispatcher_.emit(OtherConstructorDeclRefExprsTrap{label, ctorLabel});
}
codeql::UnresolvedDeclRefExpr translateUnresolvedDeclRefExpr(
const swift::UnresolvedDeclRefExpr& expr) {
codeql::UnresolvedDeclRefExpr entry{dispatcher_.assignNewLabel(expr)};
if (expr.hasName()) {
llvm::SmallVector<char> scratch;
entry.name = expr.getName().getString(scratch).str();
}
return entry;
}
codeql::UnresolvedDotExpr translateUnresolvedDotExpr(const swift::UnresolvedDotExpr& expr) {
codeql::UnresolvedDotExpr entry{dispatcher_.assignNewLabel(expr)};
assert(expr.getBase() && "Expect UnresolvedDotExpr to have a base");
entry.base = dispatcher_.fetchLabel(expr.getBase());
llvm::SmallVector<char> scratch;
entry.name = expr.getName().getString(scratch).str();
return entry;
}
codeql::UnresolvedMemberExpr translateUnresolvedMemberExpr(
const swift::UnresolvedMemberExpr& expr) {
UnresolvedMemberExpr entry{dispatcher_.assignNewLabel(expr)};
llvm::SmallVector<char> scratch;
entry.name = expr.getName().getString(scratch).str();
return entry;
}
codeql::SequenceExpr translateSequenceExpr(const swift::SequenceExpr& expr) {
SequenceExpr entry{dispatcher_.assignNewLabel(expr)};
entry.elements = dispatcher_.fetchRepeatedLabels(expr.getElements());
return entry;
}
codeql::BridgeToObjCExpr translateBridgeToObjCExpr(const swift::BridgeToObjCExpr& expr) {
BridgeToObjCExpr entry{dispatcher_.assignNewLabel(expr)};
entry.sub_expr = dispatcher_.fetchLabel(expr.getSubExpr());
return entry;
}
codeql::BridgeFromObjCExpr translateBridgeFromObjCExpr(const swift::BridgeFromObjCExpr& expr) {
BridgeFromObjCExpr entry{dispatcher_.assignNewLabel(expr)};
entry.sub_expr = dispatcher_.fetchLabel(expr.getSubExpr());
return entry;
}
codeql::DotSelfExpr translateDotSelfExpr(const swift::DotSelfExpr& expr) {
DotSelfExpr entry{dispatcher_.assignNewLabel(expr)};
fillIdentityExpr(expr, entry);
return entry;
}
codeql::ErrorExpr translateErrorExpr(const swift::ErrorExpr& expr) {
ErrorExpr entry{dispatcher_.assignNewLabel(expr)};
return entry;
}
private:
void emitAbstractClosureExpr(swift::AbstractClosureExpr* expr,
TrapLabel<AbstractClosureExprTag> label) {
@@ -566,9 +622,9 @@ class ExprVisitor : public AstVisitorBase<ExprVisitor> {
dispatcher_.emit(ExplicitCastExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
}
void emitIdentityExpr(swift::IdentityExpr* expr, TrapLabel<IdentityExprTag> label) {
assert(expr->getSubExpr() && "IdentityExpr has getSubExpr()");
dispatcher_.emit(IdentityExprsTrap{label, dispatcher_.fetchLabel(expr->getSubExpr())});
void fillIdentityExpr(const swift::IdentityExpr& expr, codeql::IdentityExpr& entry) {
assert(expr.getSubExpr() && "IdentityExpr has getSubExpr()");
entry.sub_expr = dispatcher_.fetchLabel(expr.getSubExpr());
}
void emitAnyTryExpr(swift::AnyTryExpr* expr, TrapLabel<AnyTryExprTag> label) {

View File

@@ -134,6 +134,8 @@ Element getAnImmediateChild(Element e) {
or
self_apply_exprs(e, x)
or
sequence_expr_elements(e, _, x)
or
subscript_expr_arguments(e, _, x)
or
tap_expr_sub_exprs(e, x)
@@ -146,6 +148,8 @@ Element getAnImmediateChild(Element e) {
or
type_expr_type_reprs(e, x)
or
unresolved_dot_exprs(e, x, _)
or
vararg_expansion_exprs(e, x)
or
binding_patterns(e, x)

View File

@@ -3,4 +3,15 @@ import codeql.swift.elements.expr.Expr
class SequenceExprBase extends @sequence_expr, Expr {
override string getAPrimaryQlClass() { result = "SequenceExpr" }
Expr getElement(int index) {
exists(Expr x |
sequence_expr_elements(this, index, x) and
result = x.resolve()
)
}
Expr getAnElement() { result = getElement(_) }
int getNumberOfElements() { result = count(getAnElement()) }
}

View File

@@ -3,4 +3,8 @@ import codeql.swift.elements.expr.Expr
class UnresolvedDeclRefExprBase extends @unresolved_decl_ref_expr, Expr {
override string getAPrimaryQlClass() { result = "UnresolvedDeclRefExpr" }
string getName() { unresolved_decl_ref_expr_names(this, result) }
predicate hasName() { exists(getName()) }
}

View File

@@ -3,4 +3,13 @@ import codeql.swift.elements.expr.Expr
class UnresolvedDotExprBase extends @unresolved_dot_expr, Expr {
override string getAPrimaryQlClass() { result = "UnresolvedDotExpr" }
Expr getBase() {
exists(Expr x |
unresolved_dot_exprs(this, x, _) and
result = x.resolve()
)
}
string getName() { unresolved_dot_exprs(this, _, result) }
}

View File

@@ -3,4 +3,6 @@ import codeql.swift.elements.expr.Expr
class UnresolvedMemberExprBase extends @unresolved_member_expr, Expr {
override string getAPrimaryQlClass() { result = "UnresolvedMemberExpr" }
string getName() { unresolved_member_exprs(this, result) }
}

View File

@@ -1004,6 +1004,13 @@ sequence_exprs(
unique int id: @sequence_expr
);
#keyset[id, index]
sequence_expr_elements(
int id: @sequence_expr ref,
int index: int ref,
int element: @expr ref
);
super_ref_exprs(
unique int id: @super_ref_expr,
int self: @var_decl ref
@@ -1052,12 +1059,21 @@ unresolved_decl_ref_exprs(
unique int id: @unresolved_decl_ref_expr
);
#keyset[id]
unresolved_decl_ref_expr_names(
int id: @unresolved_decl_ref_expr ref,
string name: string ref
);
unresolved_dot_exprs(
unique int id: @unresolved_dot_expr
unique int id: @unresolved_dot_expr,
int base: @expr ref,
string name: string ref
);
unresolved_member_exprs(
unique int id: @unresolved_member_expr
unique int id: @unresolved_member_expr,
string name: string ref
);
unresolved_pattern_exprs(

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,2 @@
@interface MyClass : NSObject
@property int foo @end

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,2 @@
| dotself.swift:4:9:4:14 | .self | getSubExpr: | dotself.swift:4:9:4:9 | self |
| dotself.swift:4:9:4:21 | .self | getSubExpr: | dotself.swift:4:9:4:19 | .x |

View File

@@ -0,0 +1,10 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from DotSelfExpr x, Expr getSubExpr
where
toBeTested(x) and
not x.isUnknown() and
getSubExpr = x.getSubExpr()
select x, "getSubExpr:", getSubExpr

View File

@@ -0,0 +1,2 @@
| dotself.swift:4:9:4:14 | .self | A |
| dotself.swift:4:9:4:21 | .self | @lvalue Int |

View File

@@ -0,0 +1,7 @@
// generated by codegen/codegen.py
import codeql.swift.elements
import TestUtils
from DotSelfExpr x
where toBeTested(x) and not x.isUnknown()
select x, x.getType()

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -0,0 +1,6 @@
class A {
var x: Int
init() {
self.self.x.self = 42
}
}

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted

View File

@@ -1,4 +0,0 @@
// generated by codegen/codegen.py
After a swift source file is added in this directory and codegen/codegen.py is run again, test queries
will appear and this file will be deleted