Merge branch 'main' into rdmarsh/cpp/use-taint-configuration-dtt

Fix test conflict
This commit is contained in:
Robert Marsh
2020-11-12 13:28:10 -08:00
175 changed files with 2221 additions and 1188 deletions

View File

@@ -228,7 +228,7 @@ private class ArrayContent extends Content, TArrayContent {
private predicate fieldStoreStepNoChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(StoreInstruction store, Class c |
store = node2.asInstruction() and
store.getSourceValue() = node1.asInstruction() and
store.getSourceValueOperand() = node1.asOperand() and
getWrittenField(store, f.(FieldContent).getAField(), c) and
f.hasOffset(c, _, _)
)
@@ -253,10 +253,10 @@ private predicate getWrittenField(Instruction instr, Field f, Class c) {
}
private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode node2) {
exists(StoreInstruction store, ChiInstruction chi |
node1.asInstruction() = store and
exists(ChiPartialOperand operand, ChiInstruction chi |
chi.getPartialOperand() = operand and
node1.asOperand() = operand and
node2.asInstruction() = chi and
chi.getPartial() = store and
exists(Class c |
c = chi.getResultType() and
exists(int startBit, int endBit |
@@ -264,7 +264,7 @@ private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode n
f.hasOffset(c, startBit, endBit)
)
or
getWrittenField(store, f.getAField(), c) and
getWrittenField(operand.getDef(), f.getAField(), c) and
f.hasOffset(c, _, _)
)
)
@@ -272,8 +272,13 @@ private predicate fieldStoreStepChi(Node node1, FieldContent f, PostUpdateNode n
private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode node2) {
a = TArrayContent() and
exists(StoreInstruction store |
node1.asInstruction() = store and
exists(ChiPartialOperand operand, ChiInstruction chi, StoreInstruction store |
chi.getPartialOperand() = operand and
store = operand.getDef() and
node1.asOperand() = operand and
// This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
// and `PointerStoreNode` require it in their characteristic predicates.
node2.asInstruction() = chi and
(
// `x[i] = taint()`
// This matches the characteristic predicate in `ArrayStoreNode`.
@@ -282,10 +287,7 @@ private predicate arrayStoreStepChi(Node node1, ArrayContent a, PostUpdateNode n
// `*p = taint()`
// This matches the characteristic predicate in `PointerStoreNode`.
store.getDestinationAddress().(CopyValueInstruction).getUnary() instanceof LoadInstruction
) and
// This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
// and `PointerStoreNode` require it in their characteristic predicates.
node2.asInstruction().(ChiInstruction).getPartial() = store
)
)
}
@@ -306,7 +308,7 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
private predicate fieldStoreStepAfterArraySuppression(
Node node1, FieldContent f, PostUpdateNode node2
) {
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi, Class c |
exists(WriteSideEffectInstruction write, ChiInstruction chi, Class c |
not chi.isResultConflated() and
node1.asInstruction() = chi and
node2.asInstruction() = chi and
@@ -334,17 +336,17 @@ private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
* `node2`.
*/
private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
exists(LoadInstruction load |
node2.asInstruction() = load and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
exists(LoadOperand operand |
node2.asOperand() = operand and
node1.asInstruction() = operand.getAnyDef() and
exists(Class c |
c = load.getSourceValueOperand().getAnyDef().getResultType() and
c = operand.getAnyDef().getResultType() and
exists(int startBit, int endBit |
load.getSourceValueOperand().getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
operand.getUsedInterval(unbindInt(startBit), unbindInt(endBit)) and
f.hasOffset(c, startBit, endBit)
)
or
getLoadedField(load, f.getAField(), c) and
getLoadedField(operand.getUse(), f.getAField(), c) and
f.hasOffset(c, _, _)
)
)
@@ -365,7 +367,7 @@ private predicate fieldReadStep(Node node1, FieldContent f, Node node2) {
*/
predicate suppressArrayRead(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi |
exists(WriteSideEffectInstruction write, ChiInstruction chi |
node1.asInstruction() = write and
node2.asInstruction() = chi and
chi.getPartial() = write and
@@ -386,20 +388,20 @@ private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) {
result = skipOneCopyValueInstructionRec(copy.getUnary())
}
private Instruction skipCopyValueInstructions(Instruction instr) {
not result instanceof CopyValueInstruction and result = instr
private Instruction skipCopyValueInstructions(Operand op) {
not result instanceof CopyValueInstruction and result = op.getDef()
or
result = skipOneCopyValueInstructionRec(instr)
result = skipOneCopyValueInstructionRec(op.getDef())
}
private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
// Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
exists(LoadInstruction load, Instruction address |
load.getSourceValueOperand().isDefinitionInexact() and
node1.asInstruction() = load.getSourceValueOperand().getAnyDef() and
load = node2.asInstruction() and
address = skipCopyValueInstructions(load.getSourceAddress()) and
exists(LoadOperand operand, Instruction address |
operand.isDefinitionInexact() and
node1.asInstruction() = operand.getAnyDef() and
operand = node2.asOperand() and
address = skipCopyValueInstructions(operand.getAddressOperand()) and
(
address instanceof LoadInstruction or
address instanceof ArrayToPointerConvertInstruction or
@@ -420,18 +422,18 @@ private predicate arrayReadStep(Node node1, ArrayContent a, Node node2) {
* use(x);
* ```
* the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition
* is a `BufferMayWriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
* is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
* from the access path.
*/
private predicate exactReadStep(Node node1, ArrayContent a, Node node2) {
a = TArrayContent() and
exists(BufferMayWriteSideEffectInstruction write, ChiInstruction chi |
exists(WriteSideEffectInstruction write, ChiInstruction chi |
not chi.isResultConflated() and
chi.getPartial() = write and
node1.asInstruction() = write and
node2.asInstruction() = chi and
// To distinquish this case from the `arrayReadStep` case we require that the entire variable was
// overwritten by the `BufferMayWriteSideEffectInstruction` (i.e., there is a load that reads the
// overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the
// entire variable).
exists(LoadInstruction load | load.getSourceValue() = chi)
)

View File

@@ -396,16 +396,16 @@ private FieldAddressInstruction getFieldInstruction(Instruction instr) {
/**
* The target of a `fieldStoreStepAfterArraySuppression` store step, which is used to convert
* an `ArrayContent` to a `FieldContent` when the `BufferMayWriteSideEffect` instruction stores
* an `ArrayContent` to a `FieldContent` when the `WriteSideEffect` instruction stores
* into a field. See the QLDoc for `suppressArrayRead` for an example of where such a conversion
* is inserted.
*/
private class BufferMayWriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode {
private class WriteSideEffectFieldStoreQualifierNode extends PartialDefinitionNode {
override ChiInstruction instr;
BufferMayWriteSideEffectInstruction write;
WriteSideEffectInstruction write;
FieldAddressInstruction field;
BufferMayWriteSideEffectFieldStoreQualifierNode() {
WriteSideEffectFieldStoreQualifierNode() {
not instr.isResultConflated() and
instr.getPartial() = write and
field = getFieldInstruction(write.getDestinationAddress())

View File

@@ -121,6 +121,14 @@ postWithInFlow
| complex.cpp:12:22:12:27 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:26:14:26 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:14:33:14:33 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:22:11:22:17 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:25:7:25:7 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:42:16:42:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:43:16:43:16 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:53:12:53:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:54:12:54:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:55:12:55:12 | Chi | PostUpdateNode should not be the target of local flow. |
| complex.cpp:56:12:56:12 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:20:24:20:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:21:24:21:29 | Chi | PostUpdateNode should not be the target of local flow. |
| constructors.cpp:23:28:23:28 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -4,9 +4,8 @@ edges
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] |
| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:28:57:30 | call to get |
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | B output argument [c] |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Store |
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:100:5:100:13 | Chi [a] | A.cpp:103:14:103:14 | *c [a] |
| A.cpp:100:5:100:13 | Store | A.cpp:100:5:100:13 | Chi [a] |
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
| A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] |
@@ -14,11 +13,9 @@ edges
| A.cpp:131:8:131:8 | Chi [c] | A.cpp:132:13:132:13 | c |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:131:8:131:8 | Chi [c] |
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
| A.cpp:142:7:142:20 | Store | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Store |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Chi [c] |
| A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:143:7:143:31 | Store | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Store |
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | Chi [b] |
| A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | D output argument [b] |
| A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b |
| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] |
@@ -27,20 +24,16 @@ edges
| C.cpp:18:12:18:18 | C output argument [s1] | C.cpp:27:8:27:11 | *#this [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | C.cpp:27:8:27:11 | *#this [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | C.cpp:24:5:24:25 | Chi [s1] |
| C.cpp:22:12:22:21 | Store | C.cpp:22:12:22:21 | Chi [s1] |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Store |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | Chi [s1] |
| C.cpp:24:5:24:25 | Chi [s1] | C.cpp:18:12:18:18 | C output argument [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | C.cpp:18:12:18:18 | C output argument [s3] |
| C.cpp:24:5:24:25 | Store | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Store |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | Chi [s3] |
| C.cpp:27:8:27:11 | *#this [s1] | C.cpp:29:10:29:11 | s1 |
| C.cpp:27:8:27:11 | *#this [s3] | C.cpp:31:10:31:11 | s3 |
| aliasing.cpp:9:3:9:22 | Chi [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
| aliasing.cpp:9:3:9:22 | Store | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Store |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Chi [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] |
| aliasing.cpp:13:3:13:21 | Store | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Store |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | Chi [m1] |
| aliasing.cpp:25:17:25:19 | Chi [m1] | aliasing.cpp:29:11:29:12 | m1 |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:25:17:25:19 | Chi [m1] |
| aliasing.cpp:26:19:26:20 | Chi [m1] | aliasing.cpp:30:11:30:12 | m1 |
@@ -48,15 +41,13 @@ edges
| aliasing.cpp:37:13:37:22 | call to user_input | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:11:42:20 | call to user_input | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | aliasing.cpp:61:13:61:14 | Store [m1] |
| aliasing.cpp:60:3:60:22 | Store | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Store |
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | Chi [m1] |
| aliasing.cpp:61:13:61:14 | Store [m1] | aliasing.cpp:62:14:62:15 | m1 |
| aliasing.cpp:79:11:79:20 | call to user_input | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:10:86:19 | call to user_input | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | aliasing.cpp:100:14:100:14 | Store [m1] |
| aliasing.cpp:98:3:98:21 | Store | aliasing.cpp:98:3:98:21 | Chi [m1] |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Store |
| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | Chi [m1] |
| aliasing.cpp:100:14:100:14 | Store [m1] | aliasing.cpp:102:8:102:10 | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument [array content] |
@@ -67,8 +58,7 @@ edges
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Chi [array content] | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument [array content] |
| aliasing.cpp:106:3:106:20 | Store | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Store |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:20 | Chi [array content] |
| aliasing.cpp:121:15:121:16 | Chi [array content] | aliasing.cpp:122:8:122:12 | access to array |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | aliasing.cpp:121:15:121:16 | Chi [array content] |
| aliasing.cpp:126:15:126:20 | Chi [array content] | aliasing.cpp:127:8:127:16 | * ... |
@@ -106,20 +96,16 @@ edges
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
| by_reference.cpp:84:3:84:25 | Store | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Store |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | Chi [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Chi [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] |
| by_reference.cpp:88:3:88:24 | Store | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Store |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | Chi [a] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | Chi [array content] | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument [array content] |
| by_reference.cpp:92:3:92:20 | Store | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Store |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:20 | Chi [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:124:15:124:21 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | Chi [array content] | by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] |
| by_reference.cpp:96:3:96:19 | Store | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Store |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:19 | Chi [array content] |
| by_reference.cpp:102:21:102:39 | Chi [a] | by_reference.cpp:110:27:110:27 | a |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:21:102:39 | Chi [a] |
| by_reference.cpp:104:15:104:22 | Chi | by_reference.cpp:104:15:104:22 | Chi [a] |
@@ -141,18 +127,34 @@ edges
| by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a |
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [array content] | by_reference.cpp:128:15:128:23 | Chi |
| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | Chi [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:42:16:42:16 | Chi [b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:43:18:43:18 | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | Chi [a_] |
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] |
| complex.cpp:54:12:54:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | Chi [b_] |
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | Chi [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] |
| complex.cpp:56:12:56:12 | Chi [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:40:17:40:17 | *b [a_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:56:12:56:12 | Chi [a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:40:17:40:17 | *b [b_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | Chi [b_] |
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] |
| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] |
@@ -184,19 +186,16 @@ edges
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
| simple.cpp:83:9:83:28 | Chi [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
| simple.cpp:83:9:83:28 | Store | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store |
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Chi [f1] |
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
| simple.cpp:93:20:93:20 | Store [i] | simple.cpp:94:13:94:13 | i |
| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:12:15:12 | a |
| struct_init.c:20:20:20:29 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:20:20:20:29 | Store | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Store |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | Chi [a] |
| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:22:11:22:11 | a |
| struct_init.c:27:7:27:16 | Chi [a] | struct_init.c:14:24:14:25 | *ab [a] |
| struct_init.c:27:7:27:16 | Store | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Store |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | Chi [a] |
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
nodes
| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] |
@@ -208,7 +207,6 @@ nodes
| A.cpp:57:28:57:30 | call to get | semmle.label | call to get |
| A.cpp:98:12:98:18 | new | semmle.label | new |
| A.cpp:100:5:100:13 | Chi [a] | semmle.label | Chi [a] |
| A.cpp:100:5:100:13 | Store | semmle.label | Store |
| A.cpp:103:14:103:14 | *c [a] | semmle.label | *c [a] |
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:126:5:126:5 | Chi [c] | semmle.label | Chi [c] |
@@ -218,10 +216,8 @@ nodes
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:13:132:13 | c | semmle.label | c |
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
| A.cpp:142:7:142:20 | Store | semmle.label | Store |
| A.cpp:142:14:142:20 | new | semmle.label | new |
| A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] |
| A.cpp:143:7:143:31 | Store | semmle.label | Store |
| A.cpp:143:25:143:31 | new | semmle.label | new |
| A.cpp:150:12:150:18 | new | semmle.label | new |
| A.cpp:151:12:151:24 | Chi [b] | semmle.label | Chi [b] |
@@ -233,21 +229,17 @@ nodes
| C.cpp:18:12:18:18 | C output argument [s1] | semmle.label | C output argument [s1] |
| C.cpp:18:12:18:18 | C output argument [s3] | semmle.label | C output argument [s3] |
| C.cpp:22:12:22:21 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:22:12:22:21 | Store | semmle.label | Store |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:25 | Chi [s1] | semmle.label | Chi [s1] |
| C.cpp:24:5:24:25 | Chi [s3] | semmle.label | Chi [s3] |
| C.cpp:24:5:24:25 | Store | semmle.label | Store |
| C.cpp:24:16:24:25 | new | semmle.label | new |
| C.cpp:27:8:27:11 | *#this [s1] | semmle.label | *#this [s1] |
| C.cpp:27:8:27:11 | *#this [s3] | semmle.label | *#this [s3] |
| C.cpp:29:10:29:11 | s1 | semmle.label | s1 |
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
| aliasing.cpp:9:3:9:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:9:3:9:22 | Store | semmle.label | Store |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:13:3:13:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:13:3:13:21 | Store | semmle.label | Store |
| aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:25:17:25:19 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] |
@@ -260,7 +252,6 @@ nodes
| aliasing.cpp:42:11:42:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
| aliasing.cpp:60:3:60:22 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:60:3:60:22 | Store | semmle.label | Store |
| aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:61:13:61:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 |
@@ -271,12 +262,10 @@ nodes
| aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| aliasing.cpp:98:3:98:21 | Chi [m1] | semmle.label | Chi [m1] |
| aliasing.cpp:98:3:98:21 | Store | semmle.label | Store |
| aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:100:14:100:14 | Store [m1] | semmle.label | Store [m1] |
| aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... |
| aliasing.cpp:106:3:106:20 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:106:3:106:20 | Store | semmle.label | Store |
| aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:121:15:121:16 | Chi [array content] | semmle.label | Chi [array content] |
| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument [array content] | semmle.label | taint_a_ptr output argument [array content] |
@@ -330,16 +319,12 @@ nodes
| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:84:3:84:25 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:84:3:84:25 | Store | semmle.label | Store |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:88:3:88:24 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:88:3:88:24 | Store | semmle.label | Store |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:92:3:92:20 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:92:3:92:20 | Store | semmle.label | Store |
| by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:96:3:96:19 | Chi [array content] | semmle.label | Chi [array content] |
| by_reference.cpp:96:3:96:19 | Store | semmle.label | Store |
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:102:21:102:39 | Chi [a] | semmle.label | Chi [a] |
| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] |
@@ -371,15 +356,21 @@ nodes
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
| complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] |
| complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] |
| complex.cpp:42:16:42:16 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:42:16:42:16 | a output argument [b_] | semmle.label | a output argument [b_] |
| complex.cpp:42:18:42:18 | call to a | semmle.label | call to a |
| complex.cpp:43:18:43:18 | call to b | semmle.label | call to b |
| complex.cpp:53:12:53:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:53:12:53:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:54:12:54:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:54:12:54:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:55:12:55:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:55:12:55:12 | setA output argument [a_] | semmle.label | setA output argument [a_] |
| complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input |
| complex.cpp:56:12:56:12 | Chi [a_] | semmle.label | Chi [a_] |
| complex.cpp:56:12:56:12 | Chi [b_] | semmle.label | Chi [b_] |
| complex.cpp:56:12:56:12 | setB output argument [a_] | semmle.label | setB output argument [a_] |
| complex.cpp:56:12:56:12 | setB output argument [b_] | semmle.label | setB output argument [b_] |
| complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input |
@@ -415,7 +406,6 @@ nodes
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
| simple.cpp:67:13:67:13 | i | semmle.label | i |
| simple.cpp:83:9:83:28 | Chi [f1] | semmle.label | Chi [f1] |
| simple.cpp:83:9:83:28 | Store | semmle.label | Store |
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
| simple.cpp:92:5:92:22 | Store [i] | semmle.label | Store [i] |
@@ -425,11 +415,9 @@ nodes
| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] |
| struct_init.c:15:12:15:12 | a | semmle.label | a |
| struct_init.c:20:20:20:29 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:20:20:20:29 | Store | semmle.label | Store |
| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input |
| struct_init.c:22:11:22:11 | a | semmle.label | a |
| struct_init.c:27:7:27:16 | Chi [a] | semmle.label | Chi [a] |
| struct_init.c:27:7:27:16 | Store | semmle.label | Store |
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
| struct_init.c:31:23:31:23 | a | semmle.label | a |
#select

View File

@@ -294,22 +294,16 @@
| complex.cpp:11:22:11:23 | a_ | AST only |
| complex.cpp:12:22:12:23 | b_ | AST only |
| complex.cpp:42:8:42:8 | b | AST only |
| complex.cpp:42:10:42:14 | inner | AST only |
| complex.cpp:42:16:42:16 | f | AST only |
| complex.cpp:43:8:43:8 | b | AST only |
| complex.cpp:43:10:43:14 | inner | AST only |
| complex.cpp:43:16:43:16 | f | AST only |
| complex.cpp:53:3:53:4 | b1 | AST only |
| complex.cpp:53:6:53:10 | inner | AST only |
| complex.cpp:53:12:53:12 | f | AST only |
| complex.cpp:54:3:54:4 | b2 | AST only |
| complex.cpp:54:6:54:10 | inner | AST only |
| complex.cpp:54:12:54:12 | f | AST only |
| complex.cpp:55:3:55:4 | b3 | AST only |
| complex.cpp:55:6:55:10 | inner | AST only |
| complex.cpp:55:12:55:12 | f | AST only |
| complex.cpp:56:3:56:4 | b3 | AST only |
| complex.cpp:56:6:56:10 | inner | AST only |
| complex.cpp:56:12:56:12 | f | AST only |
| complex.cpp:59:7:59:8 | b1 | AST only |
| complex.cpp:62:7:62:8 | b2 | AST only |

View File

@@ -51,6 +51,12 @@
| by_reference.cpp:128:15:128:20 | pouter |
| complex.cpp:11:22:11:23 | this |
| complex.cpp:12:22:12:23 | this |
| complex.cpp:42:10:42:14 | inner |
| complex.cpp:43:10:43:14 | inner |
| complex.cpp:53:6:53:10 | inner |
| complex.cpp:54:6:54:10 | inner |
| complex.cpp:55:6:55:10 | inner |
| complex.cpp:56:6:56:10 | inner |
| constructors.cpp:20:24:20:25 | this |
| constructors.cpp:21:24:21:25 | this |
| qualifiers.cpp:9:30:9:33 | this |

View File

@@ -1491,6 +1491,7 @@ postWithInFlow
| conditional_destructors.cpp:18:13:18:19 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:65:19:65:45 | Store | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:17:82:55 | Chi | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:45:82:48 | Chi | PostUpdateNode should not be the target of local flow. |
| defdestructordeleteexpr.cpp:4:9:4:15 | Chi | PostUpdateNode should not be the target of local flow. |
| deleteexpr.cpp:7:9:7:15 | Chi | PostUpdateNode should not be the target of local flow. |
@@ -1541,6 +1542,18 @@ postWithInFlow
| ir.cpp:659:9:659:14 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:660:13:660:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:661:9:661:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:662:9:662:19 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:663:5:663:5 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:745:8:745:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:748:10:748:10 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:754:8:754:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:757:12:757:12 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:763:8:763:8 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:766:13:766:13 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:775:15:775:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:784:15:784:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:793:15:793:15 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:943:3:943:11 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:947:3:947:25 | Chi | PostUpdateNode should not be the target of local flow. |
| ir.cpp:962:17:962:47 | Chi | PostUpdateNode should not be the target of local flow. |
@@ -1564,3 +1577,4 @@ postWithInFlow
| range_analysis.c:102:5:102:15 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:3:2:3:8 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:21:2:21:12 | Chi | PostUpdateNode should not be the target of local flow. |
| static_init_templates.cpp:240:7:240:7 | Chi | PostUpdateNode should not be the target of local flow. |

View File

@@ -5,8 +5,6 @@ edges
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | Argument 1 indirection |
| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | Argument 1 indirection |
| tests.c:28:22:28:25 | argv | tests.c:31:15:31:23 | buffer100 |
@@ -15,14 +13,6 @@ edges
| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | Argument 2 indirection |
| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 |
| tests.c:28:22:28:25 | argv | tests.c:33:21:33:29 | buffer100 |
| tests.c:28:22:28:28 | access to array | tests.c:28:22:28:28 | (const char *)... |
| tests.c:28:22:28:28 | access to array | tests.c:28:22:28:28 | access to array |
| tests.c:28:22:28:28 | access to array | tests.c:31:15:31:23 | Argument 1 indirection |
| tests.c:28:22:28:28 | access to array | tests.c:31:15:31:23 | buffer100 |
| tests.c:28:22:28:28 | access to array | tests.c:33:21:33:29 | Argument 2 indirection |
| tests.c:28:22:28:28 | access to array | tests.c:33:21:33:29 | buffer100 |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array |
@@ -35,10 +25,6 @@ edges
| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | Argument 2 indirection |
| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 |
| tests.c:29:28:29:31 | argv | tests.c:33:21:33:29 | buffer100 |
| tests.c:29:28:29:34 | access to array | tests.c:31:15:31:23 | Argument 1 indirection |
| tests.c:29:28:29:34 | access to array | tests.c:31:15:31:23 | buffer100 |
| tests.c:29:28:29:34 | access to array | tests.c:33:21:33:29 | Argument 2 indirection |
| tests.c:29:28:29:34 | access to array | tests.c:33:21:33:29 | buffer100 |
| tests.c:31:15:31:23 | buffer100 | tests.c:33:21:33:29 | Argument 2 indirection |
| tests.c:31:15:31:23 | buffer100 | tests.c:33:21:33:29 | buffer100 |
| tests.c:31:15:31:23 | scanf output argument | tests.c:33:21:33:29 | Argument 2 indirection |
@@ -49,10 +35,6 @@ edges
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array |
| tests.c:34:10:34:16 | access to array | tests.c:34:10:34:16 | (const char *)... |
| tests.c:34:10:34:16 | access to array | tests.c:34:10:34:16 | access to array |
nodes
| tests.c:28:22:28:25 | argv | semmle.label | argv |
| tests.c:28:22:28:25 | argv | semmle.label | argv |

View File

@@ -5,10 +5,6 @@ edges
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:15 | (const char *)... |
| argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:15 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array |
@@ -39,8 +35,6 @@ edges
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array |
@@ -51,16 +45,10 @@ edges
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... |
| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:106:9:106:13 | (const char *)... |
| argvLocal.c:106:9:106:13 | access to array | argvLocal.c:106:9:106:13 | access to array |
| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:110:9:110:11 | (const char *)... |
| argvLocal.c:110:9:110:11 | * ... | argvLocal.c:110:9:110:11 | * ... |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | Argument 0 indirection |
| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 |

View File

@@ -59,9 +59,8 @@ edges
| test.cpp:227:24:227:37 | (const char *)... | test.cpp:229:9:229:18 | local_size |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:279:17:279:20 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | Chi [array content] | test.cpp:295:18:295:21 | get_size output argument [array content] |
| test.cpp:241:2:241:32 | Store | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Store |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Store |
| test.cpp:241:18:241:23 | call to getenv | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:241:18:241:31 | (const char *)... | test.cpp:241:2:241:32 | Chi [array content] |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:25 | call to getenv | test.cpp:253:11:253:29 | ... * ... |
| test.cpp:249:20:249:33 | (const char *)... | test.cpp:253:11:253:29 | ... * ... |
@@ -144,7 +143,7 @@ nodes
| test.cpp:235:2:235:9 | Argument 0 | semmle.label | Argument 0 |
| test.cpp:237:2:237:8 | Argument 0 | semmle.label | Argument 0 |
| test.cpp:241:2:241:32 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:241:2:241:32 | Store | semmle.label | Store |
| test.cpp:241:2:241:32 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:241:18:241:23 | call to getenv | semmle.label | call to getenv |
| test.cpp:241:18:241:31 | (const char *)... | semmle.label | (const char *)... |
| test.cpp:249:20:249:25 | call to getenv | semmle.label | call to getenv |

View File

@@ -43,13 +43,11 @@ edges
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
| test.cpp:13:2:13:15 | Chi [array content] | test.cpp:30:13:30:14 | get_rand2 output argument [array content] |
| test.cpp:13:2:13:15 | Store | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Store |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Store |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [array content] |
| test.cpp:18:2:18:14 | Chi [array content] | test.cpp:36:13:36:13 | get_rand3 output argument [array content] |
| test.cpp:18:2:18:14 | Store | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Store |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Store |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [array content] |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
@@ -111,11 +109,11 @@ nodes
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
| test.cpp:13:2:13:15 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:13:2:13:15 | Store | semmle.label | Store |
| test.cpp:13:2:13:15 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
| test.cpp:18:2:18:14 | Chi [array content] | semmle.label | Chi [array content] |
| test.cpp:18:2:18:14 | Store | semmle.label | Store |
| test.cpp:18:2:18:14 | ChiPartial | semmle.label | ChiPartial |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand |

View File

@@ -0,0 +1,5 @@
lgtm,codescanning
* Attribute extraction has been extended to extract attributes not only from source
code, but from referenced assemblies too. This change may lead to more results in
queries that rely on attributes. Note that, as more attributes might be extracted,
the DB size might increase.

View File

@@ -198,12 +198,12 @@ namespace Semmle.Extraction.CSharp
/// Perform an analysis on an assembly.
/// </summary>
/// <param name="assembly">Assembly to analyse.</param>
private void AnalyseAssembly(PortableExecutableReference assembly)
private void AnalyseReferenceAssembly(PortableExecutableReference assembly)
{
// CIL first - it takes longer.
if (options.CIL)
extractionTasks.Add(() => DoExtractCIL(assembly));
extractionTasks.Add(() => DoAnalyseAssembly(assembly));
extractionTasks.Add(() => DoAnalyseReferenceAssembly(assembly));
}
private static bool FileIsUpToDate(string src, string dest)
@@ -250,7 +250,7 @@ namespace Semmle.Extraction.CSharp
/// extraction within the snapshot.
/// </summary>
/// <param name="r">The assembly to extract.</param>
private void DoAnalyseAssembly(PortableExecutableReference r)
private void DoAnalyseReferenceAssembly(PortableExecutableReference r)
{
try
{
@@ -294,6 +294,8 @@ namespace Semmle.Extraction.CSharp
AnalyseNamespace(cx, module.GlobalNamespace);
}
Entities.Attribute.ExtractAttributes(cx, assembly, Extraction.Entities.Assembly.Create(cx, assembly.GetSymbolLocation()));
cx.PopulateAll();
}
}
@@ -335,7 +337,7 @@ namespace Semmle.Extraction.CSharp
{
foreach (var r in compilation.References.OfType<PortableExecutableReference>())
{
AnalyseAssembly(r);
AnalyseReferenceAssembly(r);
}
}

View File

@@ -1,82 +1,134 @@
using System.IO;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
internal class Attribute : FreshEntity, IExpressionParentEntity
internal class Attribute : CachedEntity<AttributeData>, IExpressionParentEntity
{
bool IExpressionParentEntity.IsTopLevelParent => true;
private readonly AttributeData attribute;
private readonly AttributeSyntax attributeSyntax;
private readonly IEntity entity;
public Attribute(Context cx, AttributeData attribute, IEntity entity)
: base(cx)
private Attribute(Context cx, AttributeData attributeData, IEntity entity)
: base(cx, attributeData)
{
this.attribute = attribute;
this.attributeSyntax = attributeData.ApplicationSyntaxReference?.GetSyntax() as AttributeSyntax;
this.entity = entity;
TryPopulate();
}
protected override void Populate(TextWriter trapFile)
public override void WriteId(TextWriter trapFile)
{
if (attribute.ApplicationSyntaxReference != null)
if (ReportingLocation?.IsInSource == true)
{
// !! Extract attributes from assemblies.
// This is harder because the "expression" entities presume the
// existence of a syntax tree. This is not the case for compiled
// attributes.
var syntax = attribute.ApplicationSyntaxReference.GetSyntax() as AttributeSyntax;
ExtractAttribute(cx.TrapWriter.Writer, syntax, attribute.AttributeClass, entity);
trapFile.WriteSubId(Location);
trapFile.Write(";attribute");
}
else
{
trapFile.Write('*');
}
}
public Attribute(Context cx, AttributeSyntax attribute, IEntity entity)
: base(cx)
public override void WriteQuotedId(TextWriter trapFile)
{
var info = cx.GetSymbolInfo(attribute);
ExtractAttribute(cx.TrapWriter.Writer, attribute, info.Symbol.ContainingType, entity);
if (ReportingLocation?.IsInSource == true)
{
base.WriteQuotedId(trapFile);
}
else
{
trapFile.Write('*');
}
}
private void ExtractAttribute(System.IO.TextWriter trapFile, AttributeSyntax syntax, ITypeSymbol attributeClass, IEntity entity)
public override void Populate(TextWriter trapFile)
{
var type = Type.Create(cx, attributeClass);
var type = Type.Create(Context, symbol.AttributeClass);
trapFile.attributes(this, type.TypeRef, entity);
trapFile.attribute_location(this, Location);
trapFile.attribute_location(this, cx.Create(syntax.Name.GetLocation()));
if (cx.Extractor.OutputPath != null)
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(cx));
TypeMention.Create(cx, syntax.Name, this, type);
if (syntax.ArgumentList != null)
if (attributeSyntax is object)
{
cx.PopulateLater(() =>
if (Context.Extractor.OutputPath != null)
{
var child = 0;
foreach (var arg in syntax.ArgumentList.Arguments)
{
var expr = Expression.Create(cx, arg.Expression, this, child++);
if (!(arg.NameEquals is null))
{
trapFile.expr_argument_name(expr, arg.NameEquals.Name.Identifier.Text);
}
}
});
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
}
TypeMention.Create(Context, attributeSyntax.Name, this, type);
}
ExtractArguments(trapFile);
}
private void ExtractArguments(TextWriter trapFile)
{
var childIndex = 0;
foreach (var constructorArgument in symbol.ConstructorArguments)
{
CreateExpressionFromArgument(
constructorArgument,
attributeSyntax?.ArgumentList.Arguments[childIndex].Expression,
this,
childIndex++);
}
foreach (var namedArgument in symbol.NamedArguments)
{
var expr = CreateExpressionFromArgument(
namedArgument.Value,
attributeSyntax?.ArgumentList.Arguments.Single(a => a.NameEquals?.Name?.Identifier.Text == namedArgument.Key).Expression,
this,
childIndex++);
if (expr is object)
{
trapFile.expr_argument_name(expr, namedArgument.Key);
}
}
}
private Expression CreateExpressionFromArgument(TypedConstant constant, ExpressionSyntax syntax, IExpressionParentEntity parent,
int childIndex)
{
return syntax is null
? Expression.CreateGenerated(Context, constant, parent, childIndex, Location)
: Expression.Create(Context, syntax, parent, childIndex);
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
public override Microsoft.CodeAnalysis.Location ReportingLocation => attributeSyntax?.Name.GetLocation();
private Semmle.Extraction.Entities.Location location;
private Semmle.Extraction.Entities.Location Location =>
location ?? (location = Semmle.Extraction.Entities.Location.Create(Context, attributeSyntax is null ? entity.ReportingLocation : attributeSyntax.Name.GetLocation()));
public override bool NeedsPopulation => true;
public static void ExtractAttributes(Context cx, ISymbol symbol, IEntity entity)
{
foreach (var attribute in symbol.GetAttributes())
{
new Attribute(cx, attribute, entity);
Create(cx, attribute, entity);
}
}
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.OptionalLabel;
public static Attribute Create(Context cx, AttributeData attributeData, IEntity entity)
{
var init = (attributeData, entity);
return AttributeFactory.Instance.CreateEntity(cx, attributeData, init);
}
private class AttributeFactory : ICachedEntityFactory<(AttributeData attributeData, IEntity receiver), Attribute>
{
public static readonly AttributeFactory Instance = new AttributeFactory();
public Attribute Create(Context cx, (AttributeData attributeData, IEntity receiver) init) =>
new Attribute(cx, init.attributeData, init.receiver);
}
}
}

View File

@@ -1,9 +1,11 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities.Expressions;
using Semmle.Extraction.CSharp.Populators;
using Semmle.Extraction.Entities;
using Semmle.Extraction.Kinds;
using System;
using System.IO;
using System.Linq;
@@ -125,6 +127,42 @@ namespace Semmle.Extraction.CSharp.Entities
private static bool ContainsPattern(SyntaxNode node) =>
node is PatternSyntax || node is VariableDesignationSyntax || node.ChildNodes().Any(ContainsPattern);
/// <summary>
/// Creates a generated expression from a typed constant.
/// </summary>
public static Expression CreateGenerated(Context cx, TypedConstant constant, IExpressionParentEntity parent,
int childIndex, Semmle.Extraction.Entities.Location location)
{
if (constant.IsNull)
{
return Literal.CreateGeneratedNullLiteral(cx, parent, childIndex, location);
}
switch (constant.Kind)
{
case TypedConstantKind.Primitive:
return Literal.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, location);
case TypedConstantKind.Enum:
// Enum value is generated in the following format: (Enum)value
Action<Expression, int> createChild = (parent, index) => Literal.CreateGenerated(cx, parent, index, ((INamedTypeSymbol)constant.Type).EnumUnderlyingType, constant.Value, location);
var cast = Cast.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Value, createChild, location);
return cast;
case TypedConstantKind.Type:
var type = ((ITypeSymbol)constant.Value).OriginalDefinition;
return TypeOf.CreateGenerated(cx, parent, childIndex, type, location);
case TypedConstantKind.Array:
// Single dimensional arrays are in the following format:
// * new Type[N] { item1, item2, ..., itemN }
// * new Type[0]
//
// itemI is generated recursively.
return NormalArrayCreation.CreateGenerated(cx, parent, childIndex, constant.Type, constant.Values, location);
default:
cx.ExtractionError("Couldn't extract constant in attribute", constant.ToString(), location);
return null;
}
}
/// <summary>
/// Adapt the operator kind depending on whether it's a dynamic call or a user-operator call.
/// </summary>

View File

@@ -2,6 +2,7 @@ using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -10,6 +11,8 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
internal abstract class ArrayCreation<TSyntaxNode> : Expression<TSyntaxNode>
where TSyntaxNode : ExpressionSyntax
{
protected const int InitializerIndex = -1;
protected ArrayCreation(ExpressionNodeInfo info) : base(info) { }
}
@@ -48,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
if (!(Initializer is null))
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Initializer, this, InitializerIndex));
}
if (explicitlySized)
@@ -66,17 +69,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
return;
}
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, cx.Compilation.GetSpecialType(Microsoft.CodeAnalysis.SpecialType.System_Int32)), NullableAnnotation.None),
Location,
ExprKind.INT_LITERAL,
this,
level,
true,
initializer.Expressions.Count.ToString());
new Expression(info);
Literal.CreateGenerated(cx, this, level, cx.Compilation.GetSpecialType(SpecialType.System_Int32), initializer.Expressions.Count, Location);
initializer = initializer.Expressions.FirstOrDefault() as InitializerExpressionSyntax;
}
@@ -92,6 +85,37 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public override InitializerExpressionSyntax Initializer => Syntax.Initializer;
public static Expression Create(ExpressionNodeInfo info) => new NormalArrayCreation(info).TryPopulate();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, IEnumerable<TypedConstant> items, Semmle.Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
location,
ExprKind.ARRAY_CREATION,
parent,
childIndex,
true,
null);
var arrayCreation = new Expression(info);
var length = items.Count();
Literal.CreateGenerated(cx, arrayCreation, 0, cx.Compilation.GetSpecialType(SpecialType.System_Int32), length, location);
if (length > 0)
{
var arrayInit = ArrayInitializer.CreateGenerated(cx, arrayCreation, InitializerIndex, location);
var child = 0;
foreach (var item in items)
{
Expression.CreateGenerated(cx, item, arrayInit, child++, location);
}
}
return arrayCreation;
}
}
internal class StackAllocArrayCreation : ExplicitArrayCreation<StackAllocArrayCreationExpressionSyntax>
@@ -119,7 +143,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
protected override void PopulateExpression(TextWriter trapFile)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
trapFile.implicitly_typed_array_creation(this);
trapFile.stackalloc_array_creation(this);
}
@@ -135,7 +159,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
if (Syntax.Initializer != null)
{
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, -1));
ArrayInitializer.Create(new ExpressionNodeInfo(cx, Syntax.Initializer, this, InitializerIndex));
}
trapFile.implicitly_typed_array_creation(this);

