mirror of
https://github.com/github/codeql.git
synced 2026-04-28 18:25:24 +02:00
Swift: some expression extractions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
@interface MyClass : NSObject
|
||||
@property int foo @end
|
||||
@@ -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
|
||||
@@ -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 |
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
| dotself.swift:4:9:4:14 | .self | A |
|
||||
| dotself.swift:4:9:4:21 | .self | @lvalue Int |
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -0,0 +1,6 @@
|
||||
class A {
|
||||
var x: Int
|
||||
init() {
|
||||
self.self.x.self = 42
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user