mirror of
https://github.com/github/codeql.git
synced 2026-04-26 17:25:19 +02:00
Merge branch 'main' into no-dtt-in-user-controlled-bypass
This commit is contained in:
@@ -30,11 +30,6 @@ class GuardCondition extends Expr {
|
||||
or
|
||||
// no binary operators in the IR
|
||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||
or
|
||||
// the IR short-circuits if(!x)
|
||||
// don't produce a guard condition for `y = !x` and other non-short-circuited cases
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
|
||||
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,39 +135,6 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A `!` operator in the AST that guards one or more basic blocks, and does not have a corresponding
|
||||
* IR instruction.
|
||||
*/
|
||||
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
|
||||
GuardConditionFromShortCircuitNot() {
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
|
||||
exists(IRGuardCondition ir | this.getOperand() = ir.getAst())
|
||||
}
|
||||
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
this.getOperand().(GuardCondition).controls(controlled, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate comparesLt(Expr left, Expr right, int k, boolean isLessThan, boolean testIsTrue) {
|
||||
this.getOperand()
|
||||
.(GuardCondition)
|
||||
.comparesLt(left, right, k, isLessThan, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate ensuresLt(Expr left, Expr right, int k, BasicBlock block, boolean isLessThan) {
|
||||
this.getOperand().(GuardCondition).ensuresLt(left, right, k, block, isLessThan.booleanNot())
|
||||
}
|
||||
|
||||
override predicate comparesEq(Expr left, Expr right, int k, boolean areEqual, boolean testIsTrue) {
|
||||
this.getOperand().(GuardCondition).comparesEq(left, right, k, areEqual, testIsTrue.booleanNot())
|
||||
}
|
||||
|
||||
override predicate ensuresEq(Expr left, Expr right, int k, BasicBlock block, boolean areEqual) {
|
||||
this.getOperand().(GuardCondition).ensuresEq(left, right, k, block, areEqual.booleanNot())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the AST that guards one or more basic blocks and has a corresponding IR
|
||||
* instruction.
|
||||
|
||||
@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
|
||||
or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
|
||||
or
|
||||
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
|
||||
result = 0
|
||||
or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
|
||||
|
||||
pragma[noinline]
|
||||
private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
exists(int left, int right |
|
||||
binaryInstructionOperands(instr, left, right) and
|
||||
(
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
|
||||
or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
|
||||
or
|
||||
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
|
||||
result = 0
|
||||
or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
|
||||
|
||||
pragma[noinline]
|
||||
private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
exists(int left, int right |
|
||||
binaryInstructionOperands(instr, left, right) and
|
||||
(
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -77,24 +77,6 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedNotCondition extends TranslatedFlexibleCondition {
|
||||
override NotExpr expr;
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedCondition getOperand() {
|
||||
result = getTranslatedCondition(expr.getOperand().getFullyConverted())
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TranslatedNativeCondition extends TranslatedCondition, TTranslatedNativeCondition {
|
||||
TranslatedNativeCondition() { this = TTranslatedNativeCondition(expr) }
|
||||
|
||||
|
||||
@@ -190,10 +190,7 @@ private predicate isNativeCondition(Expr expr) {
|
||||
* depending on context.
|
||||
*/
|
||||
private predicate isFlexibleCondition(Expr expr) {
|
||||
(
|
||||
expr instanceof ParenthesisExpr or
|
||||
expr instanceof NotExpr
|
||||
) and
|
||||
expr instanceof ParenthesisExpr and
|
||||
usedAsCondition(expr) and
|
||||
not isIRConstant(expr)
|
||||
}
|
||||
@@ -218,11 +215,6 @@ private predicate usedAsCondition(Expr expr) {
|
||||
condExpr.getCondition().getFullyConverted() = expr and not condExpr.isTwoOperand()
|
||||
)
|
||||
or
|
||||
exists(NotExpr notExpr |
|
||||
notExpr.getOperand().getFullyConverted() = expr and
|
||||
usedAsCondition(notExpr)
|
||||
)
|
||||
or
|
||||
exists(ParenthesisExpr paren |
|
||||
paren.getExpr() = expr and
|
||||
usedAsCondition(paren)
|
||||
|
||||
@@ -12,6 +12,9 @@ int getConstantValue(Instruction instr) {
|
||||
or
|
||||
result = getConstantValue(instr.(CopyInstruction).getSourceValue())
|
||||
or
|
||||
getConstantValue(instr.(LogicalNotInstruction).getUnary()) != 0 and
|
||||
result = 0
|
||||
or
|
||||
exists(PhiInstruction phi |
|
||||
phi = instr and
|
||||
result = unique(Operand op | op = phi.getAnInputOperand() | getConstantValue(op.getDef()))
|
||||
@@ -26,28 +29,25 @@ private predicate binaryInstructionOperands(BinaryInstruction instr, int left, i
|
||||
|
||||
pragma[noinline]
|
||||
private int getBinaryInstructionValue(BinaryInstruction instr) {
|
||||
exists(int left, int right |
|
||||
binaryInstructionOperands(instr, left, right) and
|
||||
(
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
exists(int left, int right | binaryInstructionOperands(instr, left, right) |
|
||||
instr instanceof AddInstruction and result = add(left, right)
|
||||
or
|
||||
instr instanceof SubInstruction and result = sub(left, right)
|
||||
or
|
||||
instr instanceof MulInstruction and result = mul(left, right)
|
||||
or
|
||||
instr instanceof DivInstruction and result = div(left, right)
|
||||
or
|
||||
instr instanceof CompareEQInstruction and result = compareEQ(left, right)
|
||||
or
|
||||
instr instanceof CompareNEInstruction and result = compareNE(left, right)
|
||||
or
|
||||
instr instanceof CompareLTInstruction and result = compareLT(left, right)
|
||||
or
|
||||
instr instanceof CompareGTInstruction and result = compareGT(left, right)
|
||||
or
|
||||
instr instanceof CompareLEInstruction and result = compareLE(left, right)
|
||||
or
|
||||
instr instanceof CompareGEInstruction and result = compareGE(left, right)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -450,6 +450,7 @@ irGuards
|
||||
| test.c:126:12:126:26 | Call: call to test3_condition |
|
||||
| test.c:131:7:131:7 | Load: b |
|
||||
| test.c:137:7:137:7 | Constant: 0 |
|
||||
| test.c:146:7:146:8 | LogicalNot: ! ... |
|
||||
| test.c:146:8:146:8 | Load: x |
|
||||
| test.c:152:10:152:10 | Load: x |
|
||||
| test.c:152:15:152:15 | Load: y |
|
||||
@@ -640,6 +641,7 @@ irGuardsControl
|
||||
| test.c:126:12:126:26 | Call: call to test3_condition | true | 127 | 127 |
|
||||
| test.c:131:7:131:7 | Load: b | true | 132 | 132 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | false | 142 | 142 |
|
||||
| test.c:146:7:146:8 | LogicalNot: ! ... | true | 147 | 147 |
|
||||
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
|
||||
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
|
||||
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |
|
||||
|
||||
@@ -2770,43 +2770,65 @@ ir.cpp:
|
||||
# 462| m462_2(int) = Uninitialized[x] : &:r462_1
|
||||
# 463| r463_1(glval<bool>) = VariableAddress[a] :
|
||||
# 463| r463_2(bool) = Load[a] : &:r463_1, m461_6
|
||||
# 463| v463_3(void) = ConditionalBranch : r463_2
|
||||
#-----| False -> Block 1
|
||||
#-----| True -> Block 2
|
||||
# 463| r463_3(bool) = LogicalNot : r463_2
|
||||
# 463| v463_4(void) = ConditionalBranch : r463_3
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 464| Block 1
|
||||
# 464| r464_1(int) = Constant[1] :
|
||||
# 464| r464_2(glval<int>) = VariableAddress[x] :
|
||||
# 464| m464_3(int) = Store[x] : &:r464_2, r464_1
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 467| Block 2
|
||||
# 467| r467_1(glval<bool>) = VariableAddress[a] :
|
||||
# 467| r467_2(bool) = Load[a] : &:r467_1, m461_6
|
||||
# 467| v467_3(void) = ConditionalBranch : r467_2
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
# 467| r467_1(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_2(bool) = Constant[0] :
|
||||
# 467| m467_3(bool) = Store[#temp467:11] : &:r467_1, r467_2
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 467| Block 3
|
||||
# 467| r467_4(glval<bool>) = VariableAddress[b] :
|
||||
# 467| r467_5(bool) = Load[b] : &:r467_4, m461_8
|
||||
# 467| v467_6(void) = ConditionalBranch : r467_5
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 5
|
||||
# 467| m467_4(bool) = Phi : from 2:m467_3, from 4:m467_11
|
||||
# 467| r467_5(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_6(bool) = Load[#temp467:11] : &:r467_5, m467_4
|
||||
# 467| r467_7(bool) = LogicalNot : r467_6
|
||||
# 467| v467_8(void) = ConditionalBranch : r467_7
|
||||
#-----| False -> Block 8
|
||||
#-----| True -> Block 7
|
||||
|
||||
# 468| Block 4
|
||||
# 467| Block 4
|
||||
# 467| r467_9(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_10(bool) = Constant[1] :
|
||||
# 467| m467_11(bool) = Store[#temp467:11] : &:r467_9, r467_10
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 467| Block 5
|
||||
# 467| r467_12(glval<bool>) = VariableAddress[a] :
|
||||
# 467| r467_13(bool) = Load[a] : &:r467_12, m461_6
|
||||
# 467| v467_14(void) = ConditionalBranch : r467_13
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 467| Block 6
|
||||
# 467| r467_15(glval<bool>) = VariableAddress[b] :
|
||||
# 467| r467_16(bool) = Load[b] : &:r467_15, m461_8
|
||||
# 467| v467_17(void) = ConditionalBranch : r467_16
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 4
|
||||
|
||||
# 468| Block 7
|
||||
# 468| r468_1(int) = Constant[2] :
|
||||
# 468| r468_2(glval<int>) = VariableAddress[x] :
|
||||
# 468| m468_3(int) = Store[x] : &:r468_2, r468_1
|
||||
#-----| Goto -> Block 6
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 471| Block 5
|
||||
# 471| Block 8
|
||||
# 471| r471_1(int) = Constant[3] :
|
||||
# 471| r471_2(glval<int>) = VariableAddress[x] :
|
||||
# 471| m471_3(int) = Store[x] : &:r471_2, r471_1
|
||||
#-----| Goto -> Block 6
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 473| Block 6
|
||||
# 473| Block 9
|
||||
# 473| v473_1(void) = NoOp :
|
||||
# 461| v461_9(void) = ReturnVoid :
|
||||
# 461| v461_10(void) = AliasedUse : m461_3
|
||||
|
||||
@@ -2398,16 +2398,27 @@
|
||||
| ir.cpp:461:22:461:22 | Address | &:r461_5 |
|
||||
| ir.cpp:461:30:461:30 | Address | &:r461_7 |
|
||||
| ir.cpp:462:9:462:9 | Address | &:r462_1 |
|
||||
| ir.cpp:463:9:463:10 | Condition | r463_3 |
|
||||
| ir.cpp:463:10:463:10 | Address | &:r463_1 |
|
||||
| ir.cpp:463:10:463:10 | Condition | r463_2 |
|
||||
| ir.cpp:463:10:463:10 | Load | m461_6 |
|
||||
| ir.cpp:463:10:463:10 | Unary | r463_2 |
|
||||
| ir.cpp:464:9:464:9 | Address | &:r464_2 |
|
||||
| ir.cpp:464:13:464:13 | StoreValue | r464_1 |
|
||||
| ir.cpp:467:11:467:11 | Address | &:r467_1 |
|
||||
| ir.cpp:467:11:467:11 | Condition | r467_2 |
|
||||
| ir.cpp:467:9:467:17 | Condition | r467_7 |
|
||||
| ir.cpp:467:11:467:11 | Address | &:r467_12 |
|
||||
| ir.cpp:467:11:467:11 | Condition | r467_13 |
|
||||
| ir.cpp:467:11:467:11 | Load | m461_6 |
|
||||
| ir.cpp:467:16:467:16 | Address | &:r467_4 |
|
||||
| ir.cpp:467:16:467:16 | Condition | r467_5 |
|
||||
| ir.cpp:467:11:467:16 | Address | &:r467_1 |
|
||||
| ir.cpp:467:11:467:16 | Address | &:r467_5 |
|
||||
| ir.cpp:467:11:467:16 | Address | &:r467_9 |
|
||||
| ir.cpp:467:11:467:16 | Load | m467_4 |
|
||||
| ir.cpp:467:11:467:16 | Phi | from 2:m467_3 |
|
||||
| ir.cpp:467:11:467:16 | Phi | from 4:m467_11 |
|
||||
| ir.cpp:467:11:467:16 | StoreValue | r467_2 |
|
||||
| ir.cpp:467:11:467:16 | StoreValue | r467_10 |
|
||||
| ir.cpp:467:11:467:16 | Unary | r467_6 |
|
||||
| ir.cpp:467:16:467:16 | Address | &:r467_15 |
|
||||
| ir.cpp:467:16:467:16 | Condition | r467_16 |
|
||||
| ir.cpp:467:16:467:16 | Load | m461_8 |
|
||||
| ir.cpp:468:9:468:9 | Address | &:r468_2 |
|
||||
| ir.cpp:468:13:468:13 | StoreValue | r468_1 |
|
||||
|
||||
@@ -2725,43 +2725,64 @@ ir.cpp:
|
||||
# 462| mu462_2(int) = Uninitialized[x] : &:r462_1
|
||||
# 463| r463_1(glval<bool>) = VariableAddress[a] :
|
||||
# 463| r463_2(bool) = Load[a] : &:r463_1, ~m?
|
||||
# 463| v463_3(void) = ConditionalBranch : r463_2
|
||||
#-----| False -> Block 1
|
||||
#-----| True -> Block 2
|
||||
# 463| r463_3(bool) = LogicalNot : r463_2
|
||||
# 463| v463_4(void) = ConditionalBranch : r463_3
|
||||
#-----| False -> Block 5
|
||||
#-----| True -> Block 1
|
||||
|
||||
# 464| Block 1
|
||||
# 464| r464_1(int) = Constant[1] :
|
||||
# 464| r464_2(glval<int>) = VariableAddress[x] :
|
||||
# 464| mu464_3(int) = Store[x] : &:r464_2, r464_1
|
||||
#-----| Goto -> Block 2
|
||||
#-----| Goto -> Block 5
|
||||
|
||||
# 467| Block 2
|
||||
# 467| r467_1(glval<bool>) = VariableAddress[a] :
|
||||
# 467| r467_2(bool) = Load[a] : &:r467_1, ~m?
|
||||
# 467| v467_3(void) = ConditionalBranch : r467_2
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 3
|
||||
# 467| r467_1(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_2(bool) = Constant[0] :
|
||||
# 467| mu467_3(bool) = Store[#temp467:11] : &:r467_1, r467_2
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 467| Block 3
|
||||
# 467| r467_4(glval<bool>) = VariableAddress[b] :
|
||||
# 467| r467_5(bool) = Load[b] : &:r467_4, ~m?
|
||||
# 467| v467_6(void) = ConditionalBranch : r467_5
|
||||
#-----| False -> Block 4
|
||||
#-----| True -> Block 5
|
||||
# 467| r467_4(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_5(bool) = Load[#temp467:11] : &:r467_4, ~m?
|
||||
# 467| r467_6(bool) = LogicalNot : r467_5
|
||||
# 467| v467_7(void) = ConditionalBranch : r467_6
|
||||
#-----| False -> Block 8
|
||||
#-----| True -> Block 7
|
||||
|
||||
# 468| Block 4
|
||||
# 467| Block 4
|
||||
# 467| r467_8(glval<bool>) = VariableAddress[#temp467:11] :
|
||||
# 467| r467_9(bool) = Constant[1] :
|
||||
# 467| mu467_10(bool) = Store[#temp467:11] : &:r467_8, r467_9
|
||||
#-----| Goto -> Block 3
|
||||
|
||||
# 467| Block 5
|
||||
# 467| r467_11(glval<bool>) = VariableAddress[a] :
|
||||
# 467| r467_12(bool) = Load[a] : &:r467_11, ~m?
|
||||
# 467| v467_13(void) = ConditionalBranch : r467_12
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 6
|
||||
|
||||
# 467| Block 6
|
||||
# 467| r467_14(glval<bool>) = VariableAddress[b] :
|
||||
# 467| r467_15(bool) = Load[b] : &:r467_14, ~m?
|
||||
# 467| v467_16(void) = ConditionalBranch : r467_15
|
||||
#-----| False -> Block 2
|
||||
#-----| True -> Block 4
|
||||
|
||||
# 468| Block 7
|
||||
# 468| r468_1(int) = Constant[2] :
|
||||
# 468| r468_2(glval<int>) = VariableAddress[x] :
|
||||
# 468| mu468_3(int) = Store[x] : &:r468_2, r468_1
|
||||
#-----| Goto -> Block 6
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 471| Block 5
|
||||
# 471| Block 8
|
||||
# 471| r471_1(int) = Constant[3] :
|
||||
# 471| r471_2(glval<int>) = VariableAddress[x] :
|
||||
# 471| mu471_3(int) = Store[x] : &:r471_2, r471_1
|
||||
#-----| Goto -> Block 6
|
||||
#-----| Goto -> Block 9
|
||||
|
||||
# 473| Block 6
|
||||
# 473| Block 9
|
||||
# 473| v473_1(void) = NoOp :
|
||||
# 461| v461_8(void) = ReturnVoid :
|
||||
# 461| v461_9(void) = AliasedUse : ~m?
|
||||
|
||||
@@ -480,7 +480,11 @@ module Public {
|
||||
class CallNode extends ExprNode {
|
||||
override CallExpr expr;
|
||||
|
||||
/** Gets the declared target of this call */
|
||||
/**
|
||||
* Gets the declared target of this call, if it exists.
|
||||
*
|
||||
* This doesn't exist when a function is called via a variable.
|
||||
*/
|
||||
Function getTarget() { result = expr.getTarget() }
|
||||
|
||||
private DataFlow::Node getACalleeSource() { result = getACalleeSource(this) }
|
||||
@@ -637,14 +641,41 @@ module Public {
|
||||
/** Gets a result of this call. */
|
||||
Node getAResult() { result = this.getResult(_) }
|
||||
|
||||
/** Gets the data flow node corresponding to the receiver of this call, if any. */
|
||||
/**
|
||||
* Gets the data flow node corresponding to the receiver of this call, if any.
|
||||
*
|
||||
* When a method value is assigned to a variable then when it is called it
|
||||
* looks like a function call, as in the following example.
|
||||
*
|
||||
* ```go
|
||||
* file, _ := os.Open("test.txt")
|
||||
* f := file.Close
|
||||
* f()
|
||||
* ```
|
||||
*
|
||||
* In this case we use local flow to try to find the receiver (`file` in
|
||||
* the above example).
|
||||
*/
|
||||
Node getReceiver() { result = this.getACalleeSource().(MethodReadNode).getReceiver() }
|
||||
|
||||
/** Holds if this call has an ellipsis after its last argument. */
|
||||
predicate hasEllipsis() { expr.hasEllipsis() }
|
||||
}
|
||||
|
||||
/** A data flow node that represents a call to a method. */
|
||||
/**
|
||||
* A data flow node that represents a direct call to a method.
|
||||
*
|
||||
* When a method value is assigned to a variable then when it is called it
|
||||
* syntactically looks like a function call, as in the following example.
|
||||
*
|
||||
* ```go
|
||||
* file, _ := os.Open("test.txt")
|
||||
* f := file.Close
|
||||
* f()
|
||||
* ```
|
||||
*
|
||||
* In this case it will not be considered a `MethodCallNode`.
|
||||
*/
|
||||
class MethodCallNode extends CallNode {
|
||||
MethodCallNode() { expr.getTarget() instanceof Method }
|
||||
|
||||
|
||||
4
javascript/ql/lib/change-notes/2023-11-23-sqllite.md
Normal file
4
javascript/ql/lib/change-notes/2023-11-23-sqllite.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added models for the `sqlite` and `better-sqlite3` npm packages.
|
||||
@@ -104,7 +104,7 @@ private module Postgres {
|
||||
API::Node clientOrPool() { result = API::Node::ofType("pg", ["Client", "PoolClient", "Pool"]) }
|
||||
|
||||
/** A call to the Postgres `query` method. */
|
||||
private class QueryCall extends DatabaseAccess, DataFlow::MethodCallNode {
|
||||
private class QueryCall extends DatabaseAccess, API::CallNode {
|
||||
QueryCall() { this = clientOrPool().getMember(["execute", "query"]).getACall() }
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
@@ -117,15 +117,25 @@ private module Postgres {
|
||||
PromiseFlow::loadStep(this.getALocalUse(), result, Promises::valueProp())
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
result = this.getArgument(0) or result = this.getParameter(0).getMember("text").asSink()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Postgres Query class.
|
||||
* This class can be used to create reusable query objects (see https://node-postgres.com/apis/client).
|
||||
*/
|
||||
API::Node query() { result = API::moduleImport("pg").getMember("Query") }
|
||||
|
||||
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() {
|
||||
this = any(QueryCall qc).getAQueryArgument()
|
||||
or
|
||||
this = API::moduleImport("pg-cursor").getParameter(0).asSink()
|
||||
or
|
||||
this = query().getParameter(0).asSink()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +253,7 @@ private module Postgres {
|
||||
/**
|
||||
* Provides classes modeling the `sqlite3` package.
|
||||
*/
|
||||
private module Sqlite {
|
||||
private module Sqlite3 {
|
||||
/** Gets an expression that constructs or returns a Sqlite database instance. */
|
||||
API::Node database() { result = API::Node::ofType("sqlite3", "Database") }
|
||||
|
||||
@@ -267,6 +277,62 @@ private module Sqlite {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `sqlite` package.
|
||||
*/
|
||||
private module Sqlite {
|
||||
/** Gets an expression that constructs or returns a Sqlite database instance. */
|
||||
API::Node database() {
|
||||
result = API::moduleImport("sqlite").getMember("open").getReturn().getPromised()
|
||||
}
|
||||
|
||||
/** A call to a Sqlite query method. */
|
||||
private class QueryCall extends DatabaseAccess, API::CallNode {
|
||||
QueryCall() {
|
||||
this = database().getMember(["all", "each", "exec", "get", "prepare", "run"]).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() { result = this }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() { this = any(QueryCall qc).getAQueryArgument() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `better-sqlite3` package.
|
||||
*/
|
||||
private module BetterSqlite3 {
|
||||
/**
|
||||
* Gets a `better-sqlite3` database instance.
|
||||
*/
|
||||
API::Node database() {
|
||||
result =
|
||||
[
|
||||
API::moduleImport("better-sqlite3").getInstance(),
|
||||
API::moduleImport("better-sqlite3").getReturn()
|
||||
]
|
||||
or
|
||||
result = database().getMember("exec").getReturn()
|
||||
}
|
||||
|
||||
/** A call to a better-sqlite3 query method. */
|
||||
private class QueryCall extends DatabaseAccess, API::CallNode {
|
||||
QueryCall() { this = database().getMember(["exec", "prepare"]).getACall() }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** An expression that is passed to the `query` method and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() { this = any(QueryCall qc).getAQueryArgument() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides classes modeling the `mssql` package.
|
||||
*/
|
||||
|
||||
157
javascript/ql/src/experimental/semmle/javascript/SQL.qll
Normal file
157
javascript/ql/src/experimental/semmle/javascript/SQL.qll
Normal file
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* Provides classes for working with SQL connectors.
|
||||
*/
|
||||
|
||||
import javascript
|
||||
|
||||
module ExperimentalSql {
|
||||
/**
|
||||
* Provides SQL injection Sinks for the [TypeORM](https://www.npmjs.com/package/typeorm) package
|
||||
*/
|
||||
private module TypeOrm {
|
||||
/**
|
||||
* Gets a `DataSource` instance
|
||||
*
|
||||
* `DataSource` is a pre-defined connection configuration to a specific database.
|
||||
*/
|
||||
API::Node dataSource() {
|
||||
result = API::moduleImport("typeorm").getMember("DataSource").getInstance()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `QueryRunner` instance
|
||||
*/
|
||||
API::Node queryRunner() { result = dataSource().getMember("createQueryRunner").getReturn() }
|
||||
|
||||
/**
|
||||
* Gets a `*QueryBuilder` instance
|
||||
*/
|
||||
API::Node queryBuilderInstance() {
|
||||
// a `*QueryBuilder` instance of a Data Mapper based Entity
|
||||
result =
|
||||
[
|
||||
// Using DataSource
|
||||
dataSource(),
|
||||
// Using repository
|
||||
dataSource().getMember("getRepository").getReturn(),
|
||||
// Using entity manager
|
||||
dataSource().getMember("manager"), queryRunner().getMember("manager")
|
||||
].getMember("createQueryBuilder").getReturn()
|
||||
or
|
||||
// A `*QueryBuilder` instance of an Active record based Entity
|
||||
result =
|
||||
API::moduleImport("typeorm")
|
||||
.getMember("Entity")
|
||||
.getReturn()
|
||||
.getADecoratedClass()
|
||||
.getMember("createQueryBuilder")
|
||||
.getReturn()
|
||||
or
|
||||
// A WhereExpressionBuilder can be used in complex WHERE expression
|
||||
result =
|
||||
API::moduleImport("typeorm")
|
||||
.getMember(["Brackets", "NotBrackets"])
|
||||
.getParameter(0)
|
||||
.getParameter(0)
|
||||
or
|
||||
// In case of custom query builders
|
||||
result =
|
||||
API::moduleImport("typeorm")
|
||||
.getMember([
|
||||
"SelectQueryBuilder", "InsertQueryBuilder", "RelationQueryBuilder",
|
||||
"UpdateQueryBuilder", "WhereExpressionBuilder"
|
||||
])
|
||||
.getInstance()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets function names which create any type of `QueryBuilder` like `WhereExpressionBuilder` or `InsertQueryBuilder`
|
||||
*/
|
||||
string queryBuilderMethods() {
|
||||
result =
|
||||
[
|
||||
"select", "addSelect", "where", "andWhere", "orWhere", "having", "orHaving", "andHaving",
|
||||
"orderBy", "addOrderBy", "distinctOn", "groupBy", "addCommonTableExpression",
|
||||
"leftJoinAndSelect", "innerJoinAndSelect", "leftJoin", "innerJoin", "leftJoinAndMapOne",
|
||||
"innerJoinAndMapOne", "leftJoinAndMapMany", "innerJoinAndMapMany", "orUpdate", "orIgnore",
|
||||
"values", "set"
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets function names that the return values of these functions can be the results of a database query run
|
||||
*/
|
||||
string queryBuilderResult() {
|
||||
result = ["getOne", "getOneOrFail", "getMany", "getRawOne", "getRawMany", "stream"]
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a QueryBuilder instance that has a query builder function
|
||||
*/
|
||||
API::Node getASuccessorOfBuilderInstance(string queryBuilderMethod) {
|
||||
result.getMember(queryBuilderMethod) = queryBuilderInstance().getASuccessor*()
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to some successor functions of TypeORM `createQueryBuilder` function which are dangerous
|
||||
*/
|
||||
private class QueryBuilderCall extends DatabaseAccess, DataFlow::Node {
|
||||
API::Node queryBuilder;
|
||||
|
||||
QueryBuilderCall() {
|
||||
queryBuilder = getASuccessorOfBuilderInstance(queryBuilderMethods()) and
|
||||
this = queryBuilder.asSource()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAResult() {
|
||||
result = queryBuilder.getMember(queryBuilderResult()).getReturn().asSource()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAQueryArgument() {
|
||||
exists(string memberName | memberName = queryBuilderMethods() |
|
||||
memberName = ["leftJoinAndSelect", "innerJoinAndSelect", "leftJoin", "innerJoin"] and
|
||||
result = queryBuilder.getMember(memberName).getParameter(2).asSink()
|
||||
or
|
||||
memberName =
|
||||
["leftJoinAndMapOne", "innerJoinAndMapOne", "leftJoinAndMapMany", "innerJoinAndMapMany"] and
|
||||
result = queryBuilder.getMember(memberName).getParameter(3).asSink()
|
||||
or
|
||||
memberName =
|
||||
[
|
||||
"select", "addSelect", "where", "andWhere", "orWhere", "having", "orHaving",
|
||||
"andHaving", "orderBy", "addOrderBy", "distinctOn", "groupBy",
|
||||
"addCommonTableExpression"
|
||||
] and
|
||||
result = queryBuilder.getMember(memberName).getParameter(0).asSink()
|
||||
or
|
||||
memberName = ["orIgnore", "orUpdate"] and
|
||||
result = queryBuilder.getMember(memberName).getParameter([0, 1]).asSink()
|
||||
or
|
||||
// following functions if use a function as their input fields,called function parameters which are vulnerable
|
||||
memberName = ["values", "set"] and
|
||||
result =
|
||||
queryBuilder.getMember(memberName).getParameter(0).getAMember().getReturn().asSink()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to the TypeORM `query` function of a `QueryRunner`
|
||||
*/
|
||||
private class QueryRunner extends DatabaseAccess, API::CallNode {
|
||||
QueryRunner() { queryRunner().getMember("query").getACall() = this }
|
||||
|
||||
override DataFlow::Node getAResult() { result = this }
|
||||
|
||||
override DataFlow::Node getAQueryArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/** An expression that is passed to the `query` function and hence interpreted as SQL. */
|
||||
class QueryString extends SQL::SqlString {
|
||||
QueryString() {
|
||||
this = any(QueryRunner qr).getAQueryArgument() or
|
||||
this = any(QueryBuilderCall qb).getAQueryArgument()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
220
javascript/ql/test/experimental/TypeOrm/test.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import {
|
||||
BaseEntity, Brackets, DataSource, JoinColumn, NotBrackets
|
||||
, OneToOne, Entity, PrimaryGeneratedColumn, Column, SelectQueryBuilder, InsertQueryBuilder
|
||||
} from "typeorm";
|
||||
|
||||
@Entity()
|
||||
export class UserActiveRecord extends BaseEntity {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
static findByName(firstName: string, lastName: string) {
|
||||
return this.createQueryBuilder("user")
|
||||
.where("user.firstName = " + firstName) // test: SQLInjectionPoint
|
||||
.andWhere("user.lastName = " + lastName) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
}
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class Profile {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
gender: string
|
||||
@Column()
|
||||
photo: string
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
name: string
|
||||
@OneToOne(() => Profile)
|
||||
@JoinColumn()
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
@Entity()
|
||||
export class User2 {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number
|
||||
@Column()
|
||||
firstName: string
|
||||
@Column()
|
||||
lastName: string
|
||||
@Column()
|
||||
age: number
|
||||
|
||||
}
|
||||
|
||||
export const AppDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: "database.sqlite",
|
||||
synchronize: true,
|
||||
logging: false,
|
||||
entities: [User, User2, Profile, UserActiveRecord],
|
||||
migrations: [],
|
||||
subscribers: [],
|
||||
})
|
||||
|
||||
function makePaginationQuery<T>(q: SelectQueryBuilder<T>): SelectQueryBuilder<T> {
|
||||
return q;
|
||||
}
|
||||
|
||||
AppDataSource.initialize().then(async () => {
|
||||
const BadInput = "A user controllable Remote Source like `' 1=1 --` "
|
||||
|
||||
// Active record
|
||||
await UserActiveRecord.findByName(BadInput, "Saw")
|
||||
|
||||
// data mapper
|
||||
const selectQueryBuilder = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User").select());
|
||||
selectQueryBuilder.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const selectQueryBuilder2 = makePaginationQuery<User>(AppDataSource
|
||||
.createQueryBuilder(User, "User"));
|
||||
selectQueryBuilder2.where(BadInput).getMany().then(result => { // test: SQLInjectionPoint
|
||||
console.log(result)
|
||||
});
|
||||
|
||||
const insertQueryBuilder: InsertQueryBuilder<User2> = AppDataSource
|
||||
.createQueryBuilder(User2, "User2").insert();
|
||||
insertQueryBuilder.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
}).execute().then(result => {
|
||||
console.log(result)
|
||||
|
||||
|
||||
})
|
||||
|
||||
AppDataSource
|
||||
.createQueryBuilder(User2, "User")
|
||||
.insert()
|
||||
.into(User2)
|
||||
.values({
|
||||
firstName: "Timber",
|
||||
lastName: () => BadInput, // test: SQLInjectionPoint
|
||||
age: 33,
|
||||
})
|
||||
.orUpdate(
|
||||
[BadInput, BadInput], // test: SQLInjectionPoint
|
||||
[BadInput], // test: SQLInjectionPoint
|
||||
)
|
||||
.getQueryAndParameters()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("user2")
|
||||
.update(User2)
|
||||
.set({ firstName: () => BadInput, lastName: "Saw2", age: 12 }) // test: SQLInjectionPoint
|
||||
.where(BadInput,) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder('user2')
|
||||
.delete()
|
||||
.from(User2)
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.execute()
|
||||
|
||||
|
||||
const queryRunner = AppDataSource.createQueryRunner()
|
||||
await queryRunner.query(BadInput) // test: SQLInjectionPoint
|
||||
|
||||
await queryRunner.manager
|
||||
.createQueryBuilder(User2, "User")
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.where(BadInput).execute() // test: SQLInjectionPoint
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.innerJoin("User.profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User, "User")
|
||||
.leftJoinAndMapOne("User.profile", "profile", "profile", BadInput, { // test: SQLInjectionPoint
|
||||
id: 2,
|
||||
}).getMany().then(res => console.log(res))
|
||||
|
||||
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.where((qb) => {
|
||||
const subQuery = qb
|
||||
.subQuery()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "user2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.getQuery()
|
||||
return "User2.id IN " + subQuery
|
||||
})
|
||||
.setParameter("registered", true)
|
||||
.getMany()
|
||||
|
||||
|
||||
// Using repository
|
||||
await AppDataSource.getRepository(User2).createQueryBuilder("User2").where("User2.id =:kind" + BadInput, { kind: 1 }).getMany()
|
||||
|
||||
// Using DataSource
|
||||
await AppDataSource
|
||||
.createQueryBuilder()
|
||||
.select(BadInput) // test: SQLInjectionPoint
|
||||
.from(User2, "User2")
|
||||
.where(BadInput, { id: 1 }) // test: SQLInjectionPoint
|
||||
.getMany()
|
||||
|
||||
// Using entity manager
|
||||
await AppDataSource.manager
|
||||
.createQueryBuilder(User2, "User2").where("User2.id =:kind" + BadInput, { kind: '1' }).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2")
|
||||
.leftJoinAndSelect("user.photos", "photo", BadInput).getMany() // test: SQLInjectionPoint
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").groupBy("User2.id").having(BadInput).getMany() // test: SQLInjectionPoint
|
||||
// orderBy
|
||||
// it is a little bit restrictive, e.g. sqlite don't support it at all
|
||||
await AppDataSource
|
||||
.createQueryBuilder(User2, "User2").where(BadInput, { // test: SQLInjectionPoint
|
||||
firstName: "Timber",
|
||||
})
|
||||
.where(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
)
|
||||
.orderBy(BadInput).orWhere(BadInput).getMany() // test: SQLInjectionPoint
|
||||
|
||||
// relation
|
||||
AppDataSource.createQueryBuilder().relation(User, "name")
|
||||
.of(User)
|
||||
.select().where(BadInput).getMany().then(results => { // test: SQLInjectionPoint
|
||||
console.log(results)
|
||||
})
|
||||
|
||||
// Brackets
|
||||
await AppDataSource.createQueryBuilder(User2, "User2")
|
||||
.where(BadInput) // test: SQLInjectionPoint
|
||||
.andWhere(
|
||||
new Brackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput); // test: SQLInjectionPoint
|
||||
})
|
||||
).andWhere(
|
||||
new NotBrackets((qb) => {
|
||||
qb.where(BadInput).orWhere(BadInput) // test: SQLInjectionPoint
|
||||
}),
|
||||
).getMany()
|
||||
}).catch(error => console.log(error))
|
||||
32
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
32
javascript/ql/test/experimental/TypeOrm/tests.expected
Normal file
@@ -0,0 +1,32 @@
|
||||
passingPositiveTests
|
||||
| PASSED | SQLInjectionPoint | test.ts:19:54:19:79 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:20:55:20:80 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:82:70:82:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:88:70:88:95 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:97:41:97:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:111:41:111:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:115:37:115:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:116:27:116:52 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:122:74:122:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:123:29:123:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:129:28:129:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:134:41:134:66 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:138:29:138:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:139:38:139:63 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:143:61:143:86 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:149:80:149:105 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:159:37:159:62 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:161:36:161:61 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:175:29:175:54 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:177:39:177:64 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:182:108:182:133 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:185:74:185:99 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:187:94:187:119 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:191:65:191:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:196:57:196:82 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:199:58:199:83 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:204:65:204:90 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:210:28:210:53 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:213:56:213:81 | // test ... onPoint |
|
||||
| PASSED | SQLInjectionPoint | test.ts:217:56:217:81 | // test ... onPoint |
|
||||
failingPositiveTests
|
||||
34
javascript/ql/test/experimental/TypeOrm/tests.ql
Normal file
34
javascript/ql/test/experimental/TypeOrm/tests.ql
Normal file
@@ -0,0 +1,34 @@
|
||||
import javascript
|
||||
|
||||
class InlineTest extends LineComment {
|
||||
string tests;
|
||||
|
||||
InlineTest() { tests = this.getText().regexpCapture("\\s*test:(.*)", 1) }
|
||||
|
||||
string getPositiveTest() {
|
||||
result = tests.trim().splitAt(",").trim() and not result.matches("!%")
|
||||
}
|
||||
|
||||
predicate hasPositiveTest(string test) { test = this.getPositiveTest() }
|
||||
|
||||
predicate inNode(DataFlow::Node n) {
|
||||
this.getLocation().getFile() = n.getFile() and
|
||||
this.getLocation().getStartLine() = n.getStartLine()
|
||||
}
|
||||
}
|
||||
|
||||
import experimental.semmle.javascript.SQL
|
||||
|
||||
query predicate passingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "PASSED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "SQLInjectionPoint" and
|
||||
exists(SQL::SqlString n | t.inNode(n))
|
||||
}
|
||||
|
||||
query predicate failingPositiveTests(string res, string expectation, InlineTest t) {
|
||||
res = "FAILED" and
|
||||
t.hasPositiveTest(expectation) and
|
||||
expectation = "SQLInjectionPoint" and
|
||||
not exists(SQL::SqlString n | t.inNode(n))
|
||||
}
|
||||
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
15
javascript/ql/test/experimental/TypeOrm/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"es5",
|
||||
"es6"
|
||||
],
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "./build",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@
|
||||
| postgres2.js:12:13:12:20 | 'secret' | password |
|
||||
| postgres4.js:4:9:4:16 | 'dbuser' | user name |
|
||||
| postgres4.js:7:13:7:28 | 'secretpassword' | password |
|
||||
| postgres6.js:8:11:8:20 | 'postgres' | user name |
|
||||
| sequelize2.js:4:45:9:1 | {\\n dia ... word'\\n} | user name |
|
||||
| sequelize2.js:7:13:7:22 | 'username' | user name |
|
||||
| sequelize2.js:8:13:8:22 | 'password' | password |
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
| better-sqlite3.js:6:23:6:25 | sql |
|
||||
| better-sqlite3.js:7:20:7:22 | sql |
|
||||
| better-sqlite3.js:8:14:8:16 | sql |
|
||||
| better-sqlite3.js:12:20:12:22 | sql |
|
||||
| better-sqlite3.js:13:17:13:19 | sql |
|
||||
| better-sqlite3.js:14:14:14:16 | sql |
|
||||
| mssql1.js:7:40:7:72 | select ... e id = |
|
||||
| mssql1.js:7:75:7:79 | value |
|
||||
| mssql1.js:10:19:10:30 | 'SELECT 123' |
|
||||
@@ -32,6 +38,9 @@
|
||||
| postgres2.js:46:26:46:46 | 'SELECT ... users' |
|
||||
| postgres3.js:15:16:15:40 | 'SELECT ... s name' |
|
||||
| postgres5.js:8:21:8:25 | query |
|
||||
| postgres6.js:13:11:13:44 | 'SELECT ... E id=6' |
|
||||
| postgres6.js:16:20:16:27 | queryObj |
|
||||
| postgres6.js:18:11:18:44 | 'SELECT ... E id=7' |
|
||||
| postgres-types.ts:4:18:4:29 | 'SELECT 123' |
|
||||
| postgresImport.js:4:18:4:43 | 'SELECT ... number' |
|
||||
| sequelize2.js:10:17:10:118 | 'SELECT ... Y name' |
|
||||
@@ -70,8 +79,12 @@
|
||||
| spanner.js:26:12:26:38 | 'UPDATE ... = @baz' |
|
||||
| spanner.js:31:18:31:24 | queries |
|
||||
| spannerImport.js:4:8:4:17 | "SQL code" |
|
||||
| sqlite3.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
| sqlite3.js:8:8:8:45 | "UPDATE ... id = ?" |
|
||||
| sqlite-types.ts:4:12:4:49 | "UPDATE ... id = ?" |
|
||||
| sqlite.js:7:8:7:45 | "UPDATE ... id = ?" |
|
||||
| sqlite.js:8:8:8:45 | "UPDATE ... id = ?" |
|
||||
| sqlite.js:8:10:8:65 | 'SELECT ... id = 1" |
|
||||
| sqlite.js:11:10:11:65 | 'SELECT ... id = 1" |
|
||||
| sqlite.js:14:10:14:50 | 'SELECT ... id > 5' |
|
||||
| sqlite.js:17:14:18:18 | 'SELECT ... id = 1" |
|
||||
| sqlite.js:24:19:24:74 | 'SELECT ... id = 1" |
|
||||
| sqliteArray.js:6:12:6:49 | "UPDATE ... id = ?" |
|
||||
| sqliteImport.js:2:8:2:44 | "UPDATE ... id = ?" |
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import Database from 'better-sqlite3';
|
||||
|
||||
const db = new Database('BetterSqlite.db', { verbose: console.log });
|
||||
|
||||
let sql = 'SELECT name, id FROM table1'
|
||||
let stmt = db.prepare(sql);
|
||||
let exec = db.exec(sql);
|
||||
exec.prepare(sql)
|
||||
const db2 = Database('BetterSqlite.db', { verbose: console.log });
|
||||
|
||||
sql = 'SELECT name, id FROM table1'
|
||||
stmt = db2.prepare(sql);
|
||||
exec = db2.exec(sql);
|
||||
exec.prepare(sql)
|
||||
18
javascript/ql/test/library-tests/frameworks/SQL/postgres6.js
Normal file
18
javascript/ql/test/library-tests/frameworks/SQL/postgres6.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import pkg from 'pg';
|
||||
|
||||
const { Query, Client } = pkg;
|
||||
const client = new Client({
|
||||
host: '127.0.0.1',
|
||||
port: 5432,
|
||||
database: 'testsqli',
|
||||
user: 'postgres'
|
||||
})
|
||||
|
||||
const queryObj = {
|
||||
name: 'get-name',
|
||||
text: 'SELECT * FROM "user" WHERE id=6'
|
||||
}
|
||||
|
||||
await client.query(queryObj) // Already Implemented
|
||||
|
||||
new Query('SELECT * FROM "user" WHERE id=7')
|
||||
@@ -1,10 +1,33 @@
|
||||
// Adapted from https://github.com/mapbox/node-sqlite3/wiki/API, which is
|
||||
// part of the node-sqlite3 project, which is licensed under the BSD 3-Clause
|
||||
// License; see file node-sqlite3-LICENSE.
|
||||
var sqlite = require('sqlite3');
|
||||
import sqlite3 from 'sqlite3'
|
||||
import { open } from 'sqlite'
|
||||
|
||||
open({
|
||||
filename: 'database.sqlite',
|
||||
driver: sqlite3.Database
|
||||
}).then(async (db) => {
|
||||
db.get('SELECT name,id FROM table1 WHERE id > 5' + " OR id = 1").then(results => {
|
||||
console.log(results)
|
||||
})
|
||||
db.all('SELECT name,id FROM table1 WHERE id > 5' + " OR id = 1").then(results => {
|
||||
console.log(results)
|
||||
})
|
||||
db.run('SELECT name,id FROM table1 WHERE id > 5').then(results => {
|
||||
console.log(results)
|
||||
})
|
||||
db.prepare('SELECT name,id FROM table1 WHERE id > 5'
|
||||
+ " OR id = 1").then(results => {
|
||||
results.all().then(result => {
|
||||
console.log(result)
|
||||
})
|
||||
})
|
||||
try {
|
||||
await db.each('SELECT name,id FROM table1 WHERE id > 5' + " OR id = 1", (err, row) => {
|
||||
console.log(row)
|
||||
})
|
||||
|
||||
} catch (e) {
|
||||
throw e
|
||||
}
|
||||
})
|
||||
|
||||
var db = new sqlite.Database(":memory:");
|
||||
db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2)
|
||||
.run("UPDATE tbl SET name = ? WHERE id = ?", "foo", 3);
|
||||
|
||||
exports.db = db;
|
||||
|
||||
10
javascript/ql/test/library-tests/frameworks/SQL/sqlite3.js
Normal file
10
javascript/ql/test/library-tests/frameworks/SQL/sqlite3.js
Normal file
@@ -0,0 +1,10 @@
|
||||
// Adapted from https://github.com/mapbox/node-sqlite3/wiki/API, which is
|
||||
// part of the node-sqlite3 project, which is licensed under the BSD 3-Clause
|
||||
// License; see file node-sqlite3-LICENSE.
|
||||
var sqlite = require('sqlite3');
|
||||
|
||||
var db = new sqlite.Database(":memory:");
|
||||
db.run("UPDATE tbl SET name = ? WHERE id = ?", "bar", 2)
|
||||
.run("UPDATE tbl SET name = ? WHERE id = ?", "foo", 3);
|
||||
|
||||
exports.db = db;
|
||||
@@ -114,6 +114,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
|
||||
description=prop.description,
|
||||
synth=bool(cls.synth) or prop.synth,
|
||||
type_is_hideable=lookup[prop.type].hideable if prop.type in lookup else False,
|
||||
internal="ql_internal" in prop.pragmas,
|
||||
)
|
||||
if prop.is_single:
|
||||
args.update(
|
||||
@@ -151,7 +152,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, lookup: typing.Dic
|
||||
|
||||
|
||||
def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> ql.Class:
|
||||
pragmas = {k: True for k in cls.pragmas if k.startswith("ql")}
|
||||
pragmas = {k: True for k in cls.pragmas if k.startswith("qltest")}
|
||||
prev_child = ""
|
||||
properties = []
|
||||
for p in cls.properties:
|
||||
@@ -167,6 +168,7 @@ def get_ql_class(cls: schema.Class, lookup: typing.Dict[str, schema.Class]) -> q
|
||||
dir=pathlib.Path(cls.group or ""),
|
||||
doc=cls.doc,
|
||||
hideable=cls.hideable,
|
||||
internal="ql_internal" in cls.pragmas,
|
||||
**pragmas,
|
||||
)
|
||||
|
||||
@@ -313,13 +315,13 @@ def _get_stub(cls: schema.Class, base_import: str, generated_import_prefix: str)
|
||||
accessors = []
|
||||
return ql.Stub(name=cls.name, base_import=base_import, import_prefix=generated_import_prefix,
|
||||
doc=cls.doc, synth_accessors=accessors,
|
||||
ql_internal="ql_internal" in cls.pragmas)
|
||||
internal="ql_internal" in cls.pragmas)
|
||||
|
||||
|
||||
_stub_qldoc_header = "// the following QLdoc is generated: if you need to edit it, do it in the schema file\n"
|
||||
|
||||
_class_qldoc_re = re.compile(
|
||||
rf"(?P<qldoc>(?:{re.escape(_stub_qldoc_header)})?/\*\*.*?\*/\s*|^\s*)class\s+(?P<class>\w+)",
|
||||
rf"(?P<qldoc>(?:{re.escape(_stub_qldoc_header)})?/\*\*.*?\*/\s*|^\s*)(?:class\s+(?P<class>\w+))?",
|
||||
re.MULTILINE | re.DOTALL)
|
||||
|
||||
|
||||
@@ -397,7 +399,7 @@ def generate(opts, renderer):
|
||||
_patch_class_qldoc(c.name, qldoc, stub_file)
|
||||
|
||||
# for example path/to/elements -> path/to/elements.qll
|
||||
renderer.render(ql.ImportList([i for name, i in imports.items() if not classes[name].ql_internal]),
|
||||
renderer.render(ql.ImportList([i for name, i in imports.items() if not classes[name].internal]),
|
||||
include_file)
|
||||
|
||||
elements_module = get_import(include_file, opts.root_dir)
|
||||
@@ -405,7 +407,7 @@ def generate(opts, renderer):
|
||||
renderer.render(
|
||||
ql.GetParentImplementation(
|
||||
classes=list(classes.values()),
|
||||
imports=[elements_module] + [i for name, i in imports.items() if classes[name].ql_internal],
|
||||
imports=[elements_module] + [i for name, i in imports.items() if classes[name].internal],
|
||||
),
|
||||
out / 'ParentChild.qll')
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class Property:
|
||||
doc_plural: Optional[str] = None
|
||||
synth: bool = False
|
||||
type_is_hideable: bool = False
|
||||
internal: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
if self.tableparams:
|
||||
@@ -80,10 +81,6 @@ class Property:
|
||||
def is_child(self):
|
||||
return self.prev_child is not None
|
||||
|
||||
@property
|
||||
def has_description(self) -> bool:
|
||||
return bool(self.description)
|
||||
|
||||
@property
|
||||
def is_indexed(self) -> bool:
|
||||
return self.is_repeated and not self.is_unordered
|
||||
@@ -112,7 +109,7 @@ class Class:
|
||||
qltest_skip: bool = False
|
||||
qltest_collapse_hierarchy: bool = False
|
||||
qltest_uncollapse_hierarchy: bool = False
|
||||
ql_internal: bool = False
|
||||
internal: bool = False
|
||||
doc: List[str] = field(default_factory=list)
|
||||
hideable: bool = False
|
||||
|
||||
@@ -162,7 +159,7 @@ class Stub:
|
||||
base_import: str
|
||||
import_prefix: str
|
||||
synth_accessors: List[SynthUnderlyingAccessor] = field(default_factory=list)
|
||||
ql_internal: bool = False
|
||||
internal: bool = False
|
||||
doc: List[str] = field(default_factory=list)
|
||||
|
||||
@property
|
||||
@@ -171,7 +168,7 @@ class Stub:
|
||||
|
||||
@property
|
||||
def has_qldoc(self) -> bool:
|
||||
return bool(self.doc) or self.ql_internal
|
||||
return bool(self.doc) or self.internal
|
||||
|
||||
|
||||
@dataclass
|
||||
|
||||
@@ -71,6 +71,9 @@ module Generated {
|
||||
* {{>ql_property_doc}} *
|
||||
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
|
||||
* behavior of both the `Immediate` and non-`Immediate` versions.
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
{{type}} get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{^synth}}
|
||||
@@ -83,11 +86,12 @@ module Generated {
|
||||
|
||||
/**
|
||||
* {{>ql_property_doc}} *
|
||||
{{#has_description}}
|
||||
{{#description}}
|
||||
* {{.}}
|
||||
{{/description}}
|
||||
{{/has_description}}
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
final {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
exists({{type}} immediate | immediate = this.get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}index{{/is_indexed}}) and
|
||||
@@ -98,11 +102,12 @@ module Generated {
|
||||
{{^type_is_hideable}}
|
||||
/**
|
||||
* {{>ql_property_doc}} *
|
||||
{{#has_description}}
|
||||
{{#description}}
|
||||
* {{.}}
|
||||
{{/description}}
|
||||
{{/has_description}}
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{^synth}}
|
||||
@@ -117,6 +122,9 @@ module Generated {
|
||||
{{#is_optional}}
|
||||
/**
|
||||
* Holds if `{{getter}}({{#is_repeated}}index{{/is_repeated}})` exists.
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
final predicate has{{singular}}({{#is_repeated}}int index{{/is_repeated}}) {
|
||||
exists(this.{{getter}}({{#is_repeated}}index{{/is_repeated}}))
|
||||
@@ -126,6 +134,9 @@ module Generated {
|
||||
|
||||
/**
|
||||
* Gets any of the {{doc_plural}}.
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
final {{type}} {{indefinite_getter}}() {
|
||||
result = this.{{getter}}(_)
|
||||
@@ -134,6 +145,9 @@ module Generated {
|
||||
|
||||
/**
|
||||
* Gets the number of {{doc_plural}}.
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
final int getNumberOf{{plural}}() {
|
||||
result = count(int i | exists(this.{{getter}}(i)))
|
||||
@@ -143,6 +157,9 @@ module Generated {
|
||||
{{#is_unordered}}
|
||||
/**
|
||||
* Gets the number of {{doc_plural}}.
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/internal}}
|
||||
*/
|
||||
final int getNumberOf{{plural}}() {
|
||||
result = count(this.{{getter}}())
|
||||
|
||||
@@ -18,11 +18,9 @@ module Raw {
|
||||
{{^synth}}
|
||||
/**
|
||||
* {{>ql_property_doc}} *
|
||||
{{#has_description}}
|
||||
{{#description}}
|
||||
* {{.}}
|
||||
{{/description}}
|
||||
{{/has_description}}
|
||||
*/
|
||||
{{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) {
|
||||
{{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}})
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
{{#doc}}
|
||||
* {{.}}
|
||||
{{/doc}}
|
||||
{{#ql_internal}}
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/ql_internal}}
|
||||
{{/internal}}
|
||||
*/
|
||||
{{/has_qldoc}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `{{name}}`.
|
||||
{{#ql_internal}}
|
||||
{{#internal}}
|
||||
* INTERNAL: Do not use.
|
||||
{{/ql_internal}}
|
||||
{{/internal}}
|
||||
*/
|
||||
|
||||
@@ -147,28 +147,18 @@ def test_class_with_children():
|
||||
assert cls.has_children is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize("doc,ql_internal,expected",
|
||||
@pytest.mark.parametrize("doc,internal,expected",
|
||||
[
|
||||
(["foo", "bar"], False, True),
|
||||
(["foo", "bar"], True, True),
|
||||
([], False, False),
|
||||
([], True, True),
|
||||
])
|
||||
def test_has_doc(doc, ql_internal, expected):
|
||||
stub = ql.Stub("Class", base_import="foo", import_prefix="bar", doc=doc, ql_internal=ql_internal)
|
||||
def test_has_doc(doc, internal, expected):
|
||||
stub = ql.Stub("Class", base_import="foo", import_prefix="bar", doc=doc, internal=internal)
|
||||
assert stub.has_qldoc is expected
|
||||
|
||||
|
||||
def test_property_with_description():
|
||||
prop = ql.Property("X", "int", description=["foo", "bar"])
|
||||
assert prop.has_description is True
|
||||
|
||||
|
||||
def test_class_without_description():
|
||||
prop = ql.Property("X", "int")
|
||||
assert prop.has_description is False
|
||||
|
||||
|
||||
def test_synth_accessor_has_first_constructor_param_marked():
|
||||
params = ["a", "b", "c"]
|
||||
x = ql.SynthUnderlyingAccessor("foo", "bar", params)
|
||||
|
||||
@@ -157,8 +157,8 @@ def test_one_empty_internal_class(generate_classes):
|
||||
assert generate_classes([
|
||||
schema.Class("A", pragmas=["ql_internal"])
|
||||
]) == {
|
||||
"A.qll": (a_ql_stub(name="A", ql_internal=True),
|
||||
a_ql_class(name="A", final=True, ql_internal=True)),
|
||||
"A.qll": (a_ql_stub(name="A", internal=True),
|
||||
a_ql_class(name="A", final=True, internal=True)),
|
||||
}
|
||||
|
||||
|
||||
@@ -202,11 +202,11 @@ def test_hierarchy_children(generate_children_implementations):
|
||||
schema.Class("C", bases=["A"], derived={"D"}, pragmas=["ql_internal"]),
|
||||
schema.Class("D", bases=["B", "C"]),
|
||||
]) == ql.GetParentImplementation(
|
||||
classes=[a_ql_class(name="A", ql_internal=True),
|
||||
classes=[a_ql_class(name="A", internal=True),
|
||||
a_ql_class(name="B", bases=["A"], imports=[
|
||||
stub_import_prefix + "A"]),
|
||||
a_ql_class(name="C", bases=["A"], imports=[
|
||||
stub_import_prefix + "A"], ql_internal=True),
|
||||
stub_import_prefix + "A"], internal=True),
|
||||
a_ql_class(name="D", final=True, bases=["B", "C"],
|
||||
imports=[stub_import_prefix + cls for cls in "BC"]),
|
||||
],
|
||||
@@ -228,6 +228,21 @@ def test_single_property(generate_classes):
|
||||
}
|
||||
|
||||
|
||||
def test_internal_property(generate_classes):
|
||||
assert generate_classes([
|
||||
schema.Class("MyObject", properties=[
|
||||
schema.SingleProperty("foo", "bar", pragmas=["ql_internal"])]),
|
||||
]) == {
|
||||
"MyObject.qll": (a_ql_stub(name="MyObject"),
|
||||
a_ql_class(name="MyObject", final=True,
|
||||
properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects",
|
||||
tableparams=["this", "result"], doc="foo of this my object",
|
||||
internal=True),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
def test_children(generate_classes):
|
||||
assert generate_classes([
|
||||
schema.Class("FakeRoot"),
|
||||
@@ -424,7 +439,8 @@ def test_class_dir(generate_classes):
|
||||
schema.Class("A", derived={"B"}, group=dir),
|
||||
schema.Class("B", bases=["A"]),
|
||||
]) == {
|
||||
f"{dir}/A.qll": (a_ql_stub(name="A", import_prefix="another.rel.path."), a_ql_class(name="A", dir=pathlib.Path(dir))),
|
||||
f"{dir}/A.qll": (
|
||||
a_ql_stub(name="A", import_prefix="another.rel.path."), a_ql_class(name="A", dir=pathlib.Path(dir))),
|
||||
"B.qll": (a_ql_stub(name="B"),
|
||||
a_ql_class(name="B", final=True, bases=["A"],
|
||||
imports=[stub_import_prefix + "another.rel.path.A"])),
|
||||
@@ -878,9 +894,9 @@ def test_stub_on_class_with_synth_from_class(generate_classes):
|
||||
ql.SynthUnderlyingAccessor(argument="Entity", type="Raw::A", constructorparams=["result"]),
|
||||
]),
|
||||
a_ql_class(name="MyObject", final=True, properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects", synth=True,
|
||||
tableparams=["this", "result"], doc="foo of this my object"),
|
||||
])),
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects", synth=True,
|
||||
tableparams=["this", "result"], doc="foo of this my object"),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
@@ -895,9 +911,9 @@ def test_stub_on_class_with_synth_on_arguments(generate_classes):
|
||||
ql.SynthUnderlyingAccessor(argument="Label", type="string", constructorparams=["_", "_", "result"]),
|
||||
]),
|
||||
a_ql_class(name="MyObject", final=True, properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects", synth=True,
|
||||
tableparams=["this", "result"], doc="foo of this my object"),
|
||||
])),
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects", synth=True,
|
||||
tableparams=["this", "result"], doc="foo of this my object"),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
@@ -909,7 +925,8 @@ def test_synth_property(generate_classes):
|
||||
"MyObject.qll": (a_ql_stub(name="MyObject"),
|
||||
a_ql_class(name="MyObject", final=True,
|
||||
properties=[
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects", synth=True,
|
||||
ql.Property(singular="Foo", type="bar", tablename="my_objects",
|
||||
synth=True,
|
||||
tableparams=["this", "result"], doc="foo of this my object"),
|
||||
])),
|
||||
}
|
||||
@@ -934,9 +951,10 @@ def test_hideable_property(generate_classes):
|
||||
"Other.qll": (a_ql_stub(name="Other"),
|
||||
a_ql_class(name="Other", imports=[stub_import_prefix + "MyObject"],
|
||||
final=True, properties=[
|
||||
ql.Property(singular="X", type="MyObject", tablename="others", type_is_hideable=True,
|
||||
tableparams=["this", "result"], doc="x of this other"),
|
||||
])),
|
||||
ql.Property(singular="X", type="MyObject", tablename="others",
|
||||
type_is_hideable=True,
|
||||
tableparams=["this", "result"], doc="x of this other"),
|
||||
])),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
query predicate new_unspecified_elements(Element e, string property, string error) {
|
||||
unspecified_elements(e, property, error)
|
||||
or
|
||||
error = "Macro declarations removed during database downgrade. Please update your CodeQL code." and
|
||||
property = "" and
|
||||
macro_decls(e, _)
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
description: Removes MacroDecls
|
||||
compatibility: partial
|
||||
|
||||
unspecified_elements.rel: run downgrade.ql new_unspecified_elements
|
||||
|
||||
macro_decls.rel: delete
|
||||
macro_roles.rel: delete
|
||||
macro_role_conformances.rel: delete
|
||||
macro_role_names.rel: delete
|
||||
macro_decl_parameters.rel: delete
|
||||
macro_decl_roles.rel: delete
|
||||
@@ -36,7 +36,8 @@ class SwiftDispatcher {
|
||||
const swift::TypeBase*,
|
||||
const swift::CapturedValue*,
|
||||
const swift::PoundAvailableInfo*,
|
||||
const swift::AvailabilitySpec*>;
|
||||
const swift::AvailabilitySpec*,
|
||||
const swift::MacroRoleAttr*>;
|
||||
|
||||
public:
|
||||
// all references and pointers passed as parameters to this constructor are supposed to outlive
|
||||
@@ -334,6 +335,7 @@ class SwiftDispatcher {
|
||||
virtual void visit(const swift::TypeRepr* typeRepr, swift::Type type) = 0;
|
||||
virtual void visit(const swift::TypeBase* type) = 0;
|
||||
virtual void visit(const swift::CapturedValue* capture) = 0;
|
||||
virtual void visit(const swift::MacroRoleAttr* attr) = 0;
|
||||
|
||||
template <typename T>
|
||||
requires(!std::derived_from<T, swift::TypeRepr>) void visit(const T* e, swift::Type) { visit(e); }
|
||||
|
||||
@@ -28,6 +28,13 @@ concept HasStartAndEndLoc = requires(T e) {
|
||||
}
|
||||
&&!(HasSourceRange<T>);
|
||||
|
||||
template <typename T>
|
||||
concept HasLAndRParenLoc = requires(T e) {
|
||||
e.getLParenLoc();
|
||||
e.getRParenLoc();
|
||||
}
|
||||
&&!(HasSourceRange<T>)&&!(HasStartAndEndLoc<T>);
|
||||
|
||||
template <typename T>
|
||||
concept HasOneLoc = requires(T e) {
|
||||
e.getLoc();
|
||||
@@ -50,6 +57,13 @@ swift::SourceRange getSourceRange(const HasStartAndEndLoc auto& locatable) {
|
||||
return {locatable.getStartLoc()};
|
||||
}
|
||||
|
||||
swift::SourceRange getSourceRange(const HasLAndRParenLoc auto& locatable) {
|
||||
if (locatable.getLParenLoc() && locatable.getRParenLoc()) {
|
||||
return {locatable.getLParenLoc(), locatable.getRParenLoc()};
|
||||
}
|
||||
return {locatable.getLParenLoc()};
|
||||
}
|
||||
|
||||
swift::SourceRange getSourceRange(const HasOneLoc auto& locatable) {
|
||||
return {locatable.getLoc()};
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ MAP(swift::Expr, ExprTag)
|
||||
MAP(swift::OneWayExpr, OneWayExprTag)
|
||||
MAP(swift::TapExpr, TapExprTag)
|
||||
MAP(swift::TypeJoinExpr, void) // TODO (introduced in 5.8)
|
||||
MAP(swift::MacroExpansionExpr, void) // TODO (introduced in 5.8)
|
||||
MAP(swift::MacroExpansionExpr, void) // unexpanded macro in an expr context, skipping
|
||||
MAP(swift::CopyExpr, CopyExprTag)
|
||||
MAP(swift::ConsumeExpr, ConsumeExprTag)
|
||||
MAP(swift::MaterializePackExpr, void) // TODO (introduced in 5.9)
|
||||
@@ -228,7 +228,7 @@ MAP(swift::Decl, DeclTag)
|
||||
MAP(swift::FuncDecl, AccessorOrNamedFunctionTag)
|
||||
MAP_CONCRETE(swift::FuncDecl, NamedFunctionTag)
|
||||
MAP(swift::AccessorDecl, AccessorTag)
|
||||
MAP(swift::MacroDecl, void) // TODO (introduced in 5.8)
|
||||
MAP(swift::MacroDecl, MacroDeclTag)
|
||||
MAP(swift::EnumElementDecl, EnumElementDeclTag)
|
||||
MAP(swift::ExtensionDecl, ExtensionDeclTag)
|
||||
MAP(swift::TopLevelCodeDecl, TopLevelCodeDeclTag)
|
||||
@@ -243,10 +243,8 @@ MAP(swift::Decl, DeclTag)
|
||||
MAP(swift::InfixOperatorDecl, InfixOperatorDeclTag)
|
||||
MAP(swift::PrefixOperatorDecl, PrefixOperatorDeclTag)
|
||||
MAP(swift::PostfixOperatorDecl, PostfixOperatorDeclTag)
|
||||
MAP(swift::MacroExpansionDecl, void) // TODO (introduced in 5.8)
|
||||
#if CODEQL_SWIFT_VERSION_GE(5, 9)
|
||||
MAP(swift::MissingDecl, void) // TODO (introduced in 5.9)
|
||||
#endif
|
||||
MAP(swift::MacroExpansionDecl, void) // unexpanded macro in a decl context, skipping
|
||||
MAP(swift::MissingDecl, void) // appears around an unexpanded macro, skipping
|
||||
|
||||
MAP(swift::Pattern, PatternTag)
|
||||
MAP(swift::ParenPattern, ParenPatternTag)
|
||||
@@ -350,6 +348,7 @@ MAP(swift::AvailabilitySpec, AvailabilitySpecTag)
|
||||
MAP(swift::OtherPlatformAvailabilitySpec, OtherAvailabilitySpecTag)
|
||||
|
||||
MAP(swift::PoundAvailableInfo, AvailabilityInfoTag)
|
||||
MAP(swift::MacroRoleAttr, MacroRoleTag)
|
||||
|
||||
// clang-format on
|
||||
#undef MAP
|
||||
|
||||
@@ -374,4 +374,32 @@ codeql::CapturedDecl DeclTranslator::translateCapturedValue(const swift::Capture
|
||||
entry.is_escaping = !capture.isNoEscape();
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::MacroDecl DeclTranslator::translateMacroDecl(const swift::MacroDecl& decl) {
|
||||
auto entry = createEntry(decl);
|
||||
fillValueDecl(decl, entry);
|
||||
fillGenericContext(decl, entry);
|
||||
entry.name = constructName(decl.getName());
|
||||
for (auto attr : decl.getAttrs().getAttributes<swift::MacroRoleAttr>()) {
|
||||
entry.roles.emplace_back(dispatcher.fetchLabel(attr));
|
||||
}
|
||||
if (decl.getParameterList()) {
|
||||
for (auto param : *decl.getParameterList()) {
|
||||
entry.parameters.emplace_back(dispatcher.fetchLabel(param));
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
codeql::MacroRole DeclTranslator::translateMacroRoleAttr(const swift::MacroRoleAttr& attr) {
|
||||
auto entry = dispatcher.createEntry(attr);
|
||||
entry.kind = static_cast<uint32_t>(attr.getMacroRole());
|
||||
entry.macro_syntax = static_cast<uint8_t>(attr.getMacroSyntax());
|
||||
entry.conformances = dispatcher.fetchRepeatedLabels(attr.getConformances());
|
||||
for (auto& declName : attr.getNames()) {
|
||||
entry.names.emplace_back(constructName(declName.getName()));
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
} // namespace codeql
|
||||
|
||||
@@ -49,6 +49,8 @@ class DeclTranslator : public AstTranslatorBase<DeclTranslator> {
|
||||
codeql::PoundDiagnosticDecl translatePoundDiagnosticDecl(const swift::PoundDiagnosticDecl& decl);
|
||||
codeql::MissingMemberDecl translateMissingMemberDecl(const swift::MissingMemberDecl& decl);
|
||||
codeql::CapturedDecl translateCapturedValue(const swift::CapturedValue& capture);
|
||||
codeql::MacroDecl translateMacroDecl(const swift::MacroDecl& decl);
|
||||
codeql::MacroRole translateMacroRoleAttr(const swift::MacroRoleAttr& attr);
|
||||
|
||||
private:
|
||||
void fillFunction(const swift::AbstractFunctionDecl& decl, codeql::Function& entry);
|
||||
|
||||
@@ -53,6 +53,8 @@ class SwiftVisitor : private SwiftDispatcher {
|
||||
declTranslator.translateAndEmit(*capture);
|
||||
}
|
||||
|
||||
void visit(const swift::MacroRoleAttr* attr) override { declTranslator.translateAndEmit(*attr); }
|
||||
|
||||
DeclTranslator declTranslator{*this};
|
||||
ExprTranslator exprTranslator{*this};
|
||||
StmtTranslator stmtTranslator{*this};
|
||||
|
||||
@@ -89,6 +89,10 @@ class AstTranslatorBase : private swift::ASTVisitor<CrtpSubclass>,
|
||||
dispatcher.emit(static_cast<CrtpSubclass*>(this)->translateCapturedValue(e));
|
||||
}
|
||||
|
||||
void translateAndEmit(const swift::MacroRoleAttr& attr) {
|
||||
dispatcher.emit(static_cast<CrtpSubclass*>(this)->translateMacroRoleAttr(attr));
|
||||
}
|
||||
|
||||
private:
|
||||
friend class swift::ASTVisitor<CrtpSubclass>;
|
||||
|
||||
|
||||
25
swift/ql/.generated.list
generated
25
swift/ql/.generated.list
generated
@@ -8,6 +8,7 @@ lib/codeql/swift/elements/DbLocationConstructor.qll f98d927f2cc2b0b5de51eee3e0b6
|
||||
lib/codeql/swift/elements/DiagnosticsConstructor.qll 5212997161b95b0b10e7707843c9d3f9bf760af7a8646f26c5793507b5162224 2b9fbc9d84048d3dffa782db049e1ecdaaa1696744515e28ac4421ab265a5f67
|
||||
lib/codeql/swift/elements/ErrorElement.qll 4f11ac258e5babef18708553989ce792344e40900f96562ad472a53abff159fd d4d11f5fa399aca2991eb47f5d2d1f9ef1306e763a9b4221bc0026f3d50b3130
|
||||
lib/codeql/swift/elements/KeyPathComponentConstructor.qll ff71795157639520f56ce99ed49bf25486c125a0f27a3bb3ba2c8492feca13b2 5875187267cf91e37426d817a6c0c5e7ba9ddb0bd840ad358338ba003e0a877c
|
||||
lib/codeql/swift/elements/MacroRoleConstructor.qll c45c189fd441e2c23b1c94dec9f357192f5e392051e0becf52c020d830e38e54 e281ef4ba76a6e4b2b689e00f542ef585cec7a540911ccd7fbb59f3232f08a3d
|
||||
lib/codeql/swift/elements/OtherAvailabilitySpecConstructor.qll c5638ae4f3993c7a111fb2a516667190642c1948f18806cf29f78b7067021d10 cc93ac54741ba952b32385db0fe072576a9c8697cd793bcb8faed98f0fb6bda0
|
||||
lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll 015280737e71fe1084da6056410fd73dc4473a3b3296d0e46c0ca64f07dd5b7f c735c42e45ebdc308a1f02ff15d65d4d1154071e55645a9ae763d6c021d7f601
|
||||
lib/codeql/swift/elements/UnspecifiedElementConstructor.qll f7e232dae7362d0c3f9f33f952d9106da3d273f16b124008919fba6e40a944b6 eb30f05ae09f2c7bc93d758c0870b63f16bf61d0d2446ed827250f89772596ab
|
||||
@@ -36,6 +37,8 @@ lib/codeql/swift/elements/decl/ImportDeclConstructor.qll 1876052c283d9701cf2e2c9
|
||||
lib/codeql/swift/elements/decl/InfixOperatorDecl.qll f3028c9d9da2770b120498dc558f9a447b10e996f6f00c7b7456af2d8b31e314 218a02bb2f10bd7f0add10943a11ba77cb3e416b4cf2e68b7530f825d896ffed
|
||||
lib/codeql/swift/elements/decl/InfixOperatorDeclConstructor.qll 92dc3ac72c1d7b88b61cf9faa8048e6ba3e9af8b17d3bfe91919394e252e2595 d70cc9989101ce7268a6959cbcc8bf8a1e08f69a4c8734a6d85bf6abc668ddea
|
||||
lib/codeql/swift/elements/decl/InitializerConstructor.qll 0741961a1e5d65bf906ae5f2b8e745da30d215624faaca092dd869b33b82db39 72d0c8fc3d6c53923ae7b3f7c2d9eccb556352df69e5fd5566b8cec9eb0c4ee6
|
||||
lib/codeql/swift/elements/decl/MacroDecl.qll e33c90f10da798e26444787834bfe2754890c84202d82537a500f721614d1a73 f23dc7c70cb5f8eaffad4df3347e4eaff17a69e9e99888b0d5ecece3cd913349
|
||||
lib/codeql/swift/elements/decl/MacroDeclConstructor.qll fa08d8ba96541d43db4c6908fff8c8f06dce8a40d5eeaba607e20daf16df0a20 b5c1bbd697b5f309afb684e224066ff499bba5e66a1172b9269f7a579420ec40
|
||||
lib/codeql/swift/elements/decl/MissingMemberDeclConstructor.qll f7c299d55d8f14386cade490155cdc7edbe26ef67796a273cc7779d740f5e3a9 377f1fdd4f798506adb297cdc80545b5842acfe33a2187b9dfe2442f59b3120d
|
||||
lib/codeql/swift/elements/decl/ModuleDecl.qll 11e54958739679424525e889de7f0b9f1074e7e123482ee94ac45ab261e33ef8 73917bd8a2985d1d1bfa72e3db20978b56ec30a679cf8fc6c3af3ee54994fb41
|
||||
lib/codeql/swift/elements/decl/ModuleDeclConstructor.qll 51106eb585219a6211a354c4a4ae9ac0dfa088e412145e1218eff1e31f82bf4d f05597e555014a58381b75b44b05b00a03a99e7ce54faf606df1128c1a5bbfd8
|
||||
@@ -383,7 +386,7 @@ lib/codeql/swift/elements/type/UnresolvedTypeConstructor.qll 7f75d489b4d7ce65cae
|
||||
lib/codeql/swift/elements/type/VariadicSequenceTypeConstructor.qll fc74a5a2a2effa28ef24509b20ee4373d97cf6e8c71840121bb031c6adedf584 c9b2effc1d01c13c5e6a74a111122fa79a2f6554dda3cb016d68ba397e566ec4
|
||||
lib/codeql/swift/elements/type/WeakStorageType.qll edd13dd97b53040684409e187c1f975bcada6807c919e1345d8977144dbebb6f 9434c044d264a7f5f503a6422c106c9b8fedf74aaae314174473a29ea6ed17b9
|
||||
lib/codeql/swift/elements/type/WeakStorageTypeConstructor.qll 5fdce3716aba6318522174a2c455a63480970222ae81c732fb19c6dd3ae2d271 60ea79d6943e129deba0deccb566cf9d73f78398b0f7f0212674d91287d6b2ae
|
||||
lib/codeql/swift/elements.qll a3e46884bac3428bdec439ba97c65a69fea02e30b074b585f8db378844215fe3 a3e46884bac3428bdec439ba97c65a69fea02e30b074b585f8db378844215fe3
|
||||
lib/codeql/swift/elements.qll 34a49e70c33620aae14b9370dc6fdc702fbf292c206d9ebfaa23c8e7680480df 34a49e70c33620aae14b9370dc6fdc702fbf292c206d9ebfaa23c8e7680480df
|
||||
lib/codeql/swift/generated/AstNode.qll 68877daa9e14b462247ac6b7b724f5e683288e39953a8ebb02a362b7d1df8e4c 54d3512744738e1ee15645f3af116437053cb5209687f4106361a1943b38b666
|
||||
lib/codeql/swift/generated/AvailabilityInfo.qll e74e218a1ab00416cb8823610ff93642101aa784aa61cbc2b4deef61471a5bac e2c6c19860dc3e6e211041c95d8e6d52c3505ccff7018b80a849735cc98141af
|
||||
lib/codeql/swift/generated/AvailabilitySpec.qll a8afc5071887a67b4e0dec27356ab8cbf3e176b5358cb34c785e3015b2cad5a2 c7f88b0d701612c821359c983b3102f31b23edc211c3dcfe97de5adec61af386
|
||||
@@ -398,13 +401,14 @@ lib/codeql/swift/generated/File.qll 27b43d817c9335a3d11686b7a09369f5cbf4b1f6a5b7
|
||||
lib/codeql/swift/generated/KeyPathComponent.qll cdfd7123f6b03186f36204eac00a0e5a1ee323fd42c3e8997da3390cb4989caf 96fa51fbf43b690c10b13201446af73ec9c4d57187eef80b4f70689323bcf35f
|
||||
lib/codeql/swift/generated/Locatable.qll 6cb437dd7ff7331429ec6586b0af50b1af15e4f72be47b5c89278923d4a9cea0 a93ac33767e077fa5a4c65b2110111de1939c9bb73fecdaf5aee80dce54469b7
|
||||
lib/codeql/swift/generated/Location.qll 3f3bad413be87d05a596fe7b8004f415c2caa98cb759021a6aad20b589b7d700 ed30ed646962b3ffb6b47c97c6434fe47a6b1ea8e3f2e0589577bea5cf96c88e
|
||||
lib/codeql/swift/generated/MacroRole.qll aaf5631c49de81e046854955341202d6d3516713cd09bc2e7b870e40c261cc9f 6cd17d40cbf1d8fa4ef01dfb8b3462b7cee902e6058fb76417c2035be12481d1
|
||||
lib/codeql/swift/generated/OtherAvailabilitySpec.qll 06393a08e8da36106c5ec6efb9f1bd56a5c7b3d3f3d0bcefc6fa07fa96860c31 06393a08e8da36106c5ec6efb9f1bd56a5c7b3d3f3d0bcefc6fa07fa96860c31
|
||||
lib/codeql/swift/generated/ParentChild.qll a00f7eecdc91d98ad421c6d883bf2cc6e92c213befdcc494bf8ad25f2c5d4ae2 cd2c70e5940a302108319bdc16d25f49df3165be5b94fa825b64b9b5771f117d
|
||||
lib/codeql/swift/generated/ParentChild.qll fffa8748471139e0143521443cb7bf566db136f932e80e1917e7ab7140389835 c7768c3ad33fb1934b7b8955d09fe1d2978187e8d1f59a9ba0595f5bcb884d2d
|
||||
lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll 5355be9da8b778d1d8ae60d25d9c3394477da24f94e8a6ab4484c6a16d07cd7c 075438c1762ec0a7775004b39032dcf85aada038a4269e6f428c34b8282786e9
|
||||
lib/codeql/swift/generated/PureSynthConstructors.qll 40f5c0c573ce12f16322d9efb12306750f672254cbc36a200c298cb08e504229 40f5c0c573ce12f16322d9efb12306750f672254cbc36a200c298cb08e504229
|
||||
lib/codeql/swift/generated/Raw.qll f15f0b35be65adb8027e17b5fd5478eabb5000ee887dafc5c40d8abd03ced3e3 75fc6fbb74e0720b736c13ec3627247c49f8201df929647cdb2985282abf23c1
|
||||
lib/codeql/swift/generated/Synth.qll 93565d0244a9f5bf4ba3f19a0ffabef4b8dc48703c580b905ffeac716eea5445 74d977cfe6fbb3d90579dc45b40254549e686d91eb16999c9e69fec18ab7df28
|
||||
lib/codeql/swift/generated/SynthConstructors.qll fbbf618c54843d86b4c38d7b27e12cce7661b49ce52573f791dd8fcb4bbd40f5 fbbf618c54843d86b4c38d7b27e12cce7661b49ce52573f791dd8fcb4bbd40f5
|
||||
lib/codeql/swift/generated/Raw.qll 31fc7cb2d45a8699447116df6bd3ddaa9b630d437d7a898b8054371a7bc92f6e b997210dccad7802e3ba9326d803eed61aa9fc6748f9e04d8184fde5d1cba63c
|
||||
lib/codeql/swift/generated/Synth.qll 62abfaec75a308f222d8a7b8bb3260a1226977c253e87dbf9fc74f6e35398f53 c45d3237d9bdfb11d0372a5a1997d794a94a7eeeba3938d234bbbf802dacd9ad
|
||||
lib/codeql/swift/generated/SynthConstructors.qll 73604e68bac553fe06b52aa768cd5f876b3cf85ee88bca96f7e2e4db76ef997f 73604e68bac553fe06b52aa768cd5f876b3cf85ee88bca96f7e2e4db76ef997f
|
||||
lib/codeql/swift/generated/UnknownFile.qll 5325944cf96a72d5d224597745e15960fb6a9448b96b6644ececd6344dfd9d74 5325944cf96a72d5d224597745e15960fb6a9448b96b6644ececd6344dfd9d74
|
||||
lib/codeql/swift/generated/UnknownLocation.qll dfdeb8eedb2564eccaac416695784ea04fe9754a3e109e8484c695021af4e554 dfdeb8eedb2564eccaac416695784ea04fe9754a3e109e8484c695021af4e554
|
||||
lib/codeql/swift/generated/UnspecifiedElement.qll 8ecc275cc131fe5aa61052299e10c49c3718f96416df9eeacabf5aea34d97982 b02dfcf0df3859551b176e065291da943670ab4da6ed84d02a0861ff689001c6
|
||||
@@ -430,6 +434,7 @@ lib/codeql/swift/generated/decl/IfConfigDecl.qll 53082a36da6effe865bf9c2df598998
|
||||
lib/codeql/swift/generated/decl/ImportDecl.qll 540a53652ef1e11ef61c405e1c3d4b0eb198b9bb2152a88439622a6d35db6a31 1bcedef7c9bc0b02b7314cb67558d537481f9619968319ada5da6f09e59aa53a
|
||||
lib/codeql/swift/generated/decl/InfixOperatorDecl.qll 2aa1db0150f53a5d04c491013b4f65562ddd9aa3b8fa83165145663407cfbf6c 78503fd043cec744557b5398870f45eada22a67a864437a675ec4ea70d613aef
|
||||
lib/codeql/swift/generated/decl/Initializer.qll ae9f059cc6f36e6e4c571ed934cb61f4d696663f1b12c6aa28bf53069735a6ea ae9f059cc6f36e6e4c571ed934cb61f4d696663f1b12c6aa28bf53069735a6ea
|
||||
lib/codeql/swift/generated/decl/MacroDecl.qll 5446a7daac2e14410abd69245b629060a9b679d740fc42919c98686833dddb7c 9c2a72f9e77d0a45cbb3dccf9c30501d8d3b77329a1112b627e6b1135f1d113d
|
||||
lib/codeql/swift/generated/decl/MissingMemberDecl.qll 5a1c0fdfc8bc8f6d8ff2f31ae2fe53e7f44fefb14ad37a4012ad8e69de933d06 3bbd3c5715c0e0c8e9bd35b59d1617b7d8522740bfbefe52996113198a5d20ea
|
||||
lib/codeql/swift/generated/decl/ModuleDecl.qll e5104509117209567cb3d55ed63d8e44847b8e1a9480c7ce9c2f475a0129bb42 979633e839719795d4db8331056b38a33f5432a57a4d7c1c8530bf3a9a88a7c0
|
||||
lib/codeql/swift/generated/decl/NamedFunction.qll c2e342643c2b2fa9729a3838cd592bc9127c0c74bf359533ebc837686e18c8e3 c2e342643c2b2fa9729a3838cd592bc9127c0c74bf359533ebc837686e18c8e3
|
||||
@@ -439,7 +444,7 @@ lib/codeql/swift/generated/decl/OperatorDecl.qll 76901a6aa7bf34c925b93e1466e3601
|
||||
lib/codeql/swift/generated/decl/ParamDecl.qll 9774c4aea3fa140c90a00018c6991947b0ac7b7d847d4319f1ceac5b8ab0b5ac 971d3f63ab70975812cbf80f03a63516bfff113a15f53c720bd1834c82e49ca4
|
||||
lib/codeql/swift/generated/decl/PatternBindingDecl.qll ef627fd2f8a19f587b5690ea4d608f6ca6aca6be78ecd930f0b150df6c6c9a92 456c823ee71d7c81dd887fbe5b77f64a1a53d2a84e6266ed18aadca62a4bbbcb
|
||||
lib/codeql/swift/generated/decl/PostfixOperatorDecl.qll f6a26b6b6632c9eaefc5d0ee9aeb99ddd56fed792afff9037114d92c3a42bb23 f6a26b6b6632c9eaefc5d0ee9aeb99ddd56fed792afff9037114d92c3a42bb23
|
||||
lib/codeql/swift/generated/decl/PoundDiagnosticDecl.qll 975d88abaed11eefa434d266960c45ac83e040a790c8fed14c2703c2e256850d a6dedac1a7b085d512b96bb40805a70910de4e2293e60d1f765b1e512ed838a5
|
||||
lib/codeql/swift/generated/decl/PoundDiagnosticDecl.qll 6e1ef7f47d1fb7817a472724f025fc498366dfed7a31692dee66d60bd5dbacc1 9fcd2ed7afe5ede92a50d17036c1ffb14dcb5491bccac3e7218c5919f7c12efb
|
||||
lib/codeql/swift/generated/decl/PrecedenceGroupDecl.qll 40adef005cbe080485867888bf4b71c10e67fa5a3c843d4d3d79f4dd13c76605 40adef005cbe080485867888bf4b71c10e67fa5a3c843d4d3d79f4dd13c76605
|
||||
lib/codeql/swift/generated/decl/PrefixOperatorDecl.qll 853f3a15d5bbe629e5fc7cbb2b9ad2946af74771e00369ba97b66370827033cb 853f3a15d5bbe629e5fc7cbb2b9ad2946af74771e00369ba97b66370827033cb
|
||||
lib/codeql/swift/generated/decl/ProtocolDecl.qll 2de9a6b5b2fab8a3bb517ad2cf424ca9f3d29f7bd15b7c8861c0caea7d28baf7 2de9a6b5b2fab8a3bb517ad2cf424ca9f3d29f7bd15b7c8861c0caea7d28baf7
|
||||
@@ -749,6 +754,14 @@ test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getImportedModule.ql 0
|
||||
test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getMember.ql 6d48d3a93bc96dba3bda71ec9d9d6282615c2228a58da6167c169fafaedb3e17 8560b23d0f52b845c81727ce09c0b2f9647965c83d7de165e8cd3d91be5bdd42
|
||||
test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/decl/Initializer/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroDecl.ql 16900baee88fe4d7d4f88369e7455783b8c2058ee48a2af2136d1d778098854e 6dae3ea092d1810c301ed57841c5c93a5ee0d8f8187552d078ce26a74c1e4630
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getGenericTypeParam.ql ae35558863fc444ca6a034d74e90583a779a2edb755c523d33693a8ab418718f 2031af476afa267b71fe22071f7e9ec97d4872812d333ff733055b7b29ff8386
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getMember.ql 4abbe22e4c2b94b8f5d009386c93710e7a003d7faef7d044481fcb47cc85e85e 9a57fab9011773cfa77db44b1eedf7e2277380640161d708af9d4df6280df3d3
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getParameter.ql 449716b575d0a4caa69cabafeba289d328e12054a1f7aac77d0dd5c47904971f 9649a62096d5fc17e71e527bc1299cbf6a1f38d21f685c86469bc6c83a62268a
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getRole.ql d861b3ac12e38826d6e9ac72b7e6f2b82b4328e6e02bf26ea496635501cd1722 c2b606a39dd68dbeea4709d4c868a66db7ffae720f4163540f6d1e0aaeaafc11
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroRole.ql cd8c70998a177f14e1b10eb214ffefd62b2c4a7839dc845bf155ddb0888dd4a7 cdad06e902ab61005dcb552d1340754a12fc18a9256f49dd6fb3ccbd34605ef2
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroRole_getConformance.ql d36aeb229667a5b0153534872523ed84e28cdb9f8400d1f3051c15227e05c793 dc18b70f2e65edc86f12179ba3756dbfc3802dc87f875c2e11d97359b180c767
|
||||
test/extractor-tests/generated/decl/MacroDecl/MacroRole_getName.ql fa339f428f572873f76ace1dea80e643a198bd435a8ce6cc0f38cac870e590f7 fa1a87d0f0a71684c927cb7049efb627eeb42f4d436bcaef196b01e12d0e4aa7
|
||||
test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.ql d096e82574438b1e6d646b8762217dc74f9f9c40b01d642ef6a0286a55ecad9d 3eae6049885efcd3ffd6117af31cd12d792492b1591a88444a8e4a7fa31ac187
|
||||
test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql 321619519c5cffefda78f11f2c85a199af76fccbfcc51126c7a558ba12fdfd80 30e48eb820ba9d7f3ec30bf4536c0f84280c5f2ca8c63427f6b77d74a092e68b
|
||||
test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql 65fae5b1a7db3a11fd837ed78c663e8907306c36695ae73e4e29559755276fbe 3ddef1a7af7a636e66674fadb3e727ad18655a9ecb4c73fd3d6aca202f1191fb
|
||||
|
||||
13
swift/ql/.gitattributes
generated
vendored
13
swift/ql/.gitattributes
generated
vendored
@@ -10,6 +10,7 @@
|
||||
/lib/codeql/swift/elements/DiagnosticsConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/ErrorElement.qll linguist-generated
|
||||
/lib/codeql/swift/elements/KeyPathComponentConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/MacroRoleConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/OtherAvailabilitySpecConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/PlatformVersionAvailabilitySpecConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/UnspecifiedElementConstructor.qll linguist-generated
|
||||
@@ -38,6 +39,8 @@
|
||||
/lib/codeql/swift/elements/decl/InfixOperatorDecl.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/InfixOperatorDeclConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/InitializerConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/MacroDecl.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/MacroDeclConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/MissingMemberDeclConstructor.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/ModuleDecl.qll linguist-generated
|
||||
/lib/codeql/swift/elements/decl/ModuleDeclConstructor.qll linguist-generated
|
||||
@@ -400,6 +403,7 @@
|
||||
/lib/codeql/swift/generated/KeyPathComponent.qll linguist-generated
|
||||
/lib/codeql/swift/generated/Locatable.qll linguist-generated
|
||||
/lib/codeql/swift/generated/Location.qll linguist-generated
|
||||
/lib/codeql/swift/generated/MacroRole.qll linguist-generated
|
||||
/lib/codeql/swift/generated/OtherAvailabilitySpec.qll linguist-generated
|
||||
/lib/codeql/swift/generated/ParentChild.qll linguist-generated
|
||||
/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll linguist-generated
|
||||
@@ -432,6 +436,7 @@
|
||||
/lib/codeql/swift/generated/decl/ImportDecl.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/InfixOperatorDecl.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/Initializer.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/MacroDecl.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/MissingMemberDecl.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/ModuleDecl.qll linguist-generated
|
||||
/lib/codeql/swift/generated/decl/NamedFunction.qll linguist-generated
|
||||
@@ -751,6 +756,14 @@
|
||||
/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getMember.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/decl/Initializer/MISSING_SOURCE.txt linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroDecl.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getGenericTypeParam.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getMember.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getParameter.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getRole.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroRole.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getConformance.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getName.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql linguist-generated
|
||||
/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql linguist-generated
|
||||
|
||||
4
swift/ql/lib/change-notes/2023-11-21-macros.md
Normal file
4
swift/ql/lib/change-notes/2023-11-21-macros.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Extracts `MacroDecl` and some related information
|
||||
2
swift/ql/lib/codeql/swift/elements.qll
generated
2
swift/ql/lib/codeql/swift/elements.qll
generated
@@ -17,6 +17,7 @@ import codeql.swift.elements.File
|
||||
import codeql.swift.elements.KeyPathComponent
|
||||
import codeql.swift.elements.Locatable
|
||||
import codeql.swift.elements.Location
|
||||
import codeql.swift.elements.MacroRole
|
||||
import codeql.swift.elements.OtherAvailabilitySpec
|
||||
import codeql.swift.elements.PlatformVersionAvailabilitySpec
|
||||
import codeql.swift.elements.UnknownFile
|
||||
@@ -43,6 +44,7 @@ import codeql.swift.elements.decl.IfConfigDecl
|
||||
import codeql.swift.elements.decl.ImportDecl
|
||||
import codeql.swift.elements.decl.InfixOperatorDecl
|
||||
import codeql.swift.elements.decl.Initializer
|
||||
import codeql.swift.elements.decl.MacroDecl
|
||||
import codeql.swift.elements.decl.MissingMemberDecl
|
||||
import codeql.swift.elements.decl.ModuleDecl
|
||||
import codeql.swift.elements.decl.NamedFunction
|
||||
|
||||
100
swift/ql/lib/codeql/swift/elements/MacroRole.qll
Normal file
100
swift/ql/lib/codeql/swift/elements/MacroRole.qll
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `MacroRole`.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.MacroRole
|
||||
|
||||
// the following QLdoc is generated: if you need to edit it, do it in the schema file
|
||||
/**
|
||||
* The role of a macro, for example #freestanding(declaration) or @attached(member).
|
||||
*/
|
||||
class MacroRole extends Generated::MacroRole {
|
||||
/**
|
||||
* String representation of the role kind.
|
||||
*/
|
||||
string getKindName() {
|
||||
this.isExpressionKind() and result = "expression"
|
||||
or
|
||||
this.isDeclarationKind() and result = "declaration"
|
||||
or
|
||||
this.isAccessorKind() and result = "accessor"
|
||||
or
|
||||
this.isMemberAttributeKind() and result = "memberAttribute"
|
||||
or
|
||||
this.isMemberKind() and result = "member"
|
||||
or
|
||||
this.isPeerKind() and result = "peer"
|
||||
or
|
||||
this.isConformanceKind() and result = "conformance"
|
||||
or
|
||||
this.isCodeItemKind() and result = "codeItem"
|
||||
or
|
||||
this.isExtensionKind() and result = "extension"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for `expression` roles.
|
||||
*/
|
||||
predicate isExpressionKind() { this.getKind() = 1 }
|
||||
|
||||
/**
|
||||
* Holds for `declaration` roles.
|
||||
*/
|
||||
predicate isDeclarationKind() { this.getKind() = 2 }
|
||||
|
||||
/**
|
||||
* Holds for `accessor` roles.
|
||||
*/
|
||||
predicate isAccessorKind() { this.getKind() = 4 }
|
||||
|
||||
/**
|
||||
* Holds for `memberAttribute` roles.
|
||||
*/
|
||||
predicate isMemberAttributeKind() { this.getKind() = 8 }
|
||||
|
||||
/**
|
||||
* Holds for `member` roles.
|
||||
*/
|
||||
predicate isMemberKind() { this.getKind() = 16 }
|
||||
|
||||
/**
|
||||
* Holds for `peer` roles.
|
||||
*/
|
||||
predicate isPeerKind() { this.getKind() = 32 }
|
||||
|
||||
/**
|
||||
* Holds for `conformance` roles.
|
||||
*/
|
||||
predicate isConformanceKind() { this.getKind() = 64 }
|
||||
|
||||
/**
|
||||
* Holds for `codeItem` roles.
|
||||
*/
|
||||
predicate isCodeItemKind() { this.getKind() = 128 }
|
||||
|
||||
/**
|
||||
* Holds for `extension` roles.
|
||||
*/
|
||||
predicate isExtensionKind() { this.getKind() = 256 }
|
||||
|
||||
/**
|
||||
* String representation of the macro syntax.
|
||||
*/
|
||||
string getMacroSyntaxName() {
|
||||
this.isFreestandingMacroSyntax() and result = "#freestanding"
|
||||
or
|
||||
this.isAttachedMacroSyntax() and result = "@attached"
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds for #freestanding macros.
|
||||
*/
|
||||
predicate isFreestandingMacroSyntax() { this.getMacroSyntax() = 0 }
|
||||
|
||||
/**
|
||||
* Holds for @attached macros.
|
||||
*/
|
||||
predicate isAttachedMacroSyntax() { this.getMacroSyntax() = 1 }
|
||||
|
||||
override string toString() { result = this.getMacroSyntaxName() + "(" + this.getKindName() + ")" }
|
||||
}
|
||||
14
swift/ql/lib/codeql/swift/elements/MacroRoleConstructor.qll
generated
Normal file
14
swift/ql/lib/codeql/swift/elements/MacroRoleConstructor.qll
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module defines the hook used internally to tweak the characteristic predicate of
|
||||
* `MacroRole` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
/**
|
||||
* The characteristic predicate of `MacroRole` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
predicate constructMacroRole(Raw::MacroRole id) { any() }
|
||||
20
swift/ql/lib/codeql/swift/elements/decl/MacroDecl.qll
generated
Normal file
20
swift/ql/lib/codeql/swift/elements/decl/MacroDecl.qll
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module provides a hand-modifiable wrapper around the generated class `MacroDecl`.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.decl.MacroDecl
|
||||
|
||||
/**
|
||||
* A declaration of a macro. Some examples:
|
||||
*
|
||||
* ```
|
||||
* @freestanding(declaration)
|
||||
* macro A() = #externalMacro(module: "A", type: "A")
|
||||
* @freestanding(expression)
|
||||
* macro B() = Builtin.B
|
||||
* @attached(member)
|
||||
* macro C() = C.C
|
||||
* ```
|
||||
*/
|
||||
class MacroDecl extends Generated::MacroDecl { }
|
||||
14
swift/ql/lib/codeql/swift/elements/decl/MacroDeclConstructor.qll
generated
Normal file
14
swift/ql/lib/codeql/swift/elements/decl/MacroDeclConstructor.qll
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
// generated by codegen/codegen.py, remove this comment if you wish to edit this file
|
||||
/**
|
||||
* This module defines the hook used internally to tweak the characteristic predicate of
|
||||
* `MacroDecl` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.Raw
|
||||
|
||||
/**
|
||||
* The characteristic predicate of `MacroDecl` synthesized instances.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
predicate constructMacroDecl(Raw::MacroDecl id) { any() }
|
||||
91
swift/ql/lib/codeql/swift/generated/MacroRole.qll
generated
Normal file
91
swift/ql/lib/codeql/swift/generated/MacroRole.qll
generated
Normal file
@@ -0,0 +1,91 @@
|
||||
// generated by codegen/codegen.py
|
||||
/**
|
||||
* This module provides the generated definition of `MacroRole`.
|
||||
* INTERNAL: Do not import directly.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.Synth
|
||||
private import codeql.swift.generated.Raw
|
||||
import codeql.swift.elements.AstNode
|
||||
import codeql.swift.elements.expr.TypeExpr
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the fully generated definition of `MacroRole` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* The role of a macro, for example #freestanding(declaration) or @attached(member).
|
||||
* INTERNAL: Do not reference the `Generated::MacroRole` class directly.
|
||||
* Use the subclass `MacroRole`, where the following predicates are available.
|
||||
*/
|
||||
class MacroRole extends Synth::TMacroRole, AstNode {
|
||||
override string getAPrimaryQlClass() { result = "MacroRole" }
|
||||
|
||||
/**
|
||||
* Gets the kind of this macro role (declaration, expression, member, etc.).
|
||||
*
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
int getKind() { result = Synth::convertMacroRoleToRaw(this).(Raw::MacroRole).getKind() }
|
||||
|
||||
/**
|
||||
* Gets the #freestanding or @attached.
|
||||
*
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
int getMacroSyntax() {
|
||||
result = Synth::convertMacroRoleToRaw(this).(Raw::MacroRole).getMacroSyntax()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `index`th conformance of this macro role (0-based).
|
||||
*
|
||||
* This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the
|
||||
* behavior of both the `Immediate` and non-`Immediate` versions.
|
||||
*/
|
||||
TypeExpr getImmediateConformance(int index) {
|
||||
result =
|
||||
Synth::convertTypeExprFromRaw(Synth::convertMacroRoleToRaw(this)
|
||||
.(Raw::MacroRole)
|
||||
.getConformance(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `index`th conformance of this macro role (0-based).
|
||||
*/
|
||||
final TypeExpr getConformance(int index) {
|
||||
exists(TypeExpr immediate |
|
||||
immediate = this.getImmediateConformance(index) and
|
||||
result = immediate.resolve()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the conformances of this macro role.
|
||||
*/
|
||||
final TypeExpr getAConformance() { result = this.getConformance(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of conformances of this macro role.
|
||||
*/
|
||||
final int getNumberOfConformances() { result = count(int i | exists(this.getConformance(i))) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th name of this macro role (0-based).
|
||||
*/
|
||||
string getName(int index) {
|
||||
result = Synth::convertMacroRoleToRaw(this).(Raw::MacroRole).getName(index)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the names of this macro role.
|
||||
*/
|
||||
final string getAName() { result = this.getName(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of names of this macro role.
|
||||
*/
|
||||
final int getNumberOfNames() { result = count(int i | exists(this.getName(i))) }
|
||||
}
|
||||
}
|
||||
36
swift/ql/lib/codeql/swift/generated/ParentChild.qll
generated
36
swift/ql/lib/codeql/swift/generated/ParentChild.qll
generated
@@ -245,6 +245,19 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMacroRole(MacroRole e, int index, string partialPredicateCall) {
|
||||
exists(int b, int bAstNode, int n |
|
||||
b = 0 and
|
||||
bAstNode = b + 1 + max(int i | i = -1 or exists(getImmediateChildOfAstNode(e, i, _)) | i) and
|
||||
n = bAstNode and
|
||||
(
|
||||
none()
|
||||
or
|
||||
result = getImmediateChildOfAstNode(e, index - b, partialPredicateCall)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfUnspecifiedElement(
|
||||
UnspecifiedElement e, int index, string partialPredicateCall
|
||||
) {
|
||||
@@ -605,6 +618,25 @@ private module Impl {
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfMacroDecl(MacroDecl e, int index, string partialPredicateCall) {
|
||||
exists(int b, int bGenericContext, int bValueDecl, int n |
|
||||
b = 0 and
|
||||
bGenericContext =
|
||||
b + 1 + max(int i | i = -1 or exists(getImmediateChildOfGenericContext(e, i, _)) | i) and
|
||||
bValueDecl =
|
||||
bGenericContext + 1 +
|
||||
max(int i | i = -1 or exists(getImmediateChildOfValueDecl(e, i, _)) | i) and
|
||||
n = bValueDecl and
|
||||
(
|
||||
none()
|
||||
or
|
||||
result = getImmediateChildOfGenericContext(e, index - b, partialPredicateCall)
|
||||
or
|
||||
result = getImmediateChildOfValueDecl(e, index - bGenericContext, partialPredicateCall)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private Element getImmediateChildOfPostfixOperatorDecl(
|
||||
PostfixOperatorDecl e, int index, string partialPredicateCall
|
||||
) {
|
||||
@@ -5050,6 +5082,8 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfKeyPathComponent(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfMacroRole(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfUnspecifiedElement(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfOtherAvailabilitySpec(e, index, partialAccessor)
|
||||
@@ -5080,6 +5114,8 @@ private module Impl {
|
||||
or
|
||||
result = getImmediateChildOfInfixOperatorDecl(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfMacroDecl(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfPostfixOperatorDecl(e, index, partialAccessor)
|
||||
or
|
||||
result = getImmediateChildOfPrefixOperatorDecl(e, index, partialAccessor)
|
||||
|
||||
60
swift/ql/lib/codeql/swift/generated/Raw.qll
generated
60
swift/ql/lib/codeql/swift/generated/Raw.qll
generated
@@ -246,6 +246,34 @@ module Raw {
|
||||
Type getComponentType() { key_path_components(this, _, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* The role of a macro, for example #freestanding(declaration) or @attached(member).
|
||||
*/
|
||||
class MacroRole extends @macro_role, AstNode {
|
||||
override string toString() { result = "MacroRole" }
|
||||
|
||||
/**
|
||||
* Gets the kind of this macro role (declaration, expression, member, etc.).
|
||||
*/
|
||||
int getKind() { macro_roles(this, result, _) }
|
||||
|
||||
/**
|
||||
* Gets the #freestanding or @attached.
|
||||
*/
|
||||
int getMacroSyntax() { macro_roles(this, _, result) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th conformance of this macro role (0-based).
|
||||
*/
|
||||
TypeExpr getConformance(int index) { macro_role_conformances(this, index, result) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th name of this macro role (0-based).
|
||||
*/
|
||||
string getName(int index) { macro_role_names(this, index, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
@@ -557,6 +585,38 @@ module Raw {
|
||||
PrecedenceGroupDecl getPrecedenceGroup() { infix_operator_decl_precedence_groups(this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* A declaration of a macro. Some examples:
|
||||
*
|
||||
* ```
|
||||
* @freestanding(declaration)
|
||||
* macro A() = #externalMacro(module: "A", type: "A")
|
||||
* @freestanding(expression)
|
||||
* macro B() = Builtin.B
|
||||
* @attached(member)
|
||||
* macro C() = C.C
|
||||
* ```
|
||||
*/
|
||||
class MacroDecl extends @macro_decl, GenericContext, ValueDecl {
|
||||
override string toString() { result = "MacroDecl" }
|
||||
|
||||
/**
|
||||
* Gets the name of this macro.
|
||||
*/
|
||||
string getName() { macro_decls(this, result) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th parameter of this macro (0-based).
|
||||
*/
|
||||
ParamDecl getParameter(int index) { macro_decl_parameters(this, index, result) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th role of this macro (0-based).
|
||||
*/
|
||||
MacroRole getRole(int index) { macro_decl_roles(this, index, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
|
||||
56
swift/ql/lib/codeql/swift/generated/Synth.qll
generated
56
swift/ql/lib/codeql/swift/generated/Synth.qll
generated
@@ -39,6 +39,10 @@ module Synth {
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TKeyPathComponent(Raw::KeyPathComponent id) { constructKeyPathComponent(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TMacroRole(Raw::MacroRole id) { constructMacroRole(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
@@ -121,6 +125,10 @@ module Synth {
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TInitializer(Raw::Initializer id) { constructInitializer(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
TMacroDecl(Raw::MacroDecl id) { constructMacroDecl(id) } or
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
@@ -1061,7 +1069,7 @@ module Synth {
|
||||
*/
|
||||
class TAstNode =
|
||||
TAvailabilityInfo or TAvailabilitySpec or TCaseLabelItem or TConditionElement or TDecl or
|
||||
TExpr or TKeyPathComponent or TPattern or TStmt or TStmtCondition or TTypeRepr;
|
||||
TExpr or TKeyPathComponent or TMacroRole or TPattern or TStmt or TStmtCondition or TTypeRepr;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -1128,7 +1136,8 @@ module Synth {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
class TGenericContext = TExtensionDecl or TFunction or TGenericTypeDecl or TSubscriptDecl;
|
||||
class TGenericContext =
|
||||
TExtensionDecl or TFunction or TGenericTypeDecl or TMacroDecl or TSubscriptDecl;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -1153,7 +1162,8 @@ module Synth {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
class TValueDecl = TAbstractStorageDecl or TEnumElementDecl or TFunction or TTypeDecl;
|
||||
class TValueDecl =
|
||||
TAbstractStorageDecl or TEnumElementDecl or TFunction or TMacroDecl or TTypeDecl;
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -1427,6 +1437,13 @@ module Synth {
|
||||
cached
|
||||
TKeyPathComponent convertKeyPathComponentFromRaw(Raw::Element e) { result = TKeyPathComponent(e) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TMacroRole`, if possible.
|
||||
*/
|
||||
cached
|
||||
TMacroRole convertMacroRoleFromRaw(Raw::Element e) { result = TMacroRole(e) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TOtherAvailabilitySpec`, if possible.
|
||||
@@ -1579,6 +1596,13 @@ module Synth {
|
||||
cached
|
||||
TInitializer convertInitializerFromRaw(Raw::Element e) { result = TInitializer(e) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TMacroDecl`, if possible.
|
||||
*/
|
||||
cached
|
||||
TMacroDecl convertMacroDeclFromRaw(Raw::Element e) { result = TMacroDecl(e) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a raw element to a synthesized `TMissingMemberDecl`, if possible.
|
||||
@@ -3319,6 +3343,8 @@ module Synth {
|
||||
or
|
||||
result = convertKeyPathComponentFromRaw(e)
|
||||
or
|
||||
result = convertMacroRoleFromRaw(e)
|
||||
or
|
||||
result = convertPatternFromRaw(e)
|
||||
or
|
||||
result = convertStmtFromRaw(e)
|
||||
@@ -3528,6 +3554,8 @@ module Synth {
|
||||
or
|
||||
result = convertGenericTypeDeclFromRaw(e)
|
||||
or
|
||||
result = convertMacroDeclFromRaw(e)
|
||||
or
|
||||
result = convertSubscriptDeclFromRaw(e)
|
||||
}
|
||||
|
||||
@@ -3597,6 +3625,8 @@ module Synth {
|
||||
or
|
||||
result = convertFunctionFromRaw(e)
|
||||
or
|
||||
result = convertMacroDeclFromRaw(e)
|
||||
or
|
||||
result = convertTypeDeclFromRaw(e)
|
||||
}
|
||||
|
||||
@@ -4352,6 +4382,13 @@ module Synth {
|
||||
cached
|
||||
Raw::Element convertKeyPathComponentToRaw(TKeyPathComponent e) { e = TKeyPathComponent(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TMacroRole` to a raw DB element, if possible.
|
||||
*/
|
||||
cached
|
||||
Raw::Element convertMacroRoleToRaw(TMacroRole e) { e = TMacroRole(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TOtherAvailabilitySpec` to a raw DB element, if possible.
|
||||
@@ -4504,6 +4541,13 @@ module Synth {
|
||||
cached
|
||||
Raw::Element convertInitializerToRaw(TInitializer e) { e = TInitializer(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TMacroDecl` to a raw DB element, if possible.
|
||||
*/
|
||||
cached
|
||||
Raw::Element convertMacroDeclToRaw(TMacroDecl e) { e = TMacroDecl(result) }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
* Converts a synthesized `TMissingMemberDecl` to a raw DB element, if possible.
|
||||
@@ -6242,6 +6286,8 @@ module Synth {
|
||||
or
|
||||
result = convertKeyPathComponentToRaw(e)
|
||||
or
|
||||
result = convertMacroRoleToRaw(e)
|
||||
or
|
||||
result = convertPatternToRaw(e)
|
||||
or
|
||||
result = convertStmtToRaw(e)
|
||||
@@ -6451,6 +6497,8 @@ module Synth {
|
||||
or
|
||||
result = convertGenericTypeDeclToRaw(e)
|
||||
or
|
||||
result = convertMacroDeclToRaw(e)
|
||||
or
|
||||
result = convertSubscriptDeclToRaw(e)
|
||||
}
|
||||
|
||||
@@ -6520,6 +6568,8 @@ module Synth {
|
||||
or
|
||||
result = convertFunctionToRaw(e)
|
||||
or
|
||||
result = convertMacroDeclToRaw(e)
|
||||
or
|
||||
result = convertTypeDeclToRaw(e)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import codeql.swift.elements.DbFileConstructor
|
||||
import codeql.swift.elements.DbLocationConstructor
|
||||
import codeql.swift.elements.DiagnosticsConstructor
|
||||
import codeql.swift.elements.KeyPathComponentConstructor
|
||||
import codeql.swift.elements.MacroRoleConstructor
|
||||
import codeql.swift.elements.OtherAvailabilitySpecConstructor
|
||||
import codeql.swift.elements.PlatformVersionAvailabilitySpecConstructor
|
||||
import codeql.swift.elements.UnspecifiedElementConstructor
|
||||
@@ -27,6 +28,7 @@ import codeql.swift.elements.decl.IfConfigDeclConstructor
|
||||
import codeql.swift.elements.decl.ImportDeclConstructor
|
||||
import codeql.swift.elements.decl.InfixOperatorDeclConstructor
|
||||
import codeql.swift.elements.decl.InitializerConstructor
|
||||
import codeql.swift.elements.decl.MacroDeclConstructor
|
||||
import codeql.swift.elements.decl.MissingMemberDeclConstructor
|
||||
import codeql.swift.elements.decl.ModuleDeclConstructor
|
||||
import codeql.swift.elements.decl.NamedFunctionConstructor
|
||||
|
||||
81
swift/ql/lib/codeql/swift/generated/decl/MacroDecl.qll
generated
Normal file
81
swift/ql/lib/codeql/swift/generated/decl/MacroDecl.qll
generated
Normal file
@@ -0,0 +1,81 @@
|
||||
// generated by codegen/codegen.py
|
||||
/**
|
||||
* This module provides the generated definition of `MacroDecl`.
|
||||
* INTERNAL: Do not import directly.
|
||||
*/
|
||||
|
||||
private import codeql.swift.generated.Synth
|
||||
private import codeql.swift.generated.Raw
|
||||
import codeql.swift.elements.decl.GenericContext
|
||||
import codeql.swift.elements.MacroRole
|
||||
import codeql.swift.elements.decl.ParamDecl
|
||||
import codeql.swift.elements.decl.ValueDecl
|
||||
|
||||
/**
|
||||
* INTERNAL: This module contains the fully generated definition of `MacroDecl` and should not
|
||||
* be referenced directly.
|
||||
*/
|
||||
module Generated {
|
||||
/**
|
||||
* A declaration of a macro. Some examples:
|
||||
*
|
||||
* ```
|
||||
* @freestanding(declaration)
|
||||
* macro A() = #externalMacro(module: "A", type: "A")
|
||||
* @freestanding(expression)
|
||||
* macro B() = Builtin.B
|
||||
* @attached(member)
|
||||
* macro C() = C.C
|
||||
* ```
|
||||
* INTERNAL: Do not reference the `Generated::MacroDecl` class directly.
|
||||
* Use the subclass `MacroDecl`, where the following predicates are available.
|
||||
*/
|
||||
class MacroDecl extends Synth::TMacroDecl, GenericContext, ValueDecl {
|
||||
override string getAPrimaryQlClass() { result = "MacroDecl" }
|
||||
|
||||
/**
|
||||
* Gets the name of this macro.
|
||||
*/
|
||||
string getName() { result = Synth::convertMacroDeclToRaw(this).(Raw::MacroDecl).getName() }
|
||||
|
||||
/**
|
||||
* Gets the `index`th parameter of this macro (0-based).
|
||||
*/
|
||||
ParamDecl getParameter(int index) {
|
||||
result =
|
||||
Synth::convertParamDeclFromRaw(Synth::convertMacroDeclToRaw(this)
|
||||
.(Raw::MacroDecl)
|
||||
.getParameter(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the parameters of this macro.
|
||||
*/
|
||||
final ParamDecl getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of parameters of this macro.
|
||||
*/
|
||||
final int getNumberOfParameters() { result = count(int i | exists(this.getParameter(i))) }
|
||||
|
||||
/**
|
||||
* Gets the `index`th role of this macro (0-based).
|
||||
*/
|
||||
MacroRole getRole(int index) {
|
||||
result =
|
||||
Synth::convertMacroRoleFromRaw(Synth::convertMacroDeclToRaw(this)
|
||||
.(Raw::MacroDecl)
|
||||
.getRole(index))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets any of the roles of this macro.
|
||||
*/
|
||||
final MacroRole getARole() { result = this.getRole(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of roles of this macro.
|
||||
*/
|
||||
final int getNumberOfRoles() { result = count(int i | exists(this.getRole(i))) }
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ module Generated {
|
||||
* Gets the kind of this pound diagnostic declaration.
|
||||
*
|
||||
* This is 1 for `#error` and 2 for `#warning`.
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
int getKind() {
|
||||
result = Synth::convertPoundDiagnosticDeclToRaw(this).(Raw::PoundDiagnosticDecl).getKind()
|
||||
|
||||
@@ -20,7 +20,7 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
/**
|
||||
* Holds if the AST for `e` should be printed. By default, holds for all.
|
||||
*/
|
||||
predicate shouldPrint(Locatable e) { not e instanceof Diagnostics }
|
||||
predicate shouldPrint(Locatable e) { not e instanceof Diagnostics and not e instanceof MacroRole }
|
||||
}
|
||||
|
||||
private predicate shouldPrint(Locatable e) { any(PrintAstConfiguration config).shouldPrint(e) }
|
||||
|
||||
52
swift/ql/lib/swift.dbscheme
generated
52
swift/ql/lib/swift.dbscheme
generated
@@ -113,6 +113,7 @@ locations(
|
||||
| @decl
|
||||
| @expr
|
||||
| @key_path_component
|
||||
| @macro_role
|
||||
| @pattern
|
||||
| @stmt
|
||||
| @stmt_condition
|
||||
@@ -199,6 +200,26 @@ key_path_component_decl_refs(
|
||||
int decl_ref: @value_decl_or_none ref
|
||||
);
|
||||
|
||||
macro_roles(
|
||||
unique int id: @macro_role,
|
||||
int kind: int ref,
|
||||
int macro_syntax: int ref
|
||||
);
|
||||
|
||||
#keyset[id, index]
|
||||
macro_role_conformances(
|
||||
int id: @macro_role ref,
|
||||
int index: int ref,
|
||||
int conformance: @type_expr_or_none ref
|
||||
);
|
||||
|
||||
#keyset[id, index]
|
||||
macro_role_names(
|
||||
int id: @macro_role ref,
|
||||
int index: int ref,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
unspecified_elements(
|
||||
unique int id: @unspecified_element,
|
||||
string property: string ref,
|
||||
@@ -266,6 +287,7 @@ decl_members( //dir=decl
|
||||
@extension_decl
|
||||
| @function
|
||||
| @generic_type_decl
|
||||
| @macro_decl
|
||||
| @subscript_decl
|
||||
;
|
||||
|
||||
@@ -401,6 +423,7 @@ top_level_code_decls( //dir=decl
|
||||
@abstract_storage_decl
|
||||
| @enum_element_decl
|
||||
| @function
|
||||
| @macro_decl
|
||||
| @type_decl
|
||||
;
|
||||
|
||||
@@ -450,6 +473,25 @@ infix_operator_decl_precedence_groups( //dir=decl
|
||||
int precedence_group: @precedence_group_decl_or_none ref
|
||||
);
|
||||
|
||||
macro_decls( //dir=decl
|
||||
unique int id: @macro_decl,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
#keyset[id, index]
|
||||
macro_decl_parameters( //dir=decl
|
||||
int id: @macro_decl ref,
|
||||
int index: int ref,
|
||||
int parameter: @param_decl_or_none ref
|
||||
);
|
||||
|
||||
#keyset[id, index]
|
||||
macro_decl_roles( //dir=decl
|
||||
int id: @macro_decl ref,
|
||||
int index: int ref,
|
||||
int role: @macro_role_or_none ref
|
||||
);
|
||||
|
||||
postfix_operator_decls( //dir=decl
|
||||
unique int id: @postfix_operator_decl
|
||||
);
|
||||
@@ -2614,6 +2656,11 @@ variadic_sequence_types( //dir=type
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@macro_role_or_none =
|
||||
@macro_role
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@module_decl_or_none =
|
||||
@module_decl
|
||||
| @unspecified_element
|
||||
@@ -2694,6 +2741,11 @@ variadic_sequence_types( //dir=type
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@type_expr_or_none =
|
||||
@type_expr
|
||||
| @unspecified_element
|
||||
;
|
||||
|
||||
@type_repr_or_none =
|
||||
@type_repr
|
||||
| @unspecified_element
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Adds extraction of MacroDecl
|
||||
compatibility: partial
|
||||
@@ -16,6 +16,8 @@ predicate toBeTested(Element e) {
|
||||
or
|
||||
e instanceof PackArchetypeType
|
||||
or
|
||||
e instanceof MacroRole
|
||||
or
|
||||
exists(ModuleDecl m |
|
||||
m = e and
|
||||
not m.isBuiltinModule() and
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
| test.swift:2:1:2:50 | MacroDecl | getNumberOfGenericTypeParams: | 0 | getModule: | file://:0:0:0:0 | test | getNumberOfMembers: | 0 | getInterfaceType: | () -> () | getName: | A() | getNumberOfParameters: | 0 | getNumberOfRoles: | 1 |
|
||||
| test.swift:4:1:4:15 | MacroDecl | getNumberOfGenericTypeParams: | 0 | getModule: | file://:0:0:0:0 | test | getNumberOfMembers: | 0 | getInterfaceType: | () -> () | getName: | B() | getNumberOfParameters: | 0 | getNumberOfRoles: | 1 |
|
||||
| test.swift:7:1:7:15 | MacroDecl | getNumberOfGenericTypeParams: | 0 | getModule: | file://:0:0:0:0 | test | getNumberOfMembers: | 0 | getInterfaceType: | () -> () | getName: | C() | getNumberOfParameters: | 0 | getNumberOfRoles: | 2 |
|
||||
20
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl.ql
generated
Normal file
20
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl.ql
generated
Normal file
@@ -0,0 +1,20 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from
|
||||
MacroDecl x, int getNumberOfGenericTypeParams, ModuleDecl getModule, int getNumberOfMembers,
|
||||
Type getInterfaceType, string getName, int getNumberOfParameters, int getNumberOfRoles
|
||||
where
|
||||
toBeTested(x) and
|
||||
not x.isUnknown() and
|
||||
getNumberOfGenericTypeParams = x.getNumberOfGenericTypeParams() and
|
||||
getModule = x.getModule() and
|
||||
getNumberOfMembers = x.getNumberOfMembers() and
|
||||
getInterfaceType = x.getInterfaceType() and
|
||||
getName = x.getName() and
|
||||
getNumberOfParameters = x.getNumberOfParameters() and
|
||||
getNumberOfRoles = x.getNumberOfRoles()
|
||||
select x, "getNumberOfGenericTypeParams:", getNumberOfGenericTypeParams, "getModule:", getModule,
|
||||
"getNumberOfMembers:", getNumberOfMembers, "getInterfaceType:", getInterfaceType, "getName:",
|
||||
getName, "getNumberOfParameters:", getNumberOfParameters, "getNumberOfRoles:", getNumberOfRoles
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getGenericTypeParam.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getGenericTypeParam.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroDecl x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getGenericTypeParam(index)
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getMember.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getMember.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroDecl x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getMember(index)
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getParameter.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getParameter.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroDecl x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getParameter(index)
|
||||
@@ -0,0 +1,4 @@
|
||||
| test.swift:2:1:2:50 | MacroDecl | 0 | test.swift:1:14:1:26 | #freestanding(declaration) |
|
||||
| test.swift:4:1:4:15 | MacroDecl | 0 | test.swift:3:14:3:25 | #freestanding(expression) |
|
||||
| test.swift:7:1:7:15 | MacroDecl | 0 | test.swift:6:10:6:20 | @attached(extension) |
|
||||
| test.swift:7:1:7:15 | MacroDecl | 1 | test.swift:5:10:5:17 | @attached(member) |
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getRole.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroDecl_getRole.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroDecl x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getRole(index)
|
||||
@@ -0,0 +1,14 @@
|
||||
| file://:0:0:0:0 | #freestanding(declaration) | getKind: | 2 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(declaration) | getKind: | 2 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| file://:0:0:0:0 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| test.swift:1:14:1:26 | #freestanding(declaration) | getKind: | 2 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| test.swift:3:14:3:25 | #freestanding(expression) | getKind: | 1 | getMacroSyntax: | 0 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| test.swift:5:10:5:17 | @attached(member) | getKind: | 16 | getMacroSyntax: | 1 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
| test.swift:6:10:6:20 | @attached(extension) | getKind: | 256 | getMacroSyntax: | 1 | getNumberOfConformances: | 0 | getNumberOfNames: | 0 |
|
||||
14
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole.ql
generated
Normal file
14
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole.ql
generated
Normal file
@@ -0,0 +1,14 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroRole x, int getKind, int getMacroSyntax, int getNumberOfConformances, int getNumberOfNames
|
||||
where
|
||||
toBeTested(x) and
|
||||
not x.isUnknown() and
|
||||
getKind = x.getKind() and
|
||||
getMacroSyntax = x.getMacroSyntax() and
|
||||
getNumberOfConformances = x.getNumberOfConformances() and
|
||||
getNumberOfNames = x.getNumberOfNames()
|
||||
select x, "getKind:", getKind, "getMacroSyntax:", getMacroSyntax, "getNumberOfConformances:",
|
||||
getNumberOfConformances, "getNumberOfNames:", getNumberOfNames
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getConformance.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getConformance.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroRole x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getConformance(index)
|
||||
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getName.ql
generated
Normal file
7
swift/ql/test/extractor-tests/generated/decl/MacroDecl/MacroRole_getName.ql
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
// generated by codegen/codegen.py
|
||||
import codeql.swift.elements
|
||||
import TestUtils
|
||||
|
||||
from MacroRole x, int index
|
||||
where toBeTested(x) and not x.isUnknown()
|
||||
select x, index, x.getName(index)
|
||||
@@ -0,0 +1,7 @@
|
||||
@freestanding(declaration)
|
||||
macro A() = #externalMacro(module: "A", type: "A")
|
||||
@freestanding(expression)
|
||||
macro B() = B.B
|
||||
@attached(member)
|
||||
@attached(extension)
|
||||
macro C() = C.C
|
||||
@@ -143,7 +143,7 @@ class PatternBindingDecl(Decl):
|
||||
|
||||
class PoundDiagnosticDecl(Decl):
|
||||
""" A diagnostic directive, which is either `#error` or `#warning`."""
|
||||
kind: int | desc("""This is 1 for `#error` and 2 for `#warning`.""")
|
||||
kind: int | desc("""This is 1 for `#error` and 2 for `#warning`.""") | ql.internal
|
||||
message: "StringLiteralExpr" | child
|
||||
|
||||
class PrecedenceGroupDecl(Decl):
|
||||
@@ -1361,3 +1361,31 @@ class BorrowExpr(IdentityExpr):
|
||||
```
|
||||
"""
|
||||
pass
|
||||
|
||||
@qltest.test_with('MacroDecl')
|
||||
class MacroRole(AstNode):
|
||||
"""
|
||||
The role of a macro, for example #freestanding(declaration) or @attached(member).
|
||||
"""
|
||||
kind: int | doc("kind of this macro role (declaration, expression, member, etc.)") | ql.internal
|
||||
macro_syntax: int | doc("#freestanding or @attached") | ql.internal
|
||||
conformances: list[TypeExpr] | doc("conformances of this macro role")
|
||||
names: list[string] | doc("names of this macro role")
|
||||
|
||||
class MacroDecl(GenericContext, ValueDecl):
|
||||
"""
|
||||
A declaration of a macro. Some examples:
|
||||
|
||||
```
|
||||
@freestanding(declaration)
|
||||
macro A() = #externalMacro(module: "A", type: "A")
|
||||
@freestanding(expression)
|
||||
macro B() = Builtin.B
|
||||
@attached(member)
|
||||
macro C() = C.C
|
||||
```
|
||||
"""
|
||||
name: string | doc("name of this macro")
|
||||
parameters: list[ParamDecl] | doc("parameters of this macro")
|
||||
roles: list[MacroRole] | doc("roles of this macro")
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user