View File

@@ -1,22 +1,26 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Kinds;
using System;
using System.IO;
namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class Cast : Expression<CastExpressionSyntax>
{
private const int ExpressionIndex = 0;
private const int TypeAccessIndex = 1;
private Cast(ExpressionNodeInfo info) : base(info.SetKind(UnaryOperatorKind(info.Context, ExprKind.CAST, info.Node))) { }
public static Expression Create(ExpressionNodeInfo info) => new Cast(info).TryPopulate();
protected override void PopulateExpression(TextWriter trapFile)
{
Create(cx, Syntax.Expression, this, 0);
Create(cx, Syntax.Expression, this, ExpressionIndex);
if (Kind == ExprKind.CAST)
{ // Type cast
TypeAccess.Create(new ExpressionNodeInfo(cx, Syntax.Type, this, 1));
TypeAccess.Create(new ExpressionNodeInfo(cx, Syntax.Type, this, TypeAccessIndex));
}
else
{
@@ -27,5 +31,26 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
public override Microsoft.CodeAnalysis.Location ReportingLocation => Syntax.GetLocation();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, object value, Action<Expression, int> createChild, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.CAST,
parent,
childIndex,
true,
ValueAsString(value));
var ret = new Expression(info);
createChild(ret, ExpressionIndex);
TypeAccess.CreateGenerated(cx, ret, TypeAccessIndex, type, location);
return ret;
}
}
}

