mirror of
https://github.com/github/codeql.git
synced 2026-05-01 19:55:15 +02:00
Merge branch 'main' into rdmarsh/cpp/use-taint-configuration-dtt
Fix test conflict
This commit is contained in:
@@ -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)
|
||||
)
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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. |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 { ..., ... }.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from Expr argument
|
||||
where argument.fromSource()
|
||||
select argument, argument.getExplicitArgumentName()
|
||||
|
||||
27
csharp/ql/test/library-tests/attributes/Assembly1.cs_
Normal file
27
csharp/ql/test/library-tests/attributes/Assembly1.cs_
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
csharp/ql/test/library-tests/attributes/Assembly1.dll
Normal file
BIN
csharp/ql/test/library-tests/attributes/Assembly1.dll
Normal file
Binary file not shown.
@@ -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[] |
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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 | ; |
|
||||
|
||||
@@ -3,4 +3,5 @@ import Common
|
||||
import ControlFlow::Internal
|
||||
|
||||
from SourceControlFlowElement cfe
|
||||
where cfe.fromSource()
|
||||
select cfe, first(cfe)
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import csharp
|
||||
|
||||
from IntLiteral l
|
||||
where l.fromSource()
|
||||
select l
|
||||
|
||||
@@ -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() }
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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>`__"
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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/>`__
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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
|
||||
42
docs/language/learn-ql/cpp/codeql-for-cpp.rst
Normal file
42
docs/language/learn-ql/cpp/codeql-for-cpp.rst
Normal 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
19
docs/language/learn-ql/csharp/codeql-for-csharp.rst
Normal file
19
docs/language/learn-ql/csharp/codeql-for-csharp.rst
Normal 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.
|
||||
|
||||
|
||||
@@ -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
|
||||
~~~~~~~~~~~~~~~~~
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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. |
|
||||
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------+
|
||||
21
docs/language/learn-ql/go/codeql-for-go.rst
Normal file
21
docs/language/learn-ql/go/codeql-for-go.rst
Normal 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.
|
||||
@@ -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
|
||||
------------------
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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>`__."
|
||||
@@ -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
|
||||
@@ -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
|
||||
~~~~~~~~~~~~
|
||||
39
docs/language/learn-ql/java/codeql-for-java.rst
Normal file
39
docs/language/learn-ql/java/codeql-for-java.rst
Normal 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.
|
||||
|
||||
@@ -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
|
||||
---------------
|
||||
@@ -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
|
||||
----------------------
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
32
docs/language/learn-ql/javascript/codeql-for-javascript.rst
Normal file
32
docs/language/learn-ql/javascript/codeql-for-javascript.rst
Normal 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.
|
||||
@@ -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
|
||||
------
|
||||
@@ -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
|
||||
@@ -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
Reference in New Issue
Block a user