mirror of
https://github.com/github/codeql.git
synced 2026-06-03 04:40:14 +02:00
Compare commits
231 Commits
aml-auto-e
...
nickrolfe/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4aa4364200 | ||
|
|
88fb187923 | ||
|
|
cda05ed3ea | ||
|
|
2046ece2de | ||
|
|
229c95a765 | ||
|
|
753042d883 | ||
|
|
5299cd9c69 | ||
|
|
fa2d84c38c | ||
|
|
0e5aa97c46 | ||
|
|
76cfd44478 | ||
|
|
4217a50900 | ||
|
|
424f31a24a | ||
|
|
63309150e0 | ||
|
|
e7d19e849f | ||
|
|
0ce0ada4df | ||
|
|
ffd58861f0 | ||
|
|
e8a0d07217 | ||
|
|
470908f53e | ||
|
|
ac85741da8 | ||
|
|
375698f975 | ||
|
|
f761e57365 | ||
|
|
d3c3f3bed9 | ||
|
|
e0c68c3a27 | ||
|
|
b448206c19 | ||
|
|
2b316471c5 | ||
|
|
b48b5d45ef | ||
|
|
a10a2c2b01 | ||
|
|
a48b893ed6 | ||
|
|
6cb26d5129 | ||
|
|
99b2df0605 | ||
|
|
22946b176f | ||
|
|
182d7d38a8 | ||
|
|
463173eae4 | ||
|
|
9780dffa79 | ||
|
|
13fb032b1c | ||
|
|
92a38b30cf | ||
|
|
82bbe67267 | ||
|
|
61e24a888f | ||
|
|
31806b84ba | ||
|
|
2351c0288a | ||
|
|
fea1e47daa | ||
|
|
df2b586e7c | ||
|
|
3ffb2a3ee6 | ||
|
|
286fcb672c | ||
|
|
d2c74913c8 | ||
|
|
13b2b1f304 | ||
|
|
62aa5de781 | ||
|
|
56e3334c6d | ||
|
|
aefd51601c | ||
|
|
549eca1b17 | ||
|
|
e4305948ef | ||
|
|
7e0c61de2c | ||
|
|
847a64c03b | ||
|
|
be9509ceb9 | ||
|
|
52b6dd5bec | ||
|
|
162edd6883 | ||
|
|
b9937269b9 | ||
|
|
335e1a8233 | ||
|
|
7ff82bbed3 | ||
|
|
7675571daa | ||
|
|
9358070ae9 | ||
|
|
8a6d56a57d | ||
|
|
ae6dd05249 | ||
|
|
d23b128457 | ||
|
|
0c79c2836c | ||
|
|
ea4ba27297 | ||
|
|
9f1bbf2bbd | ||
|
|
cb8865f3ff | ||
|
|
49572a5218 | ||
|
|
3717cb30eb | ||
|
|
92715bac3a | ||
|
|
5cdaae7378 | ||
|
|
4df7fd248e | ||
|
|
d90257fd50 | ||
|
|
bda4cfbe5d | ||
|
|
79abb36faf | ||
|
|
97e9eab7fc | ||
|
|
d7f40c41c5 | ||
|
|
5e9196e51c | ||
|
|
494fb4c966 | ||
|
|
1d728b234f | ||
|
|
58dd521ee9 | ||
|
|
c5f36613da | ||
|
|
dea5036912 | ||
|
|
45fc62f16b | ||
|
|
1273db5a22 | ||
|
|
0f1a8a6f5b | ||
|
|
b83ca08854 | ||
|
|
88baf0883a | ||
|
|
11b2a12392 | ||
|
|
40a75fdd12 | ||
|
|
1687d08587 | ||
|
|
17dba00264 | ||
|
|
57fcfd5e7d | ||
|
|
fa503ec3f2 | ||
|
|
37795226a4 | ||
|
|
29639a0ad5 | ||
|
|
85eee886ac | ||
|
|
f2ada3d547 | ||
|
|
a7011e11c4 | ||
|
|
72429cb9e8 | ||
|
|
eed04696a9 | ||
|
|
f05d4b8410 | ||
|
|
fc10212e68 | ||
|
|
c96b938e7d | ||
|
|
853a80bdbc | ||
|
|
3d281fbb71 | ||
|
|
56055bd76a | ||
|
|
f27b5d5588 | ||
|
|
105462a1fc | ||
|
|
af41f2b903 | ||
|
|
0581b91c32 | ||
|
|
1c55bbe2e8 | ||
|
|
c40b6285a2 | ||
|
|
f4ef4342c2 | ||
|
|
257bcefaf9 | ||
|
|
f9ba190812 | ||
|
|
2a2b939078 | ||
|
|
fd99ae78b3 | ||
|
|
f774467892 | ||
|
|
a8197b27aa | ||
|
|
9aebe87c67 | ||
|
|
8ce176f2dc | ||
|
|
60f6772f9e | ||
|
|
c2b5c39436 | ||
|
|
9b4201f880 | ||
|
|
1e01657577 | ||
|
|
9acda05dbd | ||
|
|
65f3ae9829 | ||
|
|
7e13610d24 | ||
|
|
24b34cd32f | ||
|
|
7a96727c59 | ||
|
|
367c31bf17 | ||
|
|
decba39c09 | ||
|
|
3bd456e52d | ||
|
|
79c0178a7c | ||
|
|
6cef0af5df | ||
|
|
ed3d3e4ff0 | ||
|
|
e96377572e | ||
|
|
8920d73f38 | ||
|
|
a7f23b9cc7 | ||
|
|
73f279d6e7 | ||
|
|
c2dfbd47a3 | ||
|
|
8f9dafcce9 | ||
|
|
8c13738199 | ||
|
|
87cc0481a0 | ||
|
|
55b1d89fd3 | ||
|
|
e695630822 | ||
|
|
85bfc1d79e | ||
|
|
a792a7005b | ||
|
|
c3c90dd1b4 | ||
|
|
96b46de7c8 | ||
|
|
edd03020c2 | ||
|
|
639aaff9c7 | ||
|
|
9e4843d53e | ||
|
|
2351884352 | ||
|
|
a3c051bf96 | ||
|
|
40bea78186 | ||
|
|
d55993a37b | ||
|
|
33165f4f55 | ||
|
|
a30c38f38c | ||
|
|
8effbff817 | ||
|
|
dcc3f9e0a2 | ||
|
|
e33d786745 | ||
|
|
251f67dcf3 | ||
|
|
b3572747f0 | ||
|
|
311c9e4719 | ||
|
|
ce3654c6ec | ||
|
|
f3212fe01c | ||
|
|
162ec2884e | ||
|
|
70dae17d2f | ||
|
|
8056131901 | ||
|
|
494afdde96 | ||
|
|
ac03242cfc | ||
|
|
9ace52114c | ||
|
|
6d4f1ebcc6 | ||
|
|
7c74cc6420 | ||
|
|
e45e06b675 | ||
|
|
39402b842e | ||
|
|
96a46a007f | ||
|
|
6d06234048 | ||
|
|
f8d2e0e6a8 | ||
|
|
fa6da788dc | ||
|
|
5aecf0e31d | ||
|
|
f5cf8cffa3 | ||
|
|
3fe1550943 | ||
|
|
cea90d535d | ||
|
|
c4afb3a2b5 | ||
|
|
9937ae8ef9 | ||
|
|
64978b0138 | ||
|
|
40f77b25d1 | ||
|
|
a09e27f863 | ||
|
|
32ab636c77 | ||
|
|
fcd0bb13b3 | ||
|
|
260a3004f4 | ||
|
|
2414239e50 | ||
|
|
7607e67d59 | ||
|
|
633f99df6c | ||
|
|
7927e1dcd4 | ||
|
|
eb3655da1c | ||
|
|
ed8ec89497 | ||
|
|
44bd038339 | ||
|
|
a6a500ade2 | ||
|
|
6014a75e0e | ||
|
|
eed2df0fb3 | ||
|
|
414e0b20b3 | ||
|
|
f934554143 | ||
|
|
b3d9d08750 | ||
|
|
d32540469b | ||
|
|
20b2956322 | ||
|
|
01a2d16974 | ||
|
|
431aa2cb79 | ||
|
|
d9487a07b1 | ||
|
|
6d3f87f610 | ||
|
|
bc1723c0ee | ||
|
|
cdc640b544 | ||
|
|
d5ef853343 | ||
|
|
54b05e48a9 | ||
|
|
d68674a660 | ||
|
|
ba5cd08a09 | ||
|
|
c97fadd7a3 | ||
|
|
24b582d77a | ||
|
|
96a34c3690 | ||
|
|
53a34174b9 | ||
|
|
39a1cf5bd8 | ||
|
|
027365c246 | ||
|
|
c7ccff2e20 | ||
|
|
4130616ab1 | ||
|
|
ededfaa40b | ||
|
|
0fcfe5772f | ||
|
|
61017a7997 |
2
.github/workflows/go-tests.yml
vendored
2
.github/workflows/go-tests.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
env QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown
|
||||
|
||||
- name: Upload qhelp markdown
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: qhelp-markdown
|
||||
path: go/qhelp-out/**/*.md
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
## 0.4.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added subclasses of `BuiltInOperations` for `__is_same`, `__is_function`, `__is_layout_compatible`, `__is_pointer_interconvertible_base_of`, `__is_array`, `__array_rank`, `__array_extent`, `__is_arithmetic`, `__is_complete_type`, `__is_compound`, `__is_const`, `__is_floating_point`, `__is_fundamental`, `__is_integral`, `__is_lvalue_reference`, `__is_member_function_pointer`, `__is_member_object_pointer`, `__is_member_pointer`, `__is_object`, `__is_pointer`, `__is_reference`, `__is_rvalue_reference`, `__is_scalar`, `__is_signed`, `__is_unsigned`, `__is_void`, and `__is_volatile`.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed an issue in the taint tracking analysis where implicit reads were not allowed by default in sinks or additional taint steps that used flow states.
|
||||
|
||||
## 0.3.5
|
||||
|
||||
## 0.3.4
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* Fixed an issue in the taint tracking analysis where implicit reads were not allowed by default in sinks or additional taint steps that used flow states.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -1,4 +1,14 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
## 0.4.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added subclasses of `BuiltInOperations` for `__is_same`, `__is_function`, `__is_layout_compatible`, `__is_pointer_interconvertible_base_of`, `__is_array`, `__array_rank`, `__array_extent`, `__is_arithmetic`, `__is_complete_type`, `__is_compound`, `__is_const`, `__is_floating_point`, `__is_fundamental`, `__is_integral`, `__is_lvalue_reference`, `__is_member_function_pointer`, `__is_member_object_pointer`, `__is_member_pointer`, `__is_object`, `__is_pointer`, `__is_reference`, `__is_rvalue_reference`, `__is_scalar`, `__is_signed`, `__is_unsigned`, `__is_void`, and `__is_volatile`.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fixed an issue in the taint tracking analysis where implicit reads were not allowed by default in sinks or additional taint steps that used flow states.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.5
|
||||
lastReleaseVersion: 0.4.0
|
||||
|
||||
@@ -49,6 +49,46 @@ module ProductFlow {
|
||||
this.isSinkPair(sink1, sink2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited through the first projection of the product
|
||||
* dataflow graph when the flow state is `state`.
|
||||
*/
|
||||
predicate isBarrier1(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isBarrier1(node) and state = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited through the second projection of the product
|
||||
* dataflow graph when the flow state is `state`.
|
||||
*/
|
||||
predicate isBarrier2(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isBarrier2(node) and state = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited through the first projection of the product
|
||||
* dataflow graph.
|
||||
*/
|
||||
predicate isBarrier1(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow through `node` is prohibited through the second projection of the product
|
||||
* dataflow graph.
|
||||
*/
|
||||
predicate isBarrier2(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited in the first projection of the product
|
||||
* dataflow graph.
|
||||
*/
|
||||
predicate isBarrierOut1(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data flow out of `node` is prohibited in the second projection of the product
|
||||
* dataflow graph.
|
||||
*/
|
||||
predicate isBarrierOut2(DataFlow::Node node) { none() }
|
||||
|
||||
predicate hasFlowPath(
|
||||
DataFlow::PathNode source1, DataFlow2::PathNode source2, DataFlow::PathNode sink1,
|
||||
DataFlow2::PathNode sink2
|
||||
@@ -70,6 +110,14 @@ module ProductFlow {
|
||||
override predicate isSink(DataFlow::Node sink, string state) {
|
||||
exists(Configuration conf | conf.isSinkPair(sink, state, _, _))
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node, string state) {
|
||||
exists(Configuration conf | conf.isBarrier1(node, state))
|
||||
}
|
||||
|
||||
override predicate isBarrierOut(DataFlow::Node node) {
|
||||
exists(Configuration conf | conf.isBarrierOut1(node))
|
||||
}
|
||||
}
|
||||
|
||||
class Conf2 extends DataFlow2::Configuration {
|
||||
@@ -87,6 +135,14 @@ module ProductFlow {
|
||||
conf.isSinkPair(sink1, _, sink, state) and any(Conf1 c).hasFlow(_, sink1)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node node, string state) {
|
||||
exists(Configuration conf | conf.isBarrier2(node, state))
|
||||
}
|
||||
|
||||
override predicate isBarrierOut(DataFlow::Node node) {
|
||||
exists(Configuration conf | conf.isBarrierOut2(node))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -416,6 +416,21 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() }
|
||||
|
||||
override string toStringImpl() { result = "Phi" }
|
||||
|
||||
/**
|
||||
* Gets a node that is used as input to this phi node.
|
||||
* `fromBackEdge` is true if data flows along a back-edge,
|
||||
* and `false` otherwise.
|
||||
*/
|
||||
final Node getAnInput(boolean fromBackEdge) {
|
||||
localFlowStep(result, this) and
|
||||
if phi.getBasicBlock().dominates(getBasicBlock(result))
|
||||
then fromBackEdge = true
|
||||
else fromBackEdge = false
|
||||
}
|
||||
|
||||
/** Gets a node that is used as input to this phi node. */
|
||||
final Node getAnInput() { result = this.getAnInput(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -301,7 +301,12 @@ private predicate defToNode(Node nodeFrom, Def def) {
|
||||
nodeHasInstruction(nodeFrom, def.getDefiningInstruction(), def.getIndirectionIndex())
|
||||
}
|
||||
|
||||
private predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse) {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Holds if `nodeFrom` is the node that correspond to the definition or use `defOrUse`.
|
||||
*/
|
||||
predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse) {
|
||||
// Node -> Def
|
||||
defToNode(nodeFrom, defOrUse)
|
||||
or
|
||||
|
||||
@@ -7,6 +7,7 @@ private import semmle.code.cpp.ir.IR as IR
|
||||
private import Semantic
|
||||
private import experimental.semmle.code.cpp.rangeanalysis.Bound as IRBound
|
||||
private import semmle.code.cpp.controlflow.IRGuards as IRGuards
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
module SemanticExprConfig {
|
||||
class Location = Cpp::Location;
|
||||
@@ -120,7 +121,15 @@ module SemanticExprConfig {
|
||||
|
||||
newtype TSsaVariable =
|
||||
TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or
|
||||
TSsaOperand(IR::Operand op) { op.isDefinitionInexact() }
|
||||
TSsaOperand(IR::Operand op) { op.isDefinitionInexact() } or
|
||||
TSsaPointerArithmeticGuard(IR::PointerArithmeticInstruction instr) {
|
||||
exists(Guard g, IR::Operand use | use = instr.getAUse() |
|
||||
g.comparesLt(use, _, _, _, _) or
|
||||
g.comparesLt(_, use, _, _, _) or
|
||||
g.comparesEq(use, _, _, _, _) or
|
||||
g.comparesEq(_, use, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
class SsaVariable extends TSsaVariable {
|
||||
string toString() { none() }
|
||||
@@ -129,6 +138,8 @@ module SemanticExprConfig {
|
||||
|
||||
IR::Instruction asInstruction() { none() }
|
||||
|
||||
IR::PointerArithmeticInstruction asPointerArithGuard() { none() }
|
||||
|
||||
IR::Operand asOperand() { none() }
|
||||
}
|
||||
|
||||
@@ -144,6 +155,18 @@ module SemanticExprConfig {
|
||||
final override IR::Instruction asInstruction() { result = instr }
|
||||
}
|
||||
|
||||
class SsaPointerArithmeticGuard extends SsaVariable, TSsaPointerArithmeticGuard {
|
||||
IR::PointerArithmeticInstruction instr;
|
||||
|
||||
SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(instr) }
|
||||
|
||||
final override string toString() { result = instr.toString() }
|
||||
|
||||
final override Location getLocation() { result = instr.getLocation() }
|
||||
|
||||
final override IR::PointerArithmeticInstruction asPointerArithGuard() { result = instr }
|
||||
}
|
||||
|
||||
class SsaOperand extends SsaVariable, TSsaOperand {
|
||||
IR::Operand op;
|
||||
|
||||
@@ -168,7 +191,11 @@ module SemanticExprConfig {
|
||||
)
|
||||
}
|
||||
|
||||
Expr getAUse(SsaVariable v) { result.(IR::LoadInstruction).getSourceValue() = v.asInstruction() }
|
||||
Expr getAUse(SsaVariable v) {
|
||||
result.(IR::LoadInstruction).getSourceValue() = v.asInstruction()
|
||||
or
|
||||
result = valueNumber(v.asPointerArithGuard()).getAnInstruction()
|
||||
}
|
||||
|
||||
SemType getSsaVariableType(SsaVariable v) {
|
||||
result = getSemanticType(v.asInstruction().getResultIRType())
|
||||
@@ -208,7 +235,9 @@ module SemanticExprConfig {
|
||||
|
||||
final override predicate hasRead(SsaVariable v) {
|
||||
exists(IR::Operand operand |
|
||||
operand.getDef() = v.asInstruction() and
|
||||
operand.getDef() = v.asInstruction() or
|
||||
operand.getDef() = valueNumber(v.asPointerArithGuard()).getAnInstruction()
|
||||
|
|
||||
not operand instanceof IR::PhiInputOperand and
|
||||
operand.getUse().getBlock() = block
|
||||
)
|
||||
@@ -227,7 +256,9 @@ module SemanticExprConfig {
|
||||
|
||||
final override predicate hasRead(SsaVariable v) {
|
||||
exists(IR::PhiInputOperand operand |
|
||||
operand.getDef() = v.asInstruction() and
|
||||
operand.getDef() = v.asInstruction() or
|
||||
operand.getDef() = valueNumber(v.asPointerArithGuard()).getAnInstruction()
|
||||
|
|
||||
operand.getPredecessorBlock() = pred and
|
||||
operand.getUse().getBlock() = succ
|
||||
)
|
||||
|
||||
@@ -10,7 +10,7 @@ class SemSsaVariable instanceof Specific::SsaVariable {
|
||||
|
||||
final Specific::Location getLocation() { result = super.getLocation() }
|
||||
|
||||
final SemLoadExpr getAUse() { result = Specific::getAUse(this) }
|
||||
final SemExpr getAUse() { result = Specific::getAUse(this) }
|
||||
|
||||
final SemType getType() { result = Specific::getSsaVariableType(this) }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.4.0-dev
|
||||
version: 0.4.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -6,7 +6,7 @@ import cpp
|
||||
* A function that concatenates the string from its second argument
|
||||
* to the string from its first argument, for example `strcat`.
|
||||
*/
|
||||
class StrcatFunction extends Function {
|
||||
deprecated class StrcatFunction extends Function {
|
||||
StrcatFunction() {
|
||||
getName() =
|
||||
[
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -558,13 +558,16 @@ private predicate expectsContentEx(NodeEx n, Content c) {
|
||||
pragma[nomagic]
|
||||
private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) }
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()),
|
||||
contentType) and
|
||||
read(_, tc.getContent(), _, config) and
|
||||
hasReadStep(tc.getContent(), config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
@@ -598,13 +601,9 @@ private predicate hasSinkCallCtx(Configuration config) {
|
||||
}
|
||||
|
||||
private module Stage1 implements StageSig {
|
||||
class ApApprox = Unit;
|
||||
|
||||
class Ap = Unit;
|
||||
|
||||
class ApOption = Unit;
|
||||
|
||||
class Cc = boolean;
|
||||
private class Cc = boolean;
|
||||
|
||||
/* Begin: Stage 1 logic. */
|
||||
/**
|
||||
@@ -613,7 +612,7 @@ private module Stage1 implements StageSig {
|
||||
* The Boolean `cc` records whether the node is reached through an
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
sourceNode(node, _, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
@@ -753,7 +752,7 @@ private module Stage1 implements StageSig {
|
||||
* the enclosing callable in order to reach a sink.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
|
||||
revFlow0(node, toReturn, config) and
|
||||
fwdFlow(node, config)
|
||||
}
|
||||
|
||||
@@ -267,9 +267,6 @@ Instruction getSourceAddressFromNode(Node node) {
|
||||
result = getSourceAddress(node.asOperand().(SideEffectOperand).getUse())
|
||||
}
|
||||
|
||||
/** Gets the source value of `instr` if it's an instruction that behaves like a `LoadInstruction`. */
|
||||
Instruction getSourceValue(Instruction instr) { result = getSourceValueOperand(instr).getDef() }
|
||||
|
||||
/**
|
||||
* Gets the operand that represents the source value of `instr` if it's an instruction
|
||||
* that behaves like a `LoadInstruction`.
|
||||
|
||||
@@ -143,16 +143,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = getNewInstruction(oldOperand.getAnyDef())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
private predicate hasMemoryOperandDefinition(
|
||||
OldInstruction oldInstruction, OldIR::NonPhiMemoryOperand oldOperand, Overlap overlap,
|
||||
|
||||
@@ -256,12 +256,6 @@ CppType getInstructionOperandType(Instruction instruction, TypedOperandTag tag)
|
||||
.getInstructionMemoryOperandType(getInstructionTag(instruction), tag)
|
||||
}
|
||||
|
||||
Instruction getPhiOperandDefinition(
|
||||
PhiInstruction instruction, IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
Instruction getPhiInstructionBlockStart(PhiInstruction instr) { none() }
|
||||
|
||||
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
|
||||
|
||||
@@ -143,16 +143,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
Instruction getRegisterOperandDefinition(Instruction instruction, RegisterOperandTag tag) {
|
||||
exists(OldInstruction oldInstruction, OldIR::RegisterOperand oldOperand |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
oldOperand = oldInstruction.getAnOperand() and
|
||||
tag = oldOperand.getOperandTag() and
|
||||
result = getNewInstruction(oldOperand.getAnyDef())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noopt]
|
||||
private predicate hasMemoryOperandDefinition(
|
||||
OldInstruction oldInstruction, OldIR::NonPhiMemoryOperand oldOperand, Overlap overlap,
|
||||
|
||||
@@ -15,4 +15,4 @@ where
|
||||
c.fromSource() and
|
||||
c.isTopLevel() and
|
||||
c.getParentScope() instanceof GlobalNamespace
|
||||
select c, "This class is not declared in any namespace"
|
||||
select c, "This class is not declared in any namespace."
|
||||
|
||||
@@ -16,4 +16,4 @@ where
|
||||
t.fromSource() and
|
||||
n = t.getMetrics().getEfferentSourceCoupling() and
|
||||
n > 10
|
||||
select t as class_, "This class has too many dependencies (" + n.toString() + ")"
|
||||
select t as class_, "This class has too many dependencies (" + n.toString() + ")."
|
||||
|
||||
@@ -17,4 +17,4 @@ where
|
||||
n = f.getMetrics().getNumberOfCalls() and
|
||||
n > 99 and
|
||||
not f.isMultiplyDefined()
|
||||
select f as function, "This function makes too many calls (" + n.toString() + ")"
|
||||
select f as function, "This function makes too many calls (" + n.toString() + ")."
|
||||
|
||||
@@ -18,4 +18,4 @@ where
|
||||
f.getMetrics().getNumberOfParameters() > 15
|
||||
select f,
|
||||
"This function has too many parameters (" + f.getMetrics().getNumberOfParameters().toString() +
|
||||
")"
|
||||
")."
|
||||
|
||||
@@ -21,5 +21,5 @@ where
|
||||
rhsType.getAMember() = m and
|
||||
not m.(VirtualFunction).isPure()
|
||||
) // add additional checks for concrete members in in-between supertypes
|
||||
select e, "This assignment expression slices from type $@ to $@", rhsType, rhsType.getName(),
|
||||
select e, "This assignment expression slices from type $@ to $@.", rhsType, rhsType.getName(),
|
||||
lhsType, lhsType.getName()
|
||||
|
||||
@@ -72,18 +72,6 @@ predicate floatTrivial(Literal lit) {
|
||||
|
||||
predicate charLiteral(Literal lit) { lit instanceof CharLiteral }
|
||||
|
||||
Type literalType(Literal literal) { result = literal.getType() }
|
||||
|
||||
predicate stringType(DerivedType t) {
|
||||
t.getBaseType() instanceof CharType
|
||||
or
|
||||
exists(SpecifiedType constCharType |
|
||||
t.getBaseType() = constCharType and
|
||||
constCharType.isConst() and
|
||||
constCharType.getBaseType() instanceof CharType
|
||||
)
|
||||
}
|
||||
|
||||
predicate numberType(Type t) { t instanceof FloatingPointType or t instanceof IntegralType }
|
||||
|
||||
predicate stringLiteral(Literal literal) { literal instanceof StringLiteral }
|
||||
|
||||
@@ -18,4 +18,4 @@ where
|
||||
f.hasSpecifier("virtual") and
|
||||
f.getFile().fromSource() and
|
||||
not f instanceof Destructor
|
||||
select f, "Avoid having public virtual methods (NVI idiom)"
|
||||
select f, "Avoid having public virtual methods (NVI idiom)."
|
||||
|
||||
@@ -23,4 +23,4 @@ where
|
||||
fclass = f.getDeclaringType() and
|
||||
hubIndex = fclass.getMetrics().getAfferentCoupling() * fclass.getMetrics().getEfferentCoupling() and
|
||||
hubIndex > 100
|
||||
select f, "Avoid having public virtual methods (NVI idiom)"
|
||||
select f, "Avoid having public virtual methods (NVI idiom)."
|
||||
|
||||
@@ -38,5 +38,5 @@ where
|
||||
sc = switch.getASwitchCase() and
|
||||
tooLong(sc) and
|
||||
switchCaseLength(sc, lines)
|
||||
select switch, "Switch has at least one case that is too long: $@", sc,
|
||||
select switch, "Switch has at least one case that is too long: $@.", sc,
|
||||
sc.getExpr().toString() + " (" + lines.toString() + " lines)"
|
||||
|
||||
@@ -58,4 +58,4 @@ where
|
||||
not exists(AsmStmt s | f = s.getEnclosingFunction()) and
|
||||
not v.getAnAttribute().getName() = "unused" and
|
||||
not any(ErrorExpr e).getEnclosingFunction() = f // unextracted expr may use `v`
|
||||
select v, "Variable " + v.getName() + " is not used"
|
||||
select v, "Variable " + v.getName() + " is not used."
|
||||
|
||||
@@ -27,4 +27,4 @@ where
|
||||
not declarationHasSideEffects(v) and
|
||||
not v.getAnAttribute().hasName("used") and
|
||||
not v.getAnAttribute().hasName("unused")
|
||||
select v, "Static variable " + v.getName() + " is never read"
|
||||
select v, "Static variable " + v.getName() + " is never read."
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
## 0.4.0
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new medium-precision query, `cpp/missing-check-scanf`, which detects `scanf` output variables that are used without a proper return-value check to see that they were actually written. A variation of this query was originally contributed as an [experimental query by @ihsinme](https://github.com/github/codeql/pull/8246).
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Modernizations from "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) have been ported to the "Cleartext storage of sensitive information in file" (`cpp/cleartext-storage-file`), "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) and "Cleartext storage of sensitive information in an SQLite database" (`cpp/cleartext-storage-database`) queries. These changes may result in more correct results and fewer false positive results from these queries.
|
||||
* The alert message of many queries have been changed to make the message consistent with other languages.
|
||||
|
||||
## 0.3.4
|
||||
|
||||
## 0.3.3
|
||||
|
||||
@@ -64,5 +64,5 @@ where
|
||||
) and
|
||||
(if context = test then testresult = "succeed" else testresult = "fail")
|
||||
select cond,
|
||||
"Variable '" + v.getName() + "' is always " + context + " here, this check will always " +
|
||||
testresult + "."
|
||||
"Variable '" + v.getName() + "' is always " + context + ", this check will always " + testresult +
|
||||
"."
|
||||
|
||||
@@ -29,4 +29,4 @@ from Expr alloc
|
||||
where
|
||||
allocateDescriptorCall(alloc) and
|
||||
not exists(ClosedExpr closed | closed.pointsTo() = alloc)
|
||||
select alloc, "This file descriptor is never closed"
|
||||
select alloc, "This file descriptor is never closed."
|
||||
|
||||
@@ -164,4 +164,4 @@ where
|
||||
fopenVariableReaches(v, def, ret) and
|
||||
ret.getAChild*() = v.getAnAccess()
|
||||
)
|
||||
select def, "The file opened here may not be closed at $@.", ret, "this exit point"
|
||||
select def, "This file may not be closed at $@.", ret, "this exit point"
|
||||
|
||||
@@ -14,4 +14,4 @@ import FileClosed
|
||||
|
||||
from Expr alloc
|
||||
where fopenCall(alloc) and not fopenCallMayBeClosed(alloc)
|
||||
select alloc, "The file is never closed"
|
||||
select alloc, "The file is never closed."
|
||||
|
||||
@@ -27,4 +27,4 @@ where
|
||||
definitionUsePair(v, other, unchecked)
|
||||
)
|
||||
select unchecked,
|
||||
"This dereference is not guarded by a non-null check, whereas other dereferences are guarded"
|
||||
"This dereference is not guarded by a non-null check, whereas other dereferences are guarded."
|
||||
|
||||
@@ -49,4 +49,4 @@ where
|
||||
select dangerous,
|
||||
"Variable '" + v.getName() +
|
||||
"' is used as an array-offset before it is tested for being negative (test on line " +
|
||||
check.getLocation().getStartLine().toString() + "). "
|
||||
check.getLocation().getStartLine().toString() + ")."
|
||||
|
||||
@@ -190,4 +190,4 @@ where
|
||||
allocatedVariableReaches(v, def, ret) and
|
||||
ret.getAChild*() = v.getAnAccess()
|
||||
)
|
||||
select def, "The memory allocated here may not be released at $@.", ret, "this exit point"
|
||||
select def, "This memory allocation may not be released at $@.", ret, "this exit point"
|
||||
|
||||
@@ -16,4 +16,4 @@ from AllocationExpr alloc
|
||||
where
|
||||
alloc.requiresDealloc() and
|
||||
not allocMayBeFreed(alloc)
|
||||
select alloc, "This memory is never freed"
|
||||
select alloc, "This memory is never freed."
|
||||
|
||||
@@ -117,6 +117,6 @@ where
|
||||
output.getCall() = call and
|
||||
output.hasGuardedAccess(access, false)
|
||||
select access,
|
||||
"$@ is read here, but may not have been written. " +
|
||||
"This variable is read, but may not have been written. " +
|
||||
"It should be guarded by a check that the $@ returns at least " +
|
||||
output.getMinimumGuardConstant() + ".", access, access.toString(), call, call.toString()
|
||||
output.getMinimumGuardConstant() + ".", call, call.toString()
|
||||
|
||||
@@ -14,4 +14,4 @@ from Expr alloc, Expr free, Expr freed
|
||||
where
|
||||
allocReaches(freed, alloc, "new[]") and
|
||||
freeExprOrIndirect(free, freed, "delete")
|
||||
select free, "This memory may have been allocated with '$@', not 'new'.", alloc, "new[]"
|
||||
select free, "This memory may have been allocated with $@, not 'new'.", alloc, "new[]"
|
||||
|
||||
@@ -14,4 +14,4 @@ from Expr alloc, Expr free, Expr freed
|
||||
where
|
||||
allocReaches(freed, alloc, "new") and
|
||||
freeExprOrIndirect(free, freed, "delete[]")
|
||||
select free, "This memory may have been allocated with '$@', not 'new[]'.", alloc, "new"
|
||||
select free, "This memory may have been allocated with $@, not 'new[]'.", alloc, "new"
|
||||
|
||||
@@ -30,4 +30,4 @@ where
|
||||
not v.getType().getUnderlyingType() instanceof ReferenceType and
|
||||
not exists(ScopeUtilityClass util | def = util.getAUse()) and
|
||||
not def.isInMacroExpansion()
|
||||
select def, "Variable '" + v.getName() + "' is assigned a value that is never used"
|
||||
select def, "Variable '" + v.getName() + "' is assigned a value that is never used."
|
||||
|
||||
@@ -62,5 +62,5 @@ class UseAfterFreeReachability extends StackVariableReachability {
|
||||
|
||||
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e
|
||||
where r.reaches(free, v, e)
|
||||
select e, "Memory pointed to by '" + v.getName().toString() + "' may have been previously freed $@",
|
||||
free, "here"
|
||||
select e, "Memory pointed to by '" + v.getName().toString() + "' may have $@.", free,
|
||||
"been previously freed"
|
||||
|
||||
@@ -12,4 +12,4 @@ from File f
|
||||
where
|
||||
not exists(ExtractionProblem e | e.getFile() = f) and
|
||||
exists(f.getRelativePath())
|
||||
select f, "File successfully extracted"
|
||||
select f, "File successfully extracted."
|
||||
|
||||
@@ -22,4 +22,4 @@ where
|
||||
not overflowTest(cmp) and
|
||||
not cmp.isFromTemplateInstantiation(_) and
|
||||
not isFromMacroDefinition(cmp)
|
||||
select cmp, "Self comparison."
|
||||
select cmp, "This expression compares an $@ to itself.", cmp.getLeftOperand(), "expression"
|
||||
|
||||
@@ -55,5 +55,5 @@ where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
source.getNode().asExpr().getFullyConverted().getUnspecifiedType() =
|
||||
sink.getNode().asExpr().getFullyConverted().getUnspecifiedType()
|
||||
select sink, source, sink,
|
||||
"Pointer arithmetic here may be done with the wrong type because of the cast $@.", source, "here"
|
||||
select sink, source, sink, "This pointer arithmetic may be done with the wrong type because of $@.",
|
||||
source, "this cast"
|
||||
|
||||
@@ -24,4 +24,4 @@ where
|
||||
va.getExplicitlyConverted().getType().getSize() > fct.getSize() and
|
||||
va.getTarget() = fi and
|
||||
not fct.getUnspecifiedType() instanceof BoolType
|
||||
select va, "Implicit downcast of bitfield $@", fi, fi.toString()
|
||||
select va, "Implicit downcast of bitfield $@.", fi, fi.toString()
|
||||
|
||||
@@ -49,5 +49,4 @@ where
|
||||
c.hasImplicitConversion() and
|
||||
not whiteListWrapped(c)
|
||||
select c,
|
||||
"Return value of type " + t1.toString() + " is implicitly converted to " + t2.toString() +
|
||||
" here."
|
||||
"Return value of type " + t1.toString() + " is implicitly converted to " + t2.toString() + "."
|
||||
|
||||
@@ -173,4 +173,4 @@ where
|
||||
not actual.getUnspecifiedType() instanceof ErroneousType
|
||||
select arg,
|
||||
"This argument should be of type '" + expected.getName() + "' but is of type '" +
|
||||
actual.getUnspecifiedType().getName() + "'"
|
||||
actual.getUnspecifiedType().getName() + "'."
|
||||
|
||||
@@ -17,5 +17,5 @@ import LeapYear
|
||||
from Expr source, Expr sink, PossibleYearArithmeticOperationCheckConfiguration config
|
||||
where config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(sink))
|
||||
select sink,
|
||||
"This arithmetic operation $@ uses a constant value of 365 ends up modifying the date/time located at $@, without considering leap year scenarios.",
|
||||
source, source.toString(), sink, sink.toString()
|
||||
"An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios.",
|
||||
source, source.toString()
|
||||
|
||||
@@ -13,4 +13,4 @@ import NtohlArrayNoBound
|
||||
|
||||
from NetworkToBufferSizeConfiguration bufConfig, DataFlow::Node source, DataFlow::Node sink
|
||||
where bufConfig.hasFlow(source, sink)
|
||||
select sink, "Unchecked use of data from network function $@", source, source.toString()
|
||||
select sink, "Unchecked use of data from network function $@.", source, source.toString()
|
||||
|
||||
@@ -81,4 +81,4 @@ from UninitialisedLocalReachability r, LocalVariable v, VariableAccess va
|
||||
where
|
||||
r.reaches(_, v, va) and
|
||||
not va = commonException()
|
||||
select va, "The variable $@ may not be initialized here.", v, v.getName()
|
||||
select va, "The variable $@ may not be initialized at this access.", v, v.getName()
|
||||
|
||||
@@ -399,5 +399,5 @@ where
|
||||
) and
|
||||
source.asStore() = store and
|
||||
sink.asSink(_) = load
|
||||
select sink, source, sink, "Stack variable $@ escapes $@ and is used after it has expired.", var,
|
||||
var.toString(), store, "here"
|
||||
select sink, source, sink, "Stack variable $@ escapes at $@ and is used after it has expired.", var,
|
||||
var.toString(), store, "this store"
|
||||
|
||||
@@ -83,4 +83,4 @@ where
|
||||
c.getAMemberFunction().getAnOverriddenFunction() = call.getStaticCallTarget()
|
||||
)
|
||||
select call.getUnconvertedResultExpression(), source, sink,
|
||||
"Call to pure virtual function during " + msg
|
||||
"Call to pure virtual function during " + msg + "."
|
||||
|
||||
@@ -92,5 +92,6 @@ where
|
||||
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2(), e) and
|
||||
msg = "no_tlsv1_2 was set"
|
||||
)
|
||||
select cc, "Usage of $@ with protocol $@ is not configured correctly: The option $@.", cc,
|
||||
"boost::asio::ssl::context::context", protocolSource, protocolSource.toString(), e, msg
|
||||
select cc,
|
||||
"This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@.",
|
||||
protocolSource, protocolSource.toString(), e, msg
|
||||
|
||||
@@ -67,5 +67,5 @@ where
|
||||
// the pointer was null. To follow this idea to its full generality, we
|
||||
// should also give an alert when `check` post-dominates `deref`.
|
||||
deref.getBlock() = dominator
|
||||
select checked, "This null check is redundant because the value is $@ in any case", deref,
|
||||
"dereferenced here"
|
||||
select checked, "This null check is redundant because $@ in any case.", deref,
|
||||
"the value is dereferenced"
|
||||
|
||||
@@ -60,5 +60,5 @@ where
|
||||
taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and
|
||||
isUserInput(taintSource, taintCause)
|
||||
select taintedArg, sourceNode, sinkNode,
|
||||
"This argument to a file access function is derived from $@ and then passed to " + callChain,
|
||||
"This argument to a file access function is derived from $@ and then passed to " + callChain + ".",
|
||||
taintSource, "user input (" + taintCause + ")"
|
||||
|
||||
@@ -158,5 +158,5 @@ where
|
||||
concatResult = sinkNode.getState().(ExecState).getSndNode()
|
||||
select sinkAsArgumentIndirection(sinkNode.getNode()), sourceNode, sinkNode,
|
||||
"This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to "
|
||||
+ callChain, sourceNode, "user input (" + taintCause + ")", concatResult,
|
||||
+ callChain + ".", sourceNode, "user input (" + taintCause + ")", concatResult,
|
||||
concatResult.toString()
|
||||
|
||||
@@ -50,5 +50,5 @@ where
|
||||
taintedWithPath(taintSource, taintedArg, sourceNode, sinkNode) and
|
||||
isUserInput(taintSource, taintCause)
|
||||
select taintedArg, sourceNode, sinkNode,
|
||||
"This argument to a SQL query function is derived from $@ and then passed to " + callChain,
|
||||
"This argument to a SQL query function is derived from $@ and then passed to " + callChain + ".",
|
||||
taintSource, "user input (" + taintCause + ")"
|
||||
|
||||
@@ -34,5 +34,5 @@ where
|
||||
isProcessOperationExplanation(arg, processOperation) and
|
||||
taintedWithPath(source, arg, sourceNode, sinkNode)
|
||||
select arg, sourceNode, sinkNode,
|
||||
"The value of this argument may come from $@ and is being passed to " + processOperation, source,
|
||||
source.toString()
|
||||
"The value of this argument may come from $@ and is being passed to " + processOperation + ".",
|
||||
source, source.toString()
|
||||
|
||||
@@ -116,6 +116,10 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** Gets `str` where the first letter has been lowercased. */
|
||||
bindingset[str]
|
||||
string lowerFirst(string str) { result = str.prefix(1).toLowerCase() + str.suffix(1) }
|
||||
|
||||
from
|
||||
ImproperArrayIndexValidationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
string sourceType
|
||||
@@ -123,5 +127,5 @@ where
|
||||
conf.hasFlowPath(source, sink) and
|
||||
isFlowSource(source.getNode(), sourceType)
|
||||
select sink.getNode(), source, sink,
|
||||
"$@ flows to here and is used in an array indexing expression, potentially causing an invalid access.",
|
||||
source.getNode(), sourceType
|
||||
"An array indexing expression depends on $@ that might be outside the bounds of the array.",
|
||||
source.getNode(), lowerFirst(sourceType)
|
||||
|
||||
@@ -34,4 +34,4 @@ where
|
||||
isUserInput(userValue, cause)
|
||||
select arg, sourceNode, sinkNode,
|
||||
"The value of this argument may come from $@ and is being used as a formatting argument to " +
|
||||
printfFunction, userValue, cause
|
||||
printfFunction + ".", userValue, cause
|
||||
|
||||
@@ -37,4 +37,4 @@ where
|
||||
isUserInput(userValue, cause)
|
||||
select arg, sourceNode, sinkNode,
|
||||
"The value of this argument may come from $@ and is being used as a formatting argument to " +
|
||||
printfFunction, userValue, cause
|
||||
printfFunction + ".", userValue, cause
|
||||
|
||||
@@ -86,4 +86,5 @@ class TaintSource extends VariableAccess {
|
||||
|
||||
from TaintSource source, VariableAccess sink
|
||||
where source.reaches(sink)
|
||||
select sink, "$@ flows to here and may not be null terminated.", source, "User-provided value"
|
||||
select sink, "String operation depends on a $@ that may not be null terminated.", source,
|
||||
"user-provided value"
|
||||
|
||||
@@ -50,5 +50,5 @@ where
|
||||
op.getAnOperand() = e and
|
||||
missingGuard(op, e, effect)
|
||||
select e, sourceNode, sinkNode,
|
||||
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin,
|
||||
"User-provided value"
|
||||
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
|
||||
origin, "User-provided value"
|
||||
|
||||
@@ -135,5 +135,5 @@ where
|
||||
sink.getNode().asExpr() = va and
|
||||
missingGuard(va, effect)
|
||||
select sink.getNode(), source, sink,
|
||||
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".",
|
||||
getExpr(source.getNode()), "Uncontrolled value"
|
||||
"Arithmetic expression depends on an $@, potentially causing an " + effect + ".",
|
||||
getExpr(source.getNode()), "uncontrolled value"
|
||||
|
||||
@@ -75,5 +75,6 @@ where
|
||||
missingGuardAgainstOverflow(op, va) and effect = "overflow"
|
||||
) and
|
||||
causeEffectCorrespond(cause, effect)
|
||||
select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".",
|
||||
select va,
|
||||
"$@ flows to an operand of an arithmetic expression, potentially causing an " + effect + ".",
|
||||
origin, "Extreme value"
|
||||
|
||||
@@ -36,5 +36,4 @@ where
|
||||
not inSystemMacroExpansion(use) and
|
||||
// Avoid double-counting: don't include all the conversions of `use`.
|
||||
not use instanceof Conversion
|
||||
select use, "$@ flows to here and is used in an expression which might " + kind + ".", origin,
|
||||
"User-provided value"
|
||||
select use, "$@ flows an expression which might " + kind + ".", origin, "User-provided value"
|
||||
|
||||
@@ -99,5 +99,5 @@ where
|
||||
isFlowSource(source.getNode(), taintCause) and
|
||||
conf.hasFlowPath(source, sink) and
|
||||
allocSink(alloc, sink.getNode())
|
||||
select alloc, source, sink, "This allocation size is derived from $@ and might overflow",
|
||||
select alloc, source, sink, "This allocation size is derived from $@ and might overflow.",
|
||||
source.getNode(), "user input (" + taintCause + ")"
|
||||
|
||||
@@ -39,9 +39,13 @@ where
|
||||
isHresultBooleanConverted(e1, e2) and
|
||||
if e2.isImplicit()
|
||||
then
|
||||
msg = "Implicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString()
|
||||
msg =
|
||||
"Implicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
|
||||
"."
|
||||
else
|
||||
msg = "Explicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString()
|
||||
msg =
|
||||
"Explicit conversion from " + e1.getType().toString() + " to " + e2.getType().toString() +
|
||||
"."
|
||||
)
|
||||
or
|
||||
exists(ControlStructure ctls |
|
||||
@@ -49,7 +53,7 @@ where
|
||||
e1.getType().(TypedefType).hasName("HRESULT") and
|
||||
not isHresultBooleanConverted(e1) and
|
||||
not ctls instanceof SwitchStmt and // not controlled by a boolean condition
|
||||
msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression"
|
||||
msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression."
|
||||
)
|
||||
or
|
||||
(
|
||||
@@ -57,14 +61,14 @@ where
|
||||
e1.getType().(TypedefType).hasName("HRESULT") and
|
||||
msg =
|
||||
"Usage of a type " + e1.getType().toString() +
|
||||
" as an argument of a binary logical operation"
|
||||
" as an argument of a binary logical operation."
|
||||
)
|
||||
or
|
||||
exists(UnaryLogicalOperation ulop | ulop.getAnOperand() = e1 |
|
||||
e1.getType().(TypedefType).hasName("HRESULT") and
|
||||
msg =
|
||||
"Usage of a type " + e1.getType().toString() +
|
||||
" as an argument of a unary logical operation"
|
||||
" as an argument of a unary logical operation."
|
||||
) and
|
||||
not isHresultBooleanConverted(e1)
|
||||
)
|
||||
|
||||
@@ -44,5 +44,5 @@ where
|
||||
w.getASource() = sinkNode.getNode().asExpr() and
|
||||
dest = w.getDest()
|
||||
select w, sourceNode, sinkNode,
|
||||
"This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@", source,
|
||||
"This write into buffer '" + dest.toString() + "' may contain unencrypted data from $@.", source,
|
||||
"user input (" + source.getSourceType() + ")"
|
||||
|
||||
@@ -73,5 +73,5 @@ where
|
||||
not isFileName(globalValueNumber(source)) and // file names are not passwords
|
||||
not exists(string convChar | convChar = w.getSourceConvChar(mid) | not convChar = ["s", "S"]) // ignore things written with other conversion characters
|
||||
select w, sourceNode, midNode,
|
||||
"This write into file '" + dest.toString() + "' may contain unencrypted data from $@", source,
|
||||
"This write into file '" + dest.toString() + "' may contain unencrypted data from $@.", source,
|
||||
"this source."
|
||||
|
||||
@@ -258,9 +258,9 @@ where
|
||||
then
|
||||
msg =
|
||||
"This operation transmits '" + sink.toString() +
|
||||
"', which may contain unencrypted sensitive data from $@"
|
||||
"', which may contain unencrypted sensitive data from $@."
|
||||
else
|
||||
msg =
|
||||
"This operation receives into '" + sink.toString() +
|
||||
"', which may put unencrypted sensitive data into $@"
|
||||
"', which may put unencrypted sensitive data into $@."
|
||||
select networkSendRecv, source, sink, msg, source, source.getNode().toString()
|
||||
|
||||
@@ -74,5 +74,6 @@ where
|
||||
config.hasFlowPath(source, sink) and
|
||||
source.getNode().asExpr() = sensitive and
|
||||
sqliteCall.getASource() = sink.getNode().asExpr()
|
||||
select sqliteCall, source, sink, "This SQLite call may store $@ in a non-encrypted SQLite database",
|
||||
sensitive, "sensitive information"
|
||||
select sqliteCall, source, sink,
|
||||
"This SQLite call may store $@ in a non-encrypted SQLite database.", sensitive,
|
||||
"sensitive information"
|
||||
|
||||
@@ -97,4 +97,4 @@ from
|
||||
where
|
||||
config.hasFlowPath(source, sink) and
|
||||
str = source.getNode().asExpr()
|
||||
select str, source, sink, "A URL may be constructed with the HTTP protocol."
|
||||
select str, source, sink, "This URL may be constructed with the HTTP protocol."
|
||||
|
||||
@@ -10,12 +10,6 @@ private predicate reaches(ControlFlowNode a, ControlFlowNode b) = fastTC(success
|
||||
|
||||
private predicate successor(ControlFlowNode a, ControlFlowNode b) { b = a.getASuccessor() }
|
||||
|
||||
class WhitelistedCallsConfig extends string {
|
||||
WhitelistedCallsConfig() { this = "config" }
|
||||
|
||||
abstract predicate isWhitelisted(Call c);
|
||||
}
|
||||
|
||||
abstract class WhitelistedCall extends Call {
|
||||
override Function getTarget() { none() }
|
||||
}
|
||||
|
||||
@@ -44,5 +44,5 @@ where
|
||||
)
|
||||
select dest,
|
||||
"This pointer might have type $@ (size " + sourceBase.getSize() +
|
||||
"), but the pointer arithmetic here is done with type " + destType + " (size " +
|
||||
destBase.getSize() + ").", sourceLoc, sourceBase.toString()
|
||||
"), but this pointer arithmetic is done with type " + destType + " (size " + destBase.getSize() +
|
||||
").", sourceLoc, sourceBase.toString()
|
||||
|
||||
@@ -51,5 +51,5 @@ where
|
||||
destBase instanceof CharType
|
||||
select dest,
|
||||
"This pointer might have type $@ (size " + sourceBase.getSize() +
|
||||
"), but the pointer arithmetic here is done with type " + destType + " (size " +
|
||||
destBase.getSize() + ").", sourceLoc, sourceBase.toString()
|
||||
"), but this pointer arithmetic is done with type " + destType + " (size " + destBase.getSize() +
|
||||
").", sourceLoc, sourceBase.toString()
|
||||
|
||||
@@ -26,4 +26,4 @@ where
|
||||
destBase instanceof VoidType
|
||||
select dest,
|
||||
"This pointer might have type $@ (size " + sourceBase.getSize() +
|
||||
"), but the pointer arithmetic here is done with type void", sourceLoc, sourceBase.toString()
|
||||
"), but this pointer arithmetic is done with type void.", sourceLoc, sourceBase.toString()
|
||||
|
||||
@@ -18,4 +18,4 @@ from FunctionCall call, Function target
|
||||
where
|
||||
call.getTarget() = target and
|
||||
target.hasGlobalOrStdName("gets")
|
||||
select call, "gets does not guard against buffer overflow"
|
||||
select call, "'gets' does not guard against buffer overflow."
|
||||
|
||||
@@ -16,7 +16,7 @@ import cpp
|
||||
predicate potentiallyDangerousFunction(Function f, string message) {
|
||||
exists(string name | f.hasGlobalName(name) |
|
||||
name = ["gmtime", "localtime", "ctime", "asctime"] and
|
||||
message = "Call to " + name + " is potentially dangerous"
|
||||
message = "Call to '" + name + "' is potentially dangerous."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,4 +16,4 @@ import FilePermissions
|
||||
from FileCreationWithOptionalModeExpr fc
|
||||
where not fc.hasModeArgument()
|
||||
select fc,
|
||||
"A file is created here without providing a mode argument, which may leak bits from the stack."
|
||||
"This creates a file without providing a mode argument, which may leak bits from the stack."
|
||||
|
||||
@@ -37,5 +37,5 @@ from Expr source, Expr condition, Expr raise, PathNode sourceNode, PathNode sink
|
||||
where
|
||||
taintedWithPath(source, condition, sourceNode, sinkNode) and
|
||||
sensitiveCondition(condition, raise)
|
||||
select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@",
|
||||
select condition, sourceNode, sinkNode, "Reliance on untrusted input $@ to raise privilege at $@.",
|
||||
source, source.toString(), raise, raise.toString()
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The alert message of many queries have been changed to make the message consistent with other languages.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* Added a new medium-precision query, `cpp/missing-check-scanf`, which detects `scanf` output variables that are used without a proper return-value check to see that they were actually written. A variation of this query was originally contributed as an [experimental query by @ihsinme](https://github.com/github/codeql/pull/8246).
|
||||
4
cpp/ql/src/change-notes/2022-09-23-alert-messages.md
Normal file
4
cpp/ql/src/change-notes/2022-09-23-alert-messages.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The alert message of many queries have been changed to better follow the style guide and make the message consistent with other languages.
|
||||
@@ -1,4 +1,10 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 0.4.0
|
||||
|
||||
### New Queries
|
||||
|
||||
* Added a new medium-precision query, `cpp/missing-check-scanf`, which detects `scanf` output variables that are used without a proper return-value check to see that they were actually written. A variation of this query was originally contributed as an [experimental query by @ihsinme](https://github.com/github/codeql/pull/8246).
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Modernizations from "Cleartext storage of sensitive information in buffer" (`cpp/cleartext-storage-buffer`) have been ported to the "Cleartext storage of sensitive information in file" (`cpp/cleartext-storage-file`), "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) and "Cleartext storage of sensitive information in an SQLite database" (`cpp/cleartext-storage-database`) queries. These changes may result in more correct results and fewer false positive results from these queries.
|
||||
* The alert message of many queries have been changed to make the message consistent with other languages.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.3.4
|
||||
lastReleaseVersion: 0.4.0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user