View File

@@ -35,6 +35,21 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
}
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int index, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
location,
ExprKind.ARRAY_INIT,
parent,
index,
true,
null);
return new Expression(info);
}
}
// Array initializer { ..., ... }.

View File

@@ -26,8 +26,12 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
var type = info.Type.Type.symbol;
return GetExprKind(type, info.Node, info.Context);
}
switch (type.SpecialType)
private static ExprKind GetExprKind(ITypeSymbol type, ExpressionSyntax expr, Context context)
{
switch (type?.SpecialType)
{
case SpecialType.System_Boolean:
return ExprKind.BOOL_LITERAL;
@@ -63,10 +67,45 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
case SpecialType.System_UInt64:
return ExprKind.ULONG_LITERAL;
case null:
default:
info.Context.ModelError(info.Node, "Unhandled literal type");
if (expr is object)
context.ModelError(expr, "Unhandled literal type");
else
context.ModelError("Unhandled literal type");
return ExprKind.UNKNOWN;
}
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, ITypeSymbol type, object value,
Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), NullableAnnotation.None),
location,
GetExprKind(type, null, cx),
parent,
childIndex,
true,
ValueAsString(value));
return new Expression(info);
}
public static Expression CreateGeneratedNullLiteral(Context cx, IExpressionParentEntity parent, int childIndex, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
NullType.Create(cx),
location,
ExprKind.NULL_LITERAL,
parent,
childIndex,
true,
ValueAsString(null));
return new Expression(info);
}
}
}

View File

@@ -34,5 +34,20 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
public static Expression Create(ExpressionNodeInfo info) => new TypeAccess(info).TryPopulate();
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, Extraction.Entities.Location location)
{
var typeAccessInfo = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.TYPE_ACCESS,
parent,
childIndex,
true,
null);
return new Expression(typeAccessInfo);
}
}
}

View File

@@ -6,13 +6,34 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
internal class TypeOf : Expression<TypeOfExpressionSyntax>
{
private const int TypeAccessIndex = 0;
private TypeOf(ExpressionNodeInfo info) : base(info.SetKind(ExprKind.TYPEOF)) { }
public static Expression Create(ExpressionNodeInfo info) => new TypeOf(info).TryPopulate();
protected override void PopulateExpression(TextWriter trapFile)
{
TypeAccess.Create(cx, Syntax.Type, this, 0);
TypeAccess.Create(cx, Syntax.Type, this, TypeAccessIndex);
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Microsoft.CodeAnalysis.ITypeSymbol type, Extraction.Entities.Location location)
{
var info = new ExpressionInfo(
cx,
new AnnotatedType(Entities.Type.Create(cx, type), Microsoft.CodeAnalysis.NullableAnnotation.None),
location,
ExprKind.TYPEOF,
parent,
childIndex,
true,
null);
var ret = new Expression(info);
TypeAccess.CreateGenerated(cx, ret, TypeOf.TypeAccessIndex, type, location);
return ret;
}
}
}

View File

@@ -3,8 +3,12 @@ using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.CSharp.Entities;
using Semmle.Extraction.Entities;
using Semmle.Util;
using Semmle.Util.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Semmle.Extraction.CSharp.Populators
{
@@ -13,12 +17,23 @@ namespace Semmle.Extraction.CSharp.Populators
protected Context cx { get; }
protected IEntity parent { get; }
protected TextWriter trapFile { get; }
private readonly Lazy<Func<SyntaxNode, AttributeData>> attributeLookup;
public TypeContainerVisitor(Context cx, TextWriter trapFile, IEntity parent)
{
this.cx = cx;
this.parent = parent;
this.trapFile = trapFile;
attributeLookup = new Lazy<Func<SyntaxNode, AttributeData>>(() =>
{
var dict = new Dictionary<SyntaxNode, AttributeData>();
foreach (var attributeData in cx.Compilation.Assembly.GetAttributes().Concat(cx.Compilation.Assembly.Modules.SelectMany(m => m.GetAttributes())))
{
if (attributeData.ApplicationSyntaxReference?.GetSyntax() is SyntaxNode syntax)
dict.Add(syntax, attributeData);
}
return dict.GetValueOrDefault;
});
}
public override void DefaultVisit(SyntaxNode node)
@@ -59,8 +74,11 @@ namespace Semmle.Extraction.CSharp.Populators
var outputAssembly = Assembly.CreateOutputAssembly(cx);
foreach (var attribute in node.Attributes)
{
var ae = new Attribute(cx, attribute, outputAssembly);
cx.BindComments(ae, attribute.GetLocation());
if (attributeLookup.Value(attribute) is AttributeData attributeData)
{
var ae = Semmle.Extraction.CSharp.Entities.Attribute.Create(cx, attributeData, outputAssembly);
cx.BindComments(ae, attribute.GetLocation());
}
}
}
}

View File

