mirror of
https://github.com/github/codeql.git
synced 2026-05-24 16:17:07 +02:00
Compare commits
561 Commits
tiferet/co
...
dbartol/re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a851ef61bb | ||
|
|
66c1629974 | ||
|
|
d8857c7ce8 | ||
|
|
a46787ea07 | ||
|
|
bd9b96e154 | ||
|
|
8ee020f79c | ||
|
|
6e167040f5 | ||
|
|
657cd89286 | ||
|
|
13f7fd88f1 | ||
|
|
634ed91904 | ||
|
|
cf42427f54 | ||
|
|
f7f3890b40 | ||
|
|
70f76d06c7 | ||
|
|
45c0d4a3b2 | ||
|
|
7e5bfa5aa0 | ||
|
|
271b23ba8f | ||
|
|
0c3daabc51 | ||
|
|
753d886b0d | ||
|
|
6d247bfdf9 | ||
|
|
e7209d1ee1 | ||
|
|
75f3ebf051 | ||
|
|
9f69c75c50 | ||
|
|
2cd70b96cd | ||
|
|
df482a9603 | ||
|
|
470256da85 | ||
|
|
8bba3eb2b6 | ||
|
|
f08f07e19e | ||
|
|
d0a19fffee | ||
|
|
7e99426141 | ||
|
|
2bf5966fe3 | ||
|
|
fd4915a564 | ||
|
|
9d288c90a5 | ||
|
|
a7b3f1370f | ||
|
|
d0aa307bd3 | ||
|
|
b887165005 | ||
|
|
3689481c18 | ||
|
|
660e52f2bf | ||
|
|
e9e3ef3ea2 | ||
|
|
799c945299 | ||
|
|
95f8f85aa2 | ||
|
|
aacba0b522 | ||
|
|
513fe09dbb | ||
|
|
d17c055139 | ||
|
|
44a615839d | ||
|
|
f08eb8e616 | ||
|
|
69f42b9c74 | ||
|
|
38250b0821 | ||
|
|
cbc96dba8a | ||
|
|
522a4bb9fa | ||
|
|
8e11c2c476 | ||
|
|
992801b7cb | ||
|
|
9ffa236c51 | ||
|
|
c0c40cc05b | ||
|
|
3a3c7fc59e | ||
|
|
f209ff4f76 | ||
|
|
b7f7c5ba20 | ||
|
|
f63ffb0630 | ||
|
|
069cf9d17f | ||
|
|
cbd21edc99 | ||
|
|
2f85735b6a | ||
|
|
69ba2e6f8c | ||
|
|
b871342e83 | ||
|
|
13347cd102 | ||
|
|
9f4b965202 | ||
|
|
d70d1fbf81 | ||
|
|
a43704ab43 | ||
|
|
063398f24d | ||
|
|
60f3ff8c33 | ||
|
|
8bcbf8e30f | ||
|
|
8517eff0f7 | ||
|
|
b49ca6a24c | ||
|
|
a18aad8536 | ||
|
|
38d0bb4a60 | ||
|
|
1d321c692b | ||
|
|
ede1503cc6 | ||
|
|
283173ad02 | ||
|
|
3145e8f9b7 | ||
|
|
1956405d17 | ||
|
|
5735bb698d | ||
|
|
0e33f730b1 | ||
|
|
ea7063f3c6 | ||
|
|
490872173a | ||
|
|
07ca1c2ec0 | ||
|
|
e7c298d903 | ||
|
|
b502ca1ea7 | ||
|
|
a716482c1f | ||
|
|
59bac04d8f | ||
|
|
ffc858e34d | ||
|
|
bf0ecded04 | ||
|
|
7437cd4d85 | ||
|
|
f85a47d41f | ||
|
|
a2dc505c26 | ||
|
|
5183290439 | ||
|
|
322e39446d | ||
|
|
016727d6b6 | ||
|
|
b2c1b55c0c | ||
|
|
b17a93eaad | ||
|
|
4d797d6b3d | ||
|
|
da43984ba4 | ||
|
|
ee23799a59 | ||
|
|
6c739b67fa | ||
|
|
3c59aa319e | ||
|
|
7cd9369d91 | ||
|
|
33a9f86f54 | ||
|
|
dd33f4f4d2 | ||
|
|
6f42153eac | ||
|
|
4e68a4670b | ||
|
|
4765772725 | ||
|
|
243b92b28c | ||
|
|
60c0bcf8f7 | ||
|
|
c39fe59a04 | ||
|
|
7ae1047fda | ||
|
|
ff9ed0d4fb | ||
|
|
5dbbb86d46 | ||
|
|
728e3abee5 | ||
|
|
36569f997f | ||
|
|
6b1ac73a46 | ||
|
|
de1269f18f | ||
|
|
c46ede02e6 | ||
|
|
6adfea2365 | ||
|
|
daf6a4ce07 | ||
|
|
f68a40f82b | ||
|
|
fac2769d85 | ||
|
|
0e31439b7e | ||
|
|
2a3b5fc2b2 | ||
|
|
d0840afb80 | ||
|
|
9f48ae656f | ||
|
|
0805daaa56 | ||
|
|
51998294ad | ||
|
|
4ae99592a3 | ||
|
|
205233b42f | ||
|
|
3e1ebb954f | ||
|
|
0cec59e043 | ||
|
|
8ffa195538 | ||
|
|
5a2ef8321c | ||
|
|
4128f56aa9 | ||
|
|
6c6113b85b | ||
|
|
802faf1197 | ||
|
|
7ad52e1365 | ||
|
|
f00b62df76 | ||
|
|
90baef83ee | ||
|
|
8eb041c172 | ||
|
|
520f598d49 | ||
|
|
d9704d7b39 | ||
|
|
42f6dfc197 | ||
|
|
404f4a81a7 | ||
|
|
50dd4e7ee7 | ||
|
|
f2800abee4 | ||
|
|
7f44cebed7 | ||
|
|
4138296ec6 | ||
|
|
991d659cb2 | ||
|
|
976faf97d1 | ||
|
|
19c34be1ea | ||
|
|
102b5e05e1 | ||
|
|
2b349b3024 | ||
|
|
2c4ccb79a1 | ||
|
|
3043ac850c | ||
|
|
f6c36b469a | ||
|
|
f190d60912 | ||
|
|
eccba57536 | ||
|
|
7aa6c62050 | ||
|
|
05415768c9 | ||
|
|
f10f053c36 | ||
|
|
913d8361ba | ||
|
|
4609b2060a | ||
|
|
8f3be9fbfd | ||
|
|
edf7724579 | ||
|
|
37644d30d2 | ||
|
|
6327fced6f | ||
|
|
ad281c0365 | ||
|
|
a8f673ffa4 | ||
|
|
e08c734c40 | ||
|
|
55c17f453f | ||
|
|
87b968f337 | ||
|
|
9f8326a3fa | ||
|
|
a077345227 | ||
|
|
73f2f52ed8 | ||
|
|
739906b60c | ||
|
|
9e10aee8a1 | ||
|
|
cc2914be3c | ||
|
|
de53727ab3 | ||
|
|
0a3d62c92a | ||
|
|
148da611c6 | ||
|
|
aad55ffbd6 | ||
|
|
75f9a947b3 | ||
|
|
ed706d9bc1 | ||
|
|
e41cd810d3 | ||
|
|
93e291cb3e | ||
|
|
cde853c095 | ||
|
|
6742beae1b | ||
|
|
31374b485c | ||
|
|
e410244fe0 | ||
|
|
bb8f4bb7c1 | ||
|
|
ae6501d906 | ||
|
|
08be8edbce | ||
|
|
ddd4ccbb4b | ||
|
|
ff030534ff | ||
|
|
b42295801b | ||
|
|
337ce65fe5 | ||
|
|
4b221bd964 | ||
|
|
186ba428cf | ||
|
|
1243d40bb2 | ||
|
|
35a67845cf | ||
|
|
59b71df2d6 | ||
|
|
0b4d0d2772 | ||
|
|
bab8cfb62a | ||
|
|
a5b6889478 | ||
|
|
5dd2d20176 | ||
|
|
7d6664f14d | ||
|
|
540ecf3c21 | ||
|
|
755085e9fe | ||
|
|
2589034242 | ||
|
|
830908b5c8 | ||
|
|
3e914ef2ff | ||
|
|
fc05825c73 | ||
|
|
8a6a8fc28a | ||
|
|
0619453c2f | ||
|
|
b40c77d419 | ||
|
|
3f218c903b | ||
|
|
8f270b665c | ||
|
|
c91b6f7ce9 | ||
|
|
f4555ed1a2 | ||
|
|
66e086f92f | ||
|
|
9f6c0991cf | ||
|
|
5ed9029143 | ||
|
|
75fb47c76f | ||
|
|
cd8a10d0a5 | ||
|
|
96deddf053 | ||
|
|
452685bb66 | ||
|
|
310ef79fbd | ||
|
|
d0dac03bad | ||
|
|
2dfcd1dd9c | ||
|
|
27f40e08e5 | ||
|
|
d557f6fd2e | ||
|
|
41b7922c7d | ||
|
|
19802ccb73 | ||
|
|
1e026ef45e | ||
|
|
e63f9141e5 | ||
|
|
cbd7434a7e | ||
|
|
b68538376c | ||
|
|
3bcf6d68ce | ||
|
|
f8a62c4c82 | ||
|
|
58f92764f7 | ||
|
|
fd23fa94a5 | ||
|
|
e79b8f3e23 | ||
|
|
d2d5cce787 | ||
|
|
14590436f9 | ||
|
|
50d3592ad3 | ||
|
|
a91208fd2c | ||
|
|
36f14b31bc | ||
|
|
82602014ad | ||
|
|
88fb1a18cb | ||
|
|
fdcc144a98 | ||
|
|
591aeff906 | ||
|
|
19bbe6d276 | ||
|
|
d1a7feebc4 | ||
|
|
d946802057 | ||
|
|
57399b733e | ||
|
|
0e890fd788 | ||
|
|
eef3905c46 | ||
|
|
9ce248c829 | ||
|
|
c13cad7e87 | ||
|
|
d79337774d | ||
|
|
e476cde985 | ||
|
|
e1539889ef | ||
|
|
e24b15bbe7 | ||
|
|
9239d4042e | ||
|
|
fdc94365b4 | ||
|
|
db04a0dadf | ||
|
|
74158f1e3a | ||
|
|
09a11f4166 | ||
|
|
d4f3a6d4bb | ||
|
|
6c3aabe1df | ||
|
|
c3e495efe9 | ||
|
|
03b6ee3833 | ||
|
|
6ff8d4de5c | ||
|
|
00ee34c0a0 | ||
|
|
57fd397cb3 | ||
|
|
d3a4dadc7d | ||
|
|
aa9a8a0e22 | ||
|
|
36bb84d97f | ||
|
|
1ddf5fb133 | ||
|
|
29eb66d772 | ||
|
|
2af509595b | ||
|
|
7ac5791c49 | ||
|
|
f96968975b | ||
|
|
e98ab5d2c2 | ||
|
|
e9ce29664e | ||
|
|
ce63549425 | ||
|
|
db39c0b8be | ||
|
|
1d358c5f77 | ||
|
|
a06642944f | ||
|
|
f5b40731d6 | ||
|
|
e801d9636a | ||
|
|
dc0b0445ed | ||
|
|
9540beeda9 | ||
|
|
8b0bc677f4 | ||
|
|
dca1e34cd8 | ||
|
|
16e1e97ff0 | ||
|
|
af4c3122ca | ||
|
|
078a2aa03b | ||
|
|
9eb9eb606e | ||
|
|
ec0bd24b64 | ||
|
|
5b560b12e9 | ||
|
|
609d6011a2 | ||
|
|
6cb00992e8 | ||
|
|
04a3f76a8b | ||
|
|
d36a7ed10e | ||
|
|
99c8b291b2 | ||
|
|
b8732859de | ||
|
|
31400df0d4 | ||
|
|
69690a2509 | ||
|
|
4438f8c58c | ||
|
|
d3da790191 | ||
|
|
3c8f6e3c07 | ||
|
|
4c5faaf985 | ||
|
|
8abaf1247a | ||
|
|
5ffbf563b8 | ||
|
|
72a03257e7 | ||
|
|
5eb814fd8b | ||
|
|
7869733ab5 | ||
|
|
88b6bd9478 | ||
|
|
ce2b86b9e3 | ||
|
|
2eae6a3e9a | ||
|
|
6afcbce421 | ||
|
|
5d0dfe8c04 | ||
|
|
e7524dea69 | ||
|
|
4b3b1d2a8b | ||
|
|
1e752f305d | ||
|
|
08ce03cd93 | ||
|
|
3bab8c6d1d | ||
|
|
651a76c9ce | ||
|
|
c05ffd4d00 | ||
|
|
7ca3407c86 | ||
|
|
a7ec0fa900 | ||
|
|
b9d0a60ce7 | ||
|
|
b0031a0d85 | ||
|
|
1d1780b30f | ||
|
|
7dde52ced2 | ||
|
|
4efdcc22a2 | ||
|
|
f85fa87f69 | ||
|
|
2a5e0a3b77 | ||
|
|
e2652591a5 | ||
|
|
1411804e58 | ||
|
|
1d654d1eac | ||
|
|
1739673202 | ||
|
|
c74eac4930 | ||
|
|
cec91c4831 | ||
|
|
5101a8e9f3 | ||
|
|
136ecaf49a | ||
|
|
c3996b00d5 | ||
|
|
120f2045cd | ||
|
|
6d9cea90cb | ||
|
|
a3ca9ad27d | ||
|
|
e153a65216 | ||
|
|
914d3d86af | ||
|
|
3a7d51d2ee | ||
|
|
e607c51292 | ||
|
|
47448d9efc | ||
|
|
6c7a01d3d5 | ||
|
|
d493cfdf3a | ||
|
|
f9729bccef | ||
|
|
a3b263ee6e | ||
|
|
b2611fe198 | ||
|
|
2e7ddb479e | ||
|
|
4cbfc306ac | ||
|
|
133ec2e4af | ||
|
|
87a1ccd428 | ||
|
|
e56737e007 | ||
|
|
8c9e817c0d | ||
|
|
bb38c4d6fd | ||
|
|
1a90b388a9 | ||
|
|
055017de49 | ||
|
|
9538ac73e4 | ||
|
|
d626745ab1 | ||
|
|
e99a040884 | ||
|
|
8b44d5c39e | ||
|
|
30805d964c | ||
|
|
9b818a04f2 | ||
|
|
0bb11fa371 | ||
|
|
0547e4ccf2 | ||
|
|
d4e80c664e | ||
|
|
4498657384 | ||
|
|
28806fe5f4 | ||
|
|
6072ccd81d | ||
|
|
0ff9520575 | ||
|
|
b5165e3692 | ||
|
|
5202f963dd | ||
|
|
74c0197544 | ||
|
|
83d204d7a8 | ||
|
|
4d918b5e5f | ||
|
|
822890f2bd | ||
|
|
3e1164f82e | ||
|
|
055641e684 | ||
|
|
f5f67dd11a | ||
|
|
8cccee6eba | ||
|
|
0bd587b395 | ||
|
|
e185e9080c | ||
|
|
b2e40ac603 | ||
|
|
baafd9f8ba | ||
|
|
e5f473052d | ||
|
|
e711ba9d18 | ||
|
|
9d072a12ed | ||
|
|
672485ae38 | ||
|
|
21aff99637 | ||
|
|
dcca5d28bb | ||
|
|
50518b5622 | ||
|
|
b8e8ddf9ae | ||
|
|
a68b55b099 | ||
|
|
70081defdc | ||
|
|
62ae702e07 | ||
|
|
ed78d39d61 | ||
|
|
245edd41ff | ||
|
|
13459c8afc | ||
|
|
4b42c4447b | ||
|
|
5b11cfe006 | ||
|
|
752b126862 | ||
|
|
eaed870b31 | ||
|
|
f6baab6399 | ||
|
|
68c3c16ab3 | ||
|
|
186e3755c0 | ||
|
|
da39f15a9d | ||
|
|
522074940d | ||
|
|
b60fef88b5 | ||
|
|
21167f4b67 | ||
|
|
f308be7382 | ||
|
|
74221f4aba | ||
|
|
6f22867af9 | ||
|
|
ddeb700fd6 | ||
|
|
fc64faefcf | ||
|
|
e9df860431 | ||
|
|
6f2b528a32 | ||
|
|
8322a44379 | ||
|
|
f09f1c4c50 | ||
|
|
39e3254fe0 | ||
|
|
0de6511dff | ||
|
|
6060f2e3e3 | ||
|
|
c369b28a2a | ||
|
|
f39872e649 | ||
|
|
089d030bc2 | ||
|
|
9f08acab7e | ||
|
|
df6ba43cca | ||
|
|
344f7bca5b | ||
|
|
06000781e9 | ||
|
|
f63c768d9f | ||
|
|
fc43220864 | ||
|
|
6d27585b92 | ||
|
|
2b1f34ed9b | ||
|
|
418adb824c | ||
|
|
8ba864e897 | ||
|
|
47fd64fc44 | ||
|
|
2b2ff7717e | ||
|
|
75586b0cf6 | ||
|
|
a393bff6cb | ||
|
|
90a9688310 | ||
|
|
cd39d15b40 | ||
|
|
8fc7e4be43 | ||
|
|
c297a68acf | ||
|
|
e2ef780c55 | ||
|
|
38ff584307 | ||
|
|
f933d24031 | ||
|
|
70efadac77 | ||
|
|
e87a4531d8 | ||
|
|
ac20eafecc | ||
|
|
2bba31eb02 | ||
|
|
dc464879a2 | ||
|
|
cd33e4d394 | ||
|
|
b6ce37b241 | ||
|
|
8fd8c9b04d | ||
|
|
0caea17118 | ||
|
|
34feafd4fa | ||
|
|
1f3f7e9ccc | ||
|
|
4068cc9c3a | ||
|
|
bc80c9b013 | ||
|
|
fb9b16325d | ||
|
|
fd0e318eb1 | ||
|
|
923ca134e8 | ||
|
|
fd73f4094f | ||
|
|
b6a6ed5ba3 | ||
|
|
62730e7a4b | ||
|
|
a4538de3a3 | ||
|
|
2f7250a0b3 | ||
|
|
63ecae5426 | ||
|
|
2d78cce7a5 | ||
|
|
ee858d840e | ||
|
|
2218516685 | ||
|
|
af55f172ae | ||
|
|
011fc20963 | ||
|
|
1ec935dee6 | ||
|
|
bd940712de | ||
|
|
9a74f18ac5 | ||
|
|
ce004e9c1e | ||
|
|
12a3251649 | ||
|
|
a89be2e3f8 | ||
|
|
de72a765e0 | ||
|
|
9ff63b00d6 | ||
|
|
08c778241d | ||
|
|
413375992d | ||
|
|
9125b85ff0 | ||
|
|
92453bd2c5 | ||
|
|
945bb7459a | ||
|
|
a62ad5000b | ||
|
|
135ee0d0c1 | ||
|
|
028ef6f27f | ||
|
|
48e6bdb117 | ||
|
|
db6f843641 | ||
|
|
8603609698 | ||
|
|
e468434b82 | ||
|
|
ddfcfc9b67 | ||
|
|
f6d99dc00d | ||
|
|
a743067dc8 | ||
|
|
04df56d1c0 | ||
|
|
98e6fc8a88 | ||
|
|
a980f26fda | ||
|
|
9f4107d211 | ||
|
|
9e097f5430 | ||
|
|
0d4cb1e6ce | ||
|
|
6eb4525ab2 | ||
|
|
e812029c03 | ||
|
|
f0c5a80d1a | ||
|
|
0ff36cd083 | ||
|
|
b11d11c0c9 | ||
|
|
9034d74663 | ||
|
|
dbcd4d6d5d | ||
|
|
77099fe9d0 | ||
|
|
9710aeecbf | ||
|
|
556cdbaa21 | ||
|
|
37775407a9 | ||
|
|
340897f262 | ||
|
|
a23750a9c7 | ||
|
|
c65d1d9a50 | ||
|
|
10bca3544c | ||
|
|
5f78bbbf52 | ||
|
|
543bd28b03 | ||
|
|
d324f9397c | ||
|
|
25da904314 | ||
|
|
4666024419 | ||
|
|
91f99ed2a1 | ||
|
|
fad7e9489b | ||
|
|
8a412dc5fd | ||
|
|
84b38b6c32 | ||
|
|
dd17271ec8 | ||
|
|
db40ccae81 | ||
|
|
fed0a06353 | ||
|
|
7201b3e116 | ||
|
|
8536f5f5a2 | ||
|
|
bd92403b42 | ||
|
|
11154a9409 | ||
|
|
fed6a97eb8 | ||
|
|
9d50511ea4 | ||
|
|
5deb996b33 | ||
|
|
91efb61e97 | ||
|
|
0325c07bd9 | ||
|
|
ffa77f0a76 | ||
|
|
588dedc265 | ||
|
|
1a04ad98bc | ||
|
|
378db7de87 | ||
|
|
5264936fc3 | ||
|
|
272e4f6cf9 | ||
|
|
2dc38aee54 | ||
|
|
8170f01b66 |
@@ -1,11 +1,23 @@
|
||||
{ "provide": [ "ruby/.codeqlmanifest.json",
|
||||
"*/ql/src/qlpack.yml",
|
||||
"*/ql/lib/qlpack.yml",
|
||||
"*/ql/test/qlpack.yml",
|
||||
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
|
||||
"*/ql/examples/qlpack.yml",
|
||||
"*/upgrades/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
|
||||
"misc/legacy-support/*/qlpack.yml",
|
||||
"misc/suite-helpers/qlpack.yml" ] }
|
||||
{
|
||||
"provide": [
|
||||
"*/ql/src/qlpack.yml",
|
||||
"*/ql/lib/qlpack.yml",
|
||||
"*/ql/test/qlpack.yml",
|
||||
"*/ql/examples/qlpack.yml",
|
||||
"*/upgrades/qlpack.yml",
|
||||
"cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml",
|
||||
"javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml",
|
||||
"misc/legacy-support/*/qlpack.yml",
|
||||
"misc/suite-helpers/qlpack.yml",
|
||||
"ruby/extractor-pack/codeql-extractor.yml",
|
||||
"ruby/ql/consistency-queries/qlpack.yml"
|
||||
],
|
||||
"versionPolicies": {
|
||||
"default": {
|
||||
"requireChangeNotes": true,
|
||||
"committedPrereleaseSuffix": "dev",
|
||||
"committedVersion": "nextPatchRelease"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
.github/workflows/ruby-dataset-measure.yml
vendored
4
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
repo: [rails/rails, discourse/discourse, spree/spree]
|
||||
repo: [rails/rails, discourse/discourse, spree/spree, ruby/ruby]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
- name: Create database
|
||||
run: |
|
||||
codeql database create \
|
||||
--search-path "${{ github.workspace }}/ruby" \
|
||||
--search-path "${{ github.workspace }}/ruby/extractor-pack" \
|
||||
--threads 4 \
|
||||
--language ruby --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
|
||||
4
.github/workflows/ruby-qltest.yml
vendored
4
.github/workflows/ruby-qltest.yml
vendored
@@ -32,14 +32,14 @@ jobs:
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" --consistency-queries ql/consistency-queries ql/test
|
||||
codeql test run --search-path "${{ github.workspace }}/ruby/extractor-pack" --check-databases --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Check QL formatting
|
||||
run: find ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 codeql query format --check-only
|
||||
- name: Check QL compilation
|
||||
run: |
|
||||
codeql query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ruby" --additional-packs "${{ github.workspace }}" "ql/src" "ql/examples"
|
||||
codeql query compile --check-only --threads=4 --warnings=error "ql/src" "ql/examples"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
- name: Check DB upgrade scripts
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
# benjamin-buttons.md
|
||||
|
||||
This file describes the changes that have been applied to
|
||||
the library to make it behave as if it was younger.
|
||||
|
||||
## TaintedPath.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-022/TaintedPath/TaintedPath.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+pathinjection
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+tainted-path
|
||||
|
||||
Sinks from the "graceful-fs" and "fs-extra" (added before the open-sourcing squash).
|
||||
|
||||
## Xss.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-079/Xss.expected
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
- recursive type tracking for `jQuery::dollar`, `DOM::domValueRef`.
|
||||
|
||||
## SqlInjection.ql
|
||||
|
||||
Sinks added between 2020-01-01 and 2020-10-06 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
|
||||
Sinks added between 2018-08-02 and 2020-01-01 have been removed. Found by looking at:
|
||||
|
||||
- the commit titles of https://github.com/github/codeql/commits/main/javascript/ql/test/query-tests/Security/CWE-089
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sink
|
||||
- the PR titles of https://github.com/github/codeql/pulls?page=2&q=is%3Apr+label%3AJS+is%3Aclosed+sql
|
||||
|
||||
TypeTracking in SQL.qll (added before the open-sourcing squash)
|
||||
|
||||
The model of `mssql` and `sequelize` (added before the open-sourcing squash)
|
||||
|
||||
## PseudoProperties
|
||||
|
||||
Pseudo-properties (`$name$`) used in type-tracking and global dataflow configurations have been disabled.
|
||||
Found by searching for `"\$.*\$"`.
|
||||
@@ -460,9 +460,10 @@
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
|
||||
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"ReDoS Util Python/JS": [
|
||||
"ReDoS Util Python/JS/Ruby": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/ReDoSUtil.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll"
|
||||
"python/ql/lib/semmle/python/security/performance/ReDoSUtil.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/performance/ReDoSUtil.qll"
|
||||
],
|
||||
"ReDoS Exponential Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/ExponentialBackTracking.qll",
|
||||
|
||||
2
cpp/change-notes/2021-11-25-certificate-not-checked.md
Normal file
2
cpp/change-notes/2021-11-25-certificate-not-checked.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-not-checked` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* A new query `cpp/certificate-result-conflation` has been added for C/C++. The query flags unsafe use of OpenSSL and similar libraries.
|
||||
9
cpp/ql/lib/CHANGELOG.md
Normal file
9
cpp/ql/lib/CHANGELOG.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### New Features
|
||||
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
7
cpp/ql/lib/change-notes/released/0.0.4.md
Normal file
7
cpp/ql/lib/change-notes/released/0.0.4.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 0.0.4
|
||||
|
||||
### New Features
|
||||
|
||||
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
|
||||
`isFromSystemMacroDefinition` for identifying code that originates from a
|
||||
macro outside the project being analyzed.
|
||||
1
cpp/ql/lib/change-notes/released/0.0.5.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.5.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.5
|
||||
2
cpp/ql/lib/codeql-pack.release.yml
Normal file
2
cpp/ql/lib/codeql-pack.release.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
@@ -1,7 +1,8 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.2
|
||||
version: 0.0.5
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/cpp-upgrades: 0.0.2
|
||||
codeql/cpp-upgrades: 0.0.3
|
||||
|
||||
@@ -626,9 +626,9 @@ library class ExprEvaluator extends int {
|
||||
// All assignments must have the same int value
|
||||
result =
|
||||
unique(Expr value |
|
||||
value = v.getAnAssignedValue() and not ignoreVariableAssignment(e, v, value)
|
||||
value = v.getAnAssignedValue() and not this.ignoreVariableAssignment(e, v, value)
|
||||
|
|
||||
getValueInternalNonSubExpr(value)
|
||||
this.getValueInternalNonSubExpr(value)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.dataflow.internal.DataFlowUtil
|
||||
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
@@ -63,3 +65,17 @@ predicate mayBenefitFromCallContext(Call call, Function f) { none() }
|
||||
* restricted to those `call`s for which a context might make a difference.
|
||||
*/
|
||||
Function viableImplInCallContext(Call call, Call ctx) { none() }
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
tupleLimit = 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of `call` with an argument position that matches
|
||||
* parameter position `ppos`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
|
||||
exists(ArgumentPosition apos |
|
||||
arg.argumentOf(call, apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
|
||||
* currently excludes read-steps, store-steps, and flow-through.
|
||||
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||
*/
|
||||
private module LambdaFlow {
|
||||
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
pragma[noinline]
|
||||
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), ppos)
|
||||
}
|
||||
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), i)
|
||||
pragma[noinline]
|
||||
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), ppos)
|
||||
}
|
||||
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamNonLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamNonLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -322,7 +336,7 @@ private module Cached {
|
||||
or
|
||||
exists(ArgNode arg |
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -330,7 +344,7 @@ private module Cached {
|
||||
predicate returnNodeExt(Node n, ReturnKindExt k) {
|
||||
k = TValueReturn(n.(ReturnNode).getKind())
|
||||
or
|
||||
exists(ParamNode p, int pos |
|
||||
exists(ParamNode p, ParameterPosition pos |
|
||||
parameterValueFlowsToPreUpdate(p, n) and
|
||||
p.isParameterOf(_, pos) and
|
||||
k = TParamUpdate(pos)
|
||||
@@ -352,11 +366,13 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
|
||||
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
|
||||
isParameterNode(p, c, pos)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate argumentNode(Node n, DataFlowCall call, int pos) {
|
||||
n.(ArgumentNode).argumentOf(call, pos)
|
||||
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
|
||||
isArgumentNode(n, call, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,12 +390,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
|
||||
* The instance parameter is considered to have index `-1`.
|
||||
* Holds if `p` is the parameter of a viable dispatch target of `call`,
|
||||
* and `p` has position `ppos`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), i)
|
||||
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), ppos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,9 +404,9 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParam(call, i, p) and
|
||||
arg.argumentOf(call, i) and
|
||||
exists(ParameterPosition ppos |
|
||||
viableParam(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
|
||||
)
|
||||
}
|
||||
@@ -862,7 +878,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* (zero-based) position.
|
||||
* position.
|
||||
*/
|
||||
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
private int pos;
|
||||
private ParameterPosition pos;
|
||||
|
||||
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
|
||||
|
||||
int getPosition() { result = pos }
|
||||
ParameterPosition getPosition() { result = pos }
|
||||
|
||||
pragma[nomagic]
|
||||
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
}
|
||||
|
||||
@@ -9,6 +9,19 @@ private import tainttracking1.TaintTrackingParameter::Private
|
||||
private import tainttracking1.TaintTrackingParameter::Public
|
||||
|
||||
module Consistency {
|
||||
private newtype TConsistencyConfiguration = MkConsistencyConfiguration()
|
||||
|
||||
/** A class for configuring the consistency queries. */
|
||||
class ConsistencyConfiguration extends TConsistencyConfiguration {
|
||||
string toString() { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
|
||||
predicate postWithInFlowExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
RelevantNode() {
|
||||
this instanceof ArgumentNode or
|
||||
@@ -164,7 +177,7 @@ module Consistency {
|
||||
|
||||
query predicate argHasPostUpdate(ArgumentNode n, string msg) {
|
||||
not hasPost(n) and
|
||||
not isImmutableOrUnobservable(n) and
|
||||
not any(ConsistencyConfiguration c).argHasPostUpdateExclude(n) and
|
||||
msg = "ArgumentNode is missing PostUpdateNode."
|
||||
}
|
||||
|
||||
@@ -177,6 +190,7 @@ module Consistency {
|
||||
isPostUpdateNode(n) and
|
||||
not clearsContent(n, _) and
|
||||
simpleLocalFlowStep(_, n) and
|
||||
not any(ConsistencyConfiguration c).postWithInFlowExclude(n) and
|
||||
msg = "PostUpdateNode should not be the target of local flow."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -2,12 +2,20 @@ private import cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowDispatch
|
||||
private import FlowVar
|
||||
private import DataFlowImplConsistency
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
|
||||
arg.argumentOf(c, pos)
|
||||
}
|
||||
|
||||
/** Gets the instance argument of a non-static call. */
|
||||
private Node getInstanceArgument(Call call) {
|
||||
@@ -259,27 +267,6 @@ class Unit extends TUnit {
|
||||
string toString() { result = "unit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
|
||||
* modified or its modification cannot be observed, for example if it is a
|
||||
* freshly created object that is not saved in a variable.
|
||||
*
|
||||
* This predicate is only used for consistency checks.
|
||||
*/
|
||||
predicate isImmutableOrUnobservable(Node n) {
|
||||
// Is the null pointer (or something that's not really a pointer)
|
||||
exists(n.asExpr().getValue())
|
||||
or
|
||||
// Isn't a pointer or is a pointer to const
|
||||
forall(DerivedType dt | dt = n.asExpr().getActualType() |
|
||||
dt.getBaseType().isConst()
|
||||
or
|
||||
dt.getBaseType() instanceof RoutineType
|
||||
)
|
||||
// The above list of cases isn't exhaustive, but it narrows down the
|
||||
// consistency alerts enough that most of them are interesting.
|
||||
}
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) { none() }
|
||||
|
||||
@@ -302,3 +289,19 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
|
||||
* by default as a heuristic.
|
||||
*/
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
|
||||
|
||||
private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration {
|
||||
override predicate argHasPostUpdateExclude(ArgumentNode n) {
|
||||
// Is the null pointer (or something that's not really a pointer)
|
||||
exists(n.asExpr().getValue())
|
||||
or
|
||||
// Isn't a pointer or is a pointer to const
|
||||
forall(DerivedType dt | dt = n.asExpr().getActualType() |
|
||||
dt.getBaseType().isConst()
|
||||
or
|
||||
dt.getBaseType() instanceof RoutineType
|
||||
)
|
||||
// The above list of cases isn't exhaustive, but it narrows down the
|
||||
// consistency alerts enough that most of them are interesting.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,8 +484,9 @@ module TaintedWithPath {
|
||||
/** Gets the element that `pathNode` wraps, if any. */
|
||||
Element getElementFromPathNode(PathNode pathNode) {
|
||||
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
|
||||
result = node.asExpr() or
|
||||
result = node.asParameter()
|
||||
result = node.asInstruction().getAST()
|
||||
or
|
||||
result = node.asOperand().getDef().getAST()
|
||||
)
|
||||
or
|
||||
result = pathNode.(EndpointPathNode).inner()
|
||||
|
||||
@@ -2,6 +2,7 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/**
|
||||
@@ -266,3 +267,17 @@ Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) {
|
||||
result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends int {
|
||||
ParameterPosition() { any(ParameterNode p).isParameterOf(_, this) }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends int {
|
||||
ArgumentPosition() { any(ArgumentNode a).argumentOf(_, this) }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
pragma[inline]
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -256,11 +256,11 @@ private class ArgNodeEx extends NodeEx {
|
||||
private class ParamNodeEx extends NodeEx {
|
||||
ParamNodeEx() { this.asNode() instanceof ParamNode }
|
||||
|
||||
predicate isParameterOf(DataFlowCallable c, int i) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, i)
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
|
||||
this.asNode().(ParamNode).isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
int getPosition() { this.isParameterOf(_, result) }
|
||||
ParameterPosition getPosition() { this.isParameterOf(_, result) }
|
||||
|
||||
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
|
||||
}
|
||||
@@ -289,6 +289,7 @@ private predicate outBarrier(NodeEx node, Configuration config) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
exists(Node n | node.asNode() = n |
|
||||
config.isBarrier(n)
|
||||
@@ -307,11 +308,23 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
|
||||
private predicate sourceNode(NodeEx node, Configuration config) {
|
||||
config.isSource(node.asNode()) and
|
||||
not fullBarrier(node, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
|
||||
|
||||
/** Provides the relevant barriers for a step from `node1` to `node2`. */
|
||||
pragma[inline]
|
||||
private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow in one local step from `node1` to `node2`.
|
||||
*/
|
||||
@@ -320,16 +333,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
simpleLocalFlowStepExt(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.asNode() = n and
|
||||
node2.isImplicitReadNode(n, false)
|
||||
node2.isImplicitReadNode(n, false) and
|
||||
not fullBarrier(node1, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -342,16 +353,14 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config)
|
||||
stepFilter(node1, node2, config)
|
||||
)
|
||||
or
|
||||
exists(Node n |
|
||||
config.allowImplicitRead(n, _) and
|
||||
node1.isImplicitReadNode(n, true) and
|
||||
node2.asNode() = n
|
||||
node2.asNode() = n and
|
||||
not fullBarrier(node2, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -363,10 +372,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
|
||||
node1.asNode() = n1 and
|
||||
node2.asNode() = n2 and
|
||||
jumpStepCached(n1, n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
@@ -380,16 +386,14 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
|
||||
node2.asNode() = n2 and
|
||||
config.isAdditionalFlowStep(n1, n2) and
|
||||
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
|
||||
not outBarrier(node1, config) and
|
||||
not inBarrier(node2, config) and
|
||||
not fullBarrier(node1, config) and
|
||||
not fullBarrier(node2, config) and
|
||||
stepFilter(node1, node2, config) and
|
||||
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
|
||||
)
|
||||
}
|
||||
|
||||
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
|
||||
read(node1.asNode(), c, node2.asNode())
|
||||
read(node1.asNode(), c, node2.asNode()) and
|
||||
stepFilter(node1, node2, config)
|
||||
or
|
||||
exists(Node n |
|
||||
node2.isImplicitReadNode(n, true) and
|
||||
@@ -402,7 +406,8 @@ private predicate store(
|
||||
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
|
||||
) {
|
||||
store(node1.asNode(), tc, node2.asNode(), contentType) and
|
||||
read(_, tc.getContent(), _, config)
|
||||
read(_, tc.getContent(), _, config) and
|
||||
stepFilter(node1, node2, config)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
@@ -451,63 +456,59 @@ private module Stage1 {
|
||||
* argument in a call.
|
||||
*/
|
||||
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
|
||||
not fullBarrier(node, config) and
|
||||
(
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
sourceNode(node, config) and
|
||||
if hasSourceCallCtx(config) then cc = true else cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true and
|
||||
not fullBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
localFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, cc, config) and
|
||||
additionalLocalFlowStep(mid, node, config)
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
jumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
exists(NodeEx mid |
|
||||
fwdFlow(mid, _, config) and
|
||||
additionalJumpStep(mid, node, config) and
|
||||
cc = false
|
||||
)
|
||||
or
|
||||
// store
|
||||
exists(NodeEx mid |
|
||||
useFieldFlow(config) and
|
||||
fwdFlow(mid, cc, config) and
|
||||
store(mid, _, node, _, config) and
|
||||
not outBarrier(mid, config)
|
||||
)
|
||||
or
|
||||
// read
|
||||
exists(Content c |
|
||||
fwdFlowRead(c, node, cc, config) and
|
||||
fwdFlowConsCand(c, config) and
|
||||
not inBarrier(node, config)
|
||||
)
|
||||
or
|
||||
// flow into a callable
|
||||
exists(NodeEx arg |
|
||||
fwdFlow(arg, _, config) and
|
||||
viableParamArgEx(_, node, arg) and
|
||||
cc = true
|
||||
)
|
||||
or
|
||||
// flow out of a callable
|
||||
exists(DataFlowCall call |
|
||||
fwdFlowOut(call, node, false, config) and
|
||||
cc = false
|
||||
or
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
fwdFlowOutFromArg(call, node, config) and
|
||||
fwdFlowIsEntered(call, cc, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -547,7 +548,8 @@ private module Stage1 {
|
||||
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
|
||||
exists(ReturnPosition pos |
|
||||
fwdFlowReturnPosition(pos, cc, config) and
|
||||
viableReturnPosOutEx(call, pos, out)
|
||||
viableReturnPosOutEx(call, pos, out) and
|
||||
not fullBarrier(out, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -773,6 +775,7 @@ private module Stage1 {
|
||||
* Holds if flow may enter through `p` and reach a return node making `p` a
|
||||
* candidate for the origin of a summary.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(ReturnKindExt kind |
|
||||
throughFlowNodeCand(p, config) and
|
||||
@@ -1009,6 +1012,9 @@ private module Stage2 {
|
||||
|
||||
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
|
||||
|
||||
bindingset[node, ap]
|
||||
private predicate filter(NodeEx node, Ap ap) { any() }
|
||||
|
||||
bindingset[ap, contentType]
|
||||
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
|
||||
|
||||
@@ -1017,14 +1023,23 @@ private module Stage2 {
|
||||
PrevStage::revFlow(node, _, _, apa, config)
|
||||
}
|
||||
|
||||
bindingset[result, apa]
|
||||
private ApApprox unbindApa(ApApprox apa) {
|
||||
exists(ApApprox apa0 |
|
||||
apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1037,6 +1052,13 @@ private module Stage2 {
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
fwdFlow0(node, cc, argAp, ap, config) and
|
||||
flowCand(node, unbindApa(getApprox(ap)), config) and
|
||||
filter(node, ap)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
|
||||
flowCand(node, _, config) and
|
||||
sourceNode(node, config) and
|
||||
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
|
||||
@@ -1107,7 +1129,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(DataFlowType contentType |
|
||||
fwdFlow(node1, cc, argAp, ap1, config) and
|
||||
PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
|
||||
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
|
||||
typecheckStore(ap1, contentType)
|
||||
)
|
||||
}
|
||||
@@ -1142,9 +1164,8 @@ private module Stage2 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1159,9 +1180,8 @@ private module Stage2 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1171,10 +1191,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1188,7 +1206,7 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
fwdFlowIn(call, p, cc, _, argAp, ap, config) and
|
||||
PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
|
||||
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1230,6 +1248,11 @@ private module Stage2 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -1306,7 +1329,7 @@ private module Stage2 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -1341,9 +1364,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1353,9 +1375,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1365,9 +1386,8 @@ private module Stage2 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1427,7 +1447,7 @@ private module Stage2 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -1707,12 +1727,14 @@ private module Stage3 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1837,9 +1859,8 @@ private module Stage3 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1854,9 +1875,8 @@ private module Stage3 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1866,10 +1886,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1925,6 +1943,11 @@ private module Stage3 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2001,7 +2024,7 @@ private module Stage3 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2036,9 +2059,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2048,9 +2070,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2060,9 +2081,8 @@ private module Stage3 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2122,7 +2142,7 @@ private module Stage3 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2473,12 +2493,14 @@ private module Stage4 {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate flowThroughOutOfCall(
|
||||
DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
|
||||
DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
|
||||
Configuration config
|
||||
) {
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
|
||||
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
|
||||
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
|
||||
pragma[only_bind_into](config))
|
||||
pragma[only_bind_into](config)) and
|
||||
ccc.matchesCall(call)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2603,9 +2625,8 @@ private module Stage4 {
|
||||
exists(ArgNodeEx arg, boolean allowsFieldFlow |
|
||||
fwdFlow(arg, outercc, argAp, ap, config) and
|
||||
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2620,9 +2641,8 @@ private module Stage4 {
|
||||
fwdFlow(ret, innercc, argAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
inner = ret.getEnclosingCallable() and
|
||||
ccOut = getCallContextReturn(inner, call, innercc)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
ccOut = getCallContextReturn(inner, call, innercc) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2632,10 +2652,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
|
||||
fwdFlow(ret, ccc, apSome(argAp), ap, config) and
|
||||
flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
ccc.matchesCall(call)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2691,6 +2709,11 @@ private module Stage4 {
|
||||
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate returnNodeMayFlowThrough(RetNodeEx ret, Ap ap, Configuration config) {
|
||||
fwdFlow(ret, any(CcCall ccc), apSome(_), ap, config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` with access path `ap` is part of a path from a source to a
|
||||
* sink in the configuration `config`.
|
||||
@@ -2767,7 +2790,7 @@ private module Stage4 {
|
||||
// flow out of a callable
|
||||
revFlowOut(_, node, _, _, ap, config) and
|
||||
toReturn = true and
|
||||
if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
|
||||
if returnNodeMayFlowThrough(node, ap, config)
|
||||
then returnAp = apSome(ap)
|
||||
else returnAp = apNone()
|
||||
}
|
||||
@@ -2802,9 +2825,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(NodeEx out, boolean allowsFieldFlow |
|
||||
revFlow(out, toReturn, returnAp, ap, config) and
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2814,9 +2836,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, false, returnAp, ap, config) and
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowIntoCall(_, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2826,9 +2847,8 @@ private module Stage4 {
|
||||
) {
|
||||
exists(ParamNodeEx p, boolean allowsFieldFlow |
|
||||
revFlow(p, true, apSome(returnAp), ap, config) and
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
|
||||
|
|
||||
ap instanceof ApNil or allowsFieldFlow = true
|
||||
flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
|
||||
if allowsFieldFlow = false then ap instanceof ApNil else any()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2888,7 +2908,7 @@ private module Stage4 {
|
||||
}
|
||||
|
||||
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
|
||||
exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
|
||||
parameterFlow(p, ap, ap0, c, config) and
|
||||
c = ret.getEnclosingCallable() and
|
||||
revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
|
||||
@@ -2972,7 +2992,7 @@ private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
|
||||
|
||||
SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
|
||||
|
||||
int getParameterPos() { p.isParameterOf(_, result) }
|
||||
ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
|
||||
|
||||
ParamNodeEx getParamNode() { result = p }
|
||||
|
||||
@@ -3619,39 +3639,40 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate pathIntoArg(
|
||||
PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
PathNodeMid mid, ParameterPosition ppos, CallContext cc, DataFlowCall call, AccessPath ap,
|
||||
AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
apa = ap.getApprox() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate parameterCand(
|
||||
DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
|
||||
DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
|
||||
) {
|
||||
exists(ParamNodeEx p |
|
||||
Stage4::revFlow(p, _, _, apa, config) and
|
||||
p.isParameterOf(callable, i)
|
||||
p.isParameterOf(callable, pos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate pathIntoCallable0(
|
||||
PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
|
||||
AccessPath ap, Configuration config
|
||||
PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, AccessPath ap, Configuration config
|
||||
) {
|
||||
exists(AccessPathApprox apa |
|
||||
pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pathIntoArg(mid, pragma[only_bind_into](pos), outercc, call, ap, pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config)) and
|
||||
callable = resolveCall(call, outercc) and
|
||||
parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
|
||||
parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3666,9 +3687,9 @@ private predicate pathIntoCallable(
|
||||
PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
|
||||
DataFlowCall call, Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
|
||||
pathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
(
|
||||
sc = TSummaryCtxSome(p, ap)
|
||||
or
|
||||
@@ -3692,7 +3713,7 @@ private predicate paramFlowsThrough(
|
||||
ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
|
||||
Configuration config
|
||||
) {
|
||||
exists(PathNodeMid mid, RetNodeEx ret, int pos |
|
||||
exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
|
||||
mid.getNodeEx() = ret and
|
||||
kind = ret.getKind() and
|
||||
cc = mid.getCallContext() and
|
||||
@@ -4421,24 +4442,25 @@ private module FlowExploration {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate partialPathIntoArg(
|
||||
PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
PartialPathNodeFwd mid, ParameterPosition ppos, CallContext cc, DataFlowCall call,
|
||||
PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(ArgNode arg |
|
||||
exists(ArgNode arg, ArgumentPosition apos |
|
||||
arg = mid.getNodeEx().asNode() and
|
||||
cc = mid.getCallContext() and
|
||||
arg.argumentOf(call, i) and
|
||||
arg.argumentOf(call, apos) and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate partialPathIntoCallable0(
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
|
||||
PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, CallContext outercc,
|
||||
DataFlowCall call, PartialAccessPath ap, Configuration config
|
||||
) {
|
||||
partialPathIntoArg(mid, i, outercc, call, ap, config) and
|
||||
partialPathIntoArg(mid, pos, outercc, call, ap, config) and
|
||||
callable = resolveCall(call, outercc)
|
||||
}
|
||||
|
||||
@@ -4447,9 +4469,9 @@ private module FlowExploration {
|
||||
TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(int i, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, i) and
|
||||
exists(ParameterPosition pos, DataFlowCallable callable |
|
||||
partialPathIntoCallable0(mid, callable, pos, outercc, call, ap, config) and
|
||||
p.isParameterOf(callable, pos) and
|
||||
sc1 = TSummaryCtx1Param(p) and
|
||||
sc2 = TSummaryCtx2Some(ap)
|
||||
|
|
||||
@@ -4613,22 +4635,23 @@ private module FlowExploration {
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathFlowsThrough(
|
||||
int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
ArgumentPosition apos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
|
||||
RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p |
|
||||
exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
|
||||
mid.getNodeEx() = p and
|
||||
p.getPosition() = pos and
|
||||
p.getPosition() = ppos and
|
||||
sc1 = mid.getSummaryCtx1() and
|
||||
sc2 = mid.getSummaryCtx2() and
|
||||
ap = mid.getAp() and
|
||||
config = mid.getConfiguration()
|
||||
config = mid.getConfiguration() and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate revPartialPathThroughCallable0(
|
||||
DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
|
||||
DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, RevPartialAccessPath ap,
|
||||
Configuration config
|
||||
) {
|
||||
exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
|
||||
@@ -4641,7 +4664,7 @@ private module FlowExploration {
|
||||
private predicate revPartialPathThroughCallable(
|
||||
PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
|
||||
) {
|
||||
exists(DataFlowCall call, int pos |
|
||||
exists(DataFlowCall call, ArgumentPosition pos |
|
||||
revPartialPathThroughCallable0(call, mid, pos, ap, config) and
|
||||
node.asNode().(ArgNode).argumentOf(call, pos)
|
||||
)
|
||||
|
||||
@@ -62,6 +62,18 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
tupleLimit = 1000
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is an argument of `call` with an argument position that matches
|
||||
* parameter position `ppos`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) {
|
||||
exists(ArgumentPosition apos |
|
||||
arg.argumentOf(call, apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a simple data-flow analysis for resolving lambda calls. The analysis
|
||||
* currently excludes read-steps, store-steps, and flow-through.
|
||||
@@ -71,25 +83,27 @@ predicate accessPathCostLimits(int apLimit, int tupleLimit) {
|
||||
* calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly.
|
||||
*/
|
||||
private module LambdaFlow {
|
||||
private predicate viableParamNonLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), i)
|
||||
pragma[noinline]
|
||||
private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallable(call), ppos)
|
||||
}
|
||||
|
||||
private predicate viableParamLambda(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), i)
|
||||
pragma[noinline]
|
||||
private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableLambda(call, _), ppos)
|
||||
}
|
||||
|
||||
private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamNonLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamNonLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParamLambda(call, i, p) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(ParameterPosition ppos |
|
||||
viableParamLambda(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -322,7 +336,7 @@ private module Cached {
|
||||
or
|
||||
exists(ArgNode arg |
|
||||
result.(PostUpdateNode).getPreUpdateNode() = arg and
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getPosition())
|
||||
arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -330,7 +344,7 @@ private module Cached {
|
||||
predicate returnNodeExt(Node n, ReturnKindExt k) {
|
||||
k = TValueReturn(n.(ReturnNode).getKind())
|
||||
or
|
||||
exists(ParamNode p, int pos |
|
||||
exists(ParamNode p, ParameterPosition pos |
|
||||
parameterValueFlowsToPreUpdate(p, n) and
|
||||
p.isParameterOf(_, pos) and
|
||||
k = TParamUpdate(pos)
|
||||
@@ -352,11 +366,13 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate parameterNode(Node p, DataFlowCallable c, int pos) { isParameterNode(p, c, pos) }
|
||||
predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) {
|
||||
isParameterNode(p, c, pos)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate argumentNode(Node n, DataFlowCall call, int pos) {
|
||||
n.(ArgumentNode).argumentOf(call, pos)
|
||||
predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) {
|
||||
isArgumentNode(n, call, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,12 +390,12 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
|
||||
* The instance parameter is considered to have index `-1`.
|
||||
* Holds if `p` is the parameter of a viable dispatch target of `call`,
|
||||
* and `p` has position `ppos`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate viableParam(DataFlowCall call, int i, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), i)
|
||||
private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) {
|
||||
p.isParameterOf(viableCallableExt(call), ppos)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,9 +404,9 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) {
|
||||
exists(int i |
|
||||
viableParam(call, i, p) and
|
||||
arg.argumentOf(call, i) and
|
||||
exists(ParameterPosition ppos |
|
||||
viableParam(call, ppos, p) and
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p))
|
||||
)
|
||||
}
|
||||
@@ -862,7 +878,7 @@ private module Cached {
|
||||
cached
|
||||
newtype TReturnKindExt =
|
||||
TValueReturn(ReturnKind kind) or
|
||||
TParamUpdate(int pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) }
|
||||
|
||||
cached
|
||||
newtype TBooleanOption =
|
||||
@@ -1054,9 +1070,9 @@ class ParamNode extends Node {
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* (zero-based) position.
|
||||
* position.
|
||||
*/
|
||||
predicate isParameterOf(DataFlowCallable c, int i) { parameterNode(this, c, i) }
|
||||
predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) }
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
@@ -1064,7 +1080,9 @@ class ArgNode extends Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, int pos) { argumentNode(this, call, pos) }
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1110,11 +1128,14 @@ class ValueReturnKind extends ReturnKindExt, TValueReturn {
|
||||
}
|
||||
|
||||
class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate {
|
||||
private int pos;
|
||||
private ParameterPosition pos;
|
||||
|
||||
ParamUpdateReturnKind() { this = TParamUpdate(pos) }
|
||||
|
||||
int getPosition() { result = pos }
|
||||
ParameterPosition getPosition() { result = pos }
|
||||
|
||||
pragma[nomagic]
|
||||
ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) }
|
||||
|
||||
override string toString() { result = "param update " + pos }
|
||||
}
|
||||
|
||||
@@ -9,6 +9,19 @@ private import tainttracking1.TaintTrackingParameter::Private
|
||||
private import tainttracking1.TaintTrackingParameter::Public
|
||||
|
||||
module Consistency {
|
||||
private newtype TConsistencyConfiguration = MkConsistencyConfiguration()
|
||||
|
||||
/** A class for configuring the consistency queries. */
|
||||
class ConsistencyConfiguration extends TConsistencyConfiguration {
|
||||
string toString() { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */
|
||||
predicate postWithInFlowExclude(Node n) { none() }
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */
|
||||
predicate argHasPostUpdateExclude(ArgumentNode n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
RelevantNode() {
|
||||
this instanceof ArgumentNode or
|
||||
@@ -164,7 +177,7 @@ module Consistency {
|
||||
|
||||
query predicate argHasPostUpdate(ArgumentNode n, string msg) {
|
||||
not hasPost(n) and
|
||||
not isImmutableOrUnobservable(n) and
|
||||
not any(ConsistencyConfiguration c).argHasPostUpdateExclude(n) and
|
||||
msg = "ArgumentNode is missing PostUpdateNode."
|
||||
}
|
||||
|
||||
@@ -177,6 +190,7 @@ module Consistency {
|
||||
isPostUpdateNode(n) and
|
||||
not clearsContent(n, _) and
|
||||
simpleLocalFlowStep(_, n) and
|
||||
not any(ConsistencyConfiguration c).postWithInFlowExclude(n) and
|
||||
msg = "PostUpdateNode should not be the target of local flow."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,20 @@ private import cpp
|
||||
private import DataFlowUtil
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import DataFlowDispatch
|
||||
private import DataFlowImplConsistency
|
||||
|
||||
/** Gets the callable in which this node occurs. */
|
||||
DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() }
|
||||
|
||||
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, int pos) { p.isParameterOf(c, pos) }
|
||||
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) {
|
||||
p.isParameterOf(c, pos)
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
|
||||
arg.argumentOf(c, pos)
|
||||
}
|
||||
|
||||
/**
|
||||
* A data flow node that occurs as the argument of a call and is passed as-is
|
||||
@@ -285,21 +293,18 @@ class Unit extends TUnit {
|
||||
string toString() { result = "unit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` does not require a `PostUpdateNode` as it either cannot be
|
||||
* modified or its modification cannot be observed, for example if it is a
|
||||
* freshly created object that is not saved in a variable.
|
||||
*
|
||||
* This predicate is only used for consistency checks.
|
||||
*/
|
||||
predicate isImmutableOrUnobservable(Node n) {
|
||||
// The rules for whether an IR argument gets a post-update node are too
|
||||
// complex to model here.
|
||||
any()
|
||||
}
|
||||
|
||||
/** Holds if `n` should be hidden from path explanations. */
|
||||
predicate nodeIsHidden(Node n) { n instanceof OperandNode and not n instanceof ArgumentNode }
|
||||
predicate nodeIsHidden(Node n) {
|
||||
n instanceof OperandNode and not n instanceof ArgumentNode
|
||||
or
|
||||
StoreNodeFlow::flowThrough(n, _) and
|
||||
not StoreNodeFlow::flowOutOf(n, _) and
|
||||
not StoreNodeFlow::flowInto(_, n)
|
||||
or
|
||||
ReadNodeFlow::flowThrough(n, _) and
|
||||
not ReadNodeFlow::flowOutOf(n, _) and
|
||||
not ReadNodeFlow::flowInto(_, n)
|
||||
}
|
||||
|
||||
class LambdaCallKind = Unit;
|
||||
|
||||
@@ -320,3 +325,11 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
|
||||
* by default as a heuristic.
|
||||
*/
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) { none() }
|
||||
|
||||
private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration {
|
||||
override predicate argHasPostUpdateExclude(ArgumentNode n) {
|
||||
// The rules for whether an IR argument gets a post-update node are too
|
||||
// complex to model here.
|
||||
any()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
/** Holds if this phi node has input from the `rnk`'th write operation in block `block`. */
|
||||
final predicate hasInputAtRankInBlock(IRBlock block, int rnk) {
|
||||
hasInputAtRankInBlock(block, rnk, _)
|
||||
this.hasInputAtRankInBlock(block, rnk, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -806,7 +806,7 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
|
||||
or
|
||||
// Flow into, through, and out of store nodes
|
||||
StoreNodeFlow::flowInto(nodeFrom, nodeTo)
|
||||
StoreNodeFlow::flowInto(nodeFrom.asInstruction(), nodeTo)
|
||||
or
|
||||
StoreNodeFlow::flowThrough(nodeFrom, nodeTo)
|
||||
or
|
||||
@@ -831,23 +831,19 @@ private predicate adjacentDefUseFlow(Node nodeFrom, Node nodeTo) {
|
||||
//Def-use flow
|
||||
Ssa::ssaFlow(nodeFrom, nodeTo)
|
||||
or
|
||||
exists(Instruction loadAddress | loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) |
|
||||
// Use-use flow through reads
|
||||
exists(Node address |
|
||||
Ssa::addressFlowTC(address.asInstruction(), loadAddress) and
|
||||
Ssa::ssaFlow(address, nodeTo)
|
||||
)
|
||||
or
|
||||
// Use-use flow through stores.
|
||||
exists(Node store |
|
||||
Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and
|
||||
Ssa::ssaFlow(store, nodeTo)
|
||||
)
|
||||
// Use-use flow through stores.
|
||||
exists(Instruction loadAddress, Node store |
|
||||
loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) and
|
||||
Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and
|
||||
Ssa::ssaFlow(store, nodeTo)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private module ReadNodeFlow {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
module ReadNodeFlow {
|
||||
/** Holds if the read node `nodeTo` should receive flow from `nodeFrom`. */
|
||||
predicate flowInto(Node nodeFrom, ReadNode nodeTo) {
|
||||
nodeTo.isInitial() and
|
||||
@@ -867,7 +863,12 @@ private module ReadNodeFlow {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the read node `nodeTo` should receive flow from the read node `nodeFrom`. */
|
||||
/**
|
||||
* Holds if the read node `nodeTo` should receive flow from the read node `nodeFrom`.
|
||||
*
|
||||
* This happens when `readFrom` is _not_ the source of a `readStep`, and `nodeTo` is
|
||||
* the `ReadNode` that represents an address that directly depends on `nodeFrom`.
|
||||
*/
|
||||
predicate flowThrough(ReadNode nodeFrom, ReadNode nodeTo) {
|
||||
not readStep(nodeFrom, _, _) and
|
||||
nodeFrom.getOuter() = nodeTo
|
||||
@@ -906,17 +907,25 @@ private module ReadNodeFlow {
|
||||
}
|
||||
}
|
||||
|
||||
private module StoreNodeFlow {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*/
|
||||
module StoreNodeFlow {
|
||||
/** Holds if the store node `nodeTo` should receive flow from `nodeFrom`. */
|
||||
predicate flowInto(Node nodeFrom, StoreNode nodeTo) {
|
||||
nodeTo.flowInto(Ssa::getDestinationAddress(nodeFrom.asInstruction()))
|
||||
predicate flowInto(Instruction instrFrom, StoreNode nodeTo) {
|
||||
nodeTo.flowInto(Ssa::getDestinationAddress(instrFrom))
|
||||
}
|
||||
|
||||
/** Holds if the store node `nodeTo` should receive flow from `nodeFom`. */
|
||||
predicate flowThrough(StoreNode nFrom, StoreNode nodeTo) {
|
||||
/**
|
||||
* Holds if the store node `nodeTo` should receive flow from `nodeFom`.
|
||||
*
|
||||
* This happens when `nodeFrom` is _not_ the source of a `storeStep`, and `nodeFrom` is
|
||||
* the `Storenode` that represents an address that directly depends on `nodeTo`.
|
||||
*/
|
||||
predicate flowThrough(StoreNode nodeFrom, StoreNode nodeTo) {
|
||||
// Flow through a post update node that doesn't need a store step.
|
||||
not storeStep(nFrom, _, _) and
|
||||
nodeTo.getOuter() = nFrom
|
||||
not storeStep(nodeFrom, _, _) and
|
||||
nodeTo.getOuter() = nodeFrom
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -634,3 +634,29 @@ class UncertainWriteDefinition extends WriteDefinition {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides a set of consistency queries. */
|
||||
module Consistency {
|
||||
abstract class RelevantDefinition extends Definition {
|
||||
abstract predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
);
|
||||
}
|
||||
|
||||
query predicate nonUniqueDef(RelevantDefinition def, SourceVariable v, BasicBlock bb, int i) {
|
||||
ssaDefReachesRead(v, def, bb, i) and
|
||||
not exists(unique(Definition def0 | ssaDefReachesRead(v, def0, bb, i)))
|
||||
}
|
||||
|
||||
query predicate readWithoutDef(SourceVariable v, BasicBlock bb, int i) {
|
||||
variableRead(bb, i, v, _) and
|
||||
not ssaDefReachesRead(v, _, bb, i)
|
||||
}
|
||||
|
||||
query predicate deadDef(RelevantDefinition def, SourceVariable v) {
|
||||
v = def.getSourceVariable() and
|
||||
not ssaDefReachesRead(_, def, _, _) and
|
||||
not phiHasInputFromBlock(_, def, _) and
|
||||
not uncertainWriteDefinitionInput(_, def)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,17 +244,6 @@ Instruction getDestinationAddress(Instruction instr) {
|
||||
]
|
||||
}
|
||||
|
||||
class ReferenceToInstruction extends CopyValueInstruction {
|
||||
ReferenceToInstruction() {
|
||||
this.getResultType() instanceof Cpp::ReferenceType and
|
||||
not this.getUnary().getResultType() instanceof Cpp::ReferenceType
|
||||
}
|
||||
|
||||
Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() }
|
||||
|
||||
Operand getSourceAddressOperand() { result = this.getUnaryOperand() }
|
||||
}
|
||||
|
||||
/** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */
|
||||
Instruction getSourceAddress(Instruction instr) { result = getSourceAddressOperand(instr).getDef() }
|
||||
|
||||
@@ -266,11 +255,7 @@ Operand getSourceAddressOperand(Instruction instr) {
|
||||
result =
|
||||
[
|
||||
instr.(LoadInstruction).getSourceAddressOperand(),
|
||||
instr.(ReadSideEffectInstruction).getArgumentOperand(),
|
||||
// `ReferenceToInstruction` is really more of an address-of operation,
|
||||
// but by including it in this list we break out of `flowOutOfAddressStep` at an
|
||||
// instruction that, at the source level, looks like a use of a variable.
|
||||
instr.(ReferenceToInstruction).getSourceAddressOperand()
|
||||
instr.(ReadSideEffectInstruction).getArgumentOperand()
|
||||
]
|
||||
}
|
||||
|
||||
@@ -295,10 +280,6 @@ Operand getSourceValueOperand(Instruction instr) {
|
||||
result = instr.(LoadInstruction).getSourceValueOperand()
|
||||
or
|
||||
result = instr.(ReadSideEffectInstruction).getSideEffectOperand()
|
||||
or
|
||||
// See the comment on the `ReferenceToInstruction` disjunct in `getSourceAddressOperand` for why
|
||||
// this case is included.
|
||||
result = instr.(ReferenceToInstruction).getSourceValueOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -513,6 +494,64 @@ private module Cached {
|
||||
explicitWrite(false, storeNode.getStoreInstruction(), def)
|
||||
)
|
||||
or
|
||||
// The destination of a store operation has undergone lvalue-to-rvalue conversion and is now a
|
||||
// right-hand-side of a store operation.
|
||||
// Find the next use of the variable in that store operation, and recursively find the load of that
|
||||
// pointer. For example, consider this case:
|
||||
//
|
||||
// ```cpp
|
||||
// int x = source();
|
||||
// int* p = &x;
|
||||
// sink(*p);
|
||||
// ```
|
||||
//
|
||||
// if we want to find the load of the address of `x`, we see that the pointer is stored into `p`,
|
||||
// and we then need to recursively look for the load of `p`.
|
||||
exists(
|
||||
Def def, StoreInstruction store, IRBlock block1, int rnk1, Use use, IRBlock block2, int rnk2
|
||||
|
|
||||
store = def.getInstruction() and
|
||||
store.getSourceValueOperand() = operand and
|
||||
def.hasRankInBlock(block1, rnk1) and
|
||||
use.hasRankInBlock(block2, rnk2) and
|
||||
adjacentDefRead(_, block1, rnk1, block2, rnk2)
|
||||
|
|
||||
// The shared SSA library has determined that `use` is the next use of the operand
|
||||
// so we find the next load of that use (but only if there is no `PostUpdateNode`) we
|
||||
// need to flow into first.
|
||||
not StoreNodeFlow::flowInto(store, _) and
|
||||
flowOutOfAddressStep(use.getOperand(), nodeTo)
|
||||
or
|
||||
// It may also be the case that `store` gives rise to another store step. So let's make sure that
|
||||
// we also take those into account.
|
||||
StoreNodeFlow::flowInto(store, nodeTo)
|
||||
)
|
||||
or
|
||||
// As we find the next load of an address, we might come across another use of the same variable.
|
||||
// In that case, we recursively find the next use of _that_ operand, and continue searching for
|
||||
// the next load of that operand. For example, consider this case:
|
||||
//
|
||||
// ```cpp
|
||||
// int x = source();
|
||||
// use(&x);
|
||||
// int* p = &x;
|
||||
// sink(*p);
|
||||
// ```
|
||||
//
|
||||
// The next use of `x` after its definition is `use(&x)`, but there is a later load of the address
|
||||
// of `x` that we want to flow to. So we use the shared SSA library to find the next load.
|
||||
not operand = getSourceAddressOperand(_) and
|
||||
exists(Use use1, Use use2, IRBlock block1, int rnk1, IRBlock block2, int rnk2 |
|
||||
use1.getOperand() = operand and
|
||||
use1.hasRankInBlock(block1, rnk1) and
|
||||
// Don't flow to the next use if this use is part of a store operation that totally
|
||||
// overrides a variable.
|
||||
not explicitWrite(true, _, use1.getOperand().getDef()) and
|
||||
adjacentDefRead(_, block1, rnk1, block2, rnk2) and
|
||||
use2.hasRankInBlock(block2, rnk2) and
|
||||
flowOutOfAddressStep(use2.getOperand(), nodeTo)
|
||||
)
|
||||
or
|
||||
operand = getSourceAddressOperand(nodeTo.asInstruction())
|
||||
or
|
||||
exists(ReturnIndirectionInstruction ret |
|
||||
|
||||
@@ -20,6 +20,14 @@ private import internal.OperandInternal
|
||||
private class TStageOperand =
|
||||
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
|
||||
* opposed to testing `not loc isntanceof UnknownLocation`
|
||||
*/
|
||||
private class KnownLocation extends Language::Location {
|
||||
KnownLocation() { not this instanceof Language::UnknownLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
|
||||
* (the defining instruction) in another instruction (the use instruction)
|
||||
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
* By default this is where the operand is used, but some subclasses may override this
|
||||
* using `getAnyDef()` if it makes more sense.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
|
||||
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
// most `RegisterOperands` have a more meaningful location at the definition
|
||||
// the only exception are specific cases of `ThisArgumentOperand`
|
||||
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
|
||||
|
||||
final override Instruction getAnyDef() { result = defInstr }
|
||||
|
||||
final override Overlap getDefinitionOverlap() {
|
||||
@@ -293,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
final override Instruction getAnyDef() {
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing the implicit 'this' argument to a member function
|
||||
* An operand representing the implicit `this` argument to a member function
|
||||
* call.
|
||||
*/
|
||||
class ThisArgumentOperand extends ArgumentOperand {
|
||||
override ThisArgumentOperandTag tag;
|
||||
|
||||
// in most cases the def location makes more sense, but in some corner cases it
|
||||
// has an unknown location: in those cases we fall back to the use location
|
||||
override Language::Location getLocation() {
|
||||
if this.getAnyDef().getLocation() instanceof KnownLocation
|
||||
then result = this.getAnyDef().getLocation()
|
||||
else result = this.getUse().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,14 @@ private import internal.OperandInternal
|
||||
private class TStageOperand =
|
||||
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
|
||||
* opposed to testing `not loc isntanceof UnknownLocation`
|
||||
*/
|
||||
private class KnownLocation extends Language::Location {
|
||||
KnownLocation() { not this instanceof Language::UnknownLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
|
||||
* (the defining instruction) in another instruction (the use instruction)
|
||||
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
* By default this is where the operand is used, but some subclasses may override this
|
||||
* using `getAnyDef()` if it makes more sense.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
|
||||
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
// most `RegisterOperands` have a more meaningful location at the definition
|
||||
// the only exception are specific cases of `ThisArgumentOperand`
|
||||
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
|
||||
|
||||
final override Instruction getAnyDef() { result = defInstr }
|
||||
|
||||
final override Overlap getDefinitionOverlap() {
|
||||
@@ -293,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
final override Instruction getAnyDef() {
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing the implicit 'this' argument to a member function
|
||||
* An operand representing the implicit `this` argument to a member function
|
||||
* call.
|
||||
*/
|
||||
class ThisArgumentOperand extends ArgumentOperand {
|
||||
override ThisArgumentOperandTag tag;
|
||||
|
||||
// in most cases the def location makes more sense, but in some corner cases it
|
||||
// has an unknown location: in those cases we fall back to the use location
|
||||
override Language::Location getLocation() {
|
||||
if this.getAnyDef().getLocation() instanceof KnownLocation
|
||||
then result = this.getAnyDef().getLocation()
|
||||
else result = this.getUse().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,14 @@ private import internal.OperandInternal
|
||||
private class TStageOperand =
|
||||
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
|
||||
* opposed to testing `not loc isntanceof UnknownLocation`
|
||||
*/
|
||||
private class KnownLocation extends Language::Location {
|
||||
KnownLocation() { not this instanceof Language::UnknownLocation }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand of an `Instruction`. The operand represents a use of the result of one instruction
|
||||
* (the defining instruction) in another instruction (the use instruction)
|
||||
@@ -45,8 +53,10 @@ class Operand extends TStageOperand {
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
* By default this is where the operand is used, but some subclasses may override this
|
||||
* using `getAnyDef()` if it makes more sense.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
@@ -269,6 +279,10 @@ class RegisterOperand extends NonPhiOperand, TRegisterOperand {
|
||||
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
// most `RegisterOperands` have a more meaningful location at the definition
|
||||
// the only exception are specific cases of `ThisArgumentOperand`
|
||||
override Language::Location getLocation() { result = this.getAnyDef().getLocation() }
|
||||
|
||||
final override Instruction getAnyDef() { result = defInstr }
|
||||
|
||||
final override Overlap getDefinitionOverlap() {
|
||||
@@ -293,7 +307,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
final override string toString() { result = tag.toString() }
|
||||
|
||||
final override Instruction getAnyDef() {
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
result = unique(Instruction defInstr | this.hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
@@ -401,11 +415,19 @@ class ArgumentOperand extends RegisterOperand {
|
||||
}
|
||||
|
||||
/**
|
||||
* An operand representing the implicit 'this' argument to a member function
|
||||
* An operand representing the implicit `this` argument to a member function
|
||||
* call.
|
||||
*/
|
||||
class ThisArgumentOperand extends ArgumentOperand {
|
||||
override ThisArgumentOperandTag tag;
|
||||
|
||||
// in most cases the def location makes more sense, but in some corner cases it
|
||||
// has an unknown location: in those cases we fall back to the use location
|
||||
override Language::Location getLocation() {
|
||||
if this.getAnyDef().getLocation() instanceof KnownLocation
|
||||
then result = this.getAnyDef().getLocation()
|
||||
else result = this.getUse().getLocation()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,12 +18,12 @@ class SuppressionComment extends Comment {
|
||||
(
|
||||
this instanceof CppStyleComment and
|
||||
// strip the beginning slashes
|
||||
text = getContents().suffix(2)
|
||||
text = this.getContents().suffix(2)
|
||||
or
|
||||
this instanceof CStyleComment and
|
||||
// strip both the beginning /* and the end */ the comment
|
||||
exists(string text0 |
|
||||
text0 = getContents().suffix(2) and
|
||||
text0 = this.getContents().suffix(2) and
|
||||
text = text0.prefix(text0.length() - 2)
|
||||
) and
|
||||
// The /* */ comment must be a single-line comment
|
||||
|
||||
@@ -153,12 +153,12 @@ class ExtClass extends Class {
|
||||
}
|
||||
|
||||
predicate hasLocationInfo(string path, int startline, int startcol, int endline, int endcol) {
|
||||
if hasOneVariableGroup()
|
||||
if this.hasOneVariableGroup()
|
||||
then
|
||||
exists(VariableDeclarationGroup vdg | vdg.getClass() = this |
|
||||
vdg.hasLocationInfo(path, startline, startcol, endline, endcol)
|
||||
)
|
||||
else getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
|
||||
else this.getLocation().hasLocationInfo(path, startline, startcol, endline, endcol)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,16 @@ predicate reachableThing(Thing t) {
|
||||
exists(Thing mid | reachableThing(mid) and mid.callsOrAccesses() = t)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate callsOrAccessesPlus(Thing thing1, FunctionToRemove thing2) {
|
||||
thing1.callsOrAccesses() = thing2
|
||||
or
|
||||
exists(Thing mid |
|
||||
thing1.callsOrAccesses() = mid and
|
||||
callsOrAccessesPlus(mid, thing2)
|
||||
)
|
||||
}
|
||||
|
||||
class Thing extends Locatable {
|
||||
Thing() {
|
||||
this instanceof Function or
|
||||
@@ -81,7 +91,7 @@ class FunctionToRemove extends Function {
|
||||
}
|
||||
|
||||
Thing getOther() {
|
||||
result.callsOrAccesses+() = this and
|
||||
callsOrAccessesPlus(result, this) and
|
||||
this != result and
|
||||
// We will already be reporting the enclosing function of a
|
||||
// local variable, so don't also report the variable
|
||||
|
||||
7
cpp/ql/src/CHANGELOG.md
Normal file
7
cpp/ql/src/CHANGELOG.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.
|
||||
@@ -103,9 +103,9 @@ class CallWithBufferSize extends FunctionCall {
|
||||
// `upperBound(e)` defaults to `exprMaxVal(e)` when `e` isn't analyzable. So to get a meaningful
|
||||
// result in this case we pick the minimum value obtainable from dataflow and range analysis.
|
||||
result =
|
||||
upperBound(statedSizeExpr())
|
||||
upperBound(this.statedSizeExpr())
|
||||
.minimum(min(Expr statedSizeSrc |
|
||||
DataFlow::localExprFlow(statedSizeSrc, statedSizeExpr())
|
||||
DataFlow::localExprFlow(statedSizeSrc, this.statedSizeExpr())
|
||||
|
|
||||
statedSizeSrc.getValue().toInt()
|
||||
))
|
||||
|
||||
@@ -22,7 +22,7 @@ abstract class LockOperation extends FunctionCall {
|
||||
ControlFlowNode getAReachedNode() {
|
||||
result = this
|
||||
or
|
||||
exists(ControlFlowNode mid | mid = getAReachedNode() |
|
||||
exists(ControlFlowNode mid | mid = this.getAReachedNode() |
|
||||
not mid != this.getMatchingUnlock() and
|
||||
result = mid.getASuccessor()
|
||||
)
|
||||
|
||||
@@ -156,8 +156,8 @@ abstract class LeapYearFieldAccess extends YearFieldAccess {
|
||||
//
|
||||
// https://aa.usno.navy.mil/faq/docs/calendars.php
|
||||
this.isUsedInMod4Operation() and
|
||||
additionalModulusCheckForLeapYear(400) and
|
||||
additionalModulusCheckForLeapYear(100)
|
||||
this.additionalModulusCheckForLeapYear(400) and
|
||||
this.additionalModulusCheckForLeapYear(100)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,17 +176,17 @@ class StructTmLeapYearFieldAccess extends LeapYearFieldAccess {
|
||||
|
||||
override predicate isUsedInCorrectLeapYearCheck() {
|
||||
this.isUsedInMod4Operation() and
|
||||
additionalModulusCheckForLeapYear(400) and
|
||||
additionalModulusCheckForLeapYear(100) and
|
||||
this.additionalModulusCheckForLeapYear(400) and
|
||||
this.additionalModulusCheckForLeapYear(100) and
|
||||
// tm_year represents years since 1900
|
||||
(
|
||||
additionalAdditionOrSubstractionCheckForLeapYear(1900)
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(1900)
|
||||
or
|
||||
// some systems may use 2000 for 2-digit year conversions
|
||||
additionalAdditionOrSubstractionCheckForLeapYear(2000)
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(2000)
|
||||
or
|
||||
// converting from/to Unix epoch
|
||||
additionalAdditionOrSubstractionCheckForLeapYear(1970)
|
||||
this.additionalAdditionOrSubstractionCheckForLeapYear(1970)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ class LoopWithAlloca extends Stmt {
|
||||
or
|
||||
// `e == 0`
|
||||
exists(EQExpr eq |
|
||||
conditionRequires(eq, truth.booleanNot()) and
|
||||
this.conditionRequires(eq, truth.booleanNot()) and
|
||||
eq.getAnOperand().getValue().toInt() = 0 and
|
||||
e = eq.getAnOperand() and
|
||||
not exists(e.getValue())
|
||||
@@ -65,7 +65,7 @@ class LoopWithAlloca extends Stmt {
|
||||
or
|
||||
// `e != 0`
|
||||
exists(NEExpr eq |
|
||||
conditionRequires(eq, truth) and
|
||||
this.conditionRequires(eq, truth) and
|
||||
eq.getAnOperand().getValue().toInt() = 0 and
|
||||
e = eq.getAnOperand() and
|
||||
not exists(e.getValue())
|
||||
@@ -73,7 +73,7 @@ class LoopWithAlloca extends Stmt {
|
||||
or
|
||||
// `(bool)e == true`
|
||||
exists(EQExpr eq |
|
||||
conditionRequires(eq, truth) and
|
||||
this.conditionRequires(eq, truth) and
|
||||
eq.getAnOperand().getValue().toInt() = 1 and
|
||||
e = eq.getAnOperand() and
|
||||
e.getUnspecifiedType() instanceof BoolType and
|
||||
@@ -82,7 +82,7 @@ class LoopWithAlloca extends Stmt {
|
||||
or
|
||||
// `(bool)e != true`
|
||||
exists(NEExpr eq |
|
||||
conditionRequires(eq, truth.booleanNot()) and
|
||||
this.conditionRequires(eq, truth.booleanNot()) and
|
||||
eq.getAnOperand().getValue().toInt() = 1 and
|
||||
e = eq.getAnOperand() and
|
||||
e.getUnspecifiedType() instanceof BoolType and
|
||||
@@ -90,7 +90,7 @@ class LoopWithAlloca extends Stmt {
|
||||
)
|
||||
or
|
||||
exists(NotExpr notExpr |
|
||||
conditionRequires(notExpr, truth.booleanNot()) and
|
||||
this.conditionRequires(notExpr, truth.booleanNot()) and
|
||||
e = notExpr.getOperand()
|
||||
)
|
||||
or
|
||||
@@ -98,7 +98,7 @@ class LoopWithAlloca extends Stmt {
|
||||
// requires both of its operand to be true as well.
|
||||
exists(LogicalAndExpr andExpr |
|
||||
truth = true and
|
||||
conditionRequires(andExpr, truth) and
|
||||
this.conditionRequires(andExpr, truth) and
|
||||
e = andExpr.getAnOperand()
|
||||
)
|
||||
or
|
||||
@@ -106,7 +106,7 @@ class LoopWithAlloca extends Stmt {
|
||||
// it requires both of its operand to be false as well.
|
||||
exists(LogicalOrExpr orExpr |
|
||||
truth = false and
|
||||
conditionRequires(orExpr, truth) and
|
||||
this.conditionRequires(orExpr, truth) and
|
||||
e = orExpr.getAnOperand()
|
||||
)
|
||||
}
|
||||
@@ -141,9 +141,9 @@ class LoopWithAlloca extends Stmt {
|
||||
* `conditionRequiresInequality`.
|
||||
*/
|
||||
private Variable getAControllingVariable() {
|
||||
conditionRequires(result.getAnAccess(), _)
|
||||
this.conditionRequires(result.getAnAccess(), _)
|
||||
or
|
||||
conditionRequiresInequality(result.getAnAccess(), _, _)
|
||||
this.conditionRequiresInequality(result.getAnAccess(), _, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,72 +61,72 @@ class PointerArithmeticAccess extends BufferAccess, Expr {
|
||||
* A pair of buffer accesses through a call to memcpy.
|
||||
*/
|
||||
class MemCpy extends BufferAccess, FunctionCall {
|
||||
MemCpy() { getTarget().hasName("memcpy") }
|
||||
MemCpy() { this.getTarget().hasName("memcpy") }
|
||||
|
||||
override Expr getPointer() {
|
||||
result = getArgument(0) or
|
||||
result = getArgument(1)
|
||||
result = this.getArgument(0) or
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(2) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(2) }
|
||||
}
|
||||
|
||||
class StrncpySizeExpr extends BufferAccess, FunctionCall {
|
||||
StrncpySizeExpr() { getTarget().hasName("strncpy") }
|
||||
StrncpySizeExpr() { this.getTarget().hasName("strncpy") }
|
||||
|
||||
override Expr getPointer() {
|
||||
result = getArgument(0) or
|
||||
result = getArgument(1)
|
||||
result = this.getArgument(0) or
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(2) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(2) }
|
||||
}
|
||||
|
||||
class RecvSizeExpr extends BufferAccess, FunctionCall {
|
||||
RecvSizeExpr() { getTarget().hasName("recv") }
|
||||
RecvSizeExpr() { this.getTarget().hasName("recv") }
|
||||
|
||||
override Expr getPointer() { result = getArgument(1) }
|
||||
override Expr getPointer() { result = this.getArgument(1) }
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(2) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(2) }
|
||||
}
|
||||
|
||||
class SendSizeExpr extends BufferAccess, FunctionCall {
|
||||
SendSizeExpr() { getTarget().hasName("send") }
|
||||
SendSizeExpr() { this.getTarget().hasName("send") }
|
||||
|
||||
override Expr getPointer() { result = getArgument(1) }
|
||||
override Expr getPointer() { result = this.getArgument(1) }
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(2) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(2) }
|
||||
}
|
||||
|
||||
class SnprintfSizeExpr extends BufferAccess, FunctionCall {
|
||||
SnprintfSizeExpr() { getTarget().hasName("snprintf") }
|
||||
SnprintfSizeExpr() { this.getTarget().hasName("snprintf") }
|
||||
|
||||
override Expr getPointer() { result = getArgument(0) }
|
||||
override Expr getPointer() { result = this.getArgument(0) }
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(1) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
class MemcmpSizeExpr extends BufferAccess, FunctionCall {
|
||||
MemcmpSizeExpr() { getTarget().hasName("Memcmp") }
|
||||
MemcmpSizeExpr() { this.getTarget().hasName("Memcmp") }
|
||||
|
||||
override Expr getPointer() {
|
||||
result = getArgument(0) or
|
||||
result = getArgument(1)
|
||||
result = this.getArgument(0) or
|
||||
result = this.getArgument(1)
|
||||
}
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(2) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(2) }
|
||||
}
|
||||
|
||||
class MallocSizeExpr extends BufferAccess, FunctionCall {
|
||||
MallocSizeExpr() { getTarget().hasName("malloc") }
|
||||
MallocSizeExpr() { this.getTarget().hasName("malloc") }
|
||||
|
||||
override Expr getPointer() { none() }
|
||||
|
||||
override Expr getAccessedLength() { result = getArgument(0) }
|
||||
override Expr getAccessedLength() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
class NetworkFunctionCall extends FunctionCall {
|
||||
NetworkFunctionCall() { getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
|
||||
NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) }
|
||||
}
|
||||
|
||||
class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* @description Using the TLS or SSLv23 protocol from the boost::asio library, but not disabling deprecated protocols, or disabling minimum-recommended protocols.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @id cpp/boost/tls-settings-misconfiguration
|
||||
* @tags security
|
||||
* external/cwe/cwe-326
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
* @description Using a deprecated hard-coded protocol using the boost::asio library.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @id cpp/boost/use-of-deprecated-hardcoded-security-protocol
|
||||
* @tags security
|
||||
* external/cwe/cwe-327
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -13,7 +13,7 @@ import cpp
|
||||
|
||||
class MacroFunctionCall extends MacroInvocation {
|
||||
MacroFunctionCall() {
|
||||
not exists(getParentInvocation()) and
|
||||
not exists(this.getParentInvocation()) and
|
||||
this.getMacro().getHead().matches("%(%")
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import semmle.code.cpp.commons.Assertions
|
||||
|
||||
class MacroFunctionCall extends MacroInvocation {
|
||||
MacroFunctionCall() {
|
||||
not exists(getParentInvocation()) and
|
||||
not exists(this.getParentInvocation()) and
|
||||
this.getMacro().getHead().matches("%(%")
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class ExternalAPIDataNode extends DataFlow::Node {
|
||||
int getIndex() { result = i }
|
||||
|
||||
/** Gets the description of the function being called. */
|
||||
string getFunctionDescription() { result = getExternalFunction().toString() }
|
||||
string getFunctionDescription() { result = this.getExternalFunction().toString() }
|
||||
}
|
||||
|
||||
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
|
||||
|
||||
@@ -38,7 +38,7 @@ class ExternalAPIDataNode extends DataFlow::Node {
|
||||
int getIndex() { result = i }
|
||||
|
||||
/** Gets the description of the function being called. */
|
||||
string getFunctionDescription() { result = getExternalFunction().toString() }
|
||||
string getFunctionDescription() { result = this.getExternalFunction().toString() }
|
||||
}
|
||||
|
||||
/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalAPIDataNode`s. */
|
||||
|
||||
@@ -42,7 +42,7 @@ class VarargsFunction extends Function {
|
||||
}
|
||||
|
||||
private int trailingArgValueCount(string value) {
|
||||
result = strictcount(FunctionCall fc | trailingArgValue(fc) = value)
|
||||
result = strictcount(FunctionCall fc | this.trailingArgValue(fc) = value)
|
||||
}
|
||||
|
||||
string nonTrailingVarArgValue(FunctionCall fc, int index) {
|
||||
@@ -58,11 +58,11 @@ class VarargsFunction extends Function {
|
||||
|
||||
string normalTerminator(int cnt) {
|
||||
result = ["0", "-1"] and
|
||||
cnt = trailingArgValueCount(result) and
|
||||
2 * cnt > totalCount() and
|
||||
cnt = this.trailingArgValueCount(result) and
|
||||
2 * cnt > this.totalCount() and
|
||||
not exists(FunctionCall fc, int index |
|
||||
// terminator value is used in a non-terminating position
|
||||
nonTrailingVarArgValue(fc, index) = result
|
||||
this.nonTrailingVarArgValue(fc, index) = result
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class TaintSource extends VariableAccess {
|
||||
definitionUsePair(_, this, va)
|
||||
or
|
||||
exists(VariableAccess mid, Expr def |
|
||||
sourceReaches(mid) and
|
||||
this.sourceReaches(mid) and
|
||||
exprDefinition(_, def, mid) and
|
||||
definitionUsePair(_, def, va)
|
||||
)
|
||||
@@ -53,11 +53,11 @@ class TaintSource extends VariableAccess {
|
||||
* from `va`, possibly using intermediate reassignments.
|
||||
*/
|
||||
private predicate reachesSink(VariableAccess va, VariableAccess sink) {
|
||||
isSink(sink) and
|
||||
this.isSink(sink) and
|
||||
va = sink
|
||||
or
|
||||
exists(VariableAccess mid, Expr def |
|
||||
reachesSink(mid, sink) and
|
||||
this.reachesSink(mid, sink) and
|
||||
exprDefinition(_, def, va) and
|
||||
definitionUsePair(_, def, mid)
|
||||
)
|
||||
@@ -71,15 +71,15 @@ class TaintSource extends VariableAccess {
|
||||
* this source to `sink` found via `tainted(source, sink)`.)
|
||||
*/
|
||||
predicate reaches(VariableAccess sink) {
|
||||
isSink(sink) and
|
||||
this.isSink(sink) and
|
||||
not exists(VariableAccess va |
|
||||
va != this and
|
||||
va != sink and
|
||||
mayAddNullTerminator(_, va)
|
||||
|
|
||||
sourceReaches(va)
|
||||
this.sourceReaches(va)
|
||||
or
|
||||
reachesSink(va, sink)
|
||||
this.reachesSink(va, sink)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
28
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.qhelp
Normal file
28
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.qhelp
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>When checking the result of SSL certificate verification, accepting any error code may allow an attacker to impersonate someone who is trusted.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>When checking an SSL certificate with <code>SSL_get_verify_result</code>, only <code>X509_V_OK</code> is a success code. If there is any other result the certificate should not be accepted.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this example the error code <code>X509_V_ERR_CERT_HAS_EXPIRED</code> is treated the same as an OK result. An expired certificate should not be accepted as it is more likely to be compromised than a valid certificate.</p>
|
||||
|
||||
<sample src="SSLResultConflationBad.cpp" />
|
||||
|
||||
<p>In the corrected example, only a result of <code>X509_V_OK</code> is accepted.</p>
|
||||
|
||||
<sample src="SSLResultConflationGood.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
50
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql
Normal file
50
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @name Certificate result conflation
|
||||
* @description Only accept SSL certificates that pass certificate verification.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id cpp/certificate-result-conflation
|
||||
* @tags security
|
||||
* external/cwe/cwe-295
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
* A call to `SSL_get_verify_result`.
|
||||
*/
|
||||
class SSLGetVerifyResultCall extends FunctionCall {
|
||||
SSLGetVerifyResultCall() { getTarget().getName() = "SSL_get_verify_result" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Data flow from a call to `SSL_get_verify_result` to a guard condition
|
||||
* that references the result.
|
||||
*/
|
||||
class VerifyResultConfig extends DataFlow::Configuration {
|
||||
VerifyResultConfig() { this = "VerifyResultConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() instanceof SSLGetVerifyResultCall
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(GuardCondition guard | guard.getAChild*() = sink.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2,
|
||||
GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue
|
||||
where
|
||||
config.hasFlow(source, sink1) and
|
||||
config.hasFlow(source, sink2) and
|
||||
guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue
|
||||
guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue
|
||||
c1.getValue().toInt() = 0 and
|
||||
c2.getValue().toInt() != 0
|
||||
select guard, "This expression conflates OK and non-OK results from $@.", source, source.toString()
|
||||
13
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflationBad.cpp
Normal file
13
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflationBad.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// ...
|
||||
|
||||
if (cert = SSL_get_peer_certificate(ssl))
|
||||
{
|
||||
result = SSL_get_verify_result(ssl);
|
||||
|
||||
if ((result == X509_V_OK) || (result == X509_V_ERR_CERT_HAS_EXPIRED)) // BAD (conflates OK and a non-OK codes)
|
||||
{
|
||||
do_ok();
|
||||
} else {
|
||||
do_error();
|
||||
}
|
||||
}
|
||||
13
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflationGood.cpp
Normal file
13
cpp/ql/src/Security/CWE/CWE-295/SSLResultConflationGood.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
// ...
|
||||
|
||||
if (cert = SSL_get_peer_certificate(ssl))
|
||||
{
|
||||
result = SSL_get_verify_result(ssl);
|
||||
|
||||
if (result == X509_V_OK) // GOOD
|
||||
{
|
||||
do_ok();
|
||||
} else {
|
||||
do_error();
|
||||
}
|
||||
}
|
||||
28
cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.qhelp
Normal file
28
cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.qhelp
Normal file
@@ -0,0 +1,28 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>After fetching an SSL certificate, always check the result of certificate verification.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Always check the result of SSL certificate verification. A certificate that has been revoked may indicate that data is coming from an attacker, whereas a certificate that has expired or was self-signed may indicate an increased likelihood that the data is malicious.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>In this example, the <code>SSL_get_peer_certificate</code> function is used to get the certificate of a peer. However it is unsafe to use that information without checking if the certificate is valid.</p>
|
||||
|
||||
<sample src="SSLResultNotCheckedBad.cpp" />
|
||||
|
||||
<p>In the corrected example, we use <code>SSL_get_verify_result</code> to check that certificate verification was successful.</p>
|
||||
|
||||
<sample src="SSLResultNotCheckedGood.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
120
cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql
Normal file
120
cpp/ql/src/Security/CWE/CWE-295/SSLResultNotChecked.ql
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @name Certificate not checked
|
||||
* @description Always check the result of certificate verification after fetching an SSL certificate.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id cpp/certificate-not-checked
|
||||
* @tags security
|
||||
* external/cwe/cwe-295
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.controlflow.IRGuards
|
||||
|
||||
/**
|
||||
* A call to `SSL_get_peer_certificate`.
|
||||
*/
|
||||
class SSLGetPeerCertificateCall extends FunctionCall {
|
||||
SSLGetPeerCertificateCall() {
|
||||
getTarget().getName() = "SSL_get_peer_certificate" // SSL_get_peer_certificate(ssl)
|
||||
}
|
||||
|
||||
Expr getSSLArgument() { result = getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `SSL_get_verify_result`.
|
||||
*/
|
||||
class SSLGetVerifyResultCall extends FunctionCall {
|
||||
SSLGetVerifyResultCall() {
|
||||
getTarget().getName() = "SSL_get_verify_result" // SSL_get_peer_certificate(ssl)
|
||||
}
|
||||
|
||||
Expr getSSLArgument() { result = getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSL object passed into `SSL_get_peer_certificate` is checked with
|
||||
* `SSL_get_verify_result` entering `node`.
|
||||
*/
|
||||
predicate resultIsChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
||||
exists(Expr ssl, SSLGetVerifyResultCall check |
|
||||
ssl = globalValueNumber(getCertCall.getSSLArgument()).getAnExpr() and
|
||||
ssl = check.getSSLArgument() and
|
||||
node = check
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the certificate returned by `SSL_get_peer_certificate` is found to be
|
||||
* `0` on the edge `node1` to `node2`.
|
||||
*/
|
||||
predicate certIsZero(
|
||||
SSLGetPeerCertificateCall getCertCall, ControlFlowNode node1, ControlFlowNode node2
|
||||
) {
|
||||
exists(Expr cert | cert = globalValueNumber(getCertCall).getAnExpr() |
|
||||
exists(GuardCondition guard, Expr zero |
|
||||
zero.getValue().toInt() = 0 and
|
||||
node1 = guard and
|
||||
(
|
||||
// if (cert == zero) {
|
||||
guard.comparesEq(cert, zero, 0, true, true) and
|
||||
node2 = guard.getATrueSuccessor()
|
||||
or
|
||||
// if (cert != zero) { }
|
||||
guard.comparesEq(cert, zero, 0, false, true) and
|
||||
node2 = guard.getAFalseSuccessor()
|
||||
)
|
||||
)
|
||||
or
|
||||
(
|
||||
// if (cert) { }
|
||||
node1 = cert
|
||||
or
|
||||
// if (!cert) {
|
||||
node1.(NotExpr).getAChild() = cert
|
||||
) and
|
||||
node2 = node1.getASuccessor() and
|
||||
not cert.(GuardCondition).controls(node2, true) // cert may be false
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSL object passed into `SSL_get_peer_certificate` has not been checked with
|
||||
* `SSL_get_verify_result` at `node`. Note that this is only computed at the call to
|
||||
* `SSL_get_peer_certificate` and at the start and end of `BasicBlock`s.
|
||||
*/
|
||||
predicate certNotChecked(SSLGetPeerCertificateCall getCertCall, ControlFlowNode node) {
|
||||
// cert is not checked at the call to `SSL_get_peer_certificate`
|
||||
node = getCertCall
|
||||
or
|
||||
exists(BasicBlock bb, int pos |
|
||||
// flow to end of a `BasicBlock`
|
||||
certNotChecked(getCertCall, bb.getNode(pos)) and
|
||||
node = bb.getEnd() and
|
||||
// check for barrier node
|
||||
not exists(int pos2 |
|
||||
pos2 > pos and
|
||||
resultIsChecked(getCertCall, bb.getNode(pos2))
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(BasicBlock pred, BasicBlock bb |
|
||||
// flow from the end of one `BasicBlock` to the beginning of a successor
|
||||
certNotChecked(getCertCall, pred.getEnd()) and
|
||||
bb = pred.getASuccessor() and
|
||||
node = bb.getStart() and
|
||||
// check for barrier bb
|
||||
not certIsZero(getCertCall, pred.getEnd(), bb.getStart())
|
||||
)
|
||||
}
|
||||
|
||||
from SSLGetPeerCertificateCall getCertCall, ControlFlowNode node
|
||||
where
|
||||
certNotChecked(getCertCall, node) and
|
||||
node instanceof Function // (function exit)
|
||||
select getCertCall,
|
||||
"This " + getCertCall.toString() + " is not followed by a call to SSL_get_verify_result."
|
||||
@@ -0,0 +1,5 @@
|
||||
// ...
|
||||
|
||||
X509 *cert = SSL_get_peer_certificate(ssl); // BAD (SSL_get_verify_result is never called)
|
||||
|
||||
// ...
|
||||
@@ -0,0 +1,9 @@
|
||||
// ...
|
||||
|
||||
X509 *cert = SSL_get_peer_certificate(ssl); // GOOD
|
||||
if (cert)
|
||||
{
|
||||
result = SSL_get_verify_result(ssl);
|
||||
if (result == X509_V_OK)
|
||||
{
|
||||
// ...
|
||||
@@ -8,6 +8,7 @@
|
||||
* @precision high
|
||||
* @id cpp/cleartext-storage-file
|
||||
* @tags security
|
||||
* external/cwe/cwe-260
|
||||
* external/cwe/cwe-313
|
||||
*/
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class SqliteFunctionCall extends FunctionCall {
|
||||
}
|
||||
|
||||
predicate sqlite_encryption_used() {
|
||||
any(StringLiteral l).getValue().toLowerCase().regexpMatch("pragma key.*") or
|
||||
any(StringLiteral l).getValue().toLowerCase().matches("pragma key%") or
|
||||
any(StringLiteral l).getValue().toLowerCase().matches("%attach%database%key%") or
|
||||
any(FunctionCall fc).getTarget().getName().matches("sqlite%\\_key\\_%")
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ class ParameterNullCheck extends ParameterCheck {
|
||||
p.getFunction() instanceof InitializationFunction and
|
||||
p.getType().getUnspecifiedType() instanceof PointerType and
|
||||
exists(VariableAccess va | va = p.getAnAccess() |
|
||||
nullSuccessor = getATrueSuccessor() and
|
||||
notNullSuccessor = getAFalseSuccessor() and
|
||||
nullSuccessor = this.getATrueSuccessor() and
|
||||
notNullSuccessor = this.getAFalseSuccessor() and
|
||||
(
|
||||
va = this.(NotExpr).getOperand() or
|
||||
va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
|
||||
@@ -95,8 +95,8 @@ class ParameterNullCheck extends ParameterCheck {
|
||||
.getAnOperand()
|
||||
)
|
||||
or
|
||||
nullSuccessor = getAFalseSuccessor() and
|
||||
notNullSuccessor = getATrueSuccessor() and
|
||||
nullSuccessor = this.getAFalseSuccessor() and
|
||||
notNullSuccessor = this.getATrueSuccessor() and
|
||||
(
|
||||
va = this or
|
||||
va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
|
||||
@@ -132,7 +132,7 @@ class ValidatedExternalCondInitFunction extends ExternalData {
|
||||
ValidatedExternalCondInitFunction() { this.getDataPath().matches("%cond-init%.csv") }
|
||||
|
||||
predicate isExternallyVerified(Function f, int param) {
|
||||
functionSignature(f, getField(1), getField(2)) and param = getFieldAsInt(3)
|
||||
functionSignature(f, this.getField(1), this.getField(2)) and param = this.getFieldAsInt(3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ class InitializationFunction extends Function {
|
||||
.getAnOverridingFunction+()
|
||||
.(InitializationFunction)
|
||||
.initializedParameter() or
|
||||
getParameter(i) = any(InitializationFunctionCall c).getAnInitParameter()
|
||||
this.getParameter(i) = any(InitializationFunctionCall c).getAnInitParameter()
|
||||
)
|
||||
or
|
||||
// If we have no definition, we look at SAL annotations
|
||||
@@ -227,7 +227,7 @@ class InitializationFunction extends Function {
|
||||
result = getAnInitializedArgument(any(Call c))
|
||||
or
|
||||
exists(IfStmt check | result = check.getCondition().getAChild*() |
|
||||
paramReassignmentCondition(check)
|
||||
this.paramReassignmentCondition(check)
|
||||
)
|
||||
)
|
||||
or
|
||||
@@ -249,15 +249,15 @@ class InitializationFunction extends Function {
|
||||
|
||||
/** Holds if `n` can be reached without the parameter at `index` being reassigned. */
|
||||
predicate paramNotReassignedAt(ControlFlowNode n, int index, Context c) {
|
||||
c = getAContext(index) and
|
||||
c = this.getAContext(index) and
|
||||
(
|
||||
not exists(this.getEntryPoint()) and index = i and n = this
|
||||
or
|
||||
n = this.getEntryPoint() and index = i
|
||||
or
|
||||
exists(ControlFlowNode mid | paramNotReassignedAt(mid, index, c) |
|
||||
exists(ControlFlowNode mid | this.paramNotReassignedAt(mid, index, c) |
|
||||
n = mid.getASuccessor() and
|
||||
not n = paramReassignment(index) and
|
||||
not n = this.paramReassignment(index) and
|
||||
/*
|
||||
* Ignore successor edges where the parameter is null, because it is then confirmed to be
|
||||
* initialized.
|
||||
@@ -265,7 +265,7 @@ class InitializationFunction extends Function {
|
||||
|
||||
not exists(ParameterNullCheck nullCheck |
|
||||
nullCheck = mid and
|
||||
nullCheck = getANullCheck(index) and
|
||||
nullCheck = this.getANullCheck(index) and
|
||||
n = nullCheck.getNullSuccessor()
|
||||
) and
|
||||
/*
|
||||
@@ -281,13 +281,13 @@ class InitializationFunction extends Function {
|
||||
|
||||
/** Gets a null-check on the parameter at `index`. */
|
||||
private ParameterNullCheck getANullCheck(int index) {
|
||||
getParameter(index) = result.getParameter()
|
||||
this.getParameter(index) = result.getParameter()
|
||||
}
|
||||
|
||||
/** Gets a parameter which is not at the given index. */
|
||||
private Parameter getOtherParameter(int index) {
|
||||
index = i and
|
||||
result = getAParameter() and
|
||||
result = this.getAParameter() and
|
||||
not result.getIndex() = index
|
||||
}
|
||||
|
||||
@@ -306,10 +306,10 @@ class InitializationFunction extends Function {
|
||||
if
|
||||
strictcount(Parameter p |
|
||||
exists(Context c | c = ParamNull(p) or c = ParamNotNull(p)) and
|
||||
p = getOtherParameter(index)
|
||||
p = this.getOtherParameter(index)
|
||||
) = 1
|
||||
then
|
||||
exists(Parameter p | p = getOtherParameter(index) |
|
||||
exists(Parameter p | p = this.getOtherParameter(index) |
|
||||
result = ParamNull(p) or result = ParamNotNull(p)
|
||||
)
|
||||
else
|
||||
@@ -424,8 +424,8 @@ class ConditionalInitializationCall extends FunctionCall {
|
||||
|
||||
/** Gets the argument passed for the given parameter to this call. */
|
||||
Expr getArgumentForParameter(Parameter p) {
|
||||
p = getTarget().getAParameter() and
|
||||
result = getArgument(p.getIndex())
|
||||
p = this.getTarget().getAParameter() and
|
||||
result = this.getArgument(p.getIndex())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,7 +442,7 @@ class ConditionalInitializationCall extends FunctionCall {
|
||||
context = ParamNotNull(otherP) or
|
||||
context = ParamNull(otherP)
|
||||
|
|
||||
otherArg = getArgumentForParameter(otherP) and
|
||||
otherArg = this.getArgumentForParameter(otherP) and
|
||||
(otherArg instanceof AddressOfExpr implies context = ParamNotNull(otherP)) and
|
||||
(otherArg.getType() instanceof ArrayType implies context = ParamNotNull(otherP)) and
|
||||
(otherArg.getValue() = "0" implies context = ParamNull(otherP))
|
||||
@@ -511,8 +511,8 @@ class ConditionalInitializationCall extends FunctionCall {
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(ControlFlowNode mid | mid = uncheckedReaches(var) |
|
||||
not mid = getStatusVariable().getAnAccess() and
|
||||
exists(ControlFlowNode mid | mid = this.uncheckedReaches(var) |
|
||||
not mid = this.getStatusVariable().getAnAccess() and
|
||||
not mid = var.getAnAccess() and
|
||||
not exists(VariableAccess write | result = write and write = var.getAnAccess() |
|
||||
write = any(AssignExpr a).getLValue() or
|
||||
|
||||
@@ -44,7 +44,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
// Find a call that conditionally initializes this variable
|
||||
hasConditionalInitialization(f, call, this, initAccess, e) and
|
||||
// Ignore cases where the variable is assigned prior to the call
|
||||
not reaches(getAnAssignedValue(), initAccess) and
|
||||
not reaches(this.getAnAssignedValue(), initAccess) and
|
||||
// Ignore cases where the variable is assigned field-wise prior to the call.
|
||||
not exists(FieldAccess fa |
|
||||
exists(Assignment a |
|
||||
@@ -56,7 +56,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
) and
|
||||
// Ignore cases where the variable is assigned by a prior call to an initialization function
|
||||
not exists(Call c |
|
||||
getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
|
||||
this.getAnAccess() = getAnInitializedArgument(c).(AddressOfExpr).getOperand() and
|
||||
reaches(c, initAccess)
|
||||
) and
|
||||
/*
|
||||
@@ -64,7 +64,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
* the CFG, but should always be considered as initialized, so exclude them.
|
||||
*/
|
||||
|
||||
not exists(getInitializer().getExpr())
|
||||
not exists(this.getInitializer().getExpr())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
// Variable associated with this particular call
|
||||
call = initializingCall and
|
||||
// Access is a meaningful read access
|
||||
result = getAReadAccess() and
|
||||
result = this.getAReadAccess() and
|
||||
// Which occurs after the call
|
||||
reaches(call, result) and
|
||||
/*
|
||||
@@ -124,7 +124,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
call = initializingCall and
|
||||
initializingFunction = f and
|
||||
e = evidence and
|
||||
result = getAReadAccessAfterCall(initializingCall) and
|
||||
result = this.getAReadAccessAfterCall(initializingCall) and
|
||||
(
|
||||
// Access is risky because status return code ignored completely
|
||||
call instanceof ExprInVoidContext
|
||||
@@ -148,7 +148,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
call = initializingCall and
|
||||
initializingFunction = f and
|
||||
e = evidence and
|
||||
result = getAReadAccessAfterCall(initializingCall) and
|
||||
result = this.getAReadAccessAfterCall(initializingCall) and
|
||||
exists(LocalVariable status, Assignment a |
|
||||
a.getRValue() = call and
|
||||
call = status.getAnAssignedValue() and
|
||||
@@ -184,7 +184,7 @@ class ConditionallyInitializedVariable extends LocalVariable {
|
||||
ConditionalInitializationFunction initializingFunction,
|
||||
ConditionalInitializationCall initializingCall, Evidence evidence
|
||||
) {
|
||||
result = getARiskyAccessBeforeStatusCheck(initializingFunction, initializingCall, evidence) or
|
||||
result = getARiskyAccessWithNoStatusCheck(initializingFunction, initializingCall, evidence)
|
||||
result = this.getARiskyAccessBeforeStatusCheck(initializingFunction, initializingCall, evidence) or
|
||||
result = this.getARiskyAccessWithNoStatusCheck(initializingFunction, initializingCall, evidence)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,15 +31,15 @@ abstract class SystemData extends Element {
|
||||
*/
|
||||
Expr getAnExprIndirect() {
|
||||
// direct SystemData
|
||||
result = getAnExpr() or
|
||||
result = this.getAnExpr() or
|
||||
// flow via global or member variable (conservative approximation)
|
||||
result = getAnAffectedVar().getAnAccess() or
|
||||
result = this.getAnAffectedVar().getAnAccess() or
|
||||
// flow via stack variable
|
||||
definitionUsePair(_, getAnExprIndirect(), result) or
|
||||
useUsePair(_, getAnExprIndirect(), result) or
|
||||
useUsePair(_, result, getAnExprIndirect()) or
|
||||
definitionUsePair(_, this.getAnExprIndirect(), result) or
|
||||
useUsePair(_, this.getAnExprIndirect(), result) or
|
||||
useUsePair(_, result, this.getAnExprIndirect()) or
|
||||
// flow from assigned value to assignment expression
|
||||
result.(AssignExpr).getRValue() = getAnExprIndirect()
|
||||
result.(AssignExpr).getRValue() = this.getAnExprIndirect()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -67,16 +67,16 @@ class IFStream extends Type {
|
||||
*/
|
||||
class CinVariable extends NamespaceVariable {
|
||||
CinVariable() {
|
||||
getName() = ["cin", "wcin"] and
|
||||
getNamespace().getName() = "std"
|
||||
this.getName() = ["cin", "wcin"] and
|
||||
this.getNamespace().getName() = "std"
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `std::operator>>`. */
|
||||
class OperatorRShiftCall extends FunctionCall {
|
||||
OperatorRShiftCall() {
|
||||
getTarget().getNamespace().getName() = "std" and
|
||||
getTarget().hasName("operator>>")
|
||||
this.getTarget().getNamespace().getName() = "std" and
|
||||
this.getTarget().hasName("operator>>")
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -87,15 +87,15 @@ class OperatorRShiftCall extends FunctionCall {
|
||||
*/
|
||||
|
||||
Expr getSource() {
|
||||
if getTarget() instanceof MemberFunction
|
||||
then result = getQualifier()
|
||||
else result = getArgument(0)
|
||||
if this.getTarget() instanceof MemberFunction
|
||||
then result = this.getQualifier()
|
||||
else result = this.getArgument(0)
|
||||
}
|
||||
|
||||
Expr getDest() {
|
||||
if getTarget() instanceof MemberFunction
|
||||
then result = getArgument(0)
|
||||
else result = getArgument(1)
|
||||
if this.getTarget() instanceof MemberFunction
|
||||
then result = this.getArgument(0)
|
||||
else result = this.getArgument(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ abstract class PotentiallyDangerousInput extends Expr {
|
||||
* Gets the width restriction that applies to the input stream
|
||||
* for this expression, if any.
|
||||
*/
|
||||
Expr getWidth() { result = getPreviousAccess().getWidthAfter() }
|
||||
Expr getWidth() { result = this.getPreviousAccess().getWidthAfter() }
|
||||
|
||||
private Expr getWidthSetHere() {
|
||||
exists(FunctionCall widthCall |
|
||||
@@ -154,11 +154,11 @@ abstract class PotentiallyDangerousInput extends Expr {
|
||||
* after this expression, if any.
|
||||
*/
|
||||
Expr getWidthAfter() {
|
||||
result = getWidthSetHere()
|
||||
result = this.getWidthSetHere()
|
||||
or
|
||||
not exists(getWidthSetHere()) and
|
||||
not isWidthConsumedHere() and
|
||||
result = getWidth()
|
||||
not exists(this.getWidthSetHere()) and
|
||||
not this.isWidthConsumedHere() and
|
||||
result = this.getWidth()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
5
cpp/ql/src/change-notes/released/0.0.4.md
Normal file
5
cpp/ql/src/change-notes/released/0.0.4.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.0.4
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/non-https-url` has been added for C/C++. The query flags uses of `http` URLs that might be better replaced with `https`.
|
||||
1
cpp/ql/src/change-notes/released/0.0.5.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.5.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.5
|
||||
2
cpp/ql/src/codeql-pack.release.yml
Normal file
2
cpp/ql/src/codeql-pack.release.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
@@ -21,9 +21,9 @@ predicate argumentMayBeRoot(Expr e) {
|
||||
|
||||
class SetuidLikeFunctionCall extends FunctionCall {
|
||||
SetuidLikeFunctionCall() {
|
||||
(getTarget().hasGlobalName("setuid") or getTarget().hasGlobalName("setresuid")) and
|
||||
(this.getTarget().hasGlobalName("setuid") or this.getTarget().hasGlobalName("setresuid")) and
|
||||
// setuid/setresuid with the root user are false positives.
|
||||
not argumentMayBeRoot(getArgument(0))
|
||||
not argumentMayBeRoot(this.getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class SetuidLikeWrapperCall extends FunctionCall {
|
||||
|
||||
class CallBeforeSetuidFunctionCall extends FunctionCall {
|
||||
CallBeforeSetuidFunctionCall() {
|
||||
getTarget()
|
||||
this.getTarget()
|
||||
.hasGlobalName([
|
||||
"setgid", "setresgid",
|
||||
// Compatibility may require skipping initgroups and setgroups return checks.
|
||||
@@ -52,7 +52,7 @@ class CallBeforeSetuidFunctionCall extends FunctionCall {
|
||||
"initgroups", "setgroups"
|
||||
]) and
|
||||
// setgid/setresgid/etc with the root group are false positives.
|
||||
not argumentMayBeRoot(getArgument(0))
|
||||
not argumentMayBeRoot(this.getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class CallMayNotReturn extends FunctionCall {
|
||||
not exists(this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call to another function that may not return
|
||||
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
|
||||
exists(CallMayNotReturn exit | this.getTarget() = exit.getEnclosingFunction())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,13 +38,7 @@ where
|
||||
fc.getTargetType().(Class).getABaseClass+().hasGlobalOrStdName("exception") or
|
||||
fc.getTargetType().(Class).getABaseClass+().hasGlobalOrStdName("CException")
|
||||
) and
|
||||
fc instanceof ExprInVoidContext and
|
||||
not fc.isInMacroExpansion() and
|
||||
not exists(ThrowExpr texp | fc.getEnclosingStmt() = texp.getEnclosingStmt()) and
|
||||
not exists(FunctionCall fctmp | fctmp.getAnArgument() = fc) and
|
||||
not fc instanceof ConstructorDirectInit and
|
||||
not fc.getEnclosingStmt() instanceof DeclStmt and
|
||||
not fc instanceof ConstructorDelegationInit and
|
||||
not fc.getParent() instanceof Initializer and
|
||||
not fc.getParent() instanceof AllocationExpr and
|
||||
msg = "This object does not generate an exception."
|
||||
msg = "Object creation of exception type on stack. Did you forget the throw keyword?"
|
||||
select fc, msg
|
||||
|
||||
@@ -118,7 +118,7 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
}
|
||||
|
||||
class Resource extends MemberVariable {
|
||||
Resource() { not isStatic() }
|
||||
Resource() { not this.isStatic() }
|
||||
|
||||
// Check that an expr is somewhere in this class - does not have to be a constructor
|
||||
predicate inSameClass(Expr e) {
|
||||
@@ -129,7 +129,7 @@ class Resource extends MemberVariable {
|
||||
f instanceof Destructor and f.getDeclaringType() = this.getDeclaringType()
|
||||
or
|
||||
exists(Function mid, FunctionCall fc |
|
||||
calledFromDestructor(mid) and
|
||||
this.calledFromDestructor(mid) and
|
||||
fc.getEnclosingFunction() = mid and
|
||||
fc.getTarget() = f and
|
||||
f.getDeclaringType() = this.getDeclaringType()
|
||||
@@ -137,7 +137,7 @@ class Resource extends MemberVariable {
|
||||
}
|
||||
|
||||
predicate inDestructor(Expr e) {
|
||||
exists(Function f | f = e.getEnclosingFunction() | calledFromDestructor(f))
|
||||
exists(Function f | f = e.getEnclosingFunction() | this.calledFromDestructor(f))
|
||||
}
|
||||
|
||||
predicate acquisitionWithRequiredKind(Assignment acquireAssign, string kind) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.2
|
||||
version: 0.0.5
|
||||
groups: cpp
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
|
||||
@@ -29,7 +29,8 @@ class CustomAddFunctionCall extends SimpleRangeAnalysisExpr, FunctionCall {
|
||||
|
||||
class SelfSub extends SimpleRangeAnalysisExpr, SubExpr {
|
||||
SelfSub() {
|
||||
getLeftOperand().(VariableAccess).getTarget() = getRightOperand().(VariableAccess).getTarget()
|
||||
this.getLeftOperand().(VariableAccess).getTarget() =
|
||||
this.getRightOperand().(VariableAccess).getTarget()
|
||||
}
|
||||
|
||||
override float getLowerBounds() { result = 0 }
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| test.cpp:35:3:35:33 | call to runtime_error | This object does not generate an exception. |
|
||||
| test.cpp:35:3:35:33 | call to runtime_error | Object creation of exception type on stack. Did you forget the throw keyword? |
|
||||
| test.cpp:41:3:41:11 | call to funcTest1 | There is an exception in the function that requires your attention. |
|
||||
| test.cpp:42:3:42:9 | call to DllMain | DllMain contains an exeption not wrapped in a try..catch block. |
|
||||
|
||||
@@ -4,8 +4,8 @@ using SinkFunction = void (*)(int);
|
||||
|
||||
void notSink(int notSinkParam);
|
||||
|
||||
void callsSink(int sinkParam) { // $ ir-path=31:28 ir-path=32:31 ir-path=34:22
|
||||
sink(sinkParam); // $ ir-sink=31:28 ir-sink=32:31 ir-sink=34:22 ast=31:28 ast=32:31 ast=34:22 MISSING: ast,ir=28
|
||||
void callsSink(int sinkParam) { // $ ir-path=31:23 ir-path=32:26 ir-path=34:17
|
||||
sink(sinkParam); // $ ast=31:28 ast=32:31 ast=34:22 ir-sink
|
||||
}
|
||||
|
||||
struct {
|
||||
@@ -25,7 +25,7 @@ void assignGlobals() {
|
||||
};
|
||||
|
||||
void testStruct() {
|
||||
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ ir MISSING: ast
|
||||
globalStruct.sinkPtr(atoi(getenv("TAINTED"))); // $ MISSING: ir-path,ast
|
||||
globalStruct.notSinkPtr(atoi(getenv("TAINTED"))); // clean
|
||||
|
||||
globalUnion.sinkPtr(atoi(getenv("TAINTED"))); // $ ast ir-path
|
||||
@@ -48,8 +48,8 @@ class D2 : public D1 {
|
||||
|
||||
class D3 : public D2 {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 ir-path=73:30
|
||||
sink(p); // $ ir-sink=58:10 ir-sink=60:17 ir-sink=61:28 ir-sink=62:29 ir-sink=63:33 ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 SPURIOUS: ast=73:30 ir-sink=73:30
|
||||
void f(const char* p) override { // $ ir-path=58:10 ir-path=60:17 ir-path=61:28 ir-path=62:29 ir-path=63:33 SPURIOUS: ir-path=73:30
|
||||
sink(p); // $ ast=58:10 ast=60:17 ast=61:28 ast=62:29 ast=63:33 ir-sink SPURIOUS: ast=73:30
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -23,11 +23,10 @@ class SourceConfiguration extends TaintedWithPath::TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { isSinkArgument(e) }
|
||||
}
|
||||
|
||||
predicate irTaint(Element source, Element sink, string tag) {
|
||||
exists(TaintedWithPath::PathNode sinkNode, TaintedWithPath::PathNode predNode |
|
||||
predicate irTaint(Element source, TaintedWithPath::PathNode predNode, string tag) {
|
||||
exists(TaintedWithPath::PathNode sinkNode |
|
||||
TaintedWithPath::taintedWithPath(source, _, _, sinkNode) and
|
||||
predNode = getAPredecessor*(sinkNode) and
|
||||
sink = getElementFromPathNode(predNode) and
|
||||
// Make sure the path is actually reachable from this predecessor.
|
||||
// Otherwise, we could pick `predNode` to be b when `source` is
|
||||
// `source1` in this dataflow graph:
|
||||
@@ -35,7 +34,7 @@ predicate irTaint(Element source, Element sink, string tag) {
|
||||
// ^
|
||||
// source2 ---> b --/
|
||||
source = getElementFromPathNode(getAPredecessor*(predNode)) and
|
||||
if sinkNode = predNode then tag = "ir-sink" else tag = "ir-path"
|
||||
if predNode = sinkNode then tag = "ir-sink" else tag = "ir-path"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -45,21 +44,25 @@ class IRDefaultTaintTrackingTest extends InlineExpectationsTest {
|
||||
override string getARelevantTag() { result = ["ir-path", "ir-sink"] }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Element source, Element tainted, int n |
|
||||
irTaint(source, tainted, tag) and
|
||||
n = strictcount(Element otherSource | irTaint(otherSource, tainted, _)) and
|
||||
(
|
||||
n = 1 and value = ""
|
||||
or
|
||||
// If there is more than one source for this sink
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
exists(Element source, Element elem, TaintedWithPath::PathNode node, int n |
|
||||
irTaint(source, node, tag) and
|
||||
elem = getElementFromPathNode(node) and
|
||||
n = count(int startline | getAPredecessor(node).hasLocationInfo(_, startline, _, _, _)) and
|
||||
location = elem.getLocation() and
|
||||
element = elem.toString()
|
||||
|
|
||||
// Zero predecessors means it's a source, and 1 predecessor means it has a unique predecessor.
|
||||
// In either of these cases we leave out the location.
|
||||
n = [0, 1] and value = ""
|
||||
or
|
||||
// If there is more than one predecessor for this node
|
||||
// we specify the source location explicitly.
|
||||
n > 1 and
|
||||
exists(TaintedWithPath::PathNode pred | pred = getAPredecessor(node) |
|
||||
value =
|
||||
source.getLocation().getStartLine().toString() + ":" +
|
||||
source.getLocation().getStartColumn()
|
||||
) and
|
||||
location = tainted.getLocation() and
|
||||
element = tainted.toString()
|
||||
getElementFromPathNode(pred).getLocation().getStartLine().toString() + ":" +
|
||||
getElementFromPathNode(pred).getLocation().getStartColumn()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ struct S {
|
||||
}
|
||||
};
|
||||
|
||||
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=98:18
|
||||
sink(a); // $ ast=96:26 ast=98:18 ir-sink=96:26 ir-sink=98:18
|
||||
void calls_sink_with_argv(const char* a) { // $ ir-path=96:26 ir-path=102:26
|
||||
sink(a); // $ ast=96:26 ast=98:18 ir-sink
|
||||
}
|
||||
|
||||
extern int i;
|
||||
@@ -27,7 +27,7 @@ public:
|
||||
class DerivedCallsSink : public BaseWithPureVirtual {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path
|
||||
sink(p); // $ ir-sink ast=108:10 SPURIOUS: ast=111:10
|
||||
sink(p); // $ ast=108:10 ir-sink SPURIOUS: ast=111:10
|
||||
}
|
||||
};
|
||||
|
||||
@@ -49,8 +49,8 @@ public:
|
||||
};
|
||||
|
||||
class DerivesMultiple : public DerivedCallsSinkDiamond1, public DerivedDoesNotCallSinkDiamond2 {
|
||||
void f(const char* p) override { // $ ir-path
|
||||
DerivedCallsSinkDiamond1::f(p);
|
||||
void f(const char* p) override { // $ ir-path=53:37 ir-path=115:11
|
||||
DerivedCallsSinkDiamond1::f(p); // $ ir-path
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,7 +58,7 @@ template<typename T>
|
||||
class CRTP {
|
||||
public:
|
||||
void f(const char* p) { // $ ir-path
|
||||
static_cast<T*>(this)->g(p);
|
||||
static_cast<T*>(this)->g(p); // $ ir-path
|
||||
}
|
||||
};
|
||||
|
||||
@@ -79,7 +79,7 @@ class Derived2 : public Derived1 {
|
||||
class Derived3 : public Derived2 {
|
||||
public:
|
||||
void f(const char* p) override { // $ ir-path=124:19 ir-path=126:43 ir-path=128:44
|
||||
sink(p); // $ ast,ir-sink=124:19 ast,ir-sink=126:43 ast,ir-sink=128:44
|
||||
sink(p); // $ ast=124:19 ast=126:43 ast=128:44 ir-sink
|
||||
}
|
||||
};
|
||||
|
||||
@@ -97,11 +97,11 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
char*** p = &argv; // $ ast,ir-path
|
||||
|
||||
sink(*p[0]); // $ ast,ir-sink
|
||||
sink(*p[0]); // $ ast ir-sink=96:26 ir-sink=98:18
|
||||
|
||||
calls_sink_with_argv(*p[i]); // $ MISSING: ast,ir-path
|
||||
calls_sink_with_argv(*p[i]); // $ ir-path=96:26 ir-path=98:18 MISSING:ast
|
||||
|
||||
sink(*(argv + 1)); // $ ast,ir-path ir-sink
|
||||
sink(*(argv + 1)); // $ ast ir-path ir-sink
|
||||
|
||||
BaseWithPureVirtual* b = new DerivedCallsSink;
|
||||
|
||||
|
||||
@@ -190,9 +190,9 @@ void test_pointers1()
|
||||
sink(ptr1); // $ ast MISSING: ir
|
||||
sink(ptr2); // $ SPURIOUS: ast
|
||||
sink(*ptr2); // $ ast MISSING: ir
|
||||
sink(ptr3); // $ ast MISSING: ir
|
||||
sink(ptr4); // $ SPURIOUS: ast
|
||||
sink(*ptr4); // $ ast MISSING: ir
|
||||
sink(ptr3); // $ ast,ir
|
||||
sink(ptr4); // $ SPURIOUS: ast,ir
|
||||
sink(*ptr4); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_pointers2()
|
||||
|
||||
@@ -35,17 +35,17 @@ postWithInFlow
|
||||
| BarrierGuard.cpp:60:3:60:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:8:20:8:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:22:3:22:6 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:22:9:22:20 | sourceArray1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:26:8:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:26:27:26:34 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:28:3:28:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:28:22:28:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:30:8:30:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:30:27:30:34 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| clang.cpp:39:16:39:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -77,55 +77,55 @@ postWithInFlow
|
||||
| dispatch.cpp:29:29:29:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:31:8:31:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:31:16:31:24 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:32:8:32:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:32:16:32:24 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:33:3:33:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:33:11:33:16 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:35:8:35:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:35:16:35:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:36:8:36:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:36:16:36:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:37:3:37:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:37:11:37:17 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:39:8:39:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:39:8:39:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:39:15:39:23 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:40:8:40:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:40:8:40:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:40:15:40:23 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:41:3:41:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:41:3:41:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:41:10:41:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:43:8:43:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:43:8:43:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:43:15:43:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:44:8:44:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:44:8:44:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:44:15:44:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:45:3:45:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:45:3:45:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:45:10:45:16 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:51:3:51:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:55:8:55:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:55:22:55:30 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:56:8:56:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:56:22:56:30 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:58:28:58:36 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:60:3:60:14 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:60:18:60:29 | Call [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:60:18:60:29 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -140,34 +140,34 @@ postWithInFlow
|
||||
| dispatch.cpp:65:10:65:21 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:69:3:69:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:69:8:69:13 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:73:3:73:5 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:73:3:73:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:73:7:73:12 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:77:3:77:19 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:78:3:78:21 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:78:23:78:39 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:78:24:78:37 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:80:8:80:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:81:3:81:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:81:6:81:11 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:85:3:85:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:3:89:10 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:12:89:17 | (Middle *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:12:89:17 | (Top *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:12:89:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:21:89:26 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:3:90:10 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:12:90:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:18:90:23 | call to identity [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:100:3:100:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:105:5:105:17 | maybeCallSink [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:113:30:113:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -176,11 +176,11 @@ postWithInFlow
|
||||
| dispatch.cpp:127:31:127:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:129:10:129:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:129:18:129:25 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:130:10:130:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:130:10:130:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:130:17:130:24 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:148:3:148:3 | u [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:148:5:148:5 | f [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| dispatch.cpp:168:3:168:4 | u2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -191,10 +191,10 @@ postWithInFlow
|
||||
| example.c:24:9:24:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:24:20:24:20 | y [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:9:26:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:13:26:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:19:26:24 | coords [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:2:28:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:14:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:14:28:25 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:22:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:23:28:25 | pos [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -227,23 +227,23 @@ postWithInFlow
|
||||
| lambdas.cpp:43:3:43:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:43:3:43:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:43:3:43:3 | c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:3:45:3 | t [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:3:45:3 | u [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:3:45:3 | w [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:4:45:4 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:7:45:7 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:10:45:10 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:11:5:11:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:11:5:11:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:11:5:11:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:5:16:10 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:12:16:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:12:16:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:12:16:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:20:5:20:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:20:5:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:20:5:20:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -259,11 +259,11 @@ postWithInFlow
|
||||
| ref.cpp:31:7:31:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:31:7:31:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:31:7:31:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:7:37:19 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:21:37:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:21:37:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:21:37:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:39:7:39:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:39:7:39:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:39:7:39:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -276,26 +276,26 @@ postWithInFlow
|
||||
| ref.cpp:48:7:48:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:48:7:48:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:48:7:48:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:55:5:55:17 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:55:19:55:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:58:5:58:13 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:58:15:58:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:61:5:61:24 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:61:26:61:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:64:5:64:13 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:64:15:64:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:75:5:75:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:75:5:75:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:75:9:75:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:5:79:10 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:12:79:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:12:79:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:12:79:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:83:5:83:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:83:5:83:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:83:9:83:11 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -311,11 +311,11 @@ postWithInFlow
|
||||
| ref.cpp:96:7:96:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:96:7:96:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:96:11:96:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:7:102:19 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:21:102:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:21:102:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:21:102:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:104:7:104:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:104:7:104:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:104:11:104:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -328,18 +328,18 @@ postWithInFlow
|
||||
| ref.cpp:115:7:115:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:115:7:115:9 | out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:115:11:115:13 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:122:5:122:17 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:122:19:122:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:125:5:125:13 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:125:15:125:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:128:5:128:24 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:128:26:128:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:131:5:131:13 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:131:15:131:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:6:7:6:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:8:3:8:4 | t2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:12:5:12:6 | t2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -520,40 +520,40 @@ postWithInFlow
|
||||
| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:383:7:383:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:3:384:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:10:384:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:11:384:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:389:7:389:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:390:8:390:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:3:391:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:10:391:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:11:391:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:3:400:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:10:400:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:11:400:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:406:8:406:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:3:407:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:10:407:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:11:407:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:417:3:417:14 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:417:16:417:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:423:3:423:18 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:423:21:423:25 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:429:3:429:18 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:429:20:429:24 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:436:3:436:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:436:19:436:23 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:442:3:442:16 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:442:18:442:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:453:7:453:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:456:7:456:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:458:7:458:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -561,12 +561,12 @@ postWithInFlow
|
||||
| test.cpp:465:4:465:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:465:4:465:4 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:469:7:469:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:470:3:470:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:470:22:470:22 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:3:481:19 | content [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:21:481:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:21:481:30 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:21:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:24:481:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:24:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:482:8:482:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,28 +1,28 @@
|
||||
| A.cpp:25:13:25:13 | c | AST only |
|
||||
| A.cpp:27:28:27:28 | c | AST only |
|
||||
| A.cpp:31:14:31:21 | new | IR only |
|
||||
| A.cpp:40:8:40:13 | 0 | IR only |
|
||||
| A.cpp:41:8:41:13 | new | IR only |
|
||||
| A.cpp:40:15:40:21 | 0 | IR only |
|
||||
| A.cpp:41:15:41:21 | new | IR only |
|
||||
| A.cpp:41:15:41:21 | new | IR only |
|
||||
| A.cpp:47:12:47:18 | new | IR only |
|
||||
| A.cpp:54:12:54:18 | new | IR only |
|
||||
| A.cpp:55:8:55:10 | new | IR only |
|
||||
| A.cpp:55:12:55:19 | new | IR only |
|
||||
| A.cpp:55:12:55:19 | new | IR only |
|
||||
| A.cpp:57:11:57:24 | new | IR only |
|
||||
| A.cpp:57:11:57:24 | new | IR only |
|
||||
| A.cpp:57:17:57:23 | new | IR only |
|
||||
| A.cpp:57:28:57:30 | new | IR only |
|
||||
| A.cpp:57:17:57:23 | new | IR only |
|
||||
| A.cpp:62:13:62:19 | new | IR only |
|
||||
| A.cpp:64:10:64:15 | new | IR only |
|
||||
| A.cpp:64:21:64:28 | new | IR only |
|
||||
| A.cpp:64:21:64:28 | new | IR only |
|
||||
| A.cpp:71:13:71:19 | new | IR only |
|
||||
| A.cpp:73:10:73:19 | new | IR only |
|
||||
| A.cpp:73:25:73:32 | new | IR only |
|
||||
| A.cpp:73:25:73:32 | new | IR only |
|
||||
| A.cpp:89:15:89:21 | new | IR only |
|
||||
| A.cpp:99:14:99:21 | new | IR only |
|
||||
| A.cpp:100:9:100:9 | a | AST only |
|
||||
| A.cpp:116:12:116:19 | new | IR only |
|
||||
| A.cpp:126:8:126:10 | new | IR only |
|
||||
| A.cpp:126:12:126:18 | new | IR only |
|
||||
| A.cpp:126:12:126:18 | new | IR only |
|
||||
| A.cpp:130:12:130:18 | new | IR only |
|
||||
| A.cpp:142:10:142:10 | c | AST only |
|
||||
@@ -33,57 +33,57 @@
|
||||
| A.cpp:151:12:151:24 | new | IR only |
|
||||
| A.cpp:159:12:159:18 | new | IR only |
|
||||
| A.cpp:160:18:160:60 | new | IR only |
|
||||
| A.cpp:160:18:160:60 | new | IR only |
|
||||
| A.cpp:160:32:160:59 | 0 | IR only |
|
||||
| A.cpp:160:32:160:59 | 0 | IR only |
|
||||
| A.cpp:160:32:160:59 | new | IR only |
|
||||
| A.cpp:161:18:161:40 | 0 | IR only |
|
||||
| A.cpp:160:32:160:59 | new | IR only |
|
||||
| A.cpp:160:43:160:49 | 0 | IR only |
|
||||
| A.cpp:160:52:160:58 | 0 | IR only |
|
||||
| A.cpp:161:18:161:40 | new | IR only |
|
||||
| A.cpp:162:18:162:40 | 0 | IR only |
|
||||
| A.cpp:161:29:161:35 | 0 | IR only |
|
||||
| A.cpp:162:18:162:40 | new | IR only |
|
||||
| A.cpp:162:29:162:35 | 0 | IR only |
|
||||
| A.cpp:183:7:183:10 | head | AST only |
|
||||
| A.cpp:184:13:184:16 | next | AST only |
|
||||
| B.cpp:7:16:7:35 | 0 | IR only |
|
||||
| B.cpp:7:16:7:35 | new | IR only |
|
||||
| B.cpp:7:28:7:34 | 0 | IR only |
|
||||
| B.cpp:8:16:8:27 | new | IR only |
|
||||
| B.cpp:16:16:16:38 | 0 | IR only |
|
||||
| B.cpp:16:16:16:38 | new | IR only |
|
||||
| B.cpp:16:28:16:34 | 0 | IR only |
|
||||
| B.cpp:17:16:17:27 | new | IR only |
|
||||
| B.cpp:35:13:35:17 | elem1 | AST only |
|
||||
| B.cpp:36:13:36:17 | elem2 | AST only |
|
||||
| B.cpp:46:13:46:16 | box1 | AST only |
|
||||
| C.cpp:18:12:18:18 | new | IR only |
|
||||
| C.cpp:24:11:24:12 | s3 | AST only |
|
||||
| C.cpp:30:5:30:8 | s2 | IR only |
|
||||
| C.cpp:30:10:30:11 | s2 | IR only |
|
||||
| C.cpp:30:10:30:11 | this | IR only |
|
||||
| C.cpp:32:5:32:8 | s4 | IR only |
|
||||
| C.cpp:32:10:32:11 | s4 | IR only |
|
||||
| D.cpp:9:21:9:24 | elem | AST only |
|
||||
| D.cpp:11:29:11:32 | elem | AST only |
|
||||
| D.cpp:16:21:16:23 | box | AST only |
|
||||
| D.cpp:18:29:18:31 | box | AST only |
|
||||
| D.cpp:29:15:29:41 | new | IR only |
|
||||
| D.cpp:29:15:29:41 | new | IR only |
|
||||
| D.cpp:29:24:29:40 | 0 | IR only |
|
||||
| D.cpp:29:24:29:40 | new | IR only |
|
||||
| D.cpp:29:24:29:40 | new | IR only |
|
||||
| D.cpp:29:33:29:39 | 0 | IR only |
|
||||
| D.cpp:30:13:30:16 | elem | AST only |
|
||||
| D.cpp:36:15:36:41 | new | IR only |
|
||||
| D.cpp:36:15:36:41 | new | IR only |
|
||||
| D.cpp:36:24:36:40 | 0 | IR only |
|
||||
| D.cpp:36:24:36:40 | new | IR only |
|
||||
| D.cpp:36:24:36:40 | new | IR only |
|
||||
| D.cpp:36:33:36:39 | 0 | IR only |
|
||||
| D.cpp:43:15:43:41 | new | IR only |
|
||||
| D.cpp:43:15:43:41 | new | IR only |
|
||||
| D.cpp:43:24:43:40 | 0 | IR only |
|
||||
| D.cpp:43:24:43:40 | new | IR only |
|
||||
| D.cpp:43:24:43:40 | new | IR only |
|
||||
| D.cpp:43:33:43:39 | 0 | IR only |
|
||||
| D.cpp:44:19:44:22 | elem | AST only |
|
||||
| D.cpp:50:15:50:41 | new | IR only |
|
||||
| D.cpp:50:15:50:41 | new | IR only |
|
||||
| D.cpp:50:24:50:40 | 0 | IR only |
|
||||
| D.cpp:50:24:50:40 | new | IR only |
|
||||
| D.cpp:50:24:50:40 | new | IR only |
|
||||
| D.cpp:50:33:50:39 | 0 | IR only |
|
||||
| D.cpp:57:5:57:12 | boxfield | AST only |
|
||||
| D.cpp:57:16:57:42 | new | IR only |
|
||||
| D.cpp:57:16:57:42 | new | IR only |
|
||||
| D.cpp:57:25:57:41 | 0 | IR only |
|
||||
| D.cpp:57:25:57:41 | new | IR only |
|
||||
| D.cpp:57:25:57:41 | new | IR only |
|
||||
| D.cpp:57:34:57:40 | 0 | IR only |
|
||||
| D.cpp:58:20:58:23 | elem | AST only |
|
||||
| aliasing.cpp:9:6:9:7 | m1 | AST only |
|
||||
| aliasing.cpp:13:5:13:6 | m1 | AST only |
|
||||
@@ -100,13 +100,13 @@
|
||||
| aliasing.cpp:98:5:98:6 | m1 | AST only |
|
||||
| aliasing.cpp:106:3:106:5 | * ... | AST only |
|
||||
| arrays.cpp:6:3:6:8 | access to array | AST only |
|
||||
| arrays.cpp:7:3:7:6 | access to array | IR only |
|
||||
| arrays.cpp:8:3:8:6 | access to array | IR only |
|
||||
| arrays.cpp:9:3:9:6 | * ... | IR only |
|
||||
| arrays.cpp:10:3:10:6 | * ... | IR only |
|
||||
| arrays.cpp:7:8:7:13 | access to array | IR only |
|
||||
| arrays.cpp:8:8:8:13 | access to array | IR only |
|
||||
| arrays.cpp:9:8:9:11 | * ... | IR only |
|
||||
| arrays.cpp:10:8:10:15 | * ... | IR only |
|
||||
| arrays.cpp:15:3:15:10 | * ... | AST only |
|
||||
| arrays.cpp:16:3:16:6 | access to array | IR only |
|
||||
| arrays.cpp:17:3:17:6 | access to array | IR only |
|
||||
| arrays.cpp:16:8:16:13 | access to array | IR only |
|
||||
| arrays.cpp:17:8:17:13 | access to array | IR only |
|
||||
| arrays.cpp:36:19:36:22 | data | AST only |
|
||||
| arrays.cpp:42:22:42:25 | data | AST only |
|
||||
| arrays.cpp:48:22:48:25 | data | AST only |
|
||||
|
||||
@@ -12,7 +12,7 @@ struct Outer {
|
||||
};
|
||||
|
||||
void absink(struct AB *ab) {
|
||||
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast=40:20 MISSING: ir
|
||||
sink(ab->a); //$ ast,ir=20:20 ast,ir=27:7 ast,ir=40:20
|
||||
sink(ab->b); // no flow
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ int struct_init(void) {
|
||||
|
||||
sink(outer.nestedAB.a); //$ ast,ir
|
||||
sink(outer.nestedAB.b); // no flow
|
||||
sink(outer.pointerAB->a); //$ ast MISSING: ir
|
||||
sink(outer.pointerAB->a); //$ ast,ir
|
||||
sink(outer.pointerAB->b); // no flow
|
||||
|
||||
absink(&outer.nestedAB);
|
||||
|
||||
@@ -21,9 +21,9 @@ void test_unique_ptr_struct() {
|
||||
std::unique_ptr<A> p1(new A{source(), 0});
|
||||
std::unique_ptr<A> p2 = std::make_unique<A>(source(), 0);
|
||||
|
||||
sink(p1->x); // $ ir MISSING: ast
|
||||
sink(p1->x); // $ MISSING: ast,ir
|
||||
sink(p1->y);
|
||||
sink(p2->x); // $ ir=22:46 MISSING: ast
|
||||
sink(p2->x); // $ MISSING: ast,ir=22:46
|
||||
sink(p2->y);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,15 +126,15 @@ void pointer_test() {
|
||||
|
||||
*p2 = source();
|
||||
|
||||
sink(*p1); // $ ast MISSING: ir
|
||||
sink(*p1); // $ ast,ir
|
||||
sink(*p2); // $ ast,ir
|
||||
sink(*p3);
|
||||
|
||||
p3 = &t1;
|
||||
sink(*p3); // $ ast MISSING: ir
|
||||
sink(*p3); // $ ast,ir
|
||||
|
||||
*p3 = 0;
|
||||
sink(*p3); // $ SPURIOUS: ast
|
||||
sink(*p3); // $ SPURIOUS: ast,ir
|
||||
}
|
||||
|
||||
// --- return values ---
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
private import cpp
|
||||
|
||||
/**
|
||||
* Holds if the specified location is in standard headers.
|
||||
*/
|
||||
predicate locationIsInStandardHeaders(Location loc) {
|
||||
loc.getFile().getAbsolutePath().regexpMatch(".*/include/[^/]+")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the AST or IR for the specified function should be printed in the test output.
|
||||
*
|
||||
* This predicate excludes functions defined in standard headers.
|
||||
*/
|
||||
predicate shouldDumpFunction(Function func) {
|
||||
not func.getLocation().getFile().getAbsolutePath().regexpMatch(".*/include/[^/]+")
|
||||
}
|
||||
predicate shouldDumpFunction(Function func) { not locationIsInStandardHeaders(func.getLocation()) }
|
||||
|
||||
6999
cpp/ql/test/library-tests/ir/ir/operand_locations.expected
Normal file
6999
cpp/ql/test/library-tests/ir/ir/operand_locations.expected
Normal file
File diff suppressed because it is too large
Load Diff
7
cpp/ql/test/library-tests/ir/ir/operand_locations.ql
Normal file
7
cpp/ql/test/library-tests/ir/ir/operand_locations.ql
Normal file
@@ -0,0 +1,7 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import PrintConfig
|
||||
|
||||
from Operand a
|
||||
where not locationIsInStandardHeaders(a.getLocation())
|
||||
select a, a.getDumpString()
|
||||
@@ -1474,7 +1474,7 @@ reverseRead
|
||||
argHasPostUpdate
|
||||
postWithInFlow
|
||||
| FunctionTryStmt.cpp:2:3:2:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| VacuousDestructorCall.cpp:10:3:10:16 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| VacuousDestructorCall.cpp:10:22:10:22 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| abortingfunctions.cpp:49:5:49:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1497,7 +1497,7 @@ postWithInFlow
|
||||
| bad_asts.cpp:10:7:10:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:15:10:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:7:16:23 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| bad_asts.cpp:27:11:27:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:3:9:3:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| break_labels.c:5:9:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1520,35 +1520,35 @@ postWithInFlow
|
||||
| builtin.c:22:3:22:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:3:34:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:10:34:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:22:34:31 | (volatile void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:34:23:34:31 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:39:3:39:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:39:10:39:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:39:37:39:45 | carry_out [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:43:3:43:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:43:41:43:49 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:45:3:45:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:48:2:48:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:51:3:51:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:51:10:51:27 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:51:30:51:38 | staticint [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:54:3:54:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:54:10:54:26 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:54:29:54:38 | atomic_int [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.c:56:3:56:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:5:5:5:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:10:10:10:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:10:14:10:22 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:10:24:10:24 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:14:11:14:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:15:5:15:29 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:15:32:15:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| builtin.cpp:15:33:15:35 | ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1559,18 +1559,18 @@ postWithInFlow
|
||||
| condition_decls.cpp:3:13:3:22 | Call [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:3:13:3:22 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:9:5:9:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:16:6:16:20 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:16:6:16:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:16:19:16:20 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:26:10:26:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:26:10:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:26:23:26:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:41:9:41:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:41:9:41:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:41:22:41:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:16:48:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:16:48:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:22:48:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:27:48:31 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:27:48:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:34:48:36 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:39:48:53 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:39:48:53 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| condition_decls.cpp:48:52:48:53 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| conditional_destructors.cpp:6:13:6:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| conditional_destructors.cpp:6:13:6:15 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| conditional_destructors.cpp:10:9:10:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1594,8 +1594,8 @@ postWithInFlow
|
||||
| conditional_destructors.cpp:42:18:42:22 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| conditional_destructors.cpp:42:18:42:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| constmemberaccess.cpp:9:2:9:2 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| constructorinitializer.cpp:8:4:8:4 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| constructorinitializer.cpp:8:4:8:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| constructorinitializer.cpp:8:6:8:18 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp11.cpp:6:5:6:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1650,13 +1650,13 @@ postWithInFlow
|
||||
| cpp17.cpp:15:5:15:45 | Call [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:5:19:8 | 1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:5:19:8 | 2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:5:19:8 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:10:19:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:13:19:13 | 1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:13:19:13 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:13:19:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:16:19:16 | 2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:16:19:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| cpp17.cpp:19:16:19:16 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| defdestructordeleteexpr.cpp:4:5:4:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -1982,20 +1982,20 @@ postWithInFlow
|
||||
| ir.cpp:579:10:579:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:585:5:585:18 | string [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:585:32:585:39 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:591:11:591:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:592:5:592:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:593:5:593:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:594:5:594:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:616:12:616:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:616:12:616:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:617:12:617:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:617:12:617:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:617:15:617:22 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:618:12:618:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:619:12:619:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:619:12:619:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:619:16:619:30 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:631:9:631:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:635:9:635:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:639:9:639:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2011,11 +2011,11 @@ postWithInFlow
|
||||
| ir.cpp:649:9:649:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:653:9:653:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:653:15:653:36 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:654:11:654:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:654:11:654:14 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:654:17:654:38 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:655:9:655:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2042,7 +2042,7 @@ postWithInFlow
|
||||
| ir.cpp:716:5:716:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:716:12:716:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:721:3:721:54 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:721:10:721:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:721:41:721:47 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:721:41:721:47 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:726:9:726:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:728:7:728:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2110,13 +2110,13 @@ postWithInFlow
|
||||
| ir.cpp:805:11:805:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:806:12:806:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:808:5:808:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:809:5:809:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:809:7:809:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:809:7:809:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:810:5:810:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:810:7:810:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:810:7:810:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:811:3:811:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2124,20 +2124,20 @@ postWithInFlow
|
||||
| ir.cpp:813:3:813:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:814:3:814:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:816:5:816:5 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:817:5:817:5 | m [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:818:3:818:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:819:3:819:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:820:3:820:4 | pm [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:822:5:822:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:823:5:823:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:823:7:823:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:823:7:823:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:824:5:824:5 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:824:7:824:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:824:7:824:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:825:3:825:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2145,9 +2145,9 @@ postWithInFlow
|
||||
| ir.cpp:827:3:827:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:828:3:828:4 | pb [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:830:5:830:5 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:831:5:831:5 | d [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:832:3:832:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:833:3:833:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:834:3:834:4 | pd [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2170,8 +2170,8 @@ postWithInFlow
|
||||
| ir.cpp:861:23:861:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:863:9:863:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:864:15:864:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:867:1:867:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:867:1:867:14 | this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:868:3:868:12 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:873:15:873:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:874:3:874:3 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ir.cpp:875:3:875:3 | p [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2293,23 +2293,23 @@ postWithInFlow
|
||||
| misc.c:229:7:229:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:230:2:230:3 | p1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| misc.c:231:2:231:40 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:3:6:8 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:3:6:8 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:19:6:19 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:19:6:19 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:22:6:22 | 0 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| modeled-functions.cpp:6:22:6:22 | (unsigned long *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:13:8:13:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:14:8:14:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:28:3:28:8 | result [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:28:12:28:16 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:28:18:28:23 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_assume.cpp:34:1:34:1 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:11:7:11:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:11:7:11:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:11:12:11:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:28:7:28:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:28:7:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:28:12:28:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:48:5:48:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:48:5:48:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ms_try_mix.cpp:48:10:48:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| newexpr.cpp:8:2:8:20 | Call [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2321,21 +2321,21 @@ postWithInFlow
|
||||
| ops.cpp:26:31:26:53 | Call [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:8:5:8:10 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:8:12:8:21 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:8:12:8:21 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:25:5:25:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:25:5:25:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:27:8:27:13 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| parameterinitializer.cpp:30:5:30:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:23:10:23:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:26:5:26:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:27:5:27:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:27:16:27:20 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pointer_to_member.cpp:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pruning.c:69:9:69:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| pruning.c:78:9:78:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2585,9 +2585,9 @@ postWithInFlow
|
||||
| static_init_templates.cpp:3:2:3:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:3:2:3:4 | ref [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:18:7:18:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:20:2:20:10 | a [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:20:12:20:12 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:21:2:21:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:21:2:21:4 | val [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| static_init_templates.cpp:22:2:22:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2629,8 +2629,8 @@ postWithInFlow
|
||||
| staticlocals.cpp:26:19:26:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stmt_expr.cpp:13:16:13:16 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stmt_expr.cpp:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stmt_expr.cpp:13:18:13:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stmt_expr.cpp:27:5:27:7 | ptr [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:4:16:4:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:5:14:5:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
@@ -2644,9 +2644,9 @@ postWithInFlow
|
||||
| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:19:3:19:11 | xs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:19:13:19:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| stream_it.cpp:20:3:20:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| subscriptexpr.c:4:2:4:2 | i [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| switchbody.c:5:11:5:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -136,7 +136,7 @@ useNotDominatedByDefinition
|
||||
| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor<int>(int, int*) | void CallDestructor<int>(int, int*) |
|
||||
| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) |
|
||||
| static_init_templates.cpp:15:1:15:18 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | static_init_templates.cpp:15:1:15:18 | void MyClass::MyClass() | void MyClass::MyClass() |
|
||||
| try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
|
||||
| try_catch.cpp:21:9:21:9 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) |
|
||||
| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) |
|
||||
switchInstructionWithoutDefaultEdge
|
||||
notMarkedAsConflated
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-tests
|
||||
version: 0.0.2
|
||||
groups: [cpp, test]
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/cpp-queries: "*"
|
||||
|
||||
@@ -12,17 +12,17 @@ edges
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query |
|
||||
| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:5:55:15 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:5:55:15 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:5:57:15 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:5:57:15 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection |
|
||||
| search.c:55:5:55:15 | raw_query | search.c:14:24:14:28 | query |
|
||||
| search.c:55:17:55:25 | raw_query | search.c:14:24:14:28 | query |
|
||||
| search.c:55:17:55:25 | raw_query indirection | search.c:14:24:14:28 | *query |
|
||||
| search.c:57:5:57:15 | raw_query | search.c:22:24:22:28 | query |
|
||||
| search.c:57:17:57:25 | raw_query | search.c:22:24:22:28 | query |
|
||||
| search.c:57:17:57:25 | raw_query indirection | search.c:22:24:22:28 | *query |
|
||||
subpaths
|
||||
nodes
|
||||
@@ -44,9 +44,9 @@ nodes
|
||||
| search.c:23:39:23:43 | query indirection | semmle.label | query indirection |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv |
|
||||
| search.c:55:5:55:15 | raw_query | semmle.label | raw_query |
|
||||
| search.c:55:17:55:25 | raw_query | semmle.label | raw_query |
|
||||
| search.c:55:17:55:25 | raw_query indirection | semmle.label | raw_query indirection |
|
||||
| search.c:57:5:57:15 | raw_query | semmle.label | raw_query |
|
||||
| search.c:57:17:57:25 | raw_query | semmle.label | raw_query |
|
||||
| search.c:57:17:57:25 | raw_query indirection | semmle.label | raw_query indirection |
|
||||
#select
|
||||
| search.c:17:8:17:12 | query | search.c:51:21:51:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data |
|
||||
|
||||
@@ -6,11 +6,11 @@ edges
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:73:17:73:22 | data | test.cpp:37:73:37:76 | data |
|
||||
| test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data |
|
||||
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | *data |
|
||||
subpaths
|
||||
nodes
|
||||
@@ -25,7 +25,7 @@ nodes
|
||||
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:73:17:73:22 | data | semmle.label | data |
|
||||
| test.cpp:73:24:73:27 | data | semmle.label | data |
|
||||
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
|
||||
#select
|
||||
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA | test.cpp:64:30:64:35 | call to getenv | call to getenv |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user