@@ -135,7 +135,7 @@ private newtype TPrintAstNode =
} or
TAttributesNode(Attributable attributable) {
shouldPrint(attributable, _) and
exists(attributable.getAnAttribute()) and
exists(Attribute a | a = attributable.getAnAttribute() | shouldPrint(a, _)) and
not isNotNeeded(attributable)
} or
TTypeParametersNode(UnboundGeneric unboundGeneric) {
@@ -298,7 +298,10 @@ class ControlFlowElementNode extends ElementNode {
controlFlowElement.getParent*()
)
) and
not isNotNeeded(element.getParent+())
not isNotNeeded(element.getParent+()) and
// LambdaExpr is both a Callable and a ControlFlowElement,
// print it with the more specific CallableNode
not element instanceof Callable
}
override PrintAstNode getChild(int childIndex) {

View File

@@ -7,6 +7,30 @@ private import semmle.code.csharp.frameworks.System
private import ControlFlow
private import ControlFlow::BasicBlocks
private newtype TAssertionFailure =
TExceptionAssertionFailure(Class c) or
TExitAssertionFailure()
/** An entity that describes how an assertion may fail. */
class AssertionFailure extends TAssertionFailure {
/** Holds if this failure describes an exception of type `c`. */
predicate isException(Class c) { this = TExceptionAssertionFailure(c) }
/** Holds if this failure describes an exit. */
predicate isExit() { this = TExitAssertionFailure() }
/** Gets a textual representation of this element. */
string toString() {
exists(Class c |
this = TExceptionAssertionFailure(c) and
result = c.toString()
)
or
this = TExitAssertionFailure() and
result = "exit"
}
}
/** An assertion method. */
abstract class AssertMethod extends Method {
/** Gets the index of a parameter being asserted. */
@@ -32,15 +56,15 @@ abstract class AssertMethod extends Method {
*/
deprecated final Parameter getAssertedParameter() { result = getAssertedParameter(_) }
/** Gets the exception being thrown if the assertion fails for argument `i`, if any. */
abstract Class getExceptionClass(int i);
/** Gets the failure type if the assertion fails for argument `i`, if any. */
abstract AssertionFailure getAssertionFailure(int i);
/**
* DEPRECATED: Use `getExceptionClass(_)` instead.
* DEPRECATED: Use `getAssertionFailure(_)` instead.
*
* Gets the exception being thrown if the assertion fails, if any.
*/
deprecated final Class getExceptionClass() { result = this.getExceptionClass(_) }
deprecated final Class getExceptionClass() { this.getAssertionFailure(_).isException(result) }
}
/** A Boolean assertion method. */
@@ -62,7 +86,7 @@ deprecated class AssertTrueMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A negated assertion method. */
@@ -76,7 +100,7 @@ deprecated class AssertFalseMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A nullness assertion method. */
@@ -101,7 +125,7 @@ deprecated class AssertNullMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** A non-`null` assertion method. */
@@ -115,7 +139,7 @@ deprecated class AssertNonNullMethod extends AssertMethod {
final override int getAnAssertionIndex() { result = m.getAnAssertionIndex() }
final override Class getExceptionClass(int i) { result = m.getExceptionClass(i) }
final override AssertionFailure getAssertionFailure(int i) { result = m.getAssertionFailure(i) }
}
/** An assertion, that is, a call to an assertion method. */
@@ -258,7 +282,7 @@ class FailingAssertion extends Assertion {
}
/** Gets the exception being thrown by this failing assertion, if any. */
Class getExceptionClass() { result = this.getAssertMethod().getExceptionClass(i) }
AssertionFailure getAssertionFailure() { result = this.getAssertMethod().getAssertionFailure(i) }
}
/**
@@ -271,10 +295,10 @@ class SystemDiagnosticsDebugAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
// A failing assertion generates a message box, see
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.debug.assert
none()
i = 0 and result.isExit()
}
}
@@ -294,10 +318,10 @@ class SystemDiagnosticsContractAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
// A failing assertion generates a message box, see
// https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.contracts.contract.assert
none()
i = 0 and result.isExit()
}
}
@@ -321,7 +345,9 @@ class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod exte
override int getAnAssertionIndex(boolean b) { result = i_ and b = true }
override Class getExceptionClass(int i) { i = i_ and result instanceof SystemExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = i_ and result.isException(any(SystemExceptionClass c))
}
}
/**
@@ -340,7 +366,9 @@ class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertFalseMethod ext
b = false
}
override Class getExceptionClass(int i) { i = i_ and result instanceof SystemExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = i_ and result.isException(any(SystemExceptionClass c))
}
}
/** A Visual Studio assertion method. */
@@ -349,7 +377,9 @@ class VSTestAssertTrueMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio negated assertion method. */
@@ -358,7 +388,9 @@ class VSTestAssertFalseMethod extends BooleanAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = false }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio `null` assertion method. */
@@ -367,7 +399,9 @@ class VSTestAssertNullMethod extends NullnessAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = true }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** A Visual Studio non-`null` assertion method. */
@@ -376,14 +410,18 @@ class VSTestAssertNonNullMethod extends NullnessAssertMethod {
override int getAnAssertionIndex(boolean b) { result = 0 and b = false }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertFailedExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertFailedExceptionClass c))
}
}
/** An NUnit assertion method. */
abstract class NUnitAssertMethod extends AssertMethod {
override int getAnAssertionIndex() { result = 0 }
override Class getExceptionClass(int i) { i = 0 and result instanceof AssertionExceptionClass }
override AssertionFailure getAssertionFailure(int i) {
i = 0 and result.isException(any(AssertionExceptionClass c))
}
}
/** An NUnit assertion method. */
@@ -466,9 +504,9 @@ class ForwarderAssertMethod extends AssertMethod {
/** Gets the assertion index of the forwarded assertion, for assertion index `i`. */
int getAForwarderAssertionIndex(int i) { i = p.getPosition() and result = forwarderIndex }
override Class getExceptionClass(int i) {
override AssertionFailure getAssertionFailure(int i) {
i = p.getPosition() and
result = this.getUnderlyingAssertMethod().getExceptionClass(forwarderIndex)
result = this.getUnderlyingAssertMethod().getAssertionFailure(forwarderIndex)
}
/** Gets the underlying assertion method that is being forwarded to. */
@@ -507,8 +545,8 @@ class ForwarderBooleanAssertMethod extends BooleanAssertMethod {
forwarder.getAForwarderAssertionIndex(result) = underlying.getAnAssertionIndex(b)
}
override Class getExceptionClass(int i) {
result = underlying.getExceptionClass(forwarder.getAForwarderAssertionIndex(i))
override AssertionFailure getAssertionFailure(int i) {
result = underlying.getAssertionFailure(forwarder.getAForwarderAssertionIndex(i))
}
}
@@ -536,8 +574,8 @@ class ForwarderNullnessAssertMethod extends NullnessAssertMethod {
forwarder.getAForwarderAssertionIndex(result) = underlying.getAnAssertionIndex(b)
}
override Class getExceptionClass(int i) {
result = underlying.getExceptionClass(forwarder.getAForwarderAssertionIndex(i))
override AssertionFailure getAssertionFailure(int i) {
result = underlying.getAssertionFailure(forwarder.getAForwarderAssertionIndex(i))
}
}

View File

@@ -393,11 +393,13 @@ private predicate assertion(Assertion a, int i, AssertMethod am, Expr e) {
/** Gets a valid completion when argument `i` fails in assertion `a`. */
Completion assertionCompletion(Assertion a, int i) {
exists(AssertMethod am | am = a.getAssertMethod() |
result = TThrowCompletion(am.getExceptionClass(i))
or
i = am.getAnAssertionIndex() and
not exists(am.getExceptionClass(i)) and
result = TExitCompletion()
if am.getAssertionFailure(i).isExit()
then result = TExitCompletion()
else
exists(Class c |
am.getAssertionFailure(i).isException(c) and
result = TThrowCompletion(c)
)
)
}

View File

@@ -23,7 +23,7 @@ private class ExitingCall extends NonReturningCall {
ExitingCall() {
this.getTarget() instanceof ExitingCallable
or
this = any(FailingAssertion fa | not exists(fa.getExceptionClass()))
this = any(FailingAssertion fa | fa.getAssertionFailure().isExit())
}
override ExitCompletion getACompletion() { not result instanceof NestedCompletion }
@@ -37,7 +37,7 @@ private class ThrowingCall extends NonReturningCall {
(
c = this.getTarget().(ThrowingCallable).getACallCompletion()
or
c.getExceptionClass() = this.(FailingAssertion).getExceptionClass()
this.(FailingAssertion).getAssertionFailure().isException(c.getExceptionClass())
or
exists(CIL::Method m, CIL::Type ex |
this.getTarget().matchesHandle(m) and

View File

@@ -1462,7 +1462,11 @@ predicate succEntrySplits(
exists(int rnk |
succ = succEntry(pred) and
t instanceof NormalSuccessor and
succEntrySplitsFromRank(pred, succ, succSplits, rnk)
succEntrySplitsFromRank(pred, succ, succSplits, rnk) and
// Attribute arguments in assemblies are represented as expressions, even though
// they are not from source. We are not interested in constructing a CFG for such
// expressions.
succ.fromSource()
|
rnk = 0 and
not any(SplitInternal split).hasEntry(pred, succ)

View File

@@ -1,4 +1,5 @@
import csharp
from Expr argument
where argument.fromSource()
select argument, argument.getExplicitArgumentName()

View File

@@ -0,0 +1,27 @@
using System;
[assembly: Assembly1.CustomAttribute(1, new object[] { 1, 2, null }, typeof(Assembly1.CustomAttribute), (Assembly1.Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
[module: Assembly1.CustomAttribute(2, new object[] { 1, 2, null }, typeof(Assembly1.CustomAttribute), (Assembly1.Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
namespace Assembly1
{
public enum Enum1 { A = 42, B, C }
public class CustomAttribute : Attribute
{
public object[] Prop1 { get; set; }
public object[] Prop2 { get; set; }
public CustomAttribute(int i, object o, Type t, Enum1 e, int[] arr) { }
}
[Custom(3, new int[] { 1, 2, 3 }, null, (Enum1)12, null, Prop2 = new object[] { 1, typeof(int) })]
public class Class1
{
[CustomAttribute(42 + 0, new int[] { 1, 2, 3 }, typeof(Class1), Enum1.B, new int[] { 1, 2, 3 }, Prop2 = new object[] { 1, typeof(int) })]
[return: Custom(42 + 0, new int[] { 1, 2, 3 }, null, Enum1.A, new int[] { 1, 2, 3 }, Prop2 = new object[] { 1, typeof(int) })]
public int Method1()
{
return 1;
}
}
}

Binary file not shown.

View File

@@ -1,39 +1,123 @@
arguments
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 1 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 3 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 42 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 5 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \u00a9 Semmle 2018" |
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
| attributes.cs:54:6:54:16 | [My(...)] | 1 | attributes.cs:54:28:54:29 | "" |
| attributes.cs:54:6:54:16 | [My(...)] | 2 | attributes.cs:54:36:54:36 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 0 | attributes.cs:40:17:40:17 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 1 | attributes.cs:40:20:40:46 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | 2 | attributes.cs:40:49:40:69 | typeof(...) |
| attributes.cs:40:12:40:15 | [Args(...)] | 3 | attributes.cs:40:72:40:76 | (...) ... |
| attributes.cs:40:12:40:15 | [Args(...)] | 4 | attributes.cs:40:79:40:82 | null |
| attributes.cs:40:12:40:15 | [Args(...)] | 5 | attributes.cs:40:92:40:122 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 0 | attributes.cs:41:15:41:15 | 0 |
| attributes.cs:41:10:41:13 | [Args(...)] | 1 | attributes.cs:41:18:41:44 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 2 | attributes.cs:41:47:41:67 | typeof(...) |
| attributes.cs:41:10:41:13 | [Args(...)] | 3 | attributes.cs:41:70:41:74 | (...) ... |
| attributes.cs:41:10:41:13 | [Args(...)] | 4 | attributes.cs:41:77:41:80 | null |
| attributes.cs:41:10:41:13 | [Args(...)] | 5 | attributes.cs:41:90:41:120 | array creation of type Object[] |
| attributes.cs:43:2:43:22 | [AttributeUsage(...)] | 0 | attributes.cs:43:24:43:50 | access to constant All |
| attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false |
| attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true |
| attributes.cs:57:6:57:16 | [My(...)] | 1 | attributes.cs:57:28:57:29 | "" |
| attributes.cs:57:6:57:16 | [My(...)] | 2 | attributes.cs:57:36:57:36 | 0 |
| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 |
| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null |
| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) |
| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A |
| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] |
| attributes.cs:76:2:76:5 | [Args(...)] | 5 | attributes.cs:76:63:76:93 | array creation of type Object[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 5 | attributes.cs:79:68:79:98 | array creation of type Object[] |
constructorArguments
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 1 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 3 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 0 | Assembly1.dll:0:0:0:0 | 42 |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 1 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 2 | Assembly1.dll:0:0:0:0 | typeof(...) |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 3 | Assembly1.dll:0:0:0:0 | (...) ... |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | array creation of type Int32[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | 4 | Assembly1.dll:0:0:0:0 | null |
| attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | 0 | attributes.cs:10:26:10:45 | "C# attributes test" |
| attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | 0 | attributes.cs:11:32:11:56 | "A test of C# attributes" |
| attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | 0 | attributes.cs:12:34:12:35 | "" |
| attributes.cs:13:12:13:26 | [AssemblyCompany(...)] | 0 | attributes.cs:13:28:13:39 | "Semmle Plc" |
| attributes.cs:14:12:14:26 | [AssemblyProduct(...)] | 0 | attributes.cs:14:28:14:34 | "Odasa" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \ufffd Semmle 2018" |
| attributes.cs:15:12:15:28 | [AssemblyCopyright(...)] | 0 | attributes.cs:15:30:15:54 | "Copyright \u00a9 Semmle 2018" |
| attributes.cs:16:12:16:28 | [AssemblyTrademark(...)] | 0 | attributes.cs:16:30:16:31 | "" |
| attributes.cs:17:12:17:26 | [AssemblyCulture(...)] | 0 | attributes.cs:17:28:17:29 | "" |
| attributes.cs:22:12:22:21 | [ComVisible(...)] | 0 | attributes.cs:22:23:22:27 | false |
| attributes.cs:25:12:25:15 | [Guid(...)] | 0 | attributes.cs:25:17:25:54 | "2f70fdd6-14aa-4850-b053-d547adb1f476" |
| attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | 0 | attributes.cs:37:28:37:36 | "1.0.0.0" |
| attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | 0 | attributes.cs:38:32:38:40 | "1.0.0.0" |
| attributes.cs:40:2:40:22 | [AttributeUsage(...)] | 0 | attributes.cs:40:24:40:50 | access to constant All |
| attributes.cs:43:6:43:16 | [Conditional(...)] | 0 | attributes.cs:43:18:43:25 | "DEBUG2" |
| attributes.cs:51:6:51:16 | [My(...)] | 0 | attributes.cs:51:18:51:22 | false |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:21 | true |
| attributes.cs:40:12:40:15 | [Args(...)] | 0 | attributes.cs:40:17:40:17 | 0 |
| attributes.cs:40:12:40:15 | [Args(...)] | 1 | attributes.cs:40:20:40:46 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | 2 | attributes.cs:40:49:40:69 | typeof(...) |
| attributes.cs:40:12:40:15 | [Args(...)] | 3 | attributes.cs:40:72:40:76 | (...) ... |
| attributes.cs:40:12:40:15 | [Args(...)] | 4 | attributes.cs:40:79:40:82 | null |
| attributes.cs:41:10:41:13 | [Args(...)] | 0 | attributes.cs:41:15:41:15 | 0 |
| attributes.cs:41:10:41:13 | [Args(...)] | 1 | attributes.cs:41:18:41:44 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | 2 | attributes.cs:41:47:41:67 | typeof(...) |
| attributes.cs:41:10:41:13 | [Args(...)] | 3 | attributes.cs:41:70:41:74 | (...) ... |
| attributes.cs:41:10:41:13 | [Args(...)] | 4 | attributes.cs:41:77:41:80 | null |
| attributes.cs:43:2:43:22 | [AttributeUsage(...)] | 0 | attributes.cs:43:24:43:50 | access to constant All |
| attributes.cs:46:6:46:16 | [Conditional(...)] | 0 | attributes.cs:46:18:46:25 | "DEBUG2" |
| attributes.cs:54:6:54:16 | [My(...)] | 0 | attributes.cs:54:18:54:22 | false |
| attributes.cs:57:6:57:16 | [My(...)] | 0 | attributes.cs:57:18:57:21 | true |
| attributes.cs:76:2:76:5 | [Args(...)] | 0 | attributes.cs:76:7:76:8 | 42 |
| attributes.cs:76:2:76:5 | [Args(...)] | 1 | attributes.cs:76:11:76:14 | null |
| attributes.cs:76:2:76:5 | [Args(...)] | 2 | attributes.cs:76:17:76:25 | typeof(...) |
| attributes.cs:76:2:76:5 | [Args(...)] | 3 | attributes.cs:76:28:76:30 | access to constant A |
| attributes.cs:76:2:76:5 | [Args(...)] | 4 | attributes.cs:76:33:76:53 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 0 | attributes.cs:79:11:79:16 | ... + ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 1 | attributes.cs:79:19:79:39 | array creation of type Int32[] |
| attributes.cs:79:6:79:9 | [Args(...)] | 2 | attributes.cs:79:42:79:45 | null |
| attributes.cs:79:6:79:9 | [Args(...)] | 3 | attributes.cs:79:48:79:52 | (...) ... |
| attributes.cs:79:6:79:9 | [Args(...)] | 4 | attributes.cs:79:55:79:58 | null |
namedArguments
| attributes.cs:54:6:54:16 | [My(...)] | x | attributes.cs:54:36:54:36 | 0 |
| attributes.cs:54:6:54:16 | [My(...)] | y | attributes.cs:54:28:54:29 | "" |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| Assembly1.dll:0:0:0:0 | [Custom(...)] | Prop2 | Assembly1.dll:0:0:0:0 | array creation of type Object[] |
| attributes.cs:40:12:40:15 | [Args(...)] | Prop | attributes.cs:40:92:40:122 | array creation of type Object[] |
| attributes.cs:41:10:41:13 | [Args(...)] | Prop | attributes.cs:41:90:41:120 | array creation of type Object[] |
| attributes.cs:57:6:57:16 | [My(...)] | x | attributes.cs:57:36:57:36 | 0 |
| attributes.cs:57:6:57:16 | [My(...)] | y | attributes.cs:57:28:57:29 | "" |
| attributes.cs:76:2:76:5 | [Args(...)] | Prop | attributes.cs:76:63:76:93 | array creation of type Object[] |
| attributes.cs:79:6:79:9 | [Args(...)] | Prop | attributes.cs:79:68:79:98 | array creation of type Object[] |

View File

@@ -1,13 +1,31 @@
import csharp
query predicate arguments(Attribute attribute, int index, Expr e) {
private class RelevantElement extends Element {
RelevantElement() {
this.fromSource()
or
this.getLocation().(Assembly).getName() = "Assembly1"
}
}
private class RelevantAttribute extends RelevantElement, Attribute {
RelevantAttribute() {
this.fromSource()
or
this.getType().getName() = "CustomAttribute"
}
}
private class RelevantExpr extends RelevantElement, Expr { }
query predicate arguments(RelevantAttribute attribute, int index, RelevantExpr e) {
e = attribute.getArgument(index)
}
query predicate constructorArguments(Attribute attribute, int index, Expr e) {
query predicate constructorArguments(RelevantAttribute attribute, int index, RelevantExpr e) {
e = attribute.getConstructorArgument(index)
}
query predicate namedArguments(Attribute attribute, string name, Expr e) {
query predicate namedArguments(RelevantAttribute attribute, string name, RelevantExpr e) {
e = attribute.getNamedArgument(name)
}

View File

@@ -1,8 +1,21 @@
| attributes.cs:41:7:41:9 | Foo | attributes.cs:40:2:40:22 | [AttributeUsage(...)] | System.AttributeUsageAttribute |
| attributes.cs:44:17:44:19 | foo | attributes.cs:43:6:43:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute |
| attributes.cs:49:23:49:23 | x | attributes.cs:49:14:49:16 | [Foo(...)] | Foo |
| attributes.cs:52:10:52:11 | M1 | attributes.cs:51:6:51:16 | [My(...)] | MyAttribute |
| attributes.cs:55:10:55:11 | M2 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyCompany(...)] | System.Reflection.AssemblyCompanyAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyFileVersion(...)] | System.Reflection.AssemblyFileVersionAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyInformationalVersion(...)] | System.Reflection.AssemblyInformationalVersionAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyProduct(...)] | System.Reflection.AssemblyProductAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [CompilationRelaxations(...)] | System.Runtime.CompilerServices.CompilationRelaxationsAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [Custom(...)] | Assembly1.CustomAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [Debuggable(...)] | System.Diagnostics.DebuggableAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [RuntimeCompatibility(...)] | System.Runtime.CompilerServices.RuntimeCompatibilityAttribute |
| Assembly1.dll:0:0:0:0 | Assembly1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | Assembly1.dll:0:0:0:0 | [TargetFramework(...)] | System.Runtime.Versioning.TargetFrameworkAttribute |
| attributes.cs:44:7:44:9 | Foo | attributes.cs:43:2:43:22 | [AttributeUsage(...)] | System.AttributeUsageAttribute |
| attributes.cs:47:17:47:19 | foo | attributes.cs:46:6:46:16 | [Conditional(...)] | System.Diagnostics.ConditionalAttribute |
| attributes.cs:52:23:52:23 | x | attributes.cs:52:14:52:16 | [Foo(...)] | Foo |
| attributes.cs:55:10:55:11 | M1 | attributes.cs:54:6:54:16 | [My(...)] | MyAttribute |
| attributes.cs:58:10:58:11 | M2 | attributes.cs:57:6:57:16 | [My(...)] | MyAttribute |
| attributes.cs:77:14:77:14 | X | attributes.cs:76:2:76:5 | [Args(...)] | ArgsAttribute |
| attributes.cs:81:9:81:18 | SomeMethod | attributes.cs:79:6:79:9 | [Args(...)] | ArgsAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:10:12:10:24 | [AssemblyTitle(...)] | System.Reflection.AssemblyTitleAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:11:12:11:30 | [AssemblyDescription(...)] | System.Reflection.AssemblyDescriptionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:12:12:12:32 | [AssemblyConfiguration(...)] | System.Reflection.AssemblyConfigurationAttribute |
@@ -15,3 +28,5 @@
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:25:12:25:15 | [Guid(...)] | System.Runtime.InteropServices.GuidAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:37:12:37:26 | [AssemblyVersion(...)] | System.Reflection.AssemblyVersionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:38:12:38:30 | [AssemblyFileVersion(...)] | System.Reflection.AssemblyFileVersionAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:40:12:40:15 | [Args(...)] | ArgsAttribute |
| attributes.dll:0:0:0:0 | attributes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null | attributes.cs:41:10:41:13 | [Args(...)] | ArgsAttribute |

View File

@@ -1,5 +1,7 @@
import csharp
from Attributable element, Attribute attribute
where attribute = element.getAnAttribute()
where
attribute = element.getAnAttribute() and
(element.(Element).fromSource() or element.(Assembly).getName() in ["attributes", "Assembly1"])
select element, attribute, attribute.getType().getQualifiedName()

View File

@@ -16,7 +16,7 @@ attributes.cs:
# 14| 0: [StringLiteral] "Odasa"
# 15| [Attribute] [AssemblyCopyright(...)]
# 15| -1: [TypeMention] AssemblyCopyrightAttribute
# 15| 0: [StringLiteral] "Copyright <EFBFBD> Semmle 2018"
# 15| 0: [StringLiteral] "Copyright © Semmle 2018"
# 16| [Attribute] [AssemblyTrademark(...)]
# 16| -1: [TypeMention] AssemblyTrademarkAttribute
# 16| 0: [StringLiteral] ""
@@ -35,65 +35,213 @@ attributes.cs:
# 38| [Attribute] [AssemblyFileVersion(...)]
# 38| -1: [TypeMention] AssemblyFileVersionAttribute
# 38| 0: [StringLiteral] "1.0.0.0"
# 41| [Class] Foo
# 40| [Attribute] [Args(...)]
# 40| -1: [TypeMention] ArgsAttribute
# 40| 0: [IntLiteral] 0
# 40| 1: [ArrayCreation] array creation of type Object[]
# 40| -2: [TypeMention] Object[]
# 40| 1: [TypeMention] object
# 40| -1: [ArrayInitializer] { ..., ... }
# 40| 0: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 1
# 40| 1: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 2
# 40| 2: [NullLiteral] null
# 40| 2: [TypeofExpr] typeof(...)
# 40| 0: [TypeAccess] access to type ArgsAttribute
# 40| 0: [TypeMention] ArgsAttribute
# 40| 3: [CastExpr] (...) ...
# 40| 0: [TypeAccess] access to type E
# 40| 0: [TypeMention] E
# 40| 1: [IntLiteral] 12
# 40| 4: [NullLiteral] null
# 40| 5: [ArrayCreation] array creation of type Object[]
# 40| -2: [TypeMention] Object[]
# 40| 1: [TypeMention] object
# 40| -1: [ArrayInitializer] { ..., ... }
# 40| 0: [CastExpr] (...) ...
# 40| 1: [IntLiteral] 1
# 40| 1: [TypeofExpr] typeof(...)
# 40| 0: [TypeAccess] access to type Int32
# 40| 0: [TypeMention] int
# 41| [Attribute] [Args(...)]
# 41| -1: [TypeMention] ArgsAttribute
# 41| 0: [IntLiteral] 0
# 41| 1: [ArrayCreation] array creation of type Object[]
# 41| -2: [TypeMention] Object[]
# 41| 1: [TypeMention] object
# 41| -1: [ArrayInitializer] { ..., ... }
# 41| 0: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 1
# 41| 1: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 2
# 41| 2: [NullLiteral] null
# 41| 2: [TypeofExpr] typeof(...)
# 41| 0: [TypeAccess] access to type ArgsAttribute
# 41| 0: [TypeMention] ArgsAttribute
# 41| 3: [CastExpr] (...) ...
# 41| 0: [TypeAccess] access to type E
# 41| 0: [TypeMention] E
# 41| 1: [IntLiteral] 12
# 41| 4: [NullLiteral] null
# 41| 5: [ArrayCreation] array creation of type Object[]
# 41| -2: [TypeMention] Object[]
# 41| 1: [TypeMention] object
# 41| -1: [ArrayInitializer] { ..., ... }
# 41| 0: [CastExpr] (...) ...
# 41| 1: [IntLiteral] 1
# 41| 1: [TypeofExpr] typeof(...)
# 41| 0: [TypeAccess] access to type Int32
# 41| 0: [TypeMention] int
# 44| [Class] Foo
#-----| 0: (Attributes)
# 40| 1: [Attribute] [AttributeUsage(...)]
# 40| -1: [TypeMention] AttributeUsageAttribute
# 40| 0: [MemberConstantAccess] access to constant All
# 40| -1: [TypeAccess] access to type AttributeTargets
# 40| 0: [TypeMention] AttributeTargets
# 43| 1: [Attribute] [AttributeUsage(...)]
# 43| -1: [TypeMention] AttributeUsageAttribute
# 43| 0: [MemberConstantAccess] access to constant All
# 43| -1: [TypeAccess] access to type AttributeTargets
# 43| 0: [TypeMention] AttributeTargets
#-----| 3: (Base types)
# 41| 0: [TypeMention] Attribute
# 44| 5: [Method] foo
# 44| -1: [TypeMention] Void
# 44| 0: [TypeMention] Attribute
# 47| 5: [Method] foo
# 47| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 43| 1: [Attribute] [Conditional(...)]
# 43| -1: [TypeMention] ConditionalAttribute
# 43| 0: [StringLiteral] "DEBUG2"
# 44| 4: [BlockStmt] {...}
# 47| [Class] Bar
# 49| 5: [Method] inc
# 49| -1: [TypeMention] int
# 46| 1: [Attribute] [Conditional(...)]
# 46| -1: [TypeMention] ConditionalAttribute
# 46| 0: [StringLiteral] "DEBUG2"
# 47| 4: [BlockStmt] {...}
# 50| [Class] Bar
# 52| 5: [Method] inc
# 52| -1: [TypeMention] int
#-----| 2: (Parameters)
# 49| 0: [Parameter] x
# 49| -1: [TypeMention] int
# 52| 0: [Parameter] x
# 52| -1: [TypeMention] int
#-----| 0: (Attributes)
# 49| 1: [Attribute] [Foo(...)]
# 49| 0: [TypeMention] Foo
# 49| 4: [BlockStmt] {...}
# 49| 0: [ReturnStmt] return ...;
# 49| 0: [AddExpr] ... + ...
# 49| 0: [ParameterAccess] access to parameter x
# 49| 1: [IntLiteral] 1
# 52| 6: [Method] M1
# 52| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 51| 1: [Attribute] [My(...)]
# 51| -1: [TypeMention] MyAttribute
# 51| 0: [BoolLiteral] false
# 52| 1: [Attribute] [Foo(...)]
# 52| 0: [TypeMention] Foo
# 52| 4: [BlockStmt] {...}
# 55| 7: [Method] M2
# 52| 0: [ReturnStmt] return ...;
# 52| 0: [AddExpr] ... + ...
# 52| 0: [ParameterAccess] access to parameter x
# 52| 1: [IntLiteral] 1
# 55| 6: [Method] M1
# 55| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 54| 1: [Attribute] [My(...)]
# 54| -1: [TypeMention] MyAttribute
# 54| 0: [BoolLiteral] true
# 54| 1: [StringLiteral] ""
# 54| 2: [IntLiteral] 0
# 54| 0: [BoolLiteral] false
# 55| 4: [BlockStmt] {...}
# 58| [Class] MyAttribute
# 58| 7: [Method] M2
# 58| -1: [TypeMention] Void
#-----| 0: (Attributes)
# 57| 1: [Attribute] [My(...)]
# 57| -1: [TypeMention] MyAttribute
# 57| 0: [BoolLiteral] true
# 57| 1: [StringLiteral] ""
# 57| 2: [IntLiteral] 0
# 58| 4: [BlockStmt] {...}
# 61| [Class] MyAttribute
#-----| 3: (Base types)
# 58| 0: [TypeMention] Attribute
# 60| 4: [Field] x
# 60| -1: [TypeMention] int
# 61| 5: [IndexerProperty] y
# 61| -1: [TypeMention] string
# 61| 3: [Getter] get_y
# 61| 4: [Setter] set_y
# 61| 0: [TypeMention] Attribute
# 63| 4: [Field] x
# 63| -1: [TypeMention] int
# 64| 5: [IndexerProperty] y
# 64| -1: [TypeMention] string
# 64| 3: [Getter] get_y
# 64| 4: [Setter] set_y
#-----| 2: (Parameters)
# 61| 0: [Parameter] value
# 62| 6: [InstanceConstructor] MyAttribute
# 64| 0: [Parameter] value
# 65| 6: [InstanceConstructor] MyAttribute
#-----| 2: (Parameters)
# 62| 0: [Parameter] b
# 62| -1: [TypeMention] bool
# 62| 4: [BlockStmt] {...}
# 65| 0: [Parameter] b
# 65| -1: [TypeMention] bool
# 65| 4: [BlockStmt] {...}
# 68| [Enum] E
# 68| 5: [Field] A
# 68| 1: [AssignExpr] ... = ...
# 68| 0: [MemberConstantAccess] access to constant A
# 68| 1: [IntLiteral] 42
# 70| [Class] ArgsAttribute
#-----| 3: (Base types)
# 70| 0: [TypeMention] Attribute
# 72| 4: [Property] Prop
# 72| -1: [TypeMention] Object[]
# 72| 1: [TypeMention] object
# 72| 3: [Getter] get_Prop
# 72| 4: [Setter] set_Prop
#-----| 2: (Parameters)
# 72| 0: [Parameter] value
# 73| 5: [InstanceConstructor] ArgsAttribute
#-----| 2: (Parameters)
# 73| 0: [Parameter] i
# 73| -1: [TypeMention] int
# 73| 1: [Parameter] o
# 73| -1: [TypeMention] object
# 73| 2: [Parameter] t
# 73| -1: [TypeMention] Type
# 73| 3: [Parameter] e
# 73| -1: [TypeMention] E
# 73| 4: [Parameter] arr
# 73| -1: [TypeMention] Int32[]
# 73| 1: [TypeMention] int
# 73| 4: [BlockStmt] {...}
# 77| [Class] X
#-----| 0: (Attributes)
# 76| 1: [Attribute] [Args(...)]
# 76| -1: [TypeMention] ArgsAttribute
# 76| 0: [IntLiteral] 42
# 76| 1: [NullLiteral] null
# 76| 2: [TypeofExpr] typeof(...)
# 76| 0: [TypeAccess] access to type X
# 76| 0: [TypeMention] X
# 76| 3: [MemberConstantAccess] access to constant A
# 76| -1: [TypeAccess] access to type E
# 76| 0: [TypeMention] E
# 76| 4: [ArrayCreation] array creation of type Int32[]
# 76| -2: [TypeMention] Int32[]
# 76| 1: [TypeMention] int
# 76| -1: [ArrayInitializer] { ..., ... }
# 76| 0: [IntLiteral] 1
# 76| 1: [IntLiteral] 2
# 76| 2: [IntLiteral] 3
# 76| 5: [ArrayCreation] array creation of type Object[]
# 76| -2: [TypeMention] Object[]
# 76| 1: [TypeMention] object
# 76| -1: [ArrayInitializer] { ..., ... }
# 76| 0: [CastExpr] (...) ...
# 76| 1: [IntLiteral] 1
# 76| 1: [TypeofExpr] typeof(...)
# 76| 0: [TypeAccess] access to type Int32
# 76| 0: [TypeMention] int
# 81| 5: [Method] SomeMethod
# 81| -1: [TypeMention] int
#-----| 0: (Attributes)
# 79| 1: [Attribute] [Args(...)]
# 79| -1: [TypeMention] ArgsAttribute
# 79| 0: [AddExpr] ... + ...
# 79| 0: [IntLiteral] 42
# 79| 1: [IntLiteral] 0
# 79| 1: [ArrayCreation] array creation of type Int32[]
# 79| -2: [TypeMention] Int32[]
# 79| 1: [TypeMention] int
# 79| -1: [ArrayInitializer] { ..., ... }
# 79| 0: [IntLiteral] 1
# 79| 1: [IntLiteral] 2
# 79| 2: [IntLiteral] 3
# 79| 2: [NullLiteral] null
# 79| 3: [CastExpr] (...) ...
# 79| 0: [TypeAccess] access to type E
# 79| 0: [TypeMention] E
# 79| 1: [IntLiteral] 12
# 79| 4: [NullLiteral] null
# 79| 5: [ArrayCreation] array creation of type Object[]
# 79| -2: [TypeMention] Object[]
# 79| 1: [TypeMention] object
# 79| -1: [ArrayInitializer] { ..., ... }
# 79| 0: [CastExpr] (...) ...
# 79| 1: [IntLiteral] 1
# 79| 1: [TypeofExpr] typeof(...)
# 79| 0: [TypeAccess] access to type Int32
# 79| 0: [TypeMention] int
# 81| 4: [BlockStmt] {...}
# 81| 0: [ReturnStmt] return ...;
# 81| 0: [IntLiteral] 1

View File

@@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Semmle Plc")]
[assembly: AssemblyProduct("Odasa")]
[assembly: AssemblyCopyright("Copyright <EFBFBD> Semmle 2018")]
[assembly: AssemblyCopyright("Copyright © Semmle 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -37,6 +37,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: Args(0, new object[] { 1, 2, null }, typeof(ArgsAttribute), (E)12, null, Prop = new object[] { 1, typeof(int) })]
[module: Args(0, new object[] { 1, 2, null }, typeof(ArgsAttribute), (E)12, null, Prop = new object[] { 1, typeof(int) })]
[System.AttributeUsage(System.AttributeTargets.All)]
class Foo : Attribute
{
@@ -61,3 +64,19 @@ class MyAttribute : Attribute
public string y { get; set; }
public MyAttribute(bool b) { }
}
public enum E { A = 42 }
public class ArgsAttribute : Attribute
{
public object[] Prop { get; set; }
public ArgsAttribute(int i, object o, Type t, E e, int[] arr) { }
}
[Args(42, null, typeof(X), E.A, new int[] { 1, 2, 3 }, Prop = new object[] { 1, typeof(int) })]
public class X
{
[Args(42 + 0, new int[] { 1, 2, 3 }, null, (E)12, null, Prop = new object[] { 1, typeof(int) })]
[return: Args(42 + 0, new int[] { 1, 2, 3 }, null, (E)12, null, Prop = new object[] { 1, typeof(int) })]
int SomeMethod() { return 1; }
}

View File

@@ -2,11 +2,13 @@ import csharp
import Common
query predicate dominance(SourceControlFlowNode dom, SourceControlFlowNode node) {
dom.strictlyDominates(node) and dom.getASuccessor() = node
dom.strictlyDominates(node) and
dom.getASuccessor() = node
}
query predicate postDominance(SourceControlFlowNode dom, SourceControlFlowNode node) {
dom.strictlyPostDominates(node) and dom.getAPredecessor() = node
dom.strictlyPostDominates(node) and
dom.getAPredecessor() = node
}
query predicate blockDominance(SourceBasicBlock dom, SourceBasicBlock bb) { dom.dominates(bb) }

View File

@@ -189,6 +189,7 @@
| AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access |
| AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access |
| AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 |
| AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:37:58:40 | this access |
| AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 |
@@ -1600,7 +1601,9 @@
| Foreach.cs:25:5:28:5 | {...} | Foreach.cs:25:5:28:5 | {...} |
| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:36:26:39 | access to parameter args |
| Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:23:26:23 | String x |
| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 |
| Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x |
| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 |
| Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y |
| Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args |
| Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; |

View File

@@ -3,4 +3,5 @@ import Common
import ControlFlow::Internal
from SourceControlFlowElement cfe
where cfe.fromSource()
select cfe, first(cfe)

View File

@@ -189,6 +189,7 @@
| AccessorCalls.cs:58:22:58:25 | this access | AccessorCalls.cs:58:22:58:25 | this access | normal |
| AccessorCalls.cs:58:22:58:30 | access to property Prop | AccessorCalls.cs:58:22:58:25 | this access | normal |
| AccessorCalls.cs:58:33:58:44 | (..., ...) | AccessorCalls.cs:58:33:58:44 | (..., ...) | normal |
| AccessorCalls.cs:58:34:58:34 | 1 | AccessorCalls.cs:58:34:58:34 | 1 | normal |
| AccessorCalls.cs:58:37:58:40 | this access | AccessorCalls.cs:58:37:58:40 | this access | normal |
| AccessorCalls.cs:58:37:58:43 | access to indexer | AccessorCalls.cs:58:42:58:42 | 0 | normal |
| AccessorCalls.cs:58:42:58:42 | 0 | AccessorCalls.cs:58:42:58:42 | 0 | normal |
@@ -2268,7 +2269,9 @@
| Foreach.cs:25:5:28:5 | {...} | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty |
| Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | Foreach.cs:26:9:27:11 | foreach (... ... in ...) ... | empty |
| Foreach.cs:26:18:26:31 | (..., ...) | Foreach.cs:26:18:26:31 | (..., ...) | normal |
| Foreach.cs:26:19:26:23 | 1 | Foreach.cs:26:19:26:23 | 1 | normal |
| Foreach.cs:26:23:26:23 | String x | Foreach.cs:26:23:26:23 | String x | normal |
| Foreach.cs:26:26:26:30 | 1 | Foreach.cs:26:26:26:30 | 1 | normal |
| Foreach.cs:26:30:26:30 | Int32 y | Foreach.cs:26:30:26:30 | Int32 y | normal |
| Foreach.cs:26:36:26:39 | access to parameter args | Foreach.cs:26:36:26:39 | access to parameter args | normal |
| Foreach.cs:27:11:27:11 | ; | Foreach.cs:27:11:27:11 | ; | normal |

View File

@@ -4,4 +4,5 @@ private import semmle.code.csharp.controlflow.internal.Completion
import Common
from SourceControlFlowElement cfe, Completion c
where cfe.fromSource()
select cfe, last(cfe, c), c

View File

@@ -1,8 +1,12 @@
import csharp
private import semmle.code.csharp.controlflow.Guards
query predicate abstractValue(AbstractValue value, Expr e) { e = value.getAnExpr() }
query predicate abstractValue(AbstractValue value, Expr e) {
e = value.getAnExpr() and e.fromSource()
}
query predicate dualValue(AbstractValue value, AbstractValue dual) { dual = value.getDualValue() }
query predicate singletonValue(AbstractValue value) { value.isSingleton() }
query predicate singletonValue(AbstractValue value) {
value.isSingleton() and value.getAnExpr().fromSource()
}

View File

@@ -1,4 +1,5 @@
import csharp
from IntLiteral l
where l.fromSource()
select l

View File

@@ -1,11 +1,13 @@
import csharp
query predicate arrayCreation(ArrayCreation creation, int i, Expr length) {
creation.fromSource() and
length = creation.getLengthArgument(i)
}
query predicate arrayElement(ArrayCreation array, int i, Expr element) {
array.fromSource() and
element = array.getInitializer().getElement(i)
}
query predicate stackalloc(Stackalloc a) { any() }
query predicate stackalloc(Stackalloc a) { a.fromSource() }

View File

@@ -9,5 +9,9 @@ private boolean isImplicit(Expr expr) {
}
from ArrayCreation ac, Expr expr
where ac.isImplicitlySized() and not ac.isImplicitlyTyped() and expr = ac.getALengthArgument()
where
ac.isImplicitlySized() and
not ac.isImplicitlyTyped() and
expr = ac.getALengthArgument() and
ac.fromSource()
select ac, expr, isImplicit(expr)

View File

@@ -1995,15 +1995,15 @@ expressions.cs:
# 449| 2: [TypeMention] byte
# 449| 0: [LocalVariableAccess] access to local variable f1
# 449| 1: [LambdaExpr] (...) => ...
# 449| 0: [CastExpr] (...) ...
#-----| 2: (Parameters)
# 449| 0: [Parameter] x
# 449| 4: [CastExpr] (...) ...
# 449| 0: [TypeAccess] access to type Byte
# 449| 0: [TypeMention] byte
# 449| 1: [AddExpr] ... + ...
# 449| 0: [CastExpr] (...) ...
# 449| 1: [ParameterAccess] access to parameter x
# 449| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 449| 0: [Parameter] x
# 450| 1: [LocalVariableDeclStmt] ... ...;
# 450| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Double> f2 = ...
# 450| -1: [TypeMention] Func<Int32, Double>
@@ -2011,14 +2011,14 @@ expressions.cs:
# 450| 2: [TypeMention] double
# 450| 0: [LocalVariableAccess] access to local variable f2
# 450| 1: [LambdaExpr] (...) => ...
# 450| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 450| 0: [Parameter] x
# 450| 4: [BlockStmt] {...}
# 450| 0: [ReturnStmt] return ...;
# 450| 0: [CastExpr] (...) ...
# 450| 1: [AddExpr] ... + ...
# 450| 0: [ParameterAccess] access to parameter x
# 450| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 450| 0: [Parameter] x
# 451| 2: [LocalVariableDeclStmt] ... ...;
# 451| 0: [LocalVariableDeclAndInitExpr] Func<Int32,Int32> f3 = ...
# 451| -1: [TypeMention] Func<Int32, Int32>
@@ -2026,12 +2026,12 @@ expressions.cs:
# 451| 2: [TypeMention] int
# 451| 0: [LocalVariableAccess] access to local variable f3
# 451| 1: [LambdaExpr] (...) => ...
# 451| 0: [AddExpr] ... + ...
# 451| 0: [ParameterAccess] access to parameter x
# 451| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 451| 0: [Parameter] x
# 451| -1: [TypeMention] int
# 451| 4: [AddExpr] ... + ...
# 451| 0: [ParameterAccess] access to parameter x
# 451| 1: [IntLiteral] 1
# 452| 3: [LocalVariableDeclStmt] ... ...;
# 452| 0: [LocalVariableDeclAndInitExpr] Func<Int32,String> f4 = ...
# 452| -1: [TypeMention] Func<Int32, String>
@@ -2039,32 +2039,32 @@ expressions.cs:
# 452| 2: [TypeMention] string
# 452| 0: [LocalVariableAccess] access to local variable f4
# 452| 1: [LambdaExpr] (...) => ...
# 452| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 452| 0: [Parameter] x
# 452| -1: [TypeMention] int
# 452| 4: [BlockStmt] {...}
# 452| 0: [ReturnStmt] return ...;
# 452| 0: [AddExpr] ... + ...
# 452| 0: [CastExpr] (...) ...
# 452| 1: [ParameterAccess] access to parameter x
# 452| 1: [StringLiteral] ""
#-----| 2: (Parameters)
# 452| 0: [Parameter] x
# 452| -1: [TypeMention] int
# 453| 4: [LocalVariableDeclStmt] ... ...;
# 453| 0: [LocalVariableDeclAndInitExpr] S f5 = ...
# 453| -1: [TypeMention] S
# 453| 0: [LocalVariableAccess] access to local variable f5
# 453| 1: [LambdaExpr] (...) => ...
# 453| 0: [MulExpr] ... * ...
# 453| 0: [ParameterAccess] access to parameter x
# 453| 1: [ParameterAccess] access to parameter y
#-----| 2: (Parameters)
# 453| 0: [Parameter] x
# 453| 1: [Parameter] y
# 453| 4: [MulExpr] ... * ...
# 453| 0: [ParameterAccess] access to parameter x
# 453| 1: [ParameterAccess] access to parameter y
# 454| 5: [LocalVariableDeclStmt] ... ...;
# 454| 0: [LocalVariableDeclAndInitExpr] Unit f6 = ...
# 454| -1: [TypeMention] Unit
# 454| 0: [LocalVariableAccess] access to local variable f6
# 454| 1: [LambdaExpr] (...) => ...
# 454| 0: [MethodCall] call to method WriteLine
# 454| 4: [MethodCall] call to method WriteLine
# 454| -1: [TypeAccess] access to type Console
# 454| 0: [TypeMention] Console
# 455| 6: [LocalVariableDeclStmt] ... ...;
@@ -2074,14 +2074,14 @@ expressions.cs:
# 455| 2: [TypeMention] int
# 455| 0: [LocalVariableAccess] access to local variable f7
# 455| 1: [AnonymousMethodExpr] delegate(...) { ... }
# 455| 0: [BlockStmt] {...}
#-----| 2: (Parameters)
# 455| 0: [Parameter] x
# 455| -1: [TypeMention] int
# 455| 4: [BlockStmt] {...}
# 455| 0: [ReturnStmt] return ...;
# 455| 0: [AddExpr] ... + ...
# 455| 0: [ParameterAccess] access to parameter x
# 455| 1: [IntLiteral] 1
#-----| 2: (Parameters)
# 455| 0: [Parameter] x
# 455| -1: [TypeMention] int
# 456| 7: [LocalVariableDeclStmt] ... ...;
# 456| 0: [LocalVariableDeclAndInitExpr] Int32 j = ...
# 456| -1: [TypeMention] int
@@ -2093,7 +2093,7 @@ expressions.cs:
# 457| 1: [TypeMention] int
# 457| 0: [LocalVariableAccess] access to local variable f8
# 457| 1: [AnonymousMethodExpr] delegate(...) { ... }
# 457| 0: [BlockStmt] {...}
# 457| 4: [BlockStmt] {...}
# 457| 0: [ReturnStmt] return ...;
# 457| 0: [AddExpr] ... + ...
# 457| 0: [LocalVariableAccess] access to local variable j

View File

@@ -1,5 +1,5 @@
import csharp
from Expr e, Expr stripped
where stripped = e.stripCasts() and e != stripped
where stripped = e.stripCasts() and e != stripped and e.fromSource()
select e, stripped

View File

@@ -1,5 +1,5 @@
import csharp
from Expr e, Location loc
where e.getLocation() = loc
where e.getLocation() = loc and e.fromSource()
select loc.getStartLine(), loc.getStartColumn(), e.getParent(), e, e.getType().toString()

File diff suppressed because one or more lines are too long

View File

@@ -18,7 +18,7 @@ Project structure
The documentation currently consists of the following Sphinx projects:
- ``learn-ql``help topics to help you learn CodeQL and write queries
- ``ql-handbook``an overview of important concepts in QL, the language that underlies CodeQL analysis
- ``ql-language-reference``an overview of important concepts in QL, the language that underlies CodeQL analysis
- ``support``the languages and frameworks currently supported in CodeQL analysis
- ``ql-training``source files for the CodeQL training and variant analysis examples slide decks

View File

@@ -14,17 +14,17 @@ The following sections provide a brief introduction to data flow analysis with C
See the following tutorials for more information about analyzing data flow in specific languages:
- ":doc:`Analyzing data flow in C/C++ <cpp/dataflow>`"
- ":doc:`Analyzing data flow in C# <csharp/dataflow>`"
- ":doc:`Analyzing data flow in Java <java/dataflow>`"
- ":doc:`Analyzing data flow in JavaScript/TypeScript <javascript/dataflow>`"
- ":doc:`Analyzing data flow and tracking tainted data in Python <python/taint-tracking>`"
- ":doc:`Analyzing data flow in C/C++ <cpp/analyzing-data-flow-in-cpp>`"
- ":doc:`Analyzing data flow in C# <csharp/analyzing-data-flow-in-csharp>`"
- ":doc:`Analyzing data flow in Java <java/analyzing-data-flow-in-java>`"
- ":doc:`Analyzing data flow in JavaScript/TypeScript <javascript/analyzing-data-flow-in-javascript>`"
- ":doc:`Analyzing data flow and tracking tainted data in Python <python/analyzing-data-flow-and-tracking-tainted-data-in-python>`"
.. pull-quote::
Note
Data flow analysis is used extensively in path queries. To learn more about path queries, see ":doc:`Creating path queries <writing-queries/path-queries>`."
Data flow analysis is used extensively in path queries. To learn more about path queries, see ":doc:`Creating path queries <writing-queries/creating-path-queries>`."
.. _data-flow-graph:
@@ -49,8 +49,8 @@ flow between functions and through object properties. Global data flow, however,
graph that do not precisely correspond to the flow of values, but model whether some value at runtime may be derived from another, for instance through a string manipulating
operation.
The data flow graph is computed using `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ to model the program elements that represent the graph's nodes.
The flow of data between the nodes is modeled using `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ to compute the graph's edges.
The data flow graph is computed using `classes <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__ to model the program elements that represent the graph's nodes.
The flow of data between the nodes is modeled using `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ to compute the graph's edges.
Computing an accurate and complete data flow graph presents several challenges:
@@ -82,5 +82,5 @@ These flow steps are modeled in the taint-tracking library using predicates that
Further reading
***************
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"

View File

@@ -14,7 +14,7 @@ Read the examples below to learn how to define predicates and classes in QL. The
Select the southerners
----------------------
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ ``isSouthern``:
This time you only need to consider a specific group of villagers, namely those living in the south of the village. Instead of writing ``getLocation() = "south"`` in all your queries, you could define a new `predicate <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ ``isSouthern``:
.. code-block:: ql
@@ -41,7 +41,7 @@ You can now list all southerners using:
where isSouthern(p)
select p
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
This is already a nice way to simplify the logic, but we could be more efficient. Currently, the query looks at every ``Person p``, and then restricts to those who satisfy ``isSouthern(p)``. Instead, we could define a new `class <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__ ``Southerner`` containing precisely the people we want to consider.
.. code-block:: ql

View File

@@ -20,8 +20,8 @@ A solution should be a set of instructions for how to ferry the items, such as "
across the river, and come back with nothing. Then ferry the cabbage across, and come back with ..."
There are lots of ways to approach this problem and implement it in QL. Before you start, make
sure that you are familiar with how to define `classes <https://help.semmle.com/QL/ql-handbook/types.html#classes>`__
and `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ in QL.
sure that you are familiar with how to define `classes <https://help.semmle.com/QL/ql-language-reference/types.html#classes>`__
and `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ in QL.
The following walkthrough is just one of many possible implementations, so have a go at writing your
own query too! To find more example queries, see the list :ref:`below <alternatives>`.
@@ -69,7 +69,7 @@ For example, if the man is on the left shore, the goat on the right shore, and t
shore, the state should be ``Left, Right, Left, Left``.
You may find it helpful to introduce some variables that refer to the shore on which the man and the cargo items are. These
temporary variables in the body of a class are called `fields <https://help.semmle.com/QL/ql-handbook/types.html#fields>`__.
temporary variables in the body of a class are called `fields <https://help.semmle.com/QL/ql-language-reference/types.html#fields>`__.
.. container:: toggle
@@ -159,12 +159,12 @@ could ferry the goat back and forth any number of times without ever reaching an
Such a path would have an infinite number of river crossings without ever solving the puzzle.
One way to restrict our paths to a finite number of river crossings is to define a
`member predicate <https://help.semmle.com/QL/ql-handbook/types.html#member-predicates>`__
`member predicate <https://help.semmle.com/QL/ql-language-reference/types.html#member-predicates>`__
``State reachesVia(string path, int steps)``.
The result of this predicate is any state that is reachable from the current state (``this``) via
the given path in a specified finite number of steps.
You can write this as a `recursive predicate <https://help.semmle.com/QL/ql-handbook/recursion.html>`__,
You can write this as a `recursive predicate <https://help.semmle.com/QL/ql-language-reference/recursion.html>`__,
with the following base case and recursion step:
- If ``this`` *is* the result state, then it (trivially) reaches the result state via an
@@ -203,7 +203,7 @@ the given path without revisiting any previously visited states.
revisiting any previous states, and there is a ``safeFerry`` action from the intermediate state to
the result state.
(Hint: To check whether a state has previously been visited, you could check if
there is an `index of <https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string>`__
there is an `index of <ql-language-specification#built-ins-for-string>`__
``visitedStates`` at which the state occurs.)
.. container:: toggle
@@ -218,7 +218,7 @@ the given path without revisiting any previously visited states.
Display the results
~~~~~~~~~~~~~~~~~~~
Once you've defined all the necessary classes and predicates, write a `select clause <https://help.semmle.com/QL/ql-handbook/queries.html#select-clauses>`__
Once you've defined all the necessary classes and predicates, write a `select clause <https://help.semmle.com/QL/ql-language-reference/queries.html#select-clauses>`__
that returns the resulting path.
.. container:: toggle
@@ -230,7 +230,7 @@ that returns the resulting path.
.. literalinclude:: river-crossing.ql
:lines: 115-117
The `don't-care expression <https://help.semmle.com/QL/ql-handbook/expressions.html#don-t-care-expressions>`__ (``_``),
The `don't-care expression <https://help.semmle.com/QL/ql-language-reference/expressions.html#don-t-care-expressions>`__ (``_``),
as the second argument to the ``reachesVia`` predicate, represents any value of ``visitedStates``.
For now, the path defined in ``reachesVia`` just lists the order of cargo items to ferry.
@@ -254,12 +254,12 @@ Here are some more example queries that solve the river crossing puzzle:
`See solution in the query console on LGTM.com <https://lgtm.com/query/659603593702729237/>`__
#. This query models the man and the cargo items in a different way, using an
`abstract <https://help.semmle.com/QL/ql-handbook/annotations.html#abstract>`__
`abstract <https://help.semmle.com/QL/ql-language-reference/annotations.html#abstract>`__
class and predicate. It also displays the resulting path in a more visual way.
`See solution in the query console on LGTM.com <https://lgtm.com/query/1025323464423811143/>`__
#. This query introduces `algebraic datatypes <https://help.semmle.com/QL/ql-handbook/types.html#algebraic-datatypes>`__
#. This query introduces `algebraic datatypes <https://help.semmle.com/QL/ql-language-reference/types.html#algebraic-datatypes>`__
to model the situation, instead of defining everything as a subclass of ``string``.
`See solution in the query console on LGTM.com <https://lgtm.com/query/7260748307619718263/>`__

View File

@@ -106,7 +106,7 @@ You can translate this into QL as follows:
result = parentOf(ancestorOf(p))
}
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-handbook/recursion.html>`__.
As you can see, you have used the predicate ``ancestorOf()`` inside its own definition. This is an example of `recursion <https://help.semmle.com/QL/ql-language-reference/recursion.html>`__.
This kind of recursion, where the same operation (in this case ``parentOf()``) is applied multiple times, is very common in QL, and is known as the *transitive closure* of the operation. There are two special symbols ``+`` and ``*`` that are extremely useful when working with transitive closures:

View File

@@ -48,12 +48,12 @@ There is too much information to search through by hand, so you decide to use yo
#. Open the `query console on LGTM.com <https://lgtm.com/query>`__ to get started.
#. Select a language and a demo project. For this tutorial, any language and project will do.
#. Delete the default code ``import <language> select "hello world"``.
#. Delete the default code ``import <ql-language-specification> select "hello world"``.
QL libraries
------------
We've defined a number of QL `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age.
We've defined a number of QL `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ to help you extract data from your table. A QL predicate is a mini-query that expresses a relation between various pieces of data and describes some of their properties. In this case, the predicates give you information about a person, for example their height or age.
+--------------------+----------------------------------------------------------------------------------------+
| Predicate | Description |
@@ -84,14 +84,14 @@ The villagers answered "yes" to the question "Is the thief taller than 150cm?" T
where t.getHeight() > 150
select t
The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type <https://help.semmle.com/QL/ql-handbook/types.html>`__ of ``t`` is ``Person``.
The first line, ``from Person t``, declares that ``t`` must be a ``Person``. We say that the `type <https://help.semmle.com/QL/ql-language-reference/types.html>`__ of ``t`` is ``Person``.
Before you use the rest of your answers in your QL search, here are some more tools and examples to help you write your own QL queries:
Logical connectives
-------------------
Using `logical connectives <https://help.semmle.com/QL/ql-handbook/formulas.html#logical-connectives>`__, you can write more complex queries that combine different pieces of information.
Using `logical connectives <https://help.semmle.com/QL/ql-language-reference/formulas.html#logical-connectives>`__, you can write more complex queries that combine different pieces of information.
For example, if you know that the thief is older than 30 *and* has brown hair, you can use the following ``where`` clause to link two predicates:
@@ -157,7 +157,7 @@ Notice that we have only temporarily introduced the variable ``c`` and we didn't
Note
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-handbook/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``.
If you are familiar with logic, you may notice that ``exists`` in QL corresponds to the existential `quantifier <https://help.semmle.com/QL/ql-language-reference/formulas.html#quantified-formulas>`__ in logic. QL also has a universal quantifier ``forall(vars | formula 1 | formula 2)`` which is logically equivalent to ``not exists(vars | formula 1 | not formula 2)``.
The real investigation
----------------------
@@ -218,7 +218,7 @@ You are getting closer to solving the mystery! Unfortunately, you still have qui
More advanced queries
---------------------
What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates <https://help.semmle.com/QL/ql-handbook/expressions.html#aggregations>`__.
What if you want to find the oldest, youngest, tallest, or shortest person in the village? As mentioned in the previous topic, you can do this using ``exists``. However, there is also a more efficient way to do this in QL using functions like ``max`` and ``min``. These are examples of `aggregates <https://help.semmle.com/QL/ql-language-reference/expressions.html#aggregations>`__.
In general, an aggregate is a function that performs an operation on multiple pieces of data and returns a single value as its output. Common aggregates are ``count``, ``max``, ``min``, ``avg`` (average) and ``sum``. The general way to use an aggregate is:

View File

@@ -6,7 +6,7 @@ You can use data flow analysis to track the flow of potentially malicious or ins
About data flow
---------------
Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../intro-to-data-flow>`."
Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../about-data-flow-analysis>`."
Local data flow
---------------
@@ -390,7 +390,7 @@ Exercise 4
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/cpp-further-reading.rst

View File

@@ -0,0 +1,42 @@
CodeQL for C and C++
====================
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C and C++ codebases.
.. toctree::
:hidden:
basic-query-for-cpp-code
codeql-library-for-cpp
functions-in-cpp
expressions-types-and-statements-in-cpp
conversions-and-classes-in-cpp
analyzing-data-flow-in-cpp
refining-a-query-to-account-for-edge-cases
detecting-a-potential-buffer-overflow
using-the-guards-library-in-cpp
using-range-analsis-in-cpp
hash-consing-and-value-numbering
- :doc:`Basic query for C and C++ code <basic-query-for-cpp-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for C and C++ <codeql-library-for-cpp>`: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++.
- :doc:`Functions in C and C++ <functions-in-cpp>`: You can use CodeQL to explore functions in C and C++ code.
- :doc:`Expressions, types, and statements in C and C++ <expressions-types-and-statements-in-cpp>`: You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments.
- :doc:`Conversions and classes in C and C++ <conversions-and-classes-in-cpp>`: You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed.
- :doc:`Analyzing data flow in C and C++ <analyzing-data-flow-in-cpp>`: You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase.
- :doc:`Refining a query to account for edge cases <refining-a-query-to-account-for-edge-cases>`: You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases.
- :doc:`Detecting a potential buffer overflow <detecting-a-potential-buffer-overflow>`: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++.
- :doc:`Using the guards library in C and C++ <using-the-guards-library-in-cpp>`: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases.
- :doc:`Using range analysis for C and C++ <using-range-analsis-in-cpp>`: You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow.
- :doc:`Hash consing and value numbering <hash-consing-and-value-numbering>`: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases.

View File

@@ -6,7 +6,7 @@ You can use CodeQL to explore functions in C and C++ code.
Overview
--------
The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`CodeQL libraries for C and C++ <introduce-libraries-cpp>`).
The standard CodeQL library for C and C++ represents functions using the ``Function`` class (see :doc:`CodeQL libraries for C and C++ <codeql-library-for-cpp>`).
The example queries in this topic explore some of the most useful library predicates for querying functions.
@@ -28,7 +28,7 @@ This query is very general, so there are probably too many results to be interes
Finding functions that are not called
-------------------------------------
It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`CodeQL libraries for C and C++ <introduce-libraries-cpp>`). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate.
It might be more interesting to find functions that are not called, using the standard CodeQL ``FunctionCall`` class from the **abstract syntax tree** category (see :doc:`CodeQL libraries for C and C++ <codeql-library-for-cpp>`). The ``FunctionCall`` class can be used to identify places where a function is actually used, and it is related to ``Function`` through the ``FunctionCall.getTarget()`` predicate.
.. code-block:: ql

View File

@@ -1,42 +0,0 @@
CodeQL for C and C++
====================
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C and C++ codebases.
.. toctree::
:hidden:
basic-query-cpp
introduce-libraries-cpp
function-classes
expressions-types
conversions-classes
dataflow
private-field-initialization
zero-space-terminator
guards
range-analysis
value-numbering-hash-cons
- :doc:`Basic query for C and C++ code <basic-query-cpp>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for C and C++ <introduce-libraries-cpp>`: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++.
- :doc:`Functions in C and C++ <function-classes>`: You can use CodeQL to explore functions in C and C++ code.
- :doc:`Expressions, types, and statements in C and C++ <expressions-types>`: You can use CodeQL to explore expressions, types, and statements in C and C++ code to find, for example, incorrect assignments.
- :doc:`Conversions and classes in C and C++ <conversions-classes>`: You can use the standard CodeQL libraries for C and C++ to detect when the type of an expression is changed.
- :doc:`Analyzing data flow in C and C++ <dataflow>`: You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase.
- :doc:`Refining a query to account for edge cases <private-field-initialization>`: You can improve the results generated by a CodeQL query by adding conditions to remove false positive results caused by common edge cases.
- :doc:`Detecting a potential buffer overflow <zero-space-terminator>`: You can use CodeQL to detect potential buffer overflows by checking for allocations equal to ``strlen`` in C and C++.
- :doc:`Using the guards library in C and C++ <guards>`: You can use the CodeQL guards library to identify conditional expressions that control the execution of other parts of a program in C and C++ codebases.
- :doc:`Using range analysis for C and C++ <range-analysis>`: You can use range analysis to determine the upper or lower bounds on an expression, or whether an expression could potentially over or underflow.
- :doc:`Hash consing and value numbering <value-numbering-hash-cons>`: You can use specialized CodeQL libraries to recognize expressions that are syntactically identical or compute the same value at runtime in C and C++ codebases.

View File

@@ -6,7 +6,7 @@ You can improve the results generated by a CodeQL query by adding conditions to
Overview
--------
This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see ":doc:`CodeQL for C and C++ <ql-for-cpp>`."
This topic describes how a C++ query was developed. The example introduces recursive predicates and demonstrates the typical workflow used to refine a query. For a full overview of the topics available for learning to write queries for C/C++ code, see ":doc:`CodeQL for C and C++ <codeql-for-cpp>`."
Finding every private field and checking for initialization
-----------------------------------------------------------
@@ -102,7 +102,7 @@ You may also wish to consider methods called by constructors that assign to the
int m_value;
};
This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see "`Recursion <https://help.semmle.com/QL/ql-handbook/recursion.html>`__" in the QL language reference.
This case can be excluded by creating a recursive predicate. The recursive predicate is given a function and a field, then checks whether the function assigns to the field. The predicate runs itself on all the functions called by the function that it has been given. By passing the constructor to this predicate, we can check for assignments of a field in all functions called by the constructor, and then do the same for all functions called by those functions all the way down the tree of function calls. For more information, see "`Recursion <https://help.semmle.com/QL/ql-language-reference/recursion.html>`__" in the QL language reference.
.. code-block:: ql
@@ -126,7 +126,7 @@ This case can be excluded by creating a recursive predicate. The recursive predi
Refinement 4—simplifying the query
----------------------------------
Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see "`Transitive closures <https://help.semmle.com/QL/ql-handbook/recursion.html#transitive-closures>`__" in the QL language reference.
Finally we can simplify the query by using the transitive closure operator. In this final version of the query, ``c.calls*(fun)`` resolves to the set of all functions that are ``c`` itself, are called by ``c``, are called by a function that is called by ``c``, and so on. This eliminates the need to make a new predicate all together. For more information, see "`Transitive closures <https://help.semmle.com/QL/ql-language-reference/recursion.html#transitive-closures>`__" in the QL language reference.
.. code-block:: ql

View File

@@ -8,7 +8,7 @@ About this article
This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries.
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../intro-to-data-flow>`."
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../about-data-flow-analysis>`."
Local data flow
---------------
@@ -553,7 +553,7 @@ This can be adapted from the ``SystemUriFlow`` class:
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/csharp-further-reading.rst

View File

@@ -0,0 +1,19 @@
CodeQL for C#
=============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C# codebases.
.. toctree::
:hidden:
basic-query-for-csharp-code
codeql-library-for-csharp
analyzing-data-flow-in-csharp
- :doc:`Basic query for C# code <basic-query-for-csharp-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for C# <codeql-library-for-csharp>`: When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#.
- :doc:`Analyzing data flow in C# <analyzing-data-flow-in-csharp>`: You can use CodeQL to track the flow of data through a C# program to its use.

View File

@@ -14,7 +14,7 @@ There is an extensive core library for analyzing CodeQL databases extracted from
Since this is required for all C# queries, it's omitted from code snippets below.
The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. For information about these additional libraries, see ":doc:`CodeQL for C# <ql-for-csharp>`."
The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. For information about these additional libraries, see ":doc:`CodeQL for C# <codeql-for-csharp>`."
Class hierarchies
~~~~~~~~~~~~~~~~~

View File

@@ -1,19 +0,0 @@
CodeQL for C#
=============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from C# codebases.
.. toctree::
:hidden:
basic-query-csharp
introduce-libraries-csharp
dataflow
- :doc:`Basic query for C# code <basic-query-csharp>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for C# <introduce-libraries-csharp>`: When you're analyzing a C# program, you can make use of the large collection of classes in the CodeQL library for C#.
- :doc:`Analyzing data flow in C# <dataflow>`: You can use CodeQL to track the flow of data through a C# program to its use.

View File

@@ -99,8 +99,8 @@ After the initial ``import`` statement, this simple query comprises three parts
| ``where recv = m.getReceiver() and | Defines a condition on the variables. | ``recv = m.getReceiver()`` states that ``recv`` must be the receiver variable of ``m``. |
| w.writesField(recv.getARead(), f, _) and | | |
| not recv.getType() instanceof PointerType`` | | ``w.writesField(recv.getARead(), f, _)`` states that ``w`` must be a location in the code where field ``f`` of ``recv`` is modified. |
| | | We use a `'don't-care' expression <https://help.semmle.com/QL/ql-handbook/expressions.html#don-t-care-expressions>`__ _ for the |
| | | value that is written to ``f``—the actual value doesn't matter in this query. |
| | | We use a `'don't-care' expression <https://help.semmle.com/QL/ql-language-reference/expressions.html#don-t-care-expressions>`__ ``_``|
| | | for the value that is written to ``f``—the actual value doesn't matter in this query. |
| | | |
| | | ``not recv.getType() instanceof PointerType`` states that ``m`` is not a pointer method. |
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+

View File

@@ -0,0 +1,21 @@
CodeQL for Go
=============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Go codebases.
.. toctree::
:hidden:
basic-query-for-go-code
codeql-library-for-go
abstract-syntax-tree-classes-for-working-with-go-programs
modeling-data-flow-in-go-libraries
- :doc:`Basic query for Go code <basic-query-for-go-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Go <codeql-library-for-go>`: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go.
- :doc:`Abstract syntax tree classes for working with Go programs <abstract-syntax-tree-classes-for-working-with-go-programs>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Go programs.
- :doc:`Modeling data flow in Go libraries <modeling-data-flow-in-go-libraries>`: When analyzing a Go program, CodeQL does not examine the source code for external packages.
To track the flow of untrusted data through a library, you can create a model of the library.

View File

@@ -100,7 +100,7 @@ statements and expressions, respectively. This section briefly discusses some of
important subclasses and predicates. For a full reference of all the subclasses of `Stmt
<https://help.semmle.com/qldoc/go/semmle/go/Stmt.qll/type.Stmt$Stmt.html>`__ and `Expr
<https://help.semmle.com/qldoc/go/semmle/go/Expr.qll/type.Expr$Expr.html>`__, see
:doc:`Abstract syntax tree classes for Go <ast-class-reference>`.
:doc:`Abstract syntax tree classes for Go <abstract-syntax-tree-classes-for-working-with-go-programs>`.
Statements
~~~~~~~~~~
@@ -502,7 +502,7 @@ taint, you can define a subclass of ``TaintTracking::Configuration``, which work
data-flow configurations.
A detailed exposition of global data flow and taint tracking is out of scope for this brief
introduction. For a general overview of data flow and taint tracking, see "`About data flow analysis <https://help.semmle.com/QL/learn-ql/intro-to-data-flow.html>`__."
introduction. For a general overview of data flow and taint tracking, see "`About data flow analysis <https://help.semmle.com/QL/learn-ql/about-data-flow-analysis.html>`__."
Advanced libraries
------------------

View File

@@ -1,21 +0,0 @@
CodeQL for Go
=============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Go codebases.
.. toctree::
:hidden:
basic-query-go
introduce-libraries-go
ast-class-reference
library-modeling-go
- :doc:`Basic query for Go code <basic-query-go>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Go <introduce-libraries-go>`: When you're analyzing a Go program, you can make use of the large collection of classes in the CodeQL library for Go.
- :doc:`Abstract syntax tree classes for working with Go programs <ast-class-reference>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Go programs.
- :doc:`Modeling data flow in Go libraries <library-modeling-go>`: When analyzing a Go program, CodeQL does not examine the source code for external packages.
To track the flow of untrusted data through a library, you can create a model of the library.

View File

@@ -19,13 +19,13 @@ CodeQL is based on a powerful query language called QL. The following topics hel
:maxdepth: 1
beginner/ql-tutorials
writing-queries/writing-queries
cpp/ql-for-cpp
csharp/ql-for-csharp
go/ql-for-go
java/ql-for-java
javascript/ql-for-javascript
python/ql-for-python
writing-queries/codeql-queries
cpp/codeql-for-cpp
csharp/codeql-for-csharp
go/codeql-for-go
java/codeql-for-java
javascript/codeql-for-javascript
python/codeql-for-python
ql-training
.. toctree::
@@ -36,4 +36,4 @@ CodeQL is based on a powerful query language called QL. The following topics hel
Further reading
***************
- `QL language reference <https://help.semmle.com/QL/ql-handbook/index.html>`__: A description of important concepts in QL and a formal specification of the QL language.
- `QL language reference <https://help.semmle.com/QL/ql-language-reference/index.html>`__: A description of important concepts in QL and a formal specification of the QL language.

View File

@@ -15,13 +15,13 @@ QL also supports recursion and aggregates. This allows you to write complex recu
Running a query
---------------
You can try out the following examples and exercises using `CodeQL for VS Code <https://help.semmle.com/codeql/codeql-for-vscode.html>`__, or you can run them in the `query console on LGTM.com <https://lgtm.com/query>`__. Before you can run a query on LGTM.com, you need to select a language and project to query (for these logic examples, any language and project will do).
You can try out the following examples and exercises using `CodeQL for VS Code <https://help.semmle.com/codeql/codeql-for-visual-studio-code.html>`__, or you can run them in the `query console on LGTM.com <https://lgtm.com/query>`__. Before you can run a query on LGTM.com, you need to select a language and project to query (for these logic examples, any language and project will do).
Once you have selected a language, the query console is populated with the query:
.. code-block:: ql
import <language>
import <ql-language-specification>
select "hello world"
@@ -53,7 +53,7 @@ You can write simple queries using the some of the basic functions that are avai
Exercise 1
~~~~~~~~~~
Write a query which returns the length of the string ``"lgtm"``. (Hint: `here <https://help.semmle.com/QL/ql-spec/language.html#built-ins-for-string>`__ is the list of the functions that can be applied to strings.)
Write a query which returns the length of the string ``"lgtm"``. (Hint: `here <ql-language-specification#built-ins-for-string>`__ is the list of the functions that can be applied to strings.)
`See answer in the query console on LGTM.com <https://lgtm.com/query/2103060623/>`__
@@ -122,7 +122,7 @@ The following example queries *do* use these databases and give you an idea of h
Queries using the CodeQL libraries can find errors and uncover variants of important security vulnerabilities in codebases.
Visit `GitHub Security Lab <https://securitylab.github.com/>`__ to read about examples of vulnerabilities that we have recently found in open source projects.
To import the CodeQL library for a specific programming language, type ``import <language>`` at the start of the query.
To import the CodeQL library for a specific programming language, type ``import <ql-language-specification>`` at the start of the query.
.. code-block:: ql
@@ -159,4 +159,4 @@ Further reading
- To find out more about how to write your own queries, try working through the ":doc:`QL tutorials <beginner/ql-tutorials>`."
- For an overview of the other available resources, see ":doc:`Learning CodeQL <../index>`."
- For a more technical description of the underlying language, see the "`QL language reference <https://help.semmle.com/QL/ql-handbook>`__."
- For a more technical description of the underlying language, see the "`QL language reference <https://help.semmle.com/QL/ql-language-reference>`__."

View File

@@ -9,7 +9,7 @@ About this article
This article describes how data flow analysis is implemented in the CodeQL libraries for Java and includes examples to help you write your own data flow queries.
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../intro-to-data-flow>`."
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../about-data-flow-analysis>`."
Local data flow
---------------
@@ -358,7 +358,7 @@ Exercise 4
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/java-further-reading.rst

View File

@@ -180,7 +180,7 @@ Finally, we use these classes to find calls to deprecated methods, excluding cal
In our example, this query flags the call to ``A.m`` in ``A.r``, but not the one in ``A.n``.
For more information about the class ``Call``, see ":doc:`Navigating the call graph <call-graph>`."
For more information about the class ``Call``, see ":doc:`Navigating the call graph <navigating-the-call-graph>`."
Improvements
~~~~~~~~~~~~

View File

@@ -0,0 +1,39 @@
CodeQL for Java
===============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java codebases.
.. toctree::
:hidden:
basic-query-for-java-code
codeql-library-for-java
analyzing-data-flow-in-java
types-in-java
overflow-prone-comparisons-in-java
navigating-the-call-graph
annotations-in-java
javadoc
working-with-source-locations
abstract-syntax-tree-classes-for-working-with-go-programs
- :doc:`Basic query for Java code <basic-query-for-java-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Java <codeql-library-for-java>`: When analyzing Java code, you can use the large collection of classes in the CodeQL library for Java.
- :doc:`Analyzing data flow in Java <analyzing-data-flow-in-java>`: You can use CodeQL to track the flow of data through a Java program to its use.
- :doc:`Java types <types-in-java>`: You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues.
- :doc:`Overflow-prone comparisons in Java <overflow-prone-comparisons-in-java>`: You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow.
- :doc:`Navigating the call graph <navigating-the-call-graph>`: CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used.
- :doc:`Annotations in Java <annotations-in-java>`: CodeQL databases of Java projects contain information about all annotations attached to program elements.
- :doc:`Javadoc <javadoc>`: You can use CodeQL to find errors in Javadoc comments in Java code.
- :doc:`Working with source locations <working-with-source-locations>`: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem.
- :doc:`Abstract syntax tree classes for working with Java programs <abstract-syntax-tree-classes-for-working-with-go-programs>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Java programs.

View File

@@ -196,7 +196,7 @@ The wildcards ``? extends Number`` and ``? super Float`` are represented by clas
For dealing with generic methods, there are classes ``GenericMethod``, ``ParameterizedMethod`` and ``RawMethod``, which are entirely analogous to the like-named classes for representing generic types.
For more information on working with types, see the :doc:`article on Java types <types-class-hierarchy>`.
For more information on working with types, see the :doc:`article on Java types <types-in-java>`.
Variables
~~~~~~~~~
@@ -210,7 +210,7 @@ Class ``Variable`` represents a variable `in the Java sense <https://docs.oracle
Abstract syntax tree
--------------------
Classes in this category represent abstract syntax tree (AST) nodes, that is, statements (class ``Stmt``) and expressions (class ``Expr``). For a full list of expression and statement types available in the standard QL library, see ":doc:`Abstract syntax tree classes for working with Java programs <ast-class-reference>`."
Classes in this category represent abstract syntax tree (AST) nodes, that is, statements (class ``Stmt``) and expressions (class ``Expr``). For a full list of expression and statement types available in the standard QL library, see ":doc:`Abstract syntax tree classes for working with Java programs <abstract-syntax-tree-classes-for-working-with-go-programs>`."
Both ``Expr`` and ``Stmt`` provide member predicates for exploring the abstract syntax tree of a program:
@@ -260,7 +260,7 @@ Finally, here is a query that finds method bodies:
As these examples show, the parent node of an expression is not always an expression: it may also be a statement, for example, an ``IfStmt``. Similarly, the parent node of a statement is not always a statement: it may also be a method or a constructor. To capture this, the QL Java library provides two abstract class ``ExprParent`` and ``StmtParent``, the former representing any node that may be the parent node of an expression, and the latter any node that may be the parent node of a statement.
For more information on working with AST classes, see the :doc:`article on overflow-prone comparisons in Java <expressions-statements>`.
For more information on working with AST classes, see the :doc:`article on overflow-prone comparisons in Java <overflow-prone-comparisons-in-java>`.
Metadata
--------
@@ -292,7 +292,7 @@ These annotations are represented by class ``Annotation``. An annotation is simp
`See this in the query console on LGTM.com <https://lgtm.com/query/5393027107459215059/>`__. Only constructors with the ``@Deprecated`` annotation are reported this time.
For more information on working with annotations, see the :doc:`article on annotations <annotations>`.
For more information on working with annotations, see the :doc:`article on annotations <annotations-in-java>`.
For Javadoc, class ``Element`` has a member predicate ``getDoc`` that returns a delegate ``Documentable`` object, which can then be queried for its attached Javadoc comments. For example, the following query finds Javadoc comments on private fields:
@@ -379,9 +379,9 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So
where not exists(c.getAReference())
select c
`See this in the query console on LGTM.com <https://lgtm.com/query/7261739919657747703/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see ":doc:`Navigating the call graph <call-graph>`."
`See this in the query console on LGTM.com <https://lgtm.com/query/7261739919657747703/>`__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see ":doc:`Navigating the call graph <navigating-the-call-graph>`."
For more information about callables and calls, see the :doc:`article on the call graph <call-graph>`.
For more information about callables and calls, see the :doc:`article on the call graph <navigating-the-call-graph>`.
Further reading
---------------

View File

@@ -26,7 +26,7 @@ If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type ``
All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value.
We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions. For a full list, see ":doc:`Abstract syntax tree classes for working with Java programs <ast-class-reference>`."
We're going to develop a query that finds code that looks like it might exhibit this kind of behavior. We'll be using several of the standard library classes for representing statements and functions. For a full list, see ":doc:`Abstract syntax tree classes for working with Java programs <abstract-syntax-tree-classes-for-working-with-go-programs>`."
Initial query
-------------
@@ -61,7 +61,7 @@ Notice that we use the predicate ``getType`` (available on all subclasses of ``E
The class ``LoopStmt`` is a common superclass of all loops, including, in particular, ``for`` loops as in our example above. While different kinds of loops have different syntax, they all have a loop condition, which can be accessed through predicate ``getCondition``. We use the reflexive transitive closure operator ``*`` applied to the ``getAChildExpr`` predicate to express the requirement that ``expr`` should be nested inside the loop condition. In particular, it can be the loop condition itself.
The final conjunct in the ``where`` clause takes advantage of the fact that `predicates <https://help.semmle.com/QL/ql-handbook/predicates.html>`__ can return more than one value (they are really relations). In particular, ``getAnOperand`` may return *either* operand of ``expr``, so ``expr.getAnOperand().isCompileTimeConstant()`` holds if at least one of the operands is constant. Negating this condition means that the query will only find expressions where *neither* of the operands is constant.
The final conjunct in the ``where`` clause takes advantage of the fact that `predicates <https://help.semmle.com/QL/ql-language-reference/predicates.html>`__ can return more than one value (they are really relations). In particular, ``getAnOperand`` may return *either* operand of ``expr``, so ``expr.getAnOperand().isCompileTimeConstant()`` holds if at least one of the operands is constant. Negating this condition means that the query will only find expressions where *neither* of the operands is constant.
Generalizing the query
----------------------

View File

@@ -1,39 +0,0 @@
CodeQL for Java
===============
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from Java codebases.
.. toctree::
:hidden:
basic-query-java
introduce-libraries-java
dataflow
types-class-hierarchy
expressions-statements
call-graph
annotations
javadoc
source-locations
ast-class-reference
- :doc:`Basic query for Java code <basic-query-java>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Java <introduce-libraries-java>`: When analyzing Java code, you can use the large collection of classes in the CodeQL library for Java.
- :doc:`Analyzing data flow in Java <dataflow>`: You can use CodeQL to track the flow of data through a Java program to its use.
- :doc:`Java types <types-class-hierarchy>`: You can use CodeQL to find out information about data types used in Java code. This allows you to write queries to identify specific type-related issues.
- :doc:`Overflow-prone comparisons in Java <expressions-statements>`: You can use CodeQL to check for comparisons in Java code where one side of the comparison is prone to overflow.
- :doc:`Navigating the call graph <call-graph>`: CodeQL has classes for identifying code that calls other code, and code that can be called from elsewhere. This allows you to find, for example, methods that are never used.
- :doc:`Annotations in Java <annotations>`: CodeQL databases of Java projects contain information about all annotations attached to program elements.
- :doc:`Javadoc <javadoc>`: You can use CodeQL to find errors in Javadoc comments in Java code.
- :doc:`Working with source locations <source-locations>`: You can use the location of entities within Java code to look for potential errors. Locations allow you to deduce the presence, or absence, of white space which, in some cases, may indicate a problem.
- :doc:`Abstract syntax tree classes for working with Java programs <ast-class-reference>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Java programs.

View File

@@ -9,7 +9,7 @@ The various sections in this article describe how to utilize the libraries for l
As our running example, we will develop a query that identifies command-line arguments that are passed as a file path to the standard Node.js ``readFile`` function.
While this is not a problematic pattern as such, it is typical of the kind of reasoning that is frequently used in security queries.
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../intro-to-data-flow>`."
For a more general introduction to modeling data flow, see ":doc:`About data flow analysis <../about-data-flow-analysis>`."
Data flow nodes
---------------
@@ -554,7 +554,7 @@ Exercise 4
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/java-further-reading.rst

View File

@@ -0,0 +1,32 @@
CodeQL for JavaScript
=====================
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from JavaScript codebases.
.. toctree::
:hidden:
basic-query-for-javascript-code
codeql-library-for-javascript
codeql-library-for-typescript
analyzing-data-flow-in-javascript
using-flow-labels-for-precise-data-flow-analysis
using-type-tracking-for-api-modeling
abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs
data-flow-cheat-sheet-for-javascript
- :doc:`Basic query for JavaScript code <basic-query-for-javascript-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for JavaScript <codeql-library-for-javascript>`: When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript.
- :doc:`CodeQL library for TypeScript <codeql-library-for-typescript>`: When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript.
- :doc:`Analyzing data flow in JavaScript and TypeScript <analyzing-data-flow-in-javascript>`: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries.
- :doc:`Using flow labels for precise data flow analysis <using-flow-labels-for-precise-data-flow-analysis>`: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities.
- :doc:`Using type tracking for API modeling <using-type-tracking-for-api-modeling>`: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript.
- :doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs <abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs>`: CodeQL has a large selection of classes for representing the abstract syntax tree of JavaScript and TypeScript programs.
- :doc:`Data flow cheat sheet for JavaScript <data-flow-cheat-sheet-for-javascript>`: This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries.

View File

@@ -12,7 +12,7 @@ Support for analyzing TypeScript code is bundled with the CodeQL libraries for J
import javascript
:doc:`CodeQL libraries for JavaScript <introduce-libraries-js>` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates.
:doc:`CodeQL libraries for JavaScript <codeql-library-for-javascript>` covers most of this library, and is also relevant for TypeScript analysis. This document supplements the JavaScript documentation with the TypeScript-specific classes and predicates.
Syntax
------

View File

@@ -34,12 +34,12 @@ This query reports flow paths which:
- Step through variables, function calls, properties, strings, arrays, promises, exceptions, and steps added by `isAdditionalTaintStep <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/TaintTracking.qll/predicate.TaintTracking$TaintTracking$Configuration$isAdditionalTaintStep.2.html>`__.
- End at a node matched by `isSink <https://help.semmle.com/qldoc/javascript/semmle/javascript/dataflow/Configuration.qll/predicate.Configuration$Configuration$isSink.1.html>`__.
See also: "`Global data flow <https://help.semmle.com/QL/learn-ql/javascript/dataflow.html#global-data-flow>`__" and ":doc:`Creating path queries <../writing-queries/path-queries>`."
See also: "`Global data flow <https://help.semmle.com/QL/learn-ql/javascript/dataflow.html#global-data-flow>`__" and ":doc:`Creating path queries <../writing-queries/creating-path-queries>`."
DataFlow module
---------------
Use data flow nodes to match program elements independently of syntax. See also: ":doc:`Analyzing data flow in JavaScript and TypeScript <dataflow>`."
Use data flow nodes to match program elements independently of syntax. See also: ":doc:`Analyzing data flow in JavaScript and TypeScript <analyzing-data-flow-in-javascript>`."
Predicates in the ``DataFlow::`` module:
@@ -142,7 +142,7 @@ Files
AST nodes
---------
See also: ":doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs <ast-class-reference>`."
See also: ":doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs <abstract-syntax-tree-classes-for-working-with-javascript-and-typescript-programs>`."
Conversion between DataFlow and AST nodes:
@@ -163,7 +163,7 @@ String matching
Type tracking
-------------
See also: ":doc:`Using type tracking for API modeling <type-tracking>`."
See also: ":doc:`Using type tracking for API modeling <using-type-tracking-for-api-modeling>`."
Use the following template to define forward type tracking predicates:
@@ -220,7 +220,7 @@ Troubleshooting
Further reading
---------------
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-paths.html>`__"
- "`Exploring data flow with path queries <https://help.semmle.com/codeql/codeql-for-vscode/procedures/exploring-data-flow-with-path-queries.html>`__"
.. include:: ../../reusables/javascript-further-reading.rst

View File

@@ -1,32 +0,0 @@
CodeQL for JavaScript
=====================
Experiment and learn how to write effective and efficient queries for CodeQL databases generated from JavaScript codebases.
.. toctree::
:hidden:
basic-query-javascript
introduce-libraries-js
introduce-libraries-ts
dataflow
flow-labels
type-tracking
ast-class-reference
dataflow-cheat-sheet
- :doc:`Basic query for JavaScript code <basic-query-javascript>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for JavaScript <introduce-libraries-js>`: When you're analyzing a JavaScript program, you can make use of the large collection of classes in the CodeQL library for JavaScript.
- :doc:`CodeQL library for TypeScript <introduce-libraries-ts>`: When you're analyzing a TypeScript program, you can make use of the large collection of classes in the CodeQL library for TypeScript.
- :doc:`Analyzing data flow in JavaScript and TypeScript <dataflow>`: This topic describes how data flow analysis is implemented in the CodeQL libraries for JavaScript/TypeScript and includes examples to help you write your own data flow queries.
- :doc:`Using flow labels for precise data flow analysis <flow-labels>`: You can associate flow labels with each value tracked by the flow analysis to determine whether the flow contains potential vulnerabilities.
- :doc:`Using type tracking for API modeling <type-tracking>`: You can track data through an API by creating a model using the CodeQL type-tracking library for JavaScript.
- :doc:`Abstract syntax tree classes for working with JavaScript and TypeScript programs <ast-class-reference>`: CodeQL has a large selection of classes for representing the abstract syntax tree of JavaScript and TypeScript programs.
- :doc:`Data flow cheat sheet for JavaScript <dataflow-cheat-sheet>`: This article describes parts of the JavaScript libraries commonly used for variant analysis and in data flow queries.

Some files were not shown because too many files have changed in this diff Show More