mirror of
https://github.com/github/codeql.git
synced 2026-05-26 09:01:22 +02:00
Compare commits
1255 Commits
esbena/atm
...
z80coder/q
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a716d39370 | ||
|
|
335b2466a9 | ||
|
|
96ae9617ec | ||
|
|
82029663b2 | ||
|
|
4cd15ba654 | ||
|
|
c17c10e450 | ||
|
|
a0f479d503 | ||
|
|
24a5e8a8e1 | ||
|
|
427cdf480a | ||
|
|
8e1f2645cb | ||
|
|
39ec7132af | ||
|
|
f3819e7b06 | ||
|
|
c70a2bebda | ||
|
|
3adc0b57ed | ||
|
|
96aef9f63f | ||
|
|
734bfbd7ae | ||
|
|
6f2d91a8ad | ||
|
|
6c57cbba2b | ||
|
|
2626b0b3dc | ||
|
|
be076dc2c8 | ||
|
|
53a1f935b7 | ||
|
|
8fabbd697e | ||
|
|
e3b2eed2d2 | ||
|
|
8eda061d2f | ||
|
|
579b58b8fa | ||
|
|
3ef707e358 | ||
|
|
cdbd8b27d3 | ||
|
|
4a1e2ed408 | ||
|
|
e9ef53c31b | ||
|
|
7d6cba77a0 | ||
|
|
2e0ca6ce2b | ||
|
|
7d70b77141 | ||
|
|
407c265daf | ||
|
|
95d175e9e0 | ||
|
|
d777ba8a25 | ||
|
|
a26403b359 | ||
|
|
0e9c2377e3 | ||
|
|
348e3b74f3 | ||
|
|
f274f06d9b | ||
|
|
acbf7913b2 | ||
|
|
a5c055581e | ||
|
|
ddb7d722bc | ||
|
|
bdd44c1c46 | ||
|
|
034d45ddc0 | ||
|
|
440976fe63 | ||
|
|
cde98c7799 | ||
|
|
90d7b94b8a | ||
|
|
18489c0ded | ||
|
|
4ccf9bf67c | ||
|
|
8f1b2b3bb5 | ||
|
|
b53e3499cb | ||
|
|
53b3581ed0 | ||
|
|
784991cce5 | ||
|
|
79e6dcaf68 | ||
|
|
8aa4d8227e | ||
|
|
3bc6247ad8 | ||
|
|
218b746f6f | ||
|
|
4d85799fc7 | ||
|
|
615b2ec539 | ||
|
|
b226f767ad | ||
|
|
0ca9feb854 | ||
|
|
1b20506947 | ||
|
|
995e33158f | ||
|
|
04bdba85ea | ||
|
|
c1bb40f439 | ||
|
|
b2016bddac | ||
|
|
c6696adfde | ||
|
|
2187994f5c | ||
|
|
7ddfc00655 | ||
|
|
7e644d8d7b | ||
|
|
76dcfd479e | ||
|
|
133c496b94 | ||
|
|
4beaceec68 | ||
|
|
fb979231f3 | ||
|
|
0ac3e5c3ad | ||
|
|
8d91ba2a6e | ||
|
|
77cb822907 | ||
|
|
c1e4c05aa2 | ||
|
|
e2022f467c | ||
|
|
a3b25f0eb5 | ||
|
|
47002a3bd7 | ||
|
|
1426c5b406 | ||
|
|
7ce9b04941 | ||
|
|
5e80044f11 | ||
|
|
e64a6dc12a | ||
|
|
faaa74b1cd | ||
|
|
24c2578540 | ||
|
|
5d93309ada | ||
|
|
d89c41bae4 | ||
|
|
43ec721a87 | ||
|
|
9363d64166 | ||
|
|
65c301c39f | ||
|
|
0e7fdbeeab | ||
|
|
062f7fe390 | ||
|
|
a32711245f | ||
|
|
15caaa7ad6 | ||
|
|
310353060e | ||
|
|
b2082cc3da | ||
|
|
9d14a85f3f | ||
|
|
dc9187778b | ||
|
|
861ae856b3 | ||
|
|
f5788b9441 | ||
|
|
edf472b9ed | ||
|
|
fdb15d6073 | ||
|
|
633597cc90 | ||
|
|
b73b60d431 | ||
|
|
08b06422ff | ||
|
|
a04920f241 | ||
|
|
4bf2a514ac | ||
|
|
376ee33707 | ||
|
|
4a71aa2165 | ||
|
|
fc3299801b | ||
|
|
2cac729598 | ||
|
|
c5728b2951 | ||
|
|
80b9ccff2b | ||
|
|
e882cdaca4 | ||
|
|
10b2a0a54a | ||
|
|
9ea8b20e77 | ||
|
|
68a0efaf0c | ||
|
|
8eac1dcf15 | ||
|
|
56a8cdb171 | ||
|
|
d06ac78e4d | ||
|
|
3262a14f22 | ||
|
|
b524a6104d | ||
|
|
b921fc62b8 | ||
|
|
f3dcccb64b | ||
|
|
c1cf44b342 | ||
|
|
16bcb4ec86 | ||
|
|
ca5c6923da | ||
|
|
d85ed9ea7a | ||
|
|
7e947b2a65 | ||
|
|
45e416b87b | ||
|
|
dd1ae0bbb5 | ||
|
|
85ff57bae6 | ||
|
|
a9c438924e | ||
|
|
8d607e6251 | ||
|
|
37d76f5e49 | ||
|
|
6fda5e8f5b | ||
|
|
1c79d1f985 | ||
|
|
0d7d60eebd | ||
|
|
81dedfe22f | ||
|
|
aee617f911 | ||
|
|
3c57602653 | ||
|
|
f21948d0ca | ||
|
|
1949a4e59a | ||
|
|
de4458346f | ||
|
|
1b761b3d12 | ||
|
|
ff2f5a5f91 | ||
|
|
d2dc19900f | ||
|
|
dc27089714 | ||
|
|
7732c0885f | ||
|
|
0669ef505e | ||
|
|
372f099850 | ||
|
|
b18f7a9bd7 | ||
|
|
c0b61d7f73 | ||
|
|
124aac23c6 | ||
|
|
4ae92667e1 | ||
|
|
ba23393c0d | ||
|
|
a6eba04793 | ||
|
|
c66d29998e | ||
|
|
88bb8a2704 | ||
|
|
d699ca9aa8 | ||
|
|
5ed7056707 | ||
|
|
3734e1ca4f | ||
|
|
06acaef43e | ||
|
|
a089898220 | ||
|
|
85de6dd667 | ||
|
|
88d65b8fcb | ||
|
|
2020786fb0 | ||
|
|
b0242dc55b | ||
|
|
160635ba3c | ||
|
|
a6cbe6f94c | ||
|
|
fb03561a31 | ||
|
|
aa68c51797 | ||
|
|
598f283715 | ||
|
|
26194be8b6 | ||
|
|
7ff2ee695d | ||
|
|
efc9e67ec2 | ||
|
|
fad95d8935 | ||
|
|
f32d464c0f | ||
|
|
327cf444f4 | ||
|
|
f3c0eadbce | ||
|
|
58f36e4b31 | ||
|
|
90e49508a3 | ||
|
|
a4bea05fa7 | ||
|
|
6f65f22db6 | ||
|
|
be1e75471e | ||
|
|
1cab177f8a | ||
|
|
0e0c3e3937 | ||
|
|
6301e726ee | ||
|
|
1cd37dddf5 | ||
|
|
07a4f5f748 | ||
|
|
679aad138e | ||
|
|
42bf866fb3 | ||
|
|
9604ed883c | ||
|
|
d804893a49 | ||
|
|
03fb244545 | ||
|
|
a6360215f3 | ||
|
|
0ca9852cc8 | ||
|
|
6223b166c2 | ||
|
|
e1d290d4c0 | ||
|
|
1857de1f33 | ||
|
|
b80a84c156 | ||
|
|
6a1aea740f | ||
|
|
c9a87234ef | ||
|
|
66c1629974 | ||
|
|
43a10457dd | ||
|
|
b6c5b4d213 | ||
|
|
d8857c7ce8 | ||
|
|
a46787ea07 | ||
|
|
bd9b96e154 | ||
|
|
8ee020f79c | ||
|
|
13288be7fc | ||
|
|
9ffc02944d | ||
|
|
cfd2dcffa0 | ||
|
|
b0f6cf1491 | ||
|
|
9df1ac7f75 | ||
|
|
10498c3643 | ||
|
|
a1ee900f50 | ||
|
|
6e167040f5 | ||
|
|
657cd89286 | ||
|
|
d2822c2acc | ||
|
|
704a5e4bbf | ||
|
|
8ccbcf1bf8 | ||
|
|
563b771163 | ||
|
|
0a0657ada1 | ||
|
|
1c230d0888 | ||
|
|
afa58f5676 | ||
|
|
13f7fd88f1 | ||
|
|
634ed91904 | ||
|
|
cf42427f54 | ||
|
|
f7f3890b40 | ||
|
|
70f76d06c7 | ||
|
|
45c0d4a3b2 | ||
|
|
b336c29283 | ||
|
|
4ef2a5f4f1 | ||
|
|
7e5bfa5aa0 | ||
|
|
271b23ba8f | ||
|
|
0c3daabc51 | ||
|
|
753d886b0d | ||
|
|
6d247bfdf9 | ||
|
|
e7209d1ee1 | ||
|
|
75f3ebf051 | ||
|
|
9f69c75c50 | ||
|
|
2cd70b96cd | ||
|
|
1a1a7413c2 | ||
|
|
d60b90acd3 | ||
|
|
e879ca7a3b | ||
|
|
15b4b218c8 | ||
|
|
bbab0e582a | ||
|
|
9e61dfb41f | ||
|
|
5a26346ba5 | ||
|
|
5376eb89b3 | ||
|
|
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 | ||
|
|
d46564caa6 | ||
|
|
f6a8b9a7e5 | ||
|
|
b871342e83 | ||
|
|
13347cd102 | ||
|
|
9f4b965202 | ||
|
|
d70d1fbf81 | ||
|
|
a43704ab43 | ||
|
|
063398f24d | ||
|
|
60f3ff8c33 | ||
|
|
8df5aaa797 | ||
|
|
e811ba1150 | ||
|
|
8bcbf8e30f | ||
|
|
8517eff0f7 | ||
|
|
b49ca6a24c | ||
|
|
a18aad8536 | ||
|
|
38d0bb4a60 | ||
|
|
1d321c692b | ||
|
|
283173ad02 | ||
|
|
3145e8f9b7 | ||
|
|
5735bb698d | ||
|
|
490872173a | ||
|
|
07ca1c2ec0 | ||
|
|
fe1a473f07 | ||
|
|
a722aeb5e3 | ||
|
|
e7c298d903 | ||
|
|
b502ca1ea7 | ||
|
|
a716482c1f | ||
|
|
322e39446d | ||
|
|
016727d6b6 | ||
|
|
23480b2d8f | ||
|
|
614c80706f | ||
|
|
5559681916 | ||
|
|
635ac0a209 | ||
|
|
da8e67b7ee | ||
|
|
7492293c5b | ||
|
|
3cbe94ac0a | ||
|
|
64db70f3ac | ||
|
|
8af430d40f | ||
|
|
5f8ea3965d | ||
|
|
66b1612e5e | ||
|
|
b73219392b | ||
|
|
d0e94e655d | ||
|
|
400bf10cc3 | ||
|
|
71820569e1 | ||
|
|
cfb9265f0a | ||
|
|
5269933461 | ||
|
|
389a3c9073 | ||
|
|
16fa066636 | ||
|
|
3dd5d4d7b4 | ||
|
|
3ebf1e3c13 | ||
|
|
a3d11c61a8 | ||
|
|
d852b28653 | ||
|
|
44c3787457 | ||
|
|
aae4260819 | ||
|
|
e9575c3df6 | ||
|
|
7cd9369d91 | ||
|
|
33a9f86f54 | ||
|
|
dd33f4f4d2 | ||
|
|
243b92b28c | ||
|
|
60c0bcf8f7 | ||
|
|
c39fe59a04 | ||
|
|
daf6a4ce07 | ||
|
|
f68a40f82b | ||
|
|
fac2769d85 | ||
|
|
0e31439b7e | ||
|
|
2a3b5fc2b2 | ||
|
|
d0840afb80 | ||
|
|
6c6113b85b | ||
|
|
d9704d7b39 | ||
|
|
42f6dfc197 | ||
|
|
404f4a81a7 | ||
|
|
7f44cebed7 | ||
|
|
4138296ec6 | ||
|
|
87b968f337 | ||
|
|
73f2f52ed8 | ||
|
|
739906b60c | ||
|
|
de53727ab3 | ||
|
|
6742beae1b | ||
|
|
31374b485c | ||
|
|
e410244fe0 | ||
|
|
bb8f4bb7c1 | ||
|
|
ae6501d906 | ||
|
|
08be8edbce | ||
|
|
ddd4ccbb4b | ||
|
|
ff030534ff | ||
|
|
b42295801b | ||
|
|
337ce65fe5 | ||
|
|
35a67845cf | ||
|
|
540ecf3c21 | ||
|
|
755085e9fe | ||
|
|
9f6c0991cf | ||
|
|
5ed9029143 | ||
|
|
75fb47c76f | ||
|
|
cd8a10d0a5 | ||
|
|
96deddf053 | ||
|
|
452685bb66 | ||
|
|
310ef79fbd | ||
|
|
d0dac03bad | ||
|
|
2dfcd1dd9c | ||
|
|
cbd7434a7e | ||
|
|
b68538376c | ||
|
|
3bcf6d68ce | ||
|
|
58f92764f7 | ||
|
|
fd23fa94a5 | ||
|
|
e79b8f3e23 | ||
|
|
d2d5cce787 | ||
|
|
14590436f9 | ||
|
|
50d3592ad3 | ||
|
|
a91208fd2c | ||
|
|
36f14b31bc | ||
|
|
82602014ad | ||
|
|
fdcc144a98 | ||
|
|
591aeff906 | ||
|
|
19bbe6d276 | ||
|
|
d1a7feebc4 | ||
|
|
d946802057 | ||
|
|
57399b733e | ||
|
|
0e890fd788 | ||
|
|
eef3905c46 | ||
|
|
9ce248c829 | ||
|
|
8e1b4e3a58 | ||
|
|
da5c2fb415 | ||
|
|
db04a0dadf | ||
|
|
6d339e50a3 | ||
|
|
09a11f4166 | ||
|
|
6c3aabe1df | ||
|
|
c3e495efe9 | ||
|
|
03b6ee3833 | ||
|
|
04a3f76a8b | ||
|
|
d36a7ed10e | ||
|
|
99c8b291b2 | ||
|
|
b8732859de | ||
|
|
31400df0d4 | ||
|
|
69690a2509 | ||
|
|
4438f8c58c | ||
|
|
e25f03fb56 | ||
|
|
172684ce6e | ||
|
|
a86f2c3ed1 | ||
|
|
70f6493d7a | ||
|
|
1a0379a894 | ||
|
|
d89e430db2 | ||
|
|
15b56585f9 | ||
|
|
37c2db240c | ||
|
|
036d749378 | ||
|
|
44ffc7e155 | ||
|
|
a0bf13007c | ||
|
|
9a6c9c4d77 | ||
|
|
e3c0e190d9 | ||
|
|
fe097783a7 | ||
|
|
61b71807df | ||
|
|
fa54855995 | ||
|
|
fb40b8a032 | ||
|
|
c07d55325e | ||
|
|
349b556c26 | ||
|
|
1b070f1dd8 | ||
|
|
38b925b19c | ||
|
|
d64c7fc638 | ||
|
|
89604deb8d | ||
|
|
d8bf7ed6e0 | ||
|
|
97461d1f11 | ||
|
|
12a3fa77f6 | ||
|
|
112cd9d29c | ||
|
|
1cbacc41d7 | ||
|
|
33d363eb94 | ||
|
|
f320414b1c | ||
|
|
45def1b124 | ||
|
|
28444c7e9c | ||
|
|
ac4476fa82 | ||
|
|
c3f362876b | ||
|
|
84d277dc94 | ||
|
|
0154f4eba4 | ||
|
|
9d308ba0bd | ||
|
|
7c82c5e378 | ||
|
|
5a76e7d4f8 | ||
|
|
1b19a3e320 | ||
|
|
cc16fdecbb | ||
|
|
f54f70d707 | ||
|
|
7214d70ee7 | ||
|
|
fff1f1248a | ||
|
|
1f2b32fe87 | ||
|
|
3bc209ded8 | ||
|
|
631a503e55 | ||
|
|
c00e18f4b0 | ||
|
|
629605c075 | ||
|
|
ac78e26672 | ||
|
|
0760c1c13f | ||
|
|
769f787651 | ||
|
|
3f420c442e | ||
|
|
5fa1c04e2a | ||
|
|
b96ad387ef | ||
|
|
032a0dc6ae | ||
|
|
e851ba2bfd | ||
|
|
d49db9298c | ||
|
|
a089e0ed3f | ||
|
|
6cc14b16ba | ||
|
|
a9cef84b90 | ||
|
|
f29813b3f7 | ||
|
|
eded7b8da1 | ||
|
|
dc715af18b | ||
|
|
c200ec38f5 | ||
|
|
7e2b00e62c | ||
|
|
509e77bbdb | ||
|
|
ef6ea195db | ||
|
|
9a73c36389 | ||
|
|
9e4e42847b | ||
|
|
ade206184c | ||
|
|
b317d73c83 | ||
|
|
09f60f20fc | ||
|
|
89979890ad | ||
|
|
18eede5597 | ||
|
|
48d4fcd064 | ||
|
|
9127fa533a | ||
|
|
4db6702caa | ||
|
|
dc354f8fbf | ||
|
|
9681119f68 | ||
|
|
055937eefb | ||
|
|
6cec64466f | ||
|
|
2af3fb5cca | ||
|
|
8ad5b34c07 | ||
|
|
9d9663d842 | ||
|
|
84d2cb84c1 | ||
|
|
74b1c19a20 | ||
|
|
1b9793d928 | ||
|
|
b31ea30e85 | ||
|
|
a65289253e | ||
|
|
f99ce113cb | ||
|
|
928b91d975 | ||
|
|
c43ff2f9d0 | ||
|
|
4c32b7e480 | ||
|
|
c1b011d47c | ||
|
|
34d4e55459 | ||
|
|
2a5d567041 | ||
|
|
e528c6ff90 | ||
|
|
6004ecc3a4 | ||
|
|
efff86e47b | ||
|
|
f19a229e6f | ||
|
|
865e4f0441 | ||
|
|
3b1c04b71c | ||
|
|
e060708367 | ||
|
|
145efa4a1a | ||
|
|
3252c04c38 | ||
|
|
f8138c92c5 | ||
|
|
1239b1aee1 | ||
|
|
7ce2750c8a | ||
|
|
c7aa89b1d8 | ||
|
|
535904e545 | ||
|
|
b40e30790a | ||
|
|
d0aa219652 | ||
|
|
8391580301 | ||
|
|
d950b59a4d | ||
|
|
9a02a223e3 | ||
|
|
299500fdaa | ||
|
|
24334e4a3a | ||
|
|
62355f3f0e | ||
|
|
0bfedc74fa | ||
|
|
dbc3b49777 | ||
|
|
188a6b19f0 | ||
|
|
df3d5aefc7 | ||
|
|
02c26037cb | ||
|
|
f5bb1d0124 | ||
|
|
4d5901a421 | ||
|
|
eb787ae321 | ||
|
|
d6dd752764 | ||
|
|
ed17bd9106 | ||
|
|
5dbeaa17d6 | ||
|
|
5b261d88bb | ||
|
|
1375e1d9fc | ||
|
|
684600cc54 | ||
|
|
370d75bedc | ||
|
|
8ceeb71c8e | ||
|
|
7745a13efb | ||
|
|
1469766994 | ||
|
|
21caef3d7d | ||
|
|
67b65b691e | ||
|
|
ed15ee8dfb | ||
|
|
30717310e7 | ||
|
|
1d331fc678 | ||
|
|
b0bbbc54d0 | ||
|
|
510f8253e5 | ||
|
|
1a79b13bdc | ||
|
|
8aa354c4c0 | ||
|
|
10aeadb889 | ||
|
|
24959a52d0 | ||
|
|
e185382c41 | ||
|
|
6f4370a684 | ||
|
|
1fb8a175f9 | ||
|
|
53cbde0c44 | ||
|
|
ccaef199bf | ||
|
|
9c82f72720 | ||
|
|
c9f80b1052 | ||
|
|
d90de13bdb | ||
|
|
5c70c6a19b | ||
|
|
4fe43155c0 | ||
|
|
44fff659bd | ||
|
|
85e5b689a3 | ||
|
|
2a0c29156f | ||
|
|
e5dab0185d | ||
|
|
bd5243884a | ||
|
|
4238a5be2f | ||
|
|
89d2f93a16 | ||
|
|
b75e19a446 | ||
|
|
6c70f5299d | ||
|
|
3fc0bed9b5 | ||
|
|
5ef7b9797e | ||
|
|
514f8f3344 | ||
|
|
310ea6b69c | ||
|
|
53e362c994 | ||
|
|
741e4a7a38 | ||
|
|
0954584743 | ||
|
|
7f80514144 | ||
|
|
8020040b4f | ||
|
|
816bfbe4ea | ||
|
|
9f4c829b3e | ||
|
|
e3d42a1fba | ||
|
|
6fe7579fc3 | ||
|
|
ee7ac53bf6 | ||
|
|
2f77b921a0 | ||
|
|
e6b07070f6 | ||
|
|
e862dfd3dc | ||
|
|
fed640b21f | ||
|
|
2352cf7a26 | ||
|
|
e1871a2508 | ||
|
|
8e6bc11197 | ||
|
|
541dcb365f | ||
|
|
ddc0ade28c | ||
|
|
29ebe7b13d | ||
|
|
f071da499b | ||
|
|
1641d0fa93 | ||
|
|
6cd11d2e13 | ||
|
|
f19dd78d40 | ||
|
|
74a7945995 | ||
|
|
c31bd7a1e8 | ||
|
|
153f8fec0e | ||
|
|
50e80dc8b7 | ||
|
|
f29457f4ca | ||
|
|
016ff2af63 | ||
|
|
f9d8ae588c | ||
|
|
71f69997e2 | ||
|
|
632d42fe68 | ||
|
|
c6a52ed2ea | ||
|
|
37e9024343 | ||
|
|
4016a8e458 | ||
|
|
187c24e260 | ||
|
|
0a3705b7af | ||
|
|
ecf27ff24b | ||
|
|
3e2fb5a64e | ||
|
|
9330fa0f69 | ||
|
|
9b786c27c0 | ||
|
|
be36de9b0a | ||
|
|
ec6a8b933c | ||
|
|
1013cb4ccb | ||
|
|
ec292dbffd | ||
|
|
dfa0e77e39 | ||
|
|
ab11bce776 | ||
|
|
72d1473581 | ||
|
|
76880e8f93 | ||
|
|
e510593aa0 | ||
|
|
d23de3dcd8 | ||
|
|
b611b5100b | ||
|
|
6af28e37ae | ||
|
|
6d313cfb6b | ||
|
|
9b52ad2d3d | ||
|
|
fe8b466ff0 | ||
|
|
a665e94805 | ||
|
|
df972eeb05 | ||
|
|
78caab4214 | ||
|
|
1762394b9b | ||
|
|
9a15feae29 | ||
|
|
4e73b9a30f | ||
|
|
a64660aae1 | ||
|
|
aeabe67812 | ||
|
|
d7fd1e0718 | ||
|
|
9a500eecb9 | ||
|
|
c0f1d365ba | ||
|
|
dfa6f285e5 | ||
|
|
cd3839f621 | ||
|
|
63b844856d | ||
|
|
b4a05804fa | ||
|
|
97db13beb4 | ||
|
|
0f71066aaa | ||
|
|
896eca684e | ||
|
|
fd3c53da9b | ||
|
|
f872ed13e3 | ||
|
|
323ccc8cea | ||
|
|
4cb4073dd7 | ||
|
|
350620d44a | ||
|
|
220f4b373c | ||
|
|
6b4dbc3fe5 | ||
|
|
2c01b54a49 | ||
|
|
ff3aba0f5d | ||
|
|
862706f709 | ||
|
|
ffc25f8f89 | ||
|
|
744c3447c9 | ||
|
|
41a0bf154f | ||
|
|
946968b37c | ||
|
|
7955a8b6c8 | ||
|
|
69cf373f21 | ||
|
|
3d0917e6fc | ||
|
|
09d727f343 | ||
|
|
6af27c23ec | ||
|
|
5fc1b8bb29 | ||
|
|
949ead913f | ||
|
|
e167554ad9 | ||
|
|
486fc453e7 | ||
|
|
b46dfc076d | ||
|
|
626ec4d209 | ||
|
|
7bcc906d67 | ||
|
|
3e3ad8e5d4 | ||
|
|
d4b9c36343 | ||
|
|
deffeff01c | ||
|
|
8e1494b91a | ||
|
|
2f7272d1ed | ||
|
|
f4d35f6afe | ||
|
|
c900118731 | ||
|
|
c9bfd85c0d | ||
|
|
9749f797c8 | ||
|
|
ed87d77bc5 | ||
|
|
ed5960e015 | ||
|
|
4406065807 | ||
|
|
7d9c408af4 | ||
|
|
dd6abdc06b | ||
|
|
5a519c5089 | ||
|
|
b5bef24ce2 | ||
|
|
f7ff83c2e7 | ||
|
|
fb491c392e | ||
|
|
11fd4f4997 | ||
|
|
56d9c351d5 | ||
|
|
bff9665866 | ||
|
|
1762b4fb91 | ||
|
|
f0a8c77095 | ||
|
|
2cedddfce8 | ||
|
|
a5fcc5c15a | ||
|
|
5d975089c1 | ||
|
|
455a34a1ec | ||
|
|
18c427cddc | ||
|
|
e46ccc072e | ||
|
|
238fba9b6e | ||
|
|
0ff2de9b5e | ||
|
|
b0cbb31895 | ||
|
|
98b359bd9a | ||
|
|
3039206eab | ||
|
|
53e17e7835 | ||
|
|
808fd78d96 | ||
|
|
9826e7df1d | ||
|
|
946c572413 | ||
|
|
d9f38826f7 | ||
|
|
d8e1e3e8c0 | ||
|
|
c5bcb7999e | ||
|
|
c21df48bcd | ||
|
|
5e7adc661f | ||
|
|
4958b8ba0d | ||
|
|
5b881c2151 | ||
|
|
ce3a531daf | ||
|
|
c3141125af | ||
|
|
a917f240cf | ||
|
|
2543b720e6 | ||
|
|
690b7ef617 | ||
|
|
c577817882 | ||
|
|
4795cbb849 | ||
|
|
4c4fd52347 | ||
|
|
d7f08703af | ||
|
|
31394878a2 | ||
|
|
b31f705ffc | ||
|
|
06ba078ef2 | ||
|
|
823c24a7ab | ||
|
|
1a1770fc06 | ||
|
|
bc74af7307 | ||
|
|
bd01d92500 | ||
|
|
cc43230244 | ||
|
|
0704ab7bd3 | ||
|
|
7c02b6a3b2 | ||
|
|
c8c23a6eb4 | ||
|
|
161461eb6f | ||
|
|
e6242fd349 | ||
|
|
d933bf6f24 | ||
|
|
dd4f6edd62 | ||
|
|
4b73c99c56 | ||
|
|
43b1185d82 | ||
|
|
366fc23938 | ||
|
|
3e7b82a02a | ||
|
|
64a3ffdca7 | ||
|
|
06f2345bbb | ||
|
|
236989f6fd | ||
|
|
aef394e2d1 | ||
|
|
d2222ee9f2 | ||
|
|
b8d26abbc2 | ||
|
|
d41331b28b | ||
|
|
85a35544af | ||
|
|
5e1f565b6a | ||
|
|
e524076045 | ||
|
|
d0cb1384a9 | ||
|
|
94dbf2b7b4 | ||
|
|
7d68020c7b | ||
|
|
bc5e0924d2 | ||
|
|
a0e2bd57a7 | ||
|
|
48cfa9665a | ||
|
|
fb5513c1c8 | ||
|
|
95ea619cc4 | ||
|
|
d1721d0bcd | ||
|
|
2d412d63e0 | ||
|
|
411faca6ef | ||
|
|
3dab87e6ca | ||
|
|
ca81110e4b | ||
|
|
4cb004c0c6 | ||
|
|
15679dfec6 | ||
|
|
705e24690f | ||
|
|
09862b9fe7 | ||
|
|
7034933cee | ||
|
|
30040680ec | ||
|
|
1b4130fe97 | ||
|
|
c3493d6fde | ||
|
|
584702058d | ||
|
|
932f00b43e | ||
|
|
33bd267eb0 | ||
|
|
d474a76cf0 | ||
|
|
1f6eb6e763 | ||
|
|
3ed7f9664c | ||
|
|
35f6c598e7 | ||
|
|
87910e80af | ||
|
|
ddc7794c8d | ||
|
|
1265c3fbed | ||
|
|
14fae833cb | ||
|
|
fed3d80a3d | ||
|
|
88c003681b | ||
|
|
6b901429d0 | ||
|
|
6e274f640f | ||
|
|
0060fcbfd7 | ||
|
|
79c51625a8 | ||
|
|
42bf00f17e | ||
|
|
754bf84abe | ||
|
|
9ae0aad46d | ||
|
|
256af31b38 | ||
|
|
bd6825833d | ||
|
|
af3ae3f1fa | ||
|
|
df20f84ae2 | ||
|
|
825c1c4407 | ||
|
|
9b36fdf9bd | ||
|
|
c3f9d584a4 | ||
|
|
6c7d848727 | ||
|
|
7bd0bf9908 | ||
|
|
01ef4d7060 | ||
|
|
81e88f8d34 | ||
|
|
e927c43222 | ||
|
|
812597505d | ||
|
|
b4d710d58f | ||
|
|
d99d02994a | ||
|
|
46789aecaa | ||
|
|
6c55a67f9a | ||
|
|
f86a827bb6 | ||
|
|
79485ec5da | ||
|
|
f71acdf9fe | ||
|
|
ed767b4a54 | ||
|
|
eb527a5494 | ||
|
|
f71881ef78 | ||
|
|
a8b1ef83f1 | ||
|
|
76144a7f7d | ||
|
|
54b7fa3944 | ||
|
|
ef538570c8 | ||
|
|
352c50c2e5 | ||
|
|
bb3e6399a4 | ||
|
|
fbb58f1954 | ||
|
|
8c6d139d67 | ||
|
|
db6551c22d | ||
|
|
d436be7e96 | ||
|
|
4694ab4773 | ||
|
|
7b61445f83 | ||
|
|
ca21f5800b | ||
|
|
b0a237bcc1 | ||
|
|
d6d626e932 | ||
|
|
9b1836e366 | ||
|
|
b719faa627 | ||
|
|
ba40a99ef8 | ||
|
|
b8a368a47f | ||
|
|
91b8c1c4a0 | ||
|
|
23b2d43440 | ||
|
|
feb1ab86f0 | ||
|
|
b45a793e28 | ||
|
|
23e3062c3b | ||
|
|
b385dfd5a8 | ||
|
|
e79ded9046 | ||
|
|
2515fc0ebc | ||
|
|
6d1dc24fa7 | ||
|
|
7a117caaea | ||
|
|
6bff0f48a2 | ||
|
|
2fa4424f71 | ||
|
|
b9238ea436 | ||
|
|
4c4a2658fe | ||
|
|
e3a4d3074c | ||
|
|
fb8f549d93 | ||
|
|
815337dde1 | ||
|
|
76b55c4a5a | ||
|
|
1e973f3681 | ||
|
|
8d17a95265 | ||
|
|
0ff0aecb22 | ||
|
|
602c9e720e | ||
|
|
bc2932383b | ||
|
|
08dd9477c2 | ||
|
|
35dccb5f3d | ||
|
|
75a959389c | ||
|
|
c2ecad7ddb | ||
|
|
22e4606358 | ||
|
|
9abe340a1f | ||
|
|
cbd0caa4ab | ||
|
|
3cdc6a18ae | ||
|
|
ada77a3c8b | ||
|
|
6b2c96615f | ||
|
|
17ef056579 | ||
|
|
1cbcf40637 | ||
|
|
855683e980 | ||
|
|
4bbd06f51f | ||
|
|
f2f6d34f21 | ||
|
|
b3e23bcc31 | ||
|
|
3ee642868d | ||
|
|
a286dc349a | ||
|
|
12627d19fa | ||
|
|
18b6216f78 | ||
|
|
7a4e4134da | ||
|
|
7d4611941a | ||
|
|
5e89bf99a8 | ||
|
|
a349fdd367 | ||
|
|
e47c4ff2ad | ||
|
|
6c5e33e3d2 | ||
|
|
1aa7cbb918 | ||
|
|
4e8157e3cb | ||
|
|
676bc5ee2a | ||
|
|
eaf6d8123d | ||
|
|
2bbf1e37fc | ||
|
|
5c80716724 | ||
|
|
01e420fd02 | ||
|
|
33ed98e8b7 | ||
|
|
63c7b21f4b | ||
|
|
c2c0a96f40 | ||
|
|
35fe816918 | ||
|
|
48170f5ce0 | ||
|
|
f1aa5ef804 | ||
|
|
bd86ffb35b | ||
|
|
5b1bab0921 | ||
|
|
8dc3948221 | ||
|
|
7a33225fd0 | ||
|
|
c8d0384907 | ||
|
|
04ca858e85 | ||
|
|
068c57acdd | ||
|
|
c78bae69c8 | ||
|
|
2d86b13d44 | ||
|
|
aceab25d9b | ||
|
|
5dcc161f2d | ||
|
|
3d50a4d254 | ||
|
|
fb50ba407d | ||
|
|
d9aa3bbdfa | ||
|
|
8ad05b778d | ||
|
|
1ba51013a4 | ||
|
|
4140ce0f10 | ||
|
|
bb418f9614 | ||
|
|
1345fa982a | ||
|
|
3f2690c3b3 | ||
|
|
18fc76fdb8 | ||
|
|
aae4a1e3f9 | ||
|
|
0b74535b4a | ||
|
|
1feb35efb7 | ||
|
|
5658abd716 | ||
|
|
4e060ce368 | ||
|
|
010bc39465 | ||
|
|
23e4281ddb | ||
|
|
7fa3645e5d | ||
|
|
3cd7594247 | ||
|
|
9b0b4df181 | ||
|
|
109f938968 | ||
|
|
3280f02d6a | ||
|
|
24230dc205 | ||
|
|
3a045ef4e5 | ||
|
|
7d597782b8 | ||
|
|
e57f9e9a1b | ||
|
|
1d4f6e0564 | ||
|
|
e401364fa1 | ||
|
|
03fcfdd53a | ||
|
|
9e6b085e81 | ||
|
|
33fcfdef3d | ||
|
|
dd598f8aa5 | ||
|
|
5a7f349bfa | ||
|
|
64a53f8ba0 | ||
|
|
51fbee69c2 | ||
|
|
764a5d1457 | ||
|
|
64d24c744a | ||
|
|
333e18a1da | ||
|
|
2736b0149c | ||
|
|
fd8fd0b70e | ||
|
|
775a0eebaa | ||
|
|
0c61c9d2b2 | ||
|
|
fe6e7a8ed8 | ||
|
|
074ea79b9a | ||
|
|
5dec75abf3 | ||
|
|
05d1788c1f | ||
|
|
ce13360f9b | ||
|
|
42df07c23a | ||
|
|
27d0af917a | ||
|
|
51230f6ee3 | ||
|
|
7e69931455 | ||
|
|
8d245e6bc2 | ||
|
|
22cd2844d3 | ||
|
|
f15ad39181 | ||
|
|
3515580889 | ||
|
|
d171ace902 | ||
|
|
249d209f45 | ||
|
|
c3344d0734 | ||
|
|
e456098a35 | ||
|
|
e89ed8a1f9 | ||
|
|
e62e72edfd | ||
|
|
fa8efb6ca9 | ||
|
|
45ae088fd8 | ||
|
|
3f133a7e84 | ||
|
|
236f413e01 | ||
|
|
3945dbfa54 | ||
|
|
87e39c7f23 | ||
|
|
671628484b | ||
|
|
28d2daea3f | ||
|
|
41a2e020bd | ||
|
|
17f6cad0e9 | ||
|
|
5112b49b94 | ||
|
|
4110810431 | ||
|
|
cee5dd0cba | ||
|
|
c33e0a5f30 | ||
|
|
26d0e9df5d | ||
|
|
933593223f | ||
|
|
5975ee4932 | ||
|
|
99a3a09033 | ||
|
|
ac35f348c4 | ||
|
|
f46dab6c84 | ||
|
|
c8de28c0a0 | ||
|
|
d65e0a9181 | ||
|
|
535fd73cc9 | ||
|
|
752194b19e | ||
|
|
cbcc4ead36 | ||
|
|
bac0e02fae | ||
|
|
2e02e15875 | ||
|
|
f0bb846345 | ||
|
|
9113469d9d | ||
|
|
de57b2bc9f | ||
|
|
cc60ddde1c | ||
|
|
a5f5fed695 | ||
|
|
2430dbfd04 | ||
|
|
e40d713878 | ||
|
|
d1c6660c32 | ||
|
|
96a9c3446f | ||
|
|
75d77b70cc | ||
|
|
50f5c83cf2 | ||
|
|
19e33b2e29 | ||
|
|
d8b6579f59 | ||
|
|
ebcd27e1b3 | ||
|
|
da6a915779 | ||
|
|
c2c1a9200e | ||
|
|
fac92ef2d0 | ||
|
|
dc5080c61d | ||
|
|
3e87a05de8 | ||
|
|
e5a9bcd786 | ||
|
|
36248cc803 | ||
|
|
0b1d109460 | ||
|
|
d4d7c6de64 | ||
|
|
6d6c1f343d | ||
|
|
3a3f8096e7 | ||
|
|
b20aa3fb07 | ||
|
|
ef69a46f00 | ||
|
|
f99dc7b266 | ||
|
|
43ec1a77cf | ||
|
|
28f2527f86 | ||
|
|
bf98e9636c | ||
|
|
391c8150f5 | ||
|
|
6f7cbf7194 | ||
|
|
d59f0df23f | ||
|
|
09463f4e72 | ||
|
|
16cf439f6b | ||
|
|
cb991fbf14 | ||
|
|
9103e2697f | ||
|
|
77758e5ba6 | ||
|
|
497f0cd48b | ||
|
|
913cf53617 | ||
|
|
79c99b0c61 | ||
|
|
136b046b38 | ||
|
|
e8cc0ee453 | ||
|
|
d88cc79736 | ||
|
|
967553d582 | ||
|
|
4f410f53b8 | ||
|
|
8c59edefb2 | ||
|
|
0eabd4fcd9 | ||
|
|
f713d8b13e | ||
|
|
2f74e3e765 | ||
|
|
e01fe66519 | ||
|
|
93fa56fe79 | ||
|
|
c8cb81d1f9 | ||
|
|
cdac3f9726 | ||
|
|
44c8e78873 | ||
|
|
dc11ec418b | ||
|
|
1e9d8d0ca1 | ||
|
|
05e2ec3f82 | ||
|
|
a4de52d135 | ||
|
|
0e38056a3a | ||
|
|
2abb79cd57 | ||
|
|
219b123271 | ||
|
|
fd3abe42bf | ||
|
|
625b9563bf | ||
|
|
0337a0dc18 | ||
|
|
b9ea00c372 | ||
|
|
59e85abe9e | ||
|
|
e36915b0ef | ||
|
|
da65f75372 | ||
|
|
8ce59ff073 | ||
|
|
c66e7de6a8 | ||
|
|
0aa936d2d2 | ||
|
|
45e6af2d14 | ||
|
|
c6b5130ad5 | ||
|
|
fe631a5eaf | ||
|
|
f61471c451 | ||
|
|
16005fa6cf | ||
|
|
cb3e971ebc | ||
|
|
719ef68aeb | ||
|
|
3a8e1779d9 | ||
|
|
2882f6d37c | ||
|
|
69b4d577d5 | ||
|
|
9580362332 | ||
|
|
5ec1068230 | ||
|
|
e09a012064 | ||
|
|
a1fc6391d7 | ||
|
|
fc2f9b5ab6 | ||
|
|
d5bf0cb33f | ||
|
|
97468a3935 | ||
|
|
158b50f482 | ||
|
|
359b7d6b39 | ||
|
|
192ac4cae3 | ||
|
|
59c4e170a8 | ||
|
|
bb50f90a64 | ||
|
|
20e72d3304 | ||
|
|
59c0c06a8e | ||
|
|
6aa64ba2cc | ||
|
|
b79e295c71 | ||
|
|
a99a6a4721 | ||
|
|
3211545a63 | ||
|
|
21e8993c71 | ||
|
|
b4f67c9d5f | ||
|
|
80761ba069 | ||
|
|
aa23ec0714 | ||
|
|
65bdb1722c | ||
|
|
b4a03fe3f0 | ||
|
|
871f4b1be8 | ||
|
|
e1501dc830 | ||
|
|
ebb1cd3f8f | ||
|
|
f3cae6bb25 | ||
|
|
0aa7127e47 | ||
|
|
b3844cb715 | ||
|
|
c89e924b67 | ||
|
|
5a3da4b9eb | ||
|
|
c449e45b72 | ||
|
|
ae164a6049 | ||
|
|
1d7f43206e | ||
|
|
ef83783d11 | ||
|
|
4921b6cf56 | ||
|
|
58fb239cf0 | ||
|
|
cdd9978c30 | ||
|
|
3ac7fa8369 | ||
|
|
be495b28da | ||
|
|
3aebdcce7b | ||
|
|
79789e28a1 | ||
|
|
a38d9a3cbf | ||
|
|
d9a7f10cfe | ||
|
|
83a38eebab | ||
|
|
14ee979bbe | ||
|
|
1aecd5738b | ||
|
|
8f031cda5f | ||
|
|
fb30a1c893 | ||
|
|
c4c0a63104 | ||
|
|
01ae97bf22 | ||
|
|
01d4b8a41c | ||
|
|
7b64df51ab | ||
|
|
509e789510 | ||
|
|
9f68fdfb61 | ||
|
|
aaa7973906 | ||
|
|
ff591a0c57 | ||
|
|
48c9e5f3b8 | ||
|
|
d941e7cdb8 | ||
|
|
09d0cdbaf8 | ||
|
|
197a36daf6 | ||
|
|
ab20f8f74e | ||
|
|
b83c19f27b | ||
|
|
fec3d745ca | ||
|
|
abec79cb0f | ||
|
|
ee9e1914b0 | ||
|
|
6f5499eefe | ||
|
|
a692794178 | ||
|
|
c075f370c7 | ||
|
|
ec98e8a82d | ||
|
|
9536e591fb | ||
|
|
4eb836ca9b | ||
|
|
d4782e67fe | ||
|
|
3057790071 | ||
|
|
ad7d35df2a | ||
|
|
2addbfabd0 | ||
|
|
0ddac5bcee | ||
|
|
eafbd15da0 | ||
|
|
cd15cec629 | ||
|
|
2443ad3314 | ||
|
|
e554fa8277 | ||
|
|
94c1321e43 | ||
|
|
29c32a924f | ||
|
|
28968163e0 | ||
|
|
20f495dfbf | ||
|
|
7a4a4e9cdd | ||
|
|
a453c32e71 | ||
|
|
9b8acdb37f | ||
|
|
88972f04f4 | ||
|
|
8fa3a425a5 | ||
|
|
9a9b6f71c2 | ||
|
|
cb49c1ec24 | ||
|
|
407a3b5d3d | ||
|
|
a4603a49a1 | ||
|
|
7f2c999b8e | ||
|
|
00b33acfe9 | ||
|
|
e820a5a1e2 | ||
|
|
344c19f049 | ||
|
|
e35ab675ba | ||
|
|
f2edd7724c | ||
|
|
c91a2b88fd | ||
|
|
e469ce171d | ||
|
|
955f4d4d24 | ||
|
|
80b508aa03 | ||
|
|
bae0c260d9 | ||
|
|
44311e2ace | ||
|
|
54e449f3c6 | ||
|
|
f916aa9a37 | ||
|
|
9772f35984 | ||
|
|
a015b9499a | ||
|
|
5494db9b33 | ||
|
|
4ca756ddf9 | ||
|
|
571b949a06 | ||
|
|
3addd03c29 | ||
|
|
fe6595ec02 | ||
|
|
f351100f86 | ||
|
|
36497ad50a | ||
|
|
0f6d6df745 | ||
|
|
6f8f0bb749 | ||
|
|
0c3ce12520 | ||
|
|
8493f515ee | ||
|
|
9e5a4b9fbb | ||
|
|
530df51e8f | ||
|
|
041c07463f | ||
|
|
1b8f702ec6 | ||
|
|
419e69b2b5 | ||
|
|
68e9f9657b | ||
|
|
5b830fdcd1 | ||
|
|
f9f8dfb619 | ||
|
|
f04005e4ca | ||
|
|
2df49aaae8 | ||
|
|
ecde34fdf4 | ||
|
|
786f756591 | ||
|
|
d7e53bfdb3 | ||
|
|
407f63b7d2 | ||
|
|
02e1d424b2 | ||
|
|
b0d86d466f | ||
|
|
021c0a03b4 | ||
|
|
6bb91f4080 | ||
|
|
815bd4fb92 | ||
|
|
cacefbe075 | ||
|
|
ec15ba8e9c | ||
|
|
f5c1b2e645 | ||
|
|
6d04ef46f4 | ||
|
|
823ab1076a | ||
|
|
7bac6a07b6 |
@@ -10,7 +10,16 @@
|
||||
"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",
|
||||
"ruby/extractor-pack/codeql-extractor.yml"
|
||||
]
|
||||
}
|
||||
"ql/ql/consistency-queries/qlpack.yml",
|
||||
"ql/extractor-pack/codeql-extractor.yml"
|
||||
],
|
||||
"versionPolicies": {
|
||||
"default": {
|
||||
"requireChangeNotes": true,
|
||||
"committedPrereleaseSuffix": "dev",
|
||||
"committedVersion": "nextPatchRelease"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
152
.github/workflows/ql-for-ql-build.yml
vendored
Normal file
152
.github/workflows/ql-for-ql-build.yml
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
name: Run QL for QL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
queries:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- name: Get CodeQL version
|
||||
id: get-codeql-version
|
||||
run: |
|
||||
echo "::set-output name=version::$("${CODEQL}" --version | head -n 1 | rev | cut -d " " -f 1 | rev)"
|
||||
shell: bash
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Cache queries
|
||||
id: cache-queries
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ runner.temp }}/query-pack.zip
|
||||
key: queries-${{ hashFiles('ql/**/*.ql*') }}-${{ hashFiles('ql/ql/src/ql.dbscheme*') }}-${{ steps.get-codeql-version.outputs.version }}
|
||||
- name: Build query pack
|
||||
if: steps.cache-queries.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd ql/ql/src
|
||||
"${CODEQL}" pack create
|
||||
cd .codeql/pack/codeql/ql-all/0.0.0
|
||||
zip "${PACKZIP}" -r .
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
PACKZIP: ${{ runner.temp }}/query-pack.zip
|
||||
- name: Upload query pack
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: query-pack-zip
|
||||
path: ${{ runner.temp }}/query-pack.zip
|
||||
|
||||
extractors:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ql/target
|
||||
key: ${{ runner.os }}-rust-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
run: cd ql; cargo fmt --all -- --check
|
||||
- name: Build
|
||||
run: cd ql; cargo build --verbose
|
||||
- name: Run tests
|
||||
run: cd ql; cargo test --verbose
|
||||
- name: Release build
|
||||
run: cd ql; cargo build --release
|
||||
- name: Generate dbscheme
|
||||
run: ql/target/release/ql-generator --dbscheme ql/ql/src/ql.dbscheme --library ql/ql/src/codeql_ql/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: extractor-ubuntu-latest
|
||||
path: |
|
||||
ql/target/release/ql-extractor
|
||||
ql/target/release/ql-extractor.exe
|
||||
retention-days: 1
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- extractors
|
||||
- queries
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: query-pack-zip
|
||||
path: query-pack-zip
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: extractor-ubuntu-latest
|
||||
path: linux64
|
||||
- run: |
|
||||
unzip query-pack-zip/*.zip -d pack
|
||||
cp -r ql/codeql-extractor.yml ql/tools ql/ql/src/ql.dbscheme.stats pack/
|
||||
mkdir -p pack/tools/linux64
|
||||
if [[ -f linux64/ql-extractor ]]; then
|
||||
cp linux64/ql-extractor pack/tools/linux64/extractor
|
||||
chmod +x pack/tools/linux64/extractor
|
||||
fi
|
||||
cd pack
|
||||
zip -rq ../codeql-ql.zip .
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: codeql-ql-pack
|
||||
path: codeql-ql.zip
|
||||
retention-days: 1
|
||||
analyze:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs:
|
||||
- package
|
||||
|
||||
steps:
|
||||
- name: Download pack
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: codeql-ql-pack
|
||||
path: ${{ runner.temp }}/codeql-ql-pack-artifact
|
||||
|
||||
- name: Prepare pack
|
||||
run: |
|
||||
unzip "${PACK_ARTIFACT}/*.zip" -d "${PACK}"
|
||||
env:
|
||||
PACK_ARTIFACT: ${{ runner.temp }}/codeql-ql-pack-artifact
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
- name: Hack codeql-action options
|
||||
run: |
|
||||
JSON=$(jq -nc --arg pack "${PACK}" '.resolve.queries=["--search-path", $pack] | .resolve.extractor=["--search-path", $pack] | .database.init=["--search-path", $pack]')
|
||||
echo "CODEQL_ACTION_EXTRA_OPTIONS=${JSON}" >> ${GITHUB_ENV}
|
||||
env:
|
||||
PACK: ${{ runner.temp }}/pack
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: ql
|
||||
db-location: ${{ runner.temp }}/db
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@esbena/ql
|
||||
|
||||
84
.github/workflows/ql-for-ql-dataset_measure.yml
vendored
Normal file
84
.github/workflows/ql-for-ql-dataset_measure.yml
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
name: Collect database stats for QL for QL
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/ql/src/ql.dbscheme
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/ql/src/ql.dbscheme
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
|
||||
strategy:
|
||||
matrix:
|
||||
repo:
|
||||
- github/codeql
|
||||
- github/codeql-go
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ql/target
|
||||
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Build Extractor
|
||||
run: cd ql; env "PATH=$PATH:`dirname ${CODEQL}`" ./create-extractor-pack.sh
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Checkout ${{ matrix.repo }}
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
path: ${{ github.workspace }}/repo
|
||||
- name: Create database
|
||||
run: |
|
||||
"${CODEQL}" database create \
|
||||
--search-path "ql/extractor-pack" \
|
||||
--threads 4 \
|
||||
--language ql --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Measure database
|
||||
run: |
|
||||
mkdir -p "stats/${{ matrix.repo }}"
|
||||
"${CODEQL}" dataset measure --threads 4 --output "stats/${{ matrix.repo }}/stats.xml" "${{ runner.temp }}/database/db-ql"
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: measurements
|
||||
path: stats
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs: measure
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: measurements
|
||||
path: stats
|
||||
- run: |
|
||||
python -m pip install --user lxml
|
||||
find stats -name 'stats.xml' -print0 | sort -z | xargs -0 python ql/scripts/merge_stats.py --output ql/ql/src/ql.dbscheme.stats --normalise ql_tokeninfo
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ql.dbscheme.stats
|
||||
path: ql/ql/src/ql.dbscheme.stats
|
||||
52
.github/workflows/ql-for-ql-tests.yml
vendored
Normal file
52
.github/workflows/ql-for-ql-tests.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
name: Run QL for QL Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/*
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- ql/*
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Find codeql
|
||||
id: find-codeql
|
||||
uses: github/codeql-action/init@esbena/ql
|
||||
with:
|
||||
languages: javascript # does not matter
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
ql/target
|
||||
key: ${{ runner.os }}-qltest-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
- name: Build extractor
|
||||
run: |
|
||||
cd ql;
|
||||
codeqlpath=$(dirname ${{ steps.find-codeql.outputs.codeql-path }});
|
||||
env "PATH=$PATH:$codeqlpath" ./create-extractor-pack.sh
|
||||
- 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 }}/ql/extractor-pack" --consistency-queries ql/ql/consistency-queries ql/ql/test
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Check QL formatting
|
||||
run: |
|
||||
find ql/ql "(" -name "*.ql" -or -name "*.qll" ")" -print0 | xargs -0 "${CODEQL}" query format --check-only
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
- name: Check QL compilation
|
||||
run: |
|
||||
"${CODEQL}" query compile --check-only --threads=4 --warnings=error --search-path "${{ github.workspace }}/ql/extractor-pack" "ql/ql/src" "ql/ql/examples"
|
||||
env:
|
||||
CODEQL: ${{ steps.find-codeql.outputs.codeql-path }}
|
||||
@@ -25,3 +25,6 @@
|
||||
/docs/codeql-for-visual-studio-code/ @github/codeql-vscode-reviewers
|
||||
/docs/ql-language-reference/ @github/codeql-frontend-reviewers
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
|
||||
# QL for QL reviewers
|
||||
/ql/ @erik-krogh @tausbn
|
||||
@@ -17,7 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
<PackageReference Include="Microsoft.Build" Version="16.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
7
cpp/ql/lib/CHANGELOG.md
Normal file
7
cpp/ql/lib/CHANGELOG.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.
|
||||
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.
|
||||
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.4
|
||||
@@ -1,7 +1,8 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.2
|
||||
version: 0.0.5-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/cpp-upgrades: 0.0.2
|
||||
codeql/cpp-upgrades: ^0.0.3
|
||||
|
||||
@@ -9,6 +9,83 @@ import semmle.code.cpp.models.interfaces.FormattingFunction
|
||||
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
|
||||
private newtype TBufferWriteEstimationReason =
|
||||
TNoSpecifiedEstimateReason() or
|
||||
TTypeBoundsAnalysis() or
|
||||
TValueFlowAnalysis()
|
||||
|
||||
/**
|
||||
* A reason for a specific buffer write size estimate.
|
||||
*/
|
||||
abstract class BufferWriteEstimationReason extends TBufferWriteEstimationReason {
|
||||
/**
|
||||
* Returns the name of the concrete class.
|
||||
*/
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Returns a human readable representation of this reason.
|
||||
*/
|
||||
abstract string getDescription();
|
||||
|
||||
/**
|
||||
* Combine estimate reasons. Used to give a reason for the size of a format string
|
||||
* conversion given reasons coming from its individual specifiers.
|
||||
*/
|
||||
abstract BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other);
|
||||
}
|
||||
|
||||
/**
|
||||
* No particular reason given. This is currently used for backward compatibility so that
|
||||
* classes derived from BufferWrite and overriding `getMaxData/0` still work with the
|
||||
* queries as intended.
|
||||
*/
|
||||
class NoSpecifiedEstimateReason extends BufferWriteEstimationReason, TNoSpecifiedEstimateReason {
|
||||
override string toString() { result = "NoSpecifiedEstimateReason" }
|
||||
|
||||
override string getDescription() { result = "no reason specified" }
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
// this reason should not be used in format specifiers, so it should not be combined
|
||||
// with other reasons
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The estimation comes from rough bounds just based on the type (e.g.
|
||||
* `0 <= x < 2^32` for an unsigned 32 bit integer).
|
||||
*/
|
||||
class TypeBoundsAnalysis extends BufferWriteEstimationReason, TTypeBoundsAnalysis {
|
||||
override string toString() { result = "TypeBoundsAnalysis" }
|
||||
|
||||
override string getDescription() { result = "based on type bounds" }
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
other != TNoSpecifiedEstimateReason() and result = TTypeBoundsAnalysis()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The estimation comes from non trivial bounds found via actual flow analysis.
|
||||
* For example
|
||||
* ```
|
||||
* unsigned u = x;
|
||||
* if (u < 1000) {
|
||||
* //... <- estimation done here based on u
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class ValueFlowAnalysis extends BufferWriteEstimationReason, TValueFlowAnalysis {
|
||||
override string toString() { result = "ValueFlowAnalysis" }
|
||||
|
||||
override string getDescription() { result = "based on flow analysis of value bounds" }
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
other != TNoSpecifiedEstimateReason() and result = other
|
||||
}
|
||||
}
|
||||
|
||||
class PrintfFormatAttribute extends FormatAttribute {
|
||||
PrintfFormatAttribute() { this.getArchetype() = ["printf", "__printf__"] }
|
||||
}
|
||||
@@ -990,7 +1067,14 @@ class FormatLiteral extends Literal {
|
||||
* conversion specifier of this format string; has no result if this cannot
|
||||
* be determined.
|
||||
*/
|
||||
int getMaxConvertedLength(int n) {
|
||||
int getMaxConvertedLength(int n) { result = max(getMaxConvertedLength(n, _)) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by the nth
|
||||
* conversion specifier of this format string, specifying the estimation reason;
|
||||
* has no result if this cannot be determined.
|
||||
*/
|
||||
int getMaxConvertedLength(int n, BufferWriteEstimationReason reason) {
|
||||
exists(int len |
|
||||
(
|
||||
(
|
||||
@@ -1002,10 +1086,12 @@ class FormatLiteral extends Literal {
|
||||
) and
|
||||
(
|
||||
this.getConversionChar(n) = "%" and
|
||||
len = 1
|
||||
len = 1 and
|
||||
reason = TValueFlowAnalysis()
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "c" and
|
||||
len = 1 // e.g. 'a'
|
||||
len = 1 and
|
||||
reason = TValueFlowAnalysis() // e.g. 'a'
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "f" and
|
||||
exists(int dot, int afterdot |
|
||||
@@ -1019,7 +1105,8 @@ class FormatLiteral extends Literal {
|
||||
afterdot = 6
|
||||
) and
|
||||
len = 1 + 309 + dot + afterdot
|
||||
) // e.g. -1e308="-100000"...
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis() // e.g. -1e308="-100000"...
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "e" and
|
||||
exists(int dot, int afterdot |
|
||||
@@ -1033,7 +1120,8 @@ class FormatLiteral extends Literal {
|
||||
afterdot = 6
|
||||
) and
|
||||
len = 1 + 1 + dot + afterdot + 1 + 1 + 3
|
||||
) // -1e308="-1.000000e+308"
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis() // -1e308="-1.000000e+308"
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "g" and
|
||||
exists(int dot, int afterdot |
|
||||
@@ -1056,67 +1144,80 @@ class FormatLiteral extends Literal {
|
||||
// (e.g. 123456, 0.000123456 are just OK)
|
||||
// so case %f can be at most P characters + 4 zeroes, sign, dot = P + 6
|
||||
len = (afterdot.maximum(1) + 6).maximum(1 + 1 + dot + afterdot + 1 + 1 + 3)
|
||||
) // (e.g. "-1.59203e-319")
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis() // (e.g. "-1.59203e-319")
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = ["d", "i"] and
|
||||
// e.g. -2^31 = "-2147483648"
|
||||
len =
|
||||
min(float cand |
|
||||
// The first case handles length sub-specifiers
|
||||
// Subtract one in the exponent because one bit is for the sign.
|
||||
// Add 1 to account for the possible sign in the output.
|
||||
cand = 1 + lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8 - 1))
|
||||
or
|
||||
// The second case uses range analysis to deduce a length that's shorter than the length
|
||||
// of the number -2^31.
|
||||
exists(Expr arg, float lower, float upper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted())
|
||||
|
|
||||
cand =
|
||||
max(int cand0 |
|
||||
// Include the sign bit in the length if it can be negative
|
||||
(
|
||||
if lower < 0
|
||||
then cand0 = 1 + lengthInBase10(lower.abs())
|
||||
else cand0 = lengthInBase10(lower)
|
||||
)
|
||||
or
|
||||
(
|
||||
if upper < 0
|
||||
then cand0 = 1 + lengthInBase10(upper.abs())
|
||||
else cand0 = lengthInBase10(upper)
|
||||
)
|
||||
exists(float typeBasedBound, float valueBasedBound |
|
||||
// The first case handles length sub-specifiers
|
||||
// Subtract one in the exponent because one bit is for the sign.
|
||||
// Add 1 to account for the possible sign in the output.
|
||||
typeBasedBound =
|
||||
1 + lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8 - 1)) and
|
||||
// The second case uses range analysis to deduce a length that's shorter than the length
|
||||
// of the number -2^31.
|
||||
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted()) and
|
||||
typeLower = exprMinVal(arg.getFullyConverted()) and
|
||||
typeUpper = exprMaxVal(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
max(int cand |
|
||||
// Include the sign bit in the length if it can be negative
|
||||
(
|
||||
if lower < 0
|
||||
then cand = 1 + lengthInBase10(lower.abs())
|
||||
else cand = lengthInBase10(lower)
|
||||
)
|
||||
or
|
||||
(
|
||||
if upper < 0
|
||||
then cand = 1 + lengthInBase10(upper.abs())
|
||||
else cand = lengthInBase10(upper)
|
||||
)
|
||||
) and
|
||||
(
|
||||
if lower > typeLower or upper < typeUpper
|
||||
then reason = TValueFlowAnalysis()
|
||||
else reason = TTypeBoundsAnalysis()
|
||||
)
|
||||
)
|
||||
) and
|
||||
len = valueBasedBound.minimum(typeBasedBound)
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "u" and
|
||||
// e.g. 2^32 - 1 = "4294967295"
|
||||
len =
|
||||
min(float cand |
|
||||
// The first case handles length sub-specifiers
|
||||
cand = 2.pow(this.getIntegralDisplayType(n).getSize() * 8)
|
||||
or
|
||||
// The second case uses range analysis to deduce a length that's shorter than
|
||||
// the length of the number 2^31 - 1.
|
||||
exists(Expr arg, float lower |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted())
|
||||
|
|
||||
cand =
|
||||
max(float cand0 |
|
||||
exists(float typeBasedBound, float valueBasedBound |
|
||||
// The first case handles length sub-specifiers
|
||||
typeBasedBound = lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8) - 1) and
|
||||
// The second case uses range analysis to deduce a length that's shorter than
|
||||
// the length of the number 2^31 - 1.
|
||||
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted()) and
|
||||
typeLower = exprMinVal(arg.getFullyConverted()) and
|
||||
typeUpper = exprMaxVal(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
lengthInBase10(max(float cand |
|
||||
// If lower can be negative we use `(unsigned)-1` as the candidate value.
|
||||
lower < 0 and
|
||||
cand0 = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
cand = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
or
|
||||
cand0 = upperBound(arg.getFullyConverted())
|
||||
)
|
||||
cand = upper
|
||||
)) and
|
||||
(
|
||||
if lower > typeLower or upper < typeUpper
|
||||
then reason = TValueFlowAnalysis()
|
||||
else reason = TTypeBoundsAnalysis()
|
||||
)
|
||||
|
|
||||
lengthInBase10(cand)
|
||||
)
|
||||
) and
|
||||
len = valueBasedBound.minimum(typeBasedBound)
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "x" and
|
||||
// e.g. "12345678"
|
||||
@@ -1135,7 +1236,8 @@ class FormatLiteral extends Literal {
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
)
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis()
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "p" and
|
||||
exists(PointerType ptrType, int baseLen |
|
||||
@@ -1144,7 +1246,8 @@ class FormatLiteral extends Literal {
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
)
|
||||
) and
|
||||
reason = TValueFlowAnalysis()
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "o" and
|
||||
// e.g. 2^32 - 1 = "37777777777"
|
||||
@@ -1163,14 +1266,16 @@ class FormatLiteral extends Literal {
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 1 + baseLen else len = baseLen // "0"
|
||||
)
|
||||
)
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis()
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "s" and
|
||||
len =
|
||||
min(int v |
|
||||
v = this.getPrecision(n) or
|
||||
v = this.getUse().getFormatArgument(n).(AnalysedString).getMaxLength() - 1 // (don't count null terminator)
|
||||
)
|
||||
) and
|
||||
reason = TValueFlowAnalysis()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1182,10 +1287,19 @@ class FormatLiteral extends Literal {
|
||||
* determining whether a buffer overflow is caused by long float to string
|
||||
* conversions.
|
||||
*/
|
||||
int getMaxConvertedLengthLimited(int n) {
|
||||
int getMaxConvertedLengthLimited(int n) { result = max(getMaxConvertedLengthLimited(n, _)) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by the nth
|
||||
* conversion specifier of this format string, specifying the reason for the
|
||||
* estimation, except that float to string conversions are assumed to be 8
|
||||
* characters. This is helpful for determining whether a buffer overflow is
|
||||
* caused by long float to string conversions.
|
||||
*/
|
||||
int getMaxConvertedLengthLimited(int n, BufferWriteEstimationReason reason) {
|
||||
if this.getConversionChar(n).toLowerCase() = "f"
|
||||
then result = this.getMaxConvertedLength(n).minimum(8)
|
||||
else result = this.getMaxConvertedLength(n)
|
||||
then result = this.getMaxConvertedLength(n, reason).minimum(8)
|
||||
else result = this.getMaxConvertedLength(n, reason)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1225,29 +1339,35 @@ class FormatLiteral extends Literal {
|
||||
)
|
||||
}
|
||||
|
||||
private int getMaxConvertedLengthAfter(int n) {
|
||||
private int getMaxConvertedLengthAfter(int n, BufferWriteEstimationReason reason) {
|
||||
if n = this.getNumConvSpec()
|
||||
then result = this.getConstantSuffix().length() + 1
|
||||
then result = this.getConstantSuffix().length() + 1 and reason = TValueFlowAnalysis()
|
||||
else
|
||||
result =
|
||||
this.getConstantPart(n).length() + this.getMaxConvertedLength(n) +
|
||||
this.getMaxConvertedLengthAfter(n + 1)
|
||||
exists(BufferWriteEstimationReason headReason, BufferWriteEstimationReason tailReason |
|
||||
result =
|
||||
this.getConstantPart(n).length() + this.getMaxConvertedLength(n, headReason) +
|
||||
this.getMaxConvertedLengthAfter(n + 1, tailReason) and
|
||||
reason = headReason.combineWith(tailReason)
|
||||
)
|
||||
}
|
||||
|
||||
private int getMaxConvertedLengthAfterLimited(int n) {
|
||||
private int getMaxConvertedLengthAfterLimited(int n, BufferWriteEstimationReason reason) {
|
||||
if n = this.getNumConvSpec()
|
||||
then result = this.getConstantSuffix().length() + 1
|
||||
then result = this.getConstantSuffix().length() + 1 and reason = TValueFlowAnalysis()
|
||||
else
|
||||
result =
|
||||
this.getConstantPart(n).length() + this.getMaxConvertedLengthLimited(n) +
|
||||
this.getMaxConvertedLengthAfterLimited(n + 1)
|
||||
exists(BufferWriteEstimationReason headReason, BufferWriteEstimationReason tailReason |
|
||||
result =
|
||||
this.getConstantPart(n).length() + this.getMaxConvertedLengthLimited(n, headReason) +
|
||||
this.getMaxConvertedLengthAfterLimited(n + 1, tailReason) and
|
||||
reason = headReason.combineWith(tailReason)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by this format
|
||||
* string. Has no result if this cannot be determined.
|
||||
*/
|
||||
int getMaxConvertedLength() { result = this.getMaxConvertedLengthAfter(0) }
|
||||
int getMaxConvertedLength() { result = this.getMaxConvertedLengthAfter(0, _) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by this format
|
||||
@@ -1255,5 +1375,24 @@ class FormatLiteral extends Literal {
|
||||
* characters. This is helpful for determining whether a buffer overflow
|
||||
* is caused by long float to string conversions.
|
||||
*/
|
||||
int getMaxConvertedLengthLimited() { result = this.getMaxConvertedLengthAfterLimited(0) }
|
||||
int getMaxConvertedLengthLimited() { result = this.getMaxConvertedLengthAfterLimited(0, _) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by this format
|
||||
* string, specifying the reason for the estimate. Has no result if no estimate
|
||||
* can be found.
|
||||
*/
|
||||
int getMaxConvertedLengthWithReason(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxConvertedLengthAfter(0, reason)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by this format
|
||||
* string, specifying the reason for the estimate, except that float to string
|
||||
* conversions are assumed to be 8 characters. This is helpful for determining
|
||||
* whether a buffer overflow is caused by long float to string conversions.
|
||||
*/
|
||||
int getMaxConvertedLengthLimitedWithReason(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxConvertedLengthAfterLimited(0, reason)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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 }
|
||||
}
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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)
|
||||
)
|
||||
|
||||
@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
|
||||
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) {
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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 }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,14 @@ private import DataFlowImplConsistency
|
||||
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
|
||||
|
||||
@@ -71,13 +71,30 @@ abstract class BufferWrite extends Expr {
|
||||
*/
|
||||
int getMaxData() { none() }
|
||||
|
||||
/**
|
||||
* Gets an upper bound to the amount of data that's being written (if one
|
||||
* can be found), specifying the reason for the estimation.
|
||||
*/
|
||||
int getMaxData(BufferWriteEstimationReason reason) {
|
||||
reason instanceof NoSpecifiedEstimateReason and result = getMaxData()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an upper bound to the amount of data that's being written (if one
|
||||
* can be found), except that float to string conversions are assumed to be
|
||||
* much smaller (8 bytes) than their true maximum length. This can be
|
||||
* helpful in determining the cause of a buffer overflow issue.
|
||||
*/
|
||||
int getMaxDataLimited() { result = this.getMaxData() }
|
||||
int getMaxDataLimited() { result = getMaxData() }
|
||||
|
||||
/**
|
||||
* Gets an upper bound to the amount of data that's being written (if one
|
||||
* can be found), specifying the reason for the estimation, except that
|
||||
* float to string conversions are assumed to be much smaller (8 bytes)
|
||||
* than their true maximum length. This can be helpful in determining the
|
||||
* cause of a buffer overflow issue.
|
||||
*/
|
||||
int getMaxDataLimited(BufferWriteEstimationReason reason) { result = getMaxData(reason) }
|
||||
|
||||
/**
|
||||
* Gets the size of a single character of the type this
|
||||
@@ -135,10 +152,16 @@ class StrCopyBW extends BufferWriteCall {
|
||||
result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
// when result exists, it is an exact flow analysis
|
||||
reason instanceof ValueFlowAnalysis and
|
||||
result =
|
||||
this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,10 +196,16 @@ class StrCatBW extends BufferWriteCall {
|
||||
result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
// when result exists, it is an exact flow analysis
|
||||
reason instanceof ValueFlowAnalysis and
|
||||
result =
|
||||
this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,19 +262,29 @@ class SprintfBW extends BufferWriteCall {
|
||||
|
||||
override Expr getDest() { result = this.getArgument(f.getOutputParameterIndex(false)) }
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
fl = this.(FormattingFunctionCall).getFormat() and
|
||||
result = fl.getMaxConvertedLength() * this.getCharSize()
|
||||
result = fl.getMaxConvertedLengthWithReason(reason) * this.getCharSize()
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() {
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
|
||||
private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
fl = this.(FormattingFunctionCall).getFormat() and
|
||||
result = fl.getMaxConvertedLengthLimited() * this.getCharSize()
|
||||
result = fl.getMaxConvertedLengthLimitedWithReason(reason) * this.getCharSize()
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited(BufferWriteEstimationReason reason) {
|
||||
result = getMaxDataLimitedImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -336,19 +375,29 @@ class SnprintfBW extends BufferWriteCall {
|
||||
result = this.getArgument(this.getParamSize()).getValue().toInt() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
fl = this.(FormattingFunctionCall).getFormat() and
|
||||
result = fl.getMaxConvertedLength() * this.getCharSize()
|
||||
result = fl.getMaxConvertedLengthWithReason(reason) * this.getCharSize()
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() {
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
|
||||
private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
fl = this.(FormattingFunctionCall).getFormat() and
|
||||
result = fl.getMaxConvertedLengthLimited() * this.getCharSize()
|
||||
result = fl.getMaxConvertedLengthLimitedWithReason(reason) * this.getCharSize()
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited(BufferWriteEstimationReason reason) {
|
||||
result = getMaxDataLimitedImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,7 +485,9 @@ class ScanfBW extends BufferWrite {
|
||||
|
||||
override Expr getDest() { result = this }
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
// when this returns, it is based on exact flow analysis
|
||||
reason instanceof ValueFlowAnalysis and
|
||||
exists(ScanfFunctionCall fc, ScanfFormatLiteral fl, int arg |
|
||||
this = fc.getArgument(arg) and
|
||||
fl = fc.getFormat() and
|
||||
@@ -444,6 +495,10 @@ class ScanfBW extends BufferWrite {
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
|
||||
override string getBWDesc() {
|
||||
exists(FunctionCall fc |
|
||||
this = fc.getArgument(_) and
|
||||
@@ -474,8 +529,14 @@ class RealpathBW extends BufferWriteCall {
|
||||
|
||||
override Expr getASource() { result = this.getArgument(0) }
|
||||
|
||||
override int getMaxData() {
|
||||
private int getMaxDataImpl(BufferWriteEstimationReason reason) {
|
||||
// although there may be some unknown invariants guaranteeing that a real path is shorter than PATH_MAX, we can consider providing less than PATH_MAX a problem with high precision
|
||||
reason instanceof ValueFlowAnalysis and
|
||||
result = path_max() and
|
||||
this = this // Suppress a compiler warning
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
5
cpp/ql/src/CHANGELOG.md
Normal file
5
cpp/ql/src/CHANGELOG.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`.
|
||||
@@ -85,7 +85,8 @@ private predicate cancelingSubExprs(ComparisonOperation cmp, VariableAccess a1,
|
||||
exists(Variable v |
|
||||
exists(float m | m < 0 and cmpLinearSubVariable(cmp, v, a1, m)) and
|
||||
exists(float m | m > 0 and cmpLinearSubVariable(cmp, v, a2, m))
|
||||
)
|
||||
) and
|
||||
not any(ClassTemplateInstantiation inst).getATemplateArgument() = cmp.getParent*()
|
||||
}
|
||||
|
||||
from ComparisonOperation cmp, VariableAccess a1, VariableAccess a2
|
||||
|
||||
@@ -29,7 +29,9 @@ predicate pointlessSelfComparison(ComparisonOperation cmp) {
|
||||
not exists(lhs.getQualifier()) and // Avoid structure fields
|
||||
not exists(rhs.getQualifier()) and // Avoid structure fields
|
||||
not convertedExprMightOverflow(lhs) and
|
||||
not convertedExprMightOverflow(rhs)
|
||||
not convertedExprMightOverflow(rhs) and
|
||||
// Don't warn if the comparison is part of a template argument.
|
||||
not any(ClassTemplateInstantiation inst).getATemplateArgument() = cmp.getParent*()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,14 +21,15 @@ import semmle.code.cpp.commons.Alloc
|
||||
* See CWE-120/UnboundedWrite.ql for a summary of CWE-120 alert cases.
|
||||
*/
|
||||
|
||||
from BufferWrite bw, Expr dest, int destSize
|
||||
from BufferWrite bw, Expr dest, int destSize, int estimated
|
||||
where
|
||||
not bw.hasExplicitLimit() and // has no explicit size limit
|
||||
dest = bw.getDest() and
|
||||
destSize = getBufferSize(dest, _) and
|
||||
estimated = bw.getMaxDataLimited(_) and
|
||||
// we can deduce that too much data may be copied (even without
|
||||
// long '%f' conversions)
|
||||
bw.getMaxDataLimited() > destSize
|
||||
estimated > destSize
|
||||
select bw,
|
||||
"This '" + bw.getBWDesc() + "' operation requires " + bw.getMaxData() +
|
||||
"This '" + bw.getBWDesc() + "' operation requires " + estimated +
|
||||
" bytes but the destination is only " + destSize + " bytes."
|
||||
|
||||
@@ -21,14 +21,15 @@ import semmle.code.cpp.security.BufferWrite
|
||||
* See CWE-120/UnboundedWrite.ql for a summary of CWE-120 alert cases.
|
||||
*/
|
||||
|
||||
from BufferWrite bw, int destSize
|
||||
from BufferWrite bw, int destSize, int estimated, BufferWriteEstimationReason reason
|
||||
where
|
||||
not bw.hasExplicitLimit() and
|
||||
// has no explicit size limit
|
||||
destSize = getBufferSize(bw.getDest(), _) and
|
||||
bw.getMaxData() > destSize and
|
||||
estimated = bw.getMaxData(reason) and
|
||||
estimated > destSize and
|
||||
// and we can deduce that too much data may be copied
|
||||
bw.getMaxDataLimited() <= destSize // but it would fit without long '%f' conversions
|
||||
bw.getMaxDataLimited(reason) <= destSize // but it would fit without long '%f' conversions
|
||||
select bw,
|
||||
"This '" + bw.getBWDesc() + "' operation may require " + bw.getMaxData() +
|
||||
"This '" + bw.getBWDesc() + "' operation may require " + estimated +
|
||||
" bytes because of float conversions, but the target is only " + destSize + " bytes."
|
||||
|
||||
@@ -44,7 +44,7 @@ import TaintedWithPath
|
||||
|
||||
predicate isUnboundedWrite(BufferWrite bw) {
|
||||
not bw.hasExplicitLimit() and // has no explicit size limit
|
||||
not exists(bw.getMaxData()) // and we can't deduce an upper bound to the amount copied
|
||||
not exists(bw.getMaxData(_)) // and we can't deduce an upper bound to the amount copied
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,6 +28,11 @@ class PrivateHostName extends string {
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate privateHostNameFlowsToExpr(Expr e) {
|
||||
TaintTracking::localExprTaint(any(StringLiteral p | p.getValue() instanceof PrivateHostName), e)
|
||||
}
|
||||
|
||||
/**
|
||||
* A string containing an HTTP URL not in a private domain.
|
||||
*/
|
||||
@@ -38,11 +43,9 @@ class HttpStringLiteral extends StringLiteral {
|
||||
or
|
||||
exists(string tail |
|
||||
tail = s.regexpCapture("http://(.*)", 1) and not tail instanceof PrivateHostName
|
||||
) and
|
||||
not TaintTracking::localExprTaint(any(StringLiteral p |
|
||||
p.getValue() instanceof PrivateHostName
|
||||
), this.getParent*())
|
||||
)
|
||||
)
|
||||
) and
|
||||
not privateHostNameFlowsToExpr(this.getParent*())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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`.
|
||||
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.4
|
||||
@@ -1,5 +1,6 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.2
|
||||
version: 0.0.5-dev
|
||||
groups: cpp
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-tests
|
||||
version: 0.0.2
|
||||
groups: [cpp, test]
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/cpp-queries: "*"
|
||||
|
||||
@@ -20,3 +20,22 @@ bool compareValues() {
|
||||
bool callCompareValues() {
|
||||
return compareValues<C1, C2> || compareValues<C1, C1>();
|
||||
}
|
||||
|
||||
template <bool C, typename T = void>
|
||||
struct enable_if {};
|
||||
|
||||
template <typename T>
|
||||
struct enable_if<true, T> { typedef T type; };
|
||||
|
||||
template<typename T1, typename T2>
|
||||
typename enable_if<T1::value <= T2::value, bool>::type constant_comparison() {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Value0 {
|
||||
const static int value = 0;
|
||||
};
|
||||
|
||||
void instantiation_with_pointless_comparison() {
|
||||
constant_comparison<Value0, Value0>(); // GOOD
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
# This directory has its own qlpack for reasons detailed in commit 2550788598010fa2117274607c9d58f64f997f34
|
||||
name: codeql/cpp-tests-cwe-190-tainted
|
||||
version: 0.0.2
|
||||
groups: [cpp, test]
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/cpp-queries: "*"
|
||||
|
||||
1
cpp/upgrades/CHANGELOG.md
Normal file
1
cpp/upgrades/CHANGELOG.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.4
|
||||
1
cpp/upgrades/change-notes/released/0.0.4.md
Normal file
1
cpp/upgrades/change-notes/released/0.0.4.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.4
|
||||
2
cpp/upgrades/codeql-pack.release.yml
Normal file
2
cpp/upgrades/codeql-pack.release.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
@@ -1,4 +1,5 @@
|
||||
name: codeql/cpp-upgrades
|
||||
groups: cpp
|
||||
upgrades: .
|
||||
version: 0.0.2
|
||||
version: 0.0.5-dev
|
||||
library: true
|
||||
|
||||
@@ -1,25 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Autobuild.CSharp\Semmle.Autobuild.CSharp.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem" Version="4.3.0"/>
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0"/>
|
||||
<PackageReference Include="xunit" Version="2.4.1"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Autobuild.CSharp\Semmle.Autobuild.CSharp.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,30 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
|
||||
<ApplicationIcon />
|
||||
<OutputType>Exe</OutputType>
|
||||
<StartupObject />
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Util\Semmle.Util.csproj" />
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.CSharp</RootNamespace>
|
||||
<ApplicationIcon/>
|
||||
<OutputType>Exe</OutputType>
|
||||
<StartupObject/>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.11.0"/>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Util\Semmle.Util.csproj"/>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Autobuild.Shared\Semmle.Autobuild.Shared.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,24 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Autobuild.Shared</AssemblyName>
|
||||
<RootNamespace>Semmle.Autobuild.Shared</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.11.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\extractor\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,6 +1,7 @@
|
||||
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint
|
||||
Dapper,55,,,,,,55,,,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,
|
||||
MySql.Data.MySqlClient,48,,,,,,48,,,
|
||||
ServiceStack,194,,7,27,,75,92,,,7
|
||||
System,28,3,25,,4,,23,1,3,25
|
||||
package,sink,source,summary,sink:code,sink:html,sink:remote,sink:sql,sink:xss,source:local,summary:taint,summary:value
|
||||
Dapper,55,,,,,,55,,,,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,28,,,,
|
||||
MySql.Data.MySqlClient,48,,,,,,48,,,,
|
||||
Newtonsoft.Json,,,73,,,,,,,73,
|
||||
ServiceStack,194,,7,27,,75,92,,,7,
|
||||
System,28,3,1221,,4,,23,1,3,611,610
|
||||
|
||||
|
@@ -8,7 +8,7 @@ C# framework & library support
|
||||
|
||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
||||
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
||||
System,"``System.*``, ``System``",3,25,28,5
|
||||
Others,"``Dapper``, ``Microsoft.ApplicationBlocks.Data``, ``MySql.Data.MySqlClient``",,,131,
|
||||
Totals,,3,32,353,5
|
||||
System,"``System.*``, ``System``",3,1221,28,5
|
||||
Others,"``Dapper``, ``Microsoft.ApplicationBlocks.Data``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``",,73,131,
|
||||
Totals,,3,1301,353,5
|
||||
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.DiaSymReader" Version="1.3.0" />
|
||||
<PackageReference Include="Microsoft.DiaSymReader.Native" Version="1.7.0" />
|
||||
<PackageReference Include="Microsoft.DiaSymReader.PortablePdb" Version="1.5.0" />
|
||||
<PackageReference Include="Microsoft.DiaSymReader.PortablePdb" Version="1.6.0"><IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,33 +1,28 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="System.Net.Primitives" Version="4.3.1" />
|
||||
<PackageReference Include="System.Security.Principal" Version="4.3.0" />
|
||||
<PackageReference Include="System.Threading.ThreadPool" Version="4.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp.Standalone</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp.Standalone</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors/>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.11.0"/>
|
||||
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0"/>
|
||||
<PackageReference Include="System.Net.Primitives" Version="4.3.1"/>
|
||||
<PackageReference Include="System.Security.Principal" Version="4.3.0"/>
|
||||
<PackageReference Include="System.Threading.ThreadPool" Version="4.3.0"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -18,6 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
|
||||
private void VisitParameter(ParameterSyntax p)
|
||||
{
|
||||
var symbol = Context.GetModel(p).GetDeclaredSymbol(p)!;
|
||||
Context.CacheLambdaParameterSymbol(symbol, p);
|
||||
Parameter.Create(Context, symbol, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,11 +55,17 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, parent, original));
|
||||
public static Parameter Create(Context cx, IParameterSymbol param, IEntity parent, Parameter? original = null)
|
||||
{
|
||||
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
|
||||
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, parent, original));
|
||||
}
|
||||
|
||||
public static Parameter Create(Context cx, IParameterSymbol param) =>
|
||||
ParameterFactory.Instance.CreateEntity(cx, param, (param, null, null));
|
||||
public static Parameter Create(Context cx, IParameterSymbol param)
|
||||
{
|
||||
var cachedSymbol = cx.GetPossiblyCachedParameterSymbol(param);
|
||||
return ParameterFactory.Instance.CreateEntity(cx, cachedSymbol, (cachedSymbol, null, null));
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp;
|
||||
using Semmle.Extraction.CSharp.Populators;
|
||||
using Semmle.Extraction.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -36,6 +35,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
if (Symbol.TypeKind == TypeKind.Error)
|
||||
{
|
||||
UnknownType.Create(Context); // make sure this exists so we can use it in `TypeRef::getReferencedType`
|
||||
Context.Extractor.MissingType(Symbol.ToString()!, Context.FromSource);
|
||||
return;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
if (Symbol.IsBoundNullable())
|
||||
{
|
||||
// An instance of Nullable<T>
|
||||
trapFile.nullable_underlying_type(this, Create(Context, Symbol.TypeArguments[0]).TypeRef);
|
||||
trapFile.nullable_underlying_type(this, TypeArguments[0].TypeRef);
|
||||
}
|
||||
else if (Symbol.IsReallyUnbound())
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
: Type.Create(Context, Symbol.ConstructedFrom);
|
||||
trapFile.constructed_generic(this, unbound.TypeRef);
|
||||
|
||||
for (var i = 0; i < Symbol.TypeArguments.Length; ++i)
|
||||
for (var i = 0; i < TypeArguments.Length; ++i)
|
||||
{
|
||||
trapFile.type_arguments(TypeArguments[i].TypeRef, i, this);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using Microsoft.CodeAnalysis;
|
||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||
using Semmle.Util;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
@@ -24,9 +23,9 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
symbol.ContainingType is not null && ConstructedOrParentIsConstructed(symbol.ContainingType);
|
||||
}
|
||||
|
||||
private static Kinds.TypeKind GetClassType(Context cx, ITypeSymbol t, bool constructUnderlyingTupleType)
|
||||
public Kinds.TypeKind GetTypeKind(Context cx, bool constructUnderlyingTupleType)
|
||||
{
|
||||
switch (t.SpecialType)
|
||||
switch (Symbol.SpecialType)
|
||||
{
|
||||
case SpecialType.System_Int32: return Kinds.TypeKind.INT;
|
||||
case SpecialType.System_UInt32: return Kinds.TypeKind.UINT;
|
||||
@@ -44,14 +43,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
case SpecialType.System_Single: return Kinds.TypeKind.FLOAT;
|
||||
case SpecialType.System_IntPtr: return Kinds.TypeKind.INT_PTR;
|
||||
default:
|
||||
if (t.IsBoundNullable())
|
||||
if (Symbol.IsBoundNullable())
|
||||
return Kinds.TypeKind.NULLABLE;
|
||||
|
||||
switch (t.TypeKind)
|
||||
switch (Symbol.TypeKind)
|
||||
{
|
||||
case TypeKind.Class: return Kinds.TypeKind.CLASS;
|
||||
case TypeKind.Struct:
|
||||
return ((INamedTypeSymbol)t).IsTupleType && !constructUnderlyingTupleType
|
||||
return ((INamedTypeSymbol)Symbol).IsTupleType && !constructUnderlyingTupleType
|
||||
? Kinds.TypeKind.TUPLE
|
||||
: Kinds.TypeKind.STRUCT;
|
||||
case TypeKind.Interface: return Kinds.TypeKind.INTERFACE;
|
||||
@@ -62,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
case TypeKind.FunctionPointer: return Kinds.TypeKind.FUNCTION_POINTER;
|
||||
case TypeKind.Error: return Kinds.TypeKind.UNKNOWN;
|
||||
default:
|
||||
cx.ModelError(t, $"Unhandled type kind '{t.TypeKind}'");
|
||||
cx.ModelError(Symbol, $"Unhandled type kind '{Symbol.TypeKind}'");
|
||||
return Kinds.TypeKind.UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -76,7 +75,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write("types(");
|
||||
trapFile.WriteColumn(this);
|
||||
trapFile.Write(',');
|
||||
trapFile.WriteColumn((int)GetClassType(Context, Symbol, constructUnderlyingTupleType));
|
||||
trapFile.WriteColumn((int)GetTypeKind(Context, constructUnderlyingTupleType));
|
||||
trapFile.Write(",\"");
|
||||
Symbol.BuildDisplayName(Context, trapFile, constructUnderlyingTupleType);
|
||||
trapFile.WriteLine("\")");
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.IO;
|
||||
using Microsoft.CodeAnalysis;
|
||||
|
||||
namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
internal class UnknownType : Type
|
||||
{
|
||||
private UnknownType(Context cx)
|
||||
: base(cx, null) { }
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
trapFile.types(this, Kinds.TypeKind.UNKNOWN, "<unknown type>");
|
||||
}
|
||||
|
||||
public override void WriteId(EscapingTextWriter trapFile)
|
||||
{
|
||||
trapFile.Write("<unknown>;type");
|
||||
}
|
||||
|
||||
public override bool NeedsPopulation => true;
|
||||
|
||||
public override int GetHashCode() => 98744554;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is not null && obj.GetType() == typeof(UnknownType);
|
||||
}
|
||||
|
||||
public static Type Create(Context cx) => UnknownTypeFactory.Instance.CreateEntity(cx, typeof(UnknownType), null);
|
||||
|
||||
private class UnknownTypeFactory : CachedEntityFactory<ITypeSymbol?, UnknownType>
|
||||
{
|
||||
public static UnknownTypeFactory Instance { get; } = new UnknownTypeFactory();
|
||||
|
||||
public override UnknownType Create(Context cx, ITypeSymbol? init) => new UnknownType(cx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,56 @@ namespace Semmle.Extraction.CSharp
|
||||
/// </summary>
|
||||
public SemanticModel GetModel(SyntaxNode node)
|
||||
{
|
||||
// todo: when this context belongs to a SourceScope, the syntax tree can be retrieved from the scope, and
|
||||
// the node parameter could be removed. Is there any case when we pass in a node that's not from the current
|
||||
// tree?
|
||||
if (cachedModel is null || node.SyntaxTree != cachedModel.SyntaxTree)
|
||||
if (node.SyntaxTree == SourceTree)
|
||||
{
|
||||
cachedModel = Compilation.GetSemanticModel(node.SyntaxTree);
|
||||
if (cachedModelForTree is null)
|
||||
{
|
||||
cachedModelForTree = Compilation.GetSemanticModel(node.SyntaxTree);
|
||||
}
|
||||
|
||||
return cachedModelForTree;
|
||||
}
|
||||
|
||||
return cachedModel;
|
||||
if (cachedModelForOtherTrees is null || node.SyntaxTree != cachedModelForOtherTrees.SyntaxTree)
|
||||
{
|
||||
cachedModelForOtherTrees = Compilation.GetSemanticModel(node.SyntaxTree);
|
||||
}
|
||||
|
||||
return cachedModelForOtherTrees;
|
||||
}
|
||||
|
||||
private SemanticModel? cachedModel;
|
||||
private SemanticModel? cachedModelForTree;
|
||||
private SemanticModel? cachedModelForOtherTrees;
|
||||
|
||||
// The below is a workaround to the bug reported in https://github.com/dotnet/roslyn/issues/58226
|
||||
// Lambda parameters that are equal according to `SymbolEqualityComparer.Default`, might have different
|
||||
// hash-codes, and as a result might not be found in `symbolEntityCache` by hash-code lookup.
|
||||
internal IParameterSymbol GetPossiblyCachedParameterSymbol(IParameterSymbol param)
|
||||
{
|
||||
if ((param.ContainingSymbol as IMethodSymbol)?.MethodKind != MethodKind.AnonymousFunction)
|
||||
{
|
||||
return param;
|
||||
}
|
||||
|
||||
foreach (var sr in param.DeclaringSyntaxReferences)
|
||||
{
|
||||
var syntax = sr.GetSyntax();
|
||||
if (lambdaParameterCache.TryGetValue(syntax, out var cached) &&
|
||||
SymbolEqualityComparer.Default.Equals(param, cached))
|
||||
{
|
||||
return cached;
|
||||
}
|
||||
}
|
||||
|
||||
return param;
|
||||
}
|
||||
|
||||
internal void CacheLambdaParameterSymbol(IParameterSymbol param, SyntaxNode syntax)
|
||||
{
|
||||
lambdaParameterCache[syntax] = param;
|
||||
}
|
||||
|
||||
private readonly Dictionary<SyntaxNode, IParameterSymbol> lambdaParameterCache = new Dictionary<SyntaxNode, IParameterSymbol>();
|
||||
|
||||
/// <summary>
|
||||
/// The current compilation unit.
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
|
||||
<PackageReference Include="Microsoft.Build" Version="16.9.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction.CSharp</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction.CSharp</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CIL\Semmle.Extraction.CIL.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties\"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.0.1"/>
|
||||
<PackageReference Include="Microsoft.Build" Version="16.11.0"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,28 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj" />
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.FileSystem" Version="4.3.0"/>
|
||||
<PackageReference Include="System.IO.FileSystem.Primitives" Version="4.3.0"/>
|
||||
<PackageReference Include="xunit" Version="2.4.1"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp.Standalone\Semmle.Extraction.CSharp.Standalone.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Extraction.CSharp\Semmle.Extraction.CSharp.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Extraction\Semmle.Extraction.csproj"/>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,29 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CodeAnalysisRuleSet>Semmle.Extraction.ruleset</CodeAnalysisRuleSet>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;DEBUG;DEBUG_LABELS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis" Version="3.9.0" />
|
||||
<PackageReference Include="GitInfo" Version="2.1.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<AssemblyName>Semmle.Extraction</AssemblyName>
|
||||
<RootNamespace>Semmle.Extraction</RootNamespace>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<CodeAnalysisRuleSet>Semmle.Extraction.ruleset</CodeAnalysisRuleSet>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>TRACE;DEBUG;DEBUG_LABELS</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.0.1"/>
|
||||
<PackageReference Include="GitInfo" Version="2.2.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,23 +1,19 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||
<RuntimeIdentifiers>win-x64;linux-x64;osx-x64</RuntimeIdentifiers>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="xunit" Version="2.4.1"/>
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Semmle.Util\Semmle.Util.csproj"/>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
1
csharp/ql/lib/CHANGELOG.md
Normal file
1
csharp/ql/lib/CHANGELOG.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.4
|
||||
1
csharp/ql/lib/change-notes/released/0.0.4.md
Normal file
1
csharp/ql/lib/change-notes/released/0.0.4.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.4
|
||||
2
csharp/ql/lib/codeql-pack.release.yml
Normal file
2
csharp/ql/lib/codeql-pack.release.yml
Normal file
@@ -0,0 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.4
|
||||
@@ -2,40 +2,5 @@
|
||||
* The default C# QL library.
|
||||
*/
|
||||
|
||||
import Customizations
|
||||
import semmle.code.csharp.Attribute
|
||||
import semmle.code.csharp.Callable
|
||||
import semmle.code.csharp.Comments
|
||||
import semmle.code.csharp.Element
|
||||
import semmle.code.csharp.Event
|
||||
import semmle.code.csharp.File
|
||||
import semmle.code.csharp.Generics
|
||||
import semmle.code.csharp.Location
|
||||
import semmle.code.csharp.Member
|
||||
import semmle.code.csharp.Namespace
|
||||
import semmle.code.csharp.AnnotatedType
|
||||
import semmle.code.csharp.Property
|
||||
import semmle.code.csharp.Stmt
|
||||
import semmle.code.csharp.Type
|
||||
import semmle.code.csharp.Using
|
||||
import semmle.code.csharp.Variable
|
||||
import semmle.code.csharp.XML
|
||||
import semmle.code.csharp.Preprocessor
|
||||
import semmle.code.csharp.exprs.Access
|
||||
import semmle.code.csharp.exprs.ArithmeticOperation
|
||||
import semmle.code.csharp.exprs.Assignment
|
||||
import semmle.code.csharp.exprs.BitwiseOperation
|
||||
import semmle.code.csharp.exprs.Call
|
||||
import semmle.code.csharp.exprs.ComparisonOperation
|
||||
import semmle.code.csharp.exprs.Creation
|
||||
import semmle.code.csharp.exprs.Dynamic
|
||||
import semmle.code.csharp.exprs.Expr
|
||||
import semmle.code.csharp.exprs.Literal
|
||||
import semmle.code.csharp.exprs.LogicalOperation
|
||||
import semmle.code.csharp.controlflow.ControlFlowGraph
|
||||
import semmle.code.csharp.dataflow.DataFlow
|
||||
import semmle.code.csharp.dataflow.TaintTracking
|
||||
import semmle.code.csharp.dataflow.SSA
|
||||
|
||||
/** Whether the source was extracted without a build command. */
|
||||
predicate extractionIsStandalone() { exists(SourceFile f | f.extractedStandalone()) }
|
||||
// Do not add other imports here; add to `semmle.code.csharp.internal.csharp` instead
|
||||
import semmle.code.csharp.internal.csharp
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
name: codeql/csharp-all
|
||||
version: 0.0.2
|
||||
version: 0.0.5-dev
|
||||
groups: csharp
|
||||
dbscheme: semmlecode.csharp.dbscheme
|
||||
extractor: csharp
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/csharp-upgrades: 0.0.2
|
||||
codeql/csharp-upgrades: ^0.0.3
|
||||
|
||||
@@ -25,7 +25,7 @@ private module Cached {
|
||||
cached
|
||||
predicate alwaysThrowsException(Method m, Type t) {
|
||||
alwaysThrowsMethod(m) and
|
||||
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExpr().getType())
|
||||
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExceptionType())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -612,7 +612,7 @@ class ExprMissingType extends InstructionViolation {
|
||||
not instruction instanceof Opcodes::Ldvirtftn and
|
||||
not instruction instanceof Opcodes::Arglist and
|
||||
not instruction instanceof Opcodes::Refanytype and
|
||||
instruction.getPushCount() = 1 and
|
||||
instruction.getPushCount() >= 1 and
|
||||
count(instruction.getType()) != 1
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,32 @@ class ControlFlowNode extends @cil_controlflow_node {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the `i`th operand. Unlike `getOperand(i).getType()`, this
|
||||
* predicate takes into account when there are multiple possible operands with
|
||||
* different types.
|
||||
*/
|
||||
Type getOperandType(int i) {
|
||||
strictcount(this.getOperand(i)) = 1 and
|
||||
result = this.getOperand(i).getType()
|
||||
or
|
||||
strictcount(this.getOperand(i)) = 2 and
|
||||
exists(ControlFlowNode op1, ControlFlowNode op2, Type t2 |
|
||||
op1 = this.getOperand(i) and
|
||||
op2 = this.getOperand(i) and
|
||||
op1 != op2 and
|
||||
result = op1.getType() and
|
||||
t2 = op2.getType()
|
||||
|
|
||||
result = t2
|
||||
or
|
||||
result.(PrimitiveType).getUnderlyingType().getConversionIndex() >
|
||||
t2.(PrimitiveType).getUnderlyingType().getConversionIndex()
|
||||
or
|
||||
op2 instanceof NullLiteral
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an operand of this instruction, if any. */
|
||||
ControlFlowNode getAnOperand() { result = this.getOperand(_) }
|
||||
|
||||
@@ -102,7 +128,12 @@ class ControlFlowNode extends @cil_controlflow_node {
|
||||
/** Gets the method containing this control flow node. */
|
||||
MethodImplementation getImplementation() { none() }
|
||||
|
||||
/** Gets the type of the item pushed onto the stack, if any. */
|
||||
/**
|
||||
* Gets the type of the item pushed onto the stack, if any.
|
||||
*
|
||||
* If called via `ControlFlowNode::getOperand(i).getType()`, consider using
|
||||
* `ControlFlowNode::getOperandType(i)` instead.
|
||||
*/
|
||||
cached
|
||||
Type getType() { none() }
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ class ComparisonOperation extends BinaryExpr, @cil_comparison_operation {
|
||||
class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation {
|
||||
override Type getType() {
|
||||
exists(Type t0, Type t1 |
|
||||
t0 = this.getOperand(0).getType().getUnderlyingType() and
|
||||
t1 = this.getOperand(1).getType().getUnderlyingType()
|
||||
t0 = this.getOperandType(0).getUnderlyingType() and
|
||||
t1 = this.getOperandType(1).getUnderlyingType()
|
||||
|
|
||||
t0 = t1 and result = t0
|
||||
or
|
||||
@@ -242,6 +242,9 @@ class Return extends Instruction, @cil_ret {
|
||||
class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
/** Gets the type of the exception being thrown. */
|
||||
Type getExceptionType() { result = this.getOperandType(0) }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
|
||||
@@ -199,9 +199,9 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "neg" }
|
||||
|
||||
override NumericType getType() {
|
||||
result = this.getOperand().getType()
|
||||
result = this.getOperandType(0)
|
||||
or
|
||||
this.getOperand().getType() instanceof Enum and result instanceof IntType
|
||||
this.getOperandType(0) instanceof Enum and result instanceof IntType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ module Opcodes {
|
||||
|
||||
override int getPushCount() { result = 2 } // This is the only instruction that pushes 2 items
|
||||
|
||||
override Type getType() { result = this.getOperand(0).getType() }
|
||||
override Type getType() { result = this.getOperandType(0) }
|
||||
}
|
||||
|
||||
/** A `ret` instruction. */
|
||||
@@ -887,7 +887,7 @@ module Opcodes {
|
||||
class Ldelem_ref extends ReadArrayElement, @cil_ldelem_ref {
|
||||
override string getOpcodeName() { result = "ldelem.ref" }
|
||||
|
||||
override Type getType() { result = this.getArray().getType() }
|
||||
override Type getType() { result = this.getOperandType(1) }
|
||||
}
|
||||
|
||||
/** An `ldelema` instruction. */
|
||||
|
||||
@@ -205,7 +205,7 @@ private class RefArg extends AssignableAccess {
|
||||
*/
|
||||
predicate isAnalyzable(Parameter p) {
|
||||
exists(Callable callable | callable = this.getUnboundDeclarationTarget(p) |
|
||||
not callable.(Virtualizable).isOverridableOrImplementable() and
|
||||
not callable.(Overridable).isOverridableOrImplementable() and
|
||||
callable.hasBody()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Provides logic for determining interface member implementations.
|
||||
*
|
||||
* Do not use the predicates in this library directly; use the methods
|
||||
* of the class `Virtualizable` instead.
|
||||
* of the class `Overridable` instead.
|
||||
*/
|
||||
|
||||
import csharp
|
||||
@@ -35,7 +35,26 @@ private import Conversion
|
||||
* `implements(A.M, I.M, B)` and `implements(C.M, I.M, C)`.
|
||||
*/
|
||||
cached
|
||||
predicate implements(Virtualizable m1, Virtualizable m2, ValueOrRefType t) {
|
||||
predicate implements(Overridable m1, Overridable m2, ValueOrRefType t) {
|
||||
implementsVirtualizable(m1, m2, t)
|
||||
or
|
||||
exists(DeclarationWithAccessors d1, DeclarationWithAccessors d2, int kind |
|
||||
implementsVirtualizable(d1, d2, t) and
|
||||
hasAccessor(d1, m1, pragma[only_bind_into](kind)) and
|
||||
hasAccessor(d2, m2, pragma[only_bind_into](kind))
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasAccessor(DeclarationWithAccessors d, Accessor a, int kind) {
|
||||
a = d.getAnAccessor() and
|
||||
(
|
||||
accessors(a, kind, _, _, _) or
|
||||
event_accessors(a, kind, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate implementsVirtualizable(Virtualizable m1, Virtualizable m2, ValueOrRefType t) {
|
||||
exists(Interface i |
|
||||
i = m2.getDeclaringType() and
|
||||
t.getABaseInterface+() = i and
|
||||
|
||||
@@ -180,29 +180,15 @@ class Member extends DotNet::Member, Modifiable, @member {
|
||||
override predicate isStatic() { Modifiable.super.isStatic() }
|
||||
}
|
||||
|
||||
private class TOverridable = @virtualizable or @callable_accessor;
|
||||
|
||||
/**
|
||||
* A member where the `virtual` modifier is valid. That is, a method,
|
||||
* a property, an indexer, or an event.
|
||||
* A declaration that can be overridden or implemented. That is, a method,
|
||||
* a property, an indexer, an event, or an accessor.
|
||||
*
|
||||
* Equivalently, these are the members that can be defined in an interface.
|
||||
* Unlike `Virtualizable`, this class includes accessors.
|
||||
*/
|
||||
class Virtualizable extends Member, @virtualizable {
|
||||
/** Holds if this member has the modifier `override`. */
|
||||
predicate isOverride() { this.hasModifier("override") }
|
||||
|
||||
/** Holds if this member is `virtual`. */
|
||||
predicate isVirtual() { this.hasModifier("virtual") }
|
||||
|
||||
override predicate isPublic() {
|
||||
Member.super.isPublic() or
|
||||
this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
override predicate isPrivate() {
|
||||
super.isPrivate() and
|
||||
not this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
class Overridable extends Declaration, TOverridable {
|
||||
/**
|
||||
* Gets any interface this member explicitly implements; this only applies
|
||||
* to members that can be declared on an interface, i.e. methods, properties,
|
||||
@@ -216,19 +202,10 @@ class Virtualizable extends Member, @virtualizable {
|
||||
predicate implementsExplicitInterface() { exists(this.getExplicitlyImplementedInterface()) }
|
||||
|
||||
/** Holds if this member can be overridden or implemented. */
|
||||
predicate isOverridableOrImplementable() {
|
||||
not this.isSealed() and
|
||||
not this.getDeclaringType().isSealed() and
|
||||
(
|
||||
this.isVirtual() or
|
||||
this.isOverride() or
|
||||
this.isAbstract() or
|
||||
this.getDeclaringType() instanceof Interface
|
||||
)
|
||||
}
|
||||
predicate isOverridableOrImplementable() { none() }
|
||||
|
||||
/** Gets the member that is immediately overridden by this member, if any. */
|
||||
Virtualizable getOverridee() {
|
||||
Overridable getOverridee() {
|
||||
overrides(this, result)
|
||||
or
|
||||
// For accessors (which are `Callable`s), the extractor generates entries
|
||||
@@ -242,7 +219,7 @@ class Virtualizable extends Member, @virtualizable {
|
||||
}
|
||||
|
||||
/** Gets a member that immediately overrides this member, if any. */
|
||||
Virtualizable getAnOverrider() { this = result.getOverridee() }
|
||||
Overridable getAnOverrider() { this = result.getOverridee() }
|
||||
|
||||
/** Holds if this member is overridden by some other member. */
|
||||
predicate isOverridden() { exists(this.getAnOverrider()) }
|
||||
@@ -273,10 +250,10 @@ class Virtualizable extends Member, @virtualizable {
|
||||
* `A.M.getImplementee(B) = I.M` and
|
||||
* `C.M.getImplementee(C) = I.M`.
|
||||
*/
|
||||
Virtualizable getImplementee(ValueOrRefType t) { implements(this, result, t) }
|
||||
Overridable getImplementee(ValueOrRefType t) { implements(this, result, t) }
|
||||
|
||||
/** Gets the interface member that is immediately implemented by this member, if any. */
|
||||
Virtualizable getImplementee() { result = this.getImplementee(_) }
|
||||
Overridable getImplementee() { result = this.getImplementee(_) }
|
||||
|
||||
/**
|
||||
* Gets a member that immediately implements this interface member, if any.
|
||||
@@ -301,10 +278,10 @@ class Virtualizable extends Member, @virtualizable {
|
||||
* `I.M.getAnImplementor(B) = A.M` and
|
||||
* `I.M.getAnImplementor(C) = C.M`.
|
||||
*/
|
||||
Virtualizable getAnImplementor(ValueOrRefType t) { this = result.getImplementee(t) }
|
||||
Overridable getAnImplementor(ValueOrRefType t) { this = result.getImplementee(t) }
|
||||
|
||||
/** Gets a member that immediately implements this interface member, if any. */
|
||||
Virtualizable getAnImplementor() { this = result.getImplementee() }
|
||||
Overridable getAnImplementor() { this = result.getImplementee() }
|
||||
|
||||
/**
|
||||
* Gets an interface member that is (transitively) implemented by this
|
||||
@@ -334,8 +311,8 @@ class Virtualizable extends Member, @virtualizable {
|
||||
* - If this member is `D.M` then `I.M = getAnUltimateImplementee()`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Virtualizable getAnUltimateImplementee() {
|
||||
exists(Virtualizable implementation, ValueOrRefType implementationType |
|
||||
Overridable getAnUltimateImplementee() {
|
||||
exists(Overridable implementation, ValueOrRefType implementationType |
|
||||
implements(implementation, result, implementationType)
|
||||
|
|
||||
this = implementation
|
||||
@@ -354,7 +331,7 @@ class Virtualizable extends Member, @virtualizable {
|
||||
* Note that this is generally *not* equivalent with
|
||||
* `getImplementor().getAnOverrider*()` (see `getImplementee`).
|
||||
*/
|
||||
Virtualizable getAnUltimateImplementor() { this = result.getAnUltimateImplementee() }
|
||||
Overridable getAnUltimateImplementor() { this = result.getAnUltimateImplementee() }
|
||||
|
||||
/** Holds if this interface member is implemented by some other member. */
|
||||
predicate isImplemented() { exists(this.getAnImplementor()) }
|
||||
@@ -362,14 +339,59 @@ class Virtualizable extends Member, @virtualizable {
|
||||
/** Holds if this member implements (transitively) an interface member. */
|
||||
predicate implements() { exists(this.getAnUltimateImplementee()) }
|
||||
|
||||
/**
|
||||
* Holds if this member overrides or implements (transitively)
|
||||
* `that` member.
|
||||
*/
|
||||
predicate overridesOrImplements(Overridable that) {
|
||||
this.getOverridee+() = that or
|
||||
this.getAnUltimateImplementee() = that
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this member overrides or implements (reflexively, transitively)
|
||||
* `that` member.
|
||||
*/
|
||||
predicate overridesOrImplementsOrEquals(Virtualizable that) {
|
||||
predicate overridesOrImplementsOrEquals(Overridable that) {
|
||||
this = that or
|
||||
this.getOverridee+() = that or
|
||||
this.getAnUltimateImplementee() = that
|
||||
this.overridesOrImplements(that)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A member where the `virtual` modifier is valid. That is, a method,
|
||||
* a property, an indexer, or an event.
|
||||
*
|
||||
* Equivalently, these are the members that can be defined in an interface.
|
||||
*
|
||||
* Unlike `Overridable`, this class excludes accessors.
|
||||
*/
|
||||
class Virtualizable extends Overridable, Member, @virtualizable {
|
||||
/** Holds if this member has the modifier `override`. */
|
||||
predicate isOverride() { this.hasModifier("override") }
|
||||
|
||||
/** Holds if this member is `virtual`. */
|
||||
predicate isVirtual() { this.hasModifier("virtual") }
|
||||
|
||||
override predicate isPublic() {
|
||||
Member.super.isPublic() or
|
||||
this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
override predicate isPrivate() {
|
||||
super.isPrivate() and
|
||||
not this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
override predicate isOverridableOrImplementable() {
|
||||
not this.isSealed() and
|
||||
not this.getDeclaringType().isSealed() and
|
||||
(
|
||||
this.isVirtual() or
|
||||
this.isOverride() or
|
||||
this.isAbstract() or
|
||||
this.getDeclaringType() instanceof Interface
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer
|
||||
* An accessor. Either a getter (`Getter`), a setter (`Setter`), or event
|
||||
* accessor (`EventAccessor`).
|
||||
*/
|
||||
class Accessor extends Callable, Modifiable, Attributable, @callable_accessor {
|
||||
class Accessor extends Callable, Modifiable, Attributable, Overridable, @callable_accessor {
|
||||
override ValueOrRefType getDeclaringType() { result = this.getDeclaration().getDeclaringType() }
|
||||
|
||||
/** Gets the assembly name of this accessor. */
|
||||
@@ -376,6 +376,10 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor {
|
||||
not (result instanceof AccessModifier and exists(this.getAnAccessModifier()))
|
||||
}
|
||||
|
||||
override predicate isOverridableOrImplementable() {
|
||||
this.getDeclaration().isOverridableOrImplementable()
|
||||
}
|
||||
|
||||
override Accessor getUnboundDeclaration() { accessors(this, _, _, _, result) }
|
||||
|
||||
override Location getALocation() { accessor_location(this, result) }
|
||||
|
||||
@@ -75,7 +75,7 @@ class BlockStmt extends Stmt, @block_stmt {
|
||||
|
||||
/** Holds if this block is the container of the global statements. */
|
||||
predicate isGlobalStatementContainer() {
|
||||
this.getEnclosingCallable().hasQualifiedName("<Program>$.<Main>$")
|
||||
this.getEnclosingCallable().hasQualifiedName("Program.<Main>$")
|
||||
}
|
||||
|
||||
override Stmt stripSingletonBlocks() {
|
||||
|
||||
@@ -12,7 +12,12 @@ private class TypeRef extends @typeref {
|
||||
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
Type getReferencedType() { typeref_type(this, result) }
|
||||
Type getReferencedType() {
|
||||
typeref_type(this, result)
|
||||
or
|
||||
not typeref_type(this, _) and
|
||||
result instanceof UnknownType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ class MainMethod extends Method {
|
||||
(
|
||||
this.hasName("Main")
|
||||
or
|
||||
this.hasQualifiedName("<Program>$", "<Main>$")
|
||||
this.hasQualifiedName("Program.<Main>$")
|
||||
) and
|
||||
this.isStatic() and
|
||||
(this.getReturnType() instanceof VoidType or this.getReturnType() instanceof IntType) and
|
||||
|
||||
@@ -241,7 +241,7 @@ module ControlFlow {
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
|
||||
/** Gets the enclosing callable of this control flow node. */
|
||||
Callable getEnclosingCallable() { none() }
|
||||
final Callable getEnclosingCallable() { result = getNodeCfgScope(this) }
|
||||
}
|
||||
|
||||
/** Provides different types of control flow nodes. */
|
||||
@@ -253,8 +253,6 @@ module ControlFlow {
|
||||
|
||||
override BasicBlocks::EntryBlock getBasicBlock() { result = Node.super.getBasicBlock() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
private Assignable getAssignable() { this = TEntryNode(result) }
|
||||
|
||||
override Location getLocation() {
|
||||
@@ -283,8 +281,6 @@ module ControlFlow {
|
||||
result = Node.super.getBasicBlock()
|
||||
}
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
override Location getLocation() { result = scope.getLocation() }
|
||||
|
||||
override string toString() {
|
||||
@@ -309,8 +305,6 @@ module ControlFlow {
|
||||
|
||||
override BasicBlocks::ExitBlock getBasicBlock() { result = Node.super.getBasicBlock() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
override Location getLocation() { result = scope.getLocation() }
|
||||
|
||||
override string toString() { result = "exit " + scope }
|
||||
@@ -327,14 +321,7 @@ module ControlFlow {
|
||||
private Splits splits;
|
||||
private ControlFlowElement cfe;
|
||||
|
||||
ElementNode() { this = TElementNode(cfe, splits) }
|
||||
|
||||
override Callable getEnclosingCallable() {
|
||||
result = cfe.getEnclosingCallable()
|
||||
or
|
||||
result =
|
||||
this.getASplit().(Splitting::InitializerSplitting::InitializerSplit).getConstructor()
|
||||
}
|
||||
ElementNode() { this = TElementNode(_, cfe, splits) }
|
||||
|
||||
override ControlFlowElement getElement() { result = cfe }
|
||||
|
||||
|
||||
@@ -1086,7 +1086,7 @@ module Internal {
|
||||
*/
|
||||
private Callable customNullCheck(Parameter p, BooleanValue retVal, boolean isNull) {
|
||||
result.getReturnType() instanceof BoolType and
|
||||
not result.(Virtualizable).isOverridableOrImplementable() and
|
||||
not result.(Overridable).isOverridableOrImplementable() and
|
||||
p.getCallable() = result and
|
||||
not p.isParams() and
|
||||
p.getType() = any(Type t | t instanceof RefType or t instanceof NullableType) and
|
||||
|
||||
@@ -342,7 +342,7 @@ private predicate succExitSplits(
|
||||
ControlFlowElement pred, Splits predSplits, CfgScope succ, SuccessorType t
|
||||
) {
|
||||
exists(Reachability::SameSplitsBlock b, Completion c | pred = b.getAnElement() |
|
||||
b.isReachable(predSplits) and
|
||||
b.isReachable(succ, predSplits) and
|
||||
t = getAMatchingSuccessorType(c) and
|
||||
scopeLast(succ, pred, c) and
|
||||
forall(SplitImpl predSplit | predSplit = predSplits.getASplit() |
|
||||
@@ -399,7 +399,7 @@ private module SuccSplits {
|
||||
ControlFlowElement succ, Completion c
|
||||
) {
|
||||
pred = b.getAnElement() and
|
||||
b.isReachable(predSplits) and
|
||||
b.isReachable(_, predSplits) and
|
||||
succ(pred, succ, c)
|
||||
}
|
||||
|
||||
@@ -728,12 +728,12 @@ private module Reachability {
|
||||
* Holds if the elements of this block are reachable from a callable entry
|
||||
* point, with the splits `splits`.
|
||||
*/
|
||||
predicate isReachable(Splits splits) {
|
||||
predicate isReachable(CfgScope scope, Splits splits) {
|
||||
// Base case
|
||||
succEntrySplits(_, this, splits, _)
|
||||
succEntrySplits(scope, this, splits, _)
|
||||
or
|
||||
// Recursive case
|
||||
exists(SameSplitsBlock pred, Splits predSplits | pred.isReachable(predSplits) |
|
||||
exists(SameSplitsBlock pred, Splits predSplits | pred.isReachable(scope, predSplits) |
|
||||
this = pred.getASuccessor(predSplits, splits)
|
||||
)
|
||||
}
|
||||
@@ -791,18 +791,20 @@ private module Cached {
|
||||
newtype TCfgNode =
|
||||
TEntryNode(CfgScope scope) { succEntrySplits(scope, _, _, _) } or
|
||||
TAnnotatedExitNode(CfgScope scope, boolean normal) {
|
||||
exists(Reachability::SameSplitsBlock b, SuccessorType t | b.isReachable(_) |
|
||||
exists(Reachability::SameSplitsBlock b, SuccessorType t | b.isReachable(scope, _) |
|
||||
succExitSplits(b.getAnElement(), _, scope, t) and
|
||||
if isAbnormalExitType(t) then normal = false else normal = true
|
||||
)
|
||||
} or
|
||||
TExitNode(CfgScope scope) {
|
||||
exists(Reachability::SameSplitsBlock b | b.isReachable(_) |
|
||||
exists(Reachability::SameSplitsBlock b | b.isReachable(scope, _) |
|
||||
succExitSplits(b.getAnElement(), _, scope, _)
|
||||
)
|
||||
} or
|
||||
TElementNode(ControlFlowElement cfe, Splits splits) {
|
||||
exists(Reachability::SameSplitsBlock b | b.isReachable(splits) | cfe = b.getAnElement())
|
||||
TElementNode(CfgScope scope, ControlFlowElement cfe, Splits splits) {
|
||||
exists(Reachability::SameSplitsBlock b | b.isReachable(scope, splits) |
|
||||
cfe = b.getAnElement()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a successor node of a given flow type, if any. */
|
||||
@@ -810,24 +812,24 @@ private module Cached {
|
||||
TCfgNode getASuccessor(TCfgNode pred, SuccessorType t) {
|
||||
// Callable entry node -> callable body
|
||||
exists(ControlFlowElement succElement, Splits succSplits, CfgScope scope |
|
||||
result = TElementNode(succElement, succSplits) and
|
||||
result = TElementNode(scope, succElement, succSplits) and
|
||||
pred = TEntryNode(scope) and
|
||||
succEntrySplits(scope, succElement, succSplits, t)
|
||||
)
|
||||
or
|
||||
exists(ControlFlowElement predElement, Splits predSplits |
|
||||
pred = TElementNode(predElement, predSplits)
|
||||
exists(CfgScope scope, ControlFlowElement predElement, Splits predSplits |
|
||||
pred = TElementNode(pragma[only_bind_into](scope), predElement, predSplits)
|
||||
|
|
||||
// Element node -> callable exit (annotated)
|
||||
exists(CfgScope scope, boolean normal |
|
||||
result = TAnnotatedExitNode(scope, normal) and
|
||||
exists(boolean normal |
|
||||
result = TAnnotatedExitNode(pragma[only_bind_into](scope), normal) and
|
||||
succExitSplits(predElement, predSplits, scope, t) and
|
||||
if isAbnormalExitType(t) then normal = false else normal = true
|
||||
)
|
||||
or
|
||||
// Element node -> element node
|
||||
exists(ControlFlowElement succElement, Splits succSplits, Completion c |
|
||||
result = TElementNode(succElement, succSplits)
|
||||
result = TElementNode(pragma[only_bind_into](scope), succElement, succSplits)
|
||||
|
|
||||
succSplits(predElement, predSplits, succElement, succSplits, c) and
|
||||
t = getAMatchingSuccessorType(c)
|
||||
@@ -853,6 +855,23 @@ private module Cached {
|
||||
*/
|
||||
cached
|
||||
ControlFlowElement getAControlFlowExitNode(ControlFlowElement cfe) { last(cfe, result, _) }
|
||||
|
||||
/**
|
||||
* Gets the CFG scope of node `n`. Unlike `getCfgScope`, this predicate
|
||||
* is calculated based on reachability from an entry node, and it may
|
||||
* yield different results for AST elements that are split into multiple
|
||||
* scopes.
|
||||
*/
|
||||
cached
|
||||
CfgScope getNodeCfgScope(TCfgNode n) {
|
||||
n = TEntryNode(result)
|
||||
or
|
||||
n = TAnnotatedExitNode(result, _)
|
||||
or
|
||||
n = TExitNode(result)
|
||||
or
|
||||
n = TElementNode(result, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
@@ -938,14 +957,45 @@ module Consistency {
|
||||
not split.hasEntry(pred, succ, c)
|
||||
}
|
||||
|
||||
private class SimpleSuccessorType extends SuccessorType {
|
||||
SimpleSuccessorType() {
|
||||
this = getAMatchingSuccessorType(any(Completion c | completionIsSimple(c)))
|
||||
}
|
||||
}
|
||||
|
||||
private class NormalSuccessorType extends SuccessorType {
|
||||
NormalSuccessorType() {
|
||||
this = getAMatchingSuccessorType(any(Completion c | completionIsNormal(c)))
|
||||
}
|
||||
}
|
||||
|
||||
query predicate multipleSuccessors(Node node, SuccessorType t, Node successor) {
|
||||
not node instanceof TEntryNode and
|
||||
strictcount(getASuccessor(node, t)) > 1 and
|
||||
successor = getASuccessor(node, t)
|
||||
successor = getASuccessor(node, t) and
|
||||
// allow for functions with multiple bodies
|
||||
not (t instanceof SimpleSuccessorType and node instanceof TEntryNode)
|
||||
}
|
||||
|
||||
query predicate simpleAndNormalSuccessors(
|
||||
Node node, NormalSuccessorType t1, SimpleSuccessorType t2, Node succ1, Node succ2
|
||||
) {
|
||||
t1 != t2 and
|
||||
succ1 = getASuccessor(node, t1) and
|
||||
succ2 = getASuccessor(node, t2)
|
||||
}
|
||||
|
||||
query predicate deadEnd(Node node) {
|
||||
not node instanceof TExitNode and
|
||||
not exists(getASuccessor(node, _))
|
||||
}
|
||||
|
||||
query predicate nonUniqueSplitKind(SplitImpl split, SplitKind sk) {
|
||||
sk = split.getKind() and
|
||||
strictcount(split.getKind()) > 1
|
||||
}
|
||||
|
||||
query predicate nonUniqueListOrder(SplitKind sk, int ord) {
|
||||
ord = sk.getListOrder() and
|
||||
strictcount(sk.getListOrder()) > 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ module InitializerSplitting {
|
||||
*
|
||||
* respectively.
|
||||
*/
|
||||
class InitializerSplit extends Split, TInitializerSplit {
|
||||
private class InitializerSplit extends Split, TInitializerSplit {
|
||||
private Constructor c;
|
||||
|
||||
InitializerSplit() { this = TInitializerSplit(c) }
|
||||
|
||||
@@ -78,7 +78,6 @@ private import internal.DataFlowPublic
|
||||
private import internal.FlowSummaryImpl::Public
|
||||
private import internal.FlowSummaryImpl::Private::External
|
||||
private import internal.FlowSummaryImplSpecific
|
||||
private import semmle.code.csharp.dispatch.OverridableCallable
|
||||
|
||||
/**
|
||||
* A module importing the frameworks that provide external flow data,
|
||||
@@ -92,6 +91,17 @@ private module Frameworks {
|
||||
private import semmle.code.csharp.frameworks.ServiceStack
|
||||
private import semmle.code.csharp.frameworks.Sql
|
||||
private import semmle.code.csharp.frameworks.EntityFramework
|
||||
private import semmle.code.csharp.frameworks.system.Text
|
||||
private import semmle.code.csharp.frameworks.system.Net
|
||||
private import semmle.code.csharp.frameworks.system.Web
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
private import semmle.code.csharp.frameworks.system.web.ui.WebControls
|
||||
private import semmle.code.csharp.frameworks.JsonNET
|
||||
private import semmle.code.csharp.frameworks.system.IO
|
||||
private import semmle.code.csharp.frameworks.system.io.Compression
|
||||
private import semmle.code.csharp.frameworks.system.Xml
|
||||
private import semmle.code.csharp.frameworks.system.threading.Tasks
|
||||
private import semmle.code.csharp.frameworks.system.runtime.CompilerServices
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +272,7 @@ module CsvValidation {
|
||||
not name.regexpMatch("[a-zA-Z0-9_<>,]*") and
|
||||
msg = "Dubious member name \"" + name + "\" in " + pred + " model."
|
||||
or
|
||||
not signature.regexpMatch("|\\([a-zA-Z0-9_<>\\.\\+,\\[\\]]*\\)") and
|
||||
not signature.regexpMatch("|\\([a-zA-Z0-9_<>\\.\\+\\*,\\[\\]]*\\)") and
|
||||
msg = "Dubious signature \"" + signature + "\" in " + pred + " model."
|
||||
or
|
||||
not ext.regexpMatch("|Attribute") and
|
||||
@@ -348,16 +358,17 @@ private class UnboundValueOrRefType extends ValueOrRefType {
|
||||
}
|
||||
}
|
||||
|
||||
private class UnboundCallable extends Callable {
|
||||
/** An unbound callable. */
|
||||
class UnboundCallable extends Callable {
|
||||
UnboundCallable() { this.isUnboundDeclaration() }
|
||||
|
||||
/**
|
||||
* Holds if this unbound callable overrides or implements (transitively)
|
||||
* `that` unbound callable.
|
||||
*/
|
||||
predicate overridesOrImplementsUnbound(UnboundCallable that) {
|
||||
exists(Callable c |
|
||||
this.(Virtualizable).overridesOrImplementsOrEquals(c) or
|
||||
this = c.(OverridableCallable).getAnUltimateImplementor() or
|
||||
this = c.(OverridableCallable).getAnOverrider+()
|
||||
|
|
||||
this != c and
|
||||
this.(Overridable).overridesOrImplements(c) and
|
||||
that = c.getUnboundDeclaration()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
import csharp
|
||||
private import internal.FlowSummaryImpl as Impl
|
||||
private import internal.DataFlowDispatch
|
||||
private import internal.DataFlowDispatch as DataFlowDispatch
|
||||
|
||||
class ParameterPosition = DataFlowDispatch::ParameterPosition;
|
||||
|
||||
class ArgumentPosition = DataFlowDispatch::ArgumentPosition;
|
||||
|
||||
// import all instances below
|
||||
private module Summaries {
|
||||
@@ -14,7 +18,27 @@ class SummaryComponent = Impl::Public::SummaryComponent;
|
||||
|
||||
/** Provides predicates for constructing summary components. */
|
||||
module SummaryComponent {
|
||||
import Impl::Public::SummaryComponent
|
||||
private import Impl::Public::SummaryComponent as SummaryComponentInternal
|
||||
|
||||
predicate content = SummaryComponentInternal::content/1;
|
||||
|
||||
/** Gets a summary component for parameter `i`. */
|
||||
SummaryComponent parameter(int i) {
|
||||
exists(ArgumentPosition pos |
|
||||
result = SummaryComponentInternal::parameter(pos) and
|
||||
i = pos.getPosition()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a summary component for argument `i`. */
|
||||
SummaryComponent argument(int i) {
|
||||
exists(ParameterPosition pos |
|
||||
result = SummaryComponentInternal::argument(pos) and
|
||||
i = pos.getPosition()
|
||||
)
|
||||
}
|
||||
|
||||
predicate return = SummaryComponentInternal::return/1;
|
||||
|
||||
/** Gets a summary component that represents a qualifier. */
|
||||
SummaryComponent qualifier() { result = argument(-1) }
|
||||
@@ -33,14 +57,14 @@ module SummaryComponent {
|
||||
}
|
||||
|
||||
/** Gets a summary component that represents the return value of a call. */
|
||||
SummaryComponent return() { result = return(any(NormalReturnKind rk)) }
|
||||
SummaryComponent return() { result = return(any(DataFlowDispatch::NormalReturnKind rk)) }
|
||||
|
||||
/** Gets a summary component that represents a jump to `c`. */
|
||||
SummaryComponent jump(Callable c) {
|
||||
result =
|
||||
return(any(JumpReturnKind jrk |
|
||||
return(any(DataFlowDispatch::JumpReturnKind jrk |
|
||||
jrk.getTarget() = c.getUnboundDeclaration() and
|
||||
jrk.getTargetReturnKind() instanceof NormalReturnKind
|
||||
jrk.getTargetReturnKind() instanceof DataFlowDispatch::NormalReturnKind
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -49,7 +73,16 @@ class SummaryComponentStack = Impl::Public::SummaryComponentStack;
|
||||
|
||||
/** Provides predicates for constructing stacks of summary components. */
|
||||
module SummaryComponentStack {
|
||||
import Impl::Public::SummaryComponentStack
|
||||
private import Impl::Public::SummaryComponentStack as SummaryComponentStackInternal
|
||||
|
||||
predicate singleton = SummaryComponentStackInternal::singleton/1;
|
||||
|
||||
predicate push = SummaryComponentStackInternal::push/2;
|
||||
|
||||
/** Gets a singleton stack for argument `i`. */
|
||||
SummaryComponentStack argument(int i) { result = singleton(SummaryComponent::argument(i)) }
|
||||
|
||||
predicate return = SummaryComponentStackInternal::return/1;
|
||||
|
||||
/** Gets a singleton stack representing a qualifier. */
|
||||
SummaryComponentStack qualifier() { result = singleton(SummaryComponent::qualifier()) }
|
||||
@@ -84,12 +117,12 @@ private class SummarizedCallableDefaultClearsContent extends Impl::Public::Summa
|
||||
}
|
||||
|
||||
// By default, we assume that all stores into arguments are definite
|
||||
override predicate clearsContent(int i, DataFlow::Content content) {
|
||||
override predicate clearsContent(ParameterPosition pos, DataFlow::Content content) {
|
||||
exists(SummaryComponentStack output |
|
||||
this.propagatesFlow(_, output, _) and
|
||||
output.drop(_) =
|
||||
SummaryComponentStack::push(SummaryComponent::content(content),
|
||||
SummaryComponentStack::argument(i)) and
|
||||
SummaryComponentStack::argument(pos.getPosition())) and
|
||||
not content instanceof DataFlow::ElementContent
|
||||
)
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import DataFlowPublic
|
||||
private import DataFlowPrivate
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
private import semmle.code.csharp.dispatch.Dispatch
|
||||
private import semmle.code.csharp.dispatch.RuntimeCallable
|
||||
@@ -13,7 +13,7 @@ private import semmle.code.csharp.frameworks.system.Collections
|
||||
private import semmle.code.csharp.frameworks.system.collections.Generic
|
||||
|
||||
private predicate summarizedCallable(DataFlowCallable c) {
|
||||
c instanceof SummarizedCallable
|
||||
c instanceof FlowSummary::SummarizedCallable
|
||||
or
|
||||
FlowSummaryImpl::Private::summaryReturnNode(_, TJumpReturnKind(c, _))
|
||||
or
|
||||
@@ -108,13 +108,27 @@ private module Cached {
|
||||
// No need to include calls that are compiled from source
|
||||
not call.getImplementation().getMethod().compiledFromSource()
|
||||
} or
|
||||
TSummaryCall(SummarizedCallable c, Node receiver) {
|
||||
TSummaryCall(FlowSummary::SummarizedCallable c, Node receiver) {
|
||||
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
|
||||
}
|
||||
|
||||
/** Gets a viable run-time target for the call `call`. */
|
||||
cached
|
||||
DataFlowCallable viableCallable(DataFlowCall call) { result = call.getARuntimeTarget() }
|
||||
|
||||
private int parameterPosition() {
|
||||
result =
|
||||
[
|
||||
-1, any(Parameter p).getPosition(),
|
||||
ImplicitCapturedParameterNodeImpl::getParameterPosition(_)
|
||||
]
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TParameterPosition = MkParameterPosition(int i) { i = parameterPosition() }
|
||||
|
||||
cached
|
||||
newtype TArgumentPosition = MkArgumentPosition(int i) { i = parameterPosition() }
|
||||
}
|
||||
|
||||
import Cached
|
||||
@@ -388,7 +402,7 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
|
||||
* the method `Select`.
|
||||
*/
|
||||
class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
|
||||
private SummarizedCallable c;
|
||||
private FlowSummary::SummarizedCallable c;
|
||||
private Node receiver;
|
||||
|
||||
SummaryCall() { this = TSummaryCall(c, receiver) }
|
||||
@@ -410,3 +424,37 @@ class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
|
||||
|
||||
override Location getLocation() { result = c.getLocation() }
|
||||
}
|
||||
|
||||
/** A parameter position represented by an integer. */
|
||||
class ParameterPosition extends MkParameterPosition {
|
||||
private int i;
|
||||
|
||||
ParameterPosition() { this = MkParameterPosition(i) }
|
||||
|
||||
/** Gets the underlying integer. */
|
||||
int getPosition() { result = i }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() { result = i.toString() }
|
||||
}
|
||||
|
||||
/** An argument position represented by an integer. */
|
||||
class ArgumentPosition extends MkArgumentPosition {
|
||||
private int i;
|
||||
|
||||
ArgumentPosition() { this = MkArgumentPosition(i) }
|
||||
|
||||
/** Gets the underlying integer. */
|
||||
int getPosition() { result = i }
|
||||
|
||||
/** Gets a textual representation of this position. */
|
||||
string toString() { result = i.toString() }
|
||||
}
|
||||
|
||||
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
|
||||
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
|
||||
exists(int i |
|
||||
ppos = MkParameterPosition(i) and
|
||||
apos = MkArgumentPosition(i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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()) }
|
||||
}
|
||||
@@ -1447,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),
|
||||
@@ -2142,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),
|
||||
@@ -2908,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),
|
||||
@@ -2992,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 }
|
||||
|
||||
@@ -3639,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))
|
||||
)
|
||||
}
|
||||
@@ -3686,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
|
||||
@@ -3712,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
|
||||
@@ -4441,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)
|
||||
}
|
||||
|
||||
@@ -4467,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)
|
||||
|
|
||||
@@ -4633,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 |
|
||||
@@ -4661,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 }
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ private import DataFlowDispatch
|
||||
private import DataFlowImplCommon
|
||||
private import ControlFlowReachability
|
||||
private import FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dataflow.FlowSummary as FlowSummary
|
||||
private import semmle.code.csharp.Conversion
|
||||
private import semmle.code.csharp.dataflow.internal.SsaImpl as SsaImpl
|
||||
private import semmle.code.csharp.ExprOrStmtParent
|
||||
@@ -22,7 +22,14 @@ private import semmle.code.csharp.frameworks.system.threading.Tasks
|
||||
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) {
|
||||
exists(int i | pos = MkParameterPosition(i) and p.isParameterOf(c, i))
|
||||
}
|
||||
|
||||
/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */
|
||||
predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) {
|
||||
exists(int i | pos = MkArgumentPosition(i) and arg.argumentOf(c, i))
|
||||
}
|
||||
|
||||
abstract class NodeImpl extends Node {
|
||||
/** Do not call: use `getEnclosingCallable()` instead. */
|
||||
@@ -494,9 +501,12 @@ private predicate fieldOrPropertyStore(Expr e, Content c, Expr src, Expr q, bool
|
||||
f.isFieldLike() and
|
||||
f instanceof InstanceFieldOrProperty
|
||||
or
|
||||
exists(SummarizedCallable callable, FlowSummaryImpl::Public::SummaryComponentStack input |
|
||||
exists(
|
||||
FlowSummary::SummarizedCallable callable,
|
||||
FlowSummaryImpl::Public::SummaryComponentStack input
|
||||
|
|
||||
callable.propagatesFlow(input, _, _) and
|
||||
input.contains(SummaryComponent::content(f.getContent()))
|
||||
input.contains(FlowSummary::SummaryComponent::content(f.getContent()))
|
||||
)
|
||||
)
|
||||
|
|
||||
@@ -718,7 +728,7 @@ private module Cached {
|
||||
cfn.getElement() = fla.getQualifier()
|
||||
)
|
||||
} or
|
||||
TSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
||||
TSummaryNode(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
|
||||
FlowSummaryImpl::Private::summaryNodeRange(c, state)
|
||||
} or
|
||||
TParamsArgumentNode(ControlFlow::Node callCfn) {
|
||||
@@ -749,7 +759,8 @@ private module Cached {
|
||||
newtype TContent =
|
||||
TFieldContent(Field f) { f.isUnboundDeclaration() } or
|
||||
TPropertyContent(Property p) { p.isUnboundDeclaration() } or
|
||||
TElementContent()
|
||||
TElementContent() or
|
||||
TSyntheticFieldContent(SyntheticField f)
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate commonSubTypeGeneral(DataFlowTypeOrUnifiable t1, RelevantDataFlowType t2) {
|
||||
@@ -794,11 +805,13 @@ predicate nodeIsHidden(Node n) {
|
||||
exists(Parameter p | p = n.(ParameterNode).getParameter() |
|
||||
not p.fromSource()
|
||||
or
|
||||
p.getCallable() instanceof SummarizedCallable
|
||||
p.getCallable() instanceof FlowSummary::SummarizedCallable
|
||||
)
|
||||
or
|
||||
n =
|
||||
TInstanceParameterNode(any(Callable c | not c.fromSource() or c instanceof SummarizedCallable))
|
||||
TInstanceParameterNode(any(Callable c |
|
||||
not c.fromSource() or c instanceof FlowSummary::SummarizedCallable
|
||||
))
|
||||
or
|
||||
n instanceof YieldReturnNode
|
||||
or
|
||||
@@ -1131,7 +1144,10 @@ private module ArgumentNodes {
|
||||
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
|
||||
|
||||
override predicate argumentOf(DataFlowCall call, int pos) {
|
||||
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
|
||||
exists(ArgumentPosition apos |
|
||||
FlowSummaryImpl::Private::summaryArgumentNode(call, this, apos) and
|
||||
apos.getPosition() = pos
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1421,7 +1437,7 @@ import OutNodes
|
||||
|
||||
/** A data-flow node used to model flow summaries. */
|
||||
private class SummaryNode extends NodeImpl, TSummaryNode {
|
||||
private SummarizedCallable c;
|
||||
private FlowSummary::SummarizedCallable c;
|
||||
private FlowSummaryImpl::Private::SummaryNodeState state;
|
||||
|
||||
SummaryNode() { this = TSummaryNode(c, state) }
|
||||
@@ -1764,6 +1780,10 @@ private class DataFlowNullType extends DataFlowType {
|
||||
}
|
||||
}
|
||||
|
||||
private class DataFlowUnknownType extends DataFlowType {
|
||||
DataFlowUnknownType() { this = Gvn::getGlobalValueNumber(any(UnknownType ut)) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
|
||||
* a node of type `t1` to a node of type `t2`.
|
||||
@@ -1783,6 +1803,10 @@ predicate compatibleTypes(DataFlowType t1, DataFlowType t2) {
|
||||
t1 instanceof Gvn::TypeParameterGvnType
|
||||
or
|
||||
t2 instanceof Gvn::TypeParameterGvnType
|
||||
or
|
||||
t1 instanceof DataFlowUnknownType
|
||||
or
|
||||
t2 instanceof DataFlowUnknownType
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2023,3 +2047,12 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves
|
||||
predicate allowParameterReturnInSelf(ParameterNode p) {
|
||||
FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(p)
|
||||
}
|
||||
|
||||
/** A synthetic field. */
|
||||
abstract class SyntheticField extends string {
|
||||
bindingset[this]
|
||||
SyntheticField() { any() }
|
||||
|
||||
/** Gets the type of this synthetic field. */
|
||||
Type getType() { result instanceof ObjectType }
|
||||
}
|
||||
|
||||
@@ -224,6 +224,18 @@ class FieldContent extends Content, TFieldContent {
|
||||
deprecated override Gvn::GvnType getType() { result = Gvn::getGlobalValueNumber(f.getType()) }
|
||||
}
|
||||
|
||||
/** A reference to a synthetic field. */
|
||||
class SyntheticFieldContent extends Content, TSyntheticFieldContent {
|
||||
private SyntheticField f;
|
||||
|
||||
SyntheticFieldContent() { this = TSyntheticFieldContent(f) }
|
||||
|
||||
/** Gets the underlying synthetic field. */
|
||||
SyntheticField getField() { result = f }
|
||||
|
||||
override string toString() { result = "synthetic " + f.toString() }
|
||||
}
|
||||
|
||||
/** A reference to a property. */
|
||||
class PropertyContent extends Content, TPropertyContent {
|
||||
private Property p;
|
||||
|
||||
@@ -12,7 +12,6 @@ private import semmle.code.csharp.dataflow.CallContext
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowDispatch
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.csharp.dataflow.internal.DataFlowPublic
|
||||
private import semmle.code.csharp.dataflow.FlowSummary
|
||||
private import semmle.code.csharp.dispatch.Dispatch
|
||||
private import semmle.code.csharp.frameworks.system.linq.Expressions
|
||||
|
||||
|
||||
@@ -26,9 +26,13 @@ module Public {
|
||||
string toString() {
|
||||
exists(Content c | this = TContentSummaryComponent(c) and result = c.toString())
|
||||
or
|
||||
exists(int i | this = TParameterSummaryComponent(i) and result = "parameter " + i)
|
||||
exists(ArgumentPosition pos |
|
||||
this = TParameterSummaryComponent(pos) and result = "parameter " + pos
|
||||
)
|
||||
or
|
||||
exists(int i | this = TArgumentSummaryComponent(i) and result = "argument " + i)
|
||||
exists(ParameterPosition pos |
|
||||
this = TArgumentSummaryComponent(pos) and result = "argument " + pos
|
||||
)
|
||||
or
|
||||
exists(ReturnKind rk | this = TReturnSummaryComponent(rk) and result = "return (" + rk + ")")
|
||||
}
|
||||
@@ -39,11 +43,11 @@ module Public {
|
||||
/** Gets a summary component for content `c`. */
|
||||
SummaryComponent content(Content c) { result = TContentSummaryComponent(c) }
|
||||
|
||||
/** Gets a summary component for parameter `i`. */
|
||||
SummaryComponent parameter(int i) { result = TParameterSummaryComponent(i) }
|
||||
/** Gets a summary component for a parameter at position `pos`. */
|
||||
SummaryComponent parameter(ArgumentPosition pos) { result = TParameterSummaryComponent(pos) }
|
||||
|
||||
/** Gets a summary component for argument `i`. */
|
||||
SummaryComponent argument(int i) { result = TArgumentSummaryComponent(i) }
|
||||
/** Gets a summary component for an argument at position `pos`. */
|
||||
SummaryComponent argument(ParameterPosition pos) { result = TArgumentSummaryComponent(pos) }
|
||||
|
||||
/** Gets a summary component for a return of kind `rk`. */
|
||||
SummaryComponent return(ReturnKind rk) { result = TReturnSummaryComponent(rk) }
|
||||
@@ -120,8 +124,10 @@ module Public {
|
||||
result = TConsSummaryComponentStack(head, tail)
|
||||
}
|
||||
|
||||
/** Gets a singleton stack for argument `i`. */
|
||||
SummaryComponentStack argument(int i) { result = singleton(SummaryComponent::argument(i)) }
|
||||
/** Gets a singleton stack for an argument at position `pos`. */
|
||||
SummaryComponentStack argument(ParameterPosition pos) {
|
||||
result = singleton(SummaryComponent::argument(pos))
|
||||
}
|
||||
|
||||
/** Gets a singleton stack representing a return of kind `rk`. */
|
||||
SummaryComponentStack return(ReturnKind rk) { result = singleton(SummaryComponent::return(rk)) }
|
||||
@@ -137,9 +143,15 @@ module Public {
|
||||
or
|
||||
noComponentSpecificCsv(sc) and
|
||||
(
|
||||
exists(int i | sc = TParameterSummaryComponent(i) and result = "Parameter[" + i + "]")
|
||||
exists(ArgumentPosition pos |
|
||||
sc = TParameterSummaryComponent(pos) and
|
||||
result = "Parameter[" + getArgumentPositionCsv(pos) + "]"
|
||||
)
|
||||
or
|
||||
exists(int i | sc = TArgumentSummaryComponent(i) and result = "Argument[" + i + "]")
|
||||
exists(ParameterPosition pos |
|
||||
sc = TArgumentSummaryComponent(pos) and
|
||||
result = "Argument[" + getParameterPositionCsv(pos) + "]"
|
||||
)
|
||||
or
|
||||
sc = TReturnSummaryComponent(getReturnValueKind()) and result = "ReturnValue"
|
||||
)
|
||||
@@ -201,10 +213,10 @@ module Public {
|
||||
|
||||
/**
|
||||
* Holds if values stored inside `content` are cleared on objects passed as
|
||||
* the `i`th argument to this callable.
|
||||
* arguments at position `pos` to this callable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate clearsContent(int i, Content content) { none() }
|
||||
predicate clearsContent(ParameterPosition pos, Content content) { none() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,11 +229,11 @@ module Private {
|
||||
|
||||
newtype TSummaryComponent =
|
||||
TContentSummaryComponent(Content c) or
|
||||
TParameterSummaryComponent(int i) { parameterPosition(i) } or
|
||||
TArgumentSummaryComponent(int i) { parameterPosition(i) } or
|
||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||
TReturnSummaryComponent(ReturnKind rk)
|
||||
|
||||
private TSummaryComponent thisParam() {
|
||||
private TParameterSummaryComponent thisParam() {
|
||||
result = TParameterSummaryComponent(instanceParameterPosition())
|
||||
}
|
||||
|
||||
@@ -285,9 +297,9 @@ module Private {
|
||||
|
||||
/**
|
||||
* Holds if `c` has a flow summary from `input` to `arg`, where `arg`
|
||||
* writes to (contents of) the `i`th argument, and `c` has a
|
||||
* value-preserving flow summary from the `i`th argument to a return value
|
||||
* (`return`).
|
||||
* writes to (contents of) arguments at position `pos`, and `c` has a
|
||||
* value-preserving flow summary from the arguments at position `pos`
|
||||
* to a return value (`return`).
|
||||
*
|
||||
* In such a case, we derive flow from `input` to (contents of) the return
|
||||
* value.
|
||||
@@ -302,10 +314,10 @@ module Private {
|
||||
SummarizedCallable c, SummaryComponentStack input, SummaryComponentStack arg,
|
||||
SummaryComponentStack return, boolean preservesValue
|
||||
) {
|
||||
exists(int i |
|
||||
exists(ParameterPosition pos |
|
||||
summary(c, input, arg, preservesValue) and
|
||||
isContentOfArgument(arg, i) and
|
||||
summary(c, SummaryComponentStack::singleton(TArgumentSummaryComponent(i)), return, true) and
|
||||
isContentOfArgument(arg, pos) and
|
||||
summary(c, SummaryComponentStack::argument(pos), return, true) and
|
||||
return.bottom() = TReturnSummaryComponent(_)
|
||||
)
|
||||
}
|
||||
@@ -330,10 +342,10 @@ module Private {
|
||||
s.head() = TParameterSummaryComponent(_) and exists(s.tail())
|
||||
}
|
||||
|
||||
private predicate isContentOfArgument(SummaryComponentStack s, int i) {
|
||||
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail(), i)
|
||||
private predicate isContentOfArgument(SummaryComponentStack s, ParameterPosition pos) {
|
||||
s.head() = TContentSummaryComponent(_) and isContentOfArgument(s.tail(), pos)
|
||||
or
|
||||
s = TSingletonSummaryComponentStack(TArgumentSummaryComponent(i))
|
||||
s = SummaryComponentStack::argument(pos)
|
||||
}
|
||||
|
||||
private predicate outputState(SummarizedCallable c, SummaryComponentStack s) {
|
||||
@@ -364,8 +376,8 @@ module Private {
|
||||
private newtype TSummaryNodeState =
|
||||
TSummaryNodeInputState(SummaryComponentStack s) { inputState(_, s) } or
|
||||
TSummaryNodeOutputState(SummaryComponentStack s) { outputState(_, s) } or
|
||||
TSummaryNodeClearsContentState(int i, boolean post) {
|
||||
any(SummarizedCallable sc).clearsContent(i, _) and post in [false, true]
|
||||
TSummaryNodeClearsContentState(ParameterPosition pos, boolean post) {
|
||||
any(SummarizedCallable sc).clearsContent(pos, _) and post in [false, true]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,21 +426,23 @@ module Private {
|
||||
result = "to write: " + s
|
||||
)
|
||||
or
|
||||
exists(int i, boolean post, string postStr |
|
||||
this = TSummaryNodeClearsContentState(i, post) and
|
||||
exists(ParameterPosition pos, boolean post, string postStr |
|
||||
this = TSummaryNodeClearsContentState(pos, post) and
|
||||
(if post = true then postStr = " (post)" else postStr = "") and
|
||||
result = "clear: " + i + postStr
|
||||
result = "clear: " + pos + postStr
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `state` represents having read the `i`th argument for `c`. In this case
|
||||
* we are not synthesizing a data-flow node, but instead assume that a relevant
|
||||
* parameter node already exists.
|
||||
* Holds if `state` represents having read from a parameter at position
|
||||
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
|
||||
* but instead assume that a relevant parameter node already exists.
|
||||
*/
|
||||
private predicate parameterReadState(SummarizedCallable c, SummaryNodeState state, int i) {
|
||||
state.isInputState(c, SummaryComponentStack::argument(i))
|
||||
private predicate parameterReadState(
|
||||
SummarizedCallable c, SummaryNodeState state, ParameterPosition pos
|
||||
) {
|
||||
state.isInputState(c, SummaryComponentStack::argument(pos))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,9 +455,9 @@ module Private {
|
||||
or
|
||||
state.isOutputState(c, _)
|
||||
or
|
||||
exists(int i |
|
||||
c.clearsContent(i, _) and
|
||||
state = TSummaryNodeClearsContentState(i, _)
|
||||
exists(ParameterPosition pos |
|
||||
c.clearsContent(pos, _) and
|
||||
state = TSummaryNodeClearsContentState(pos, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -452,9 +466,9 @@ module Private {
|
||||
exists(SummaryNodeState state | state.isInputState(c, s) |
|
||||
result = summaryNode(c, state)
|
||||
or
|
||||
exists(int i |
|
||||
parameterReadState(c, state, i) and
|
||||
result.(ParamNode).isParameterOf(c, i)
|
||||
exists(ParameterPosition pos |
|
||||
parameterReadState(c, state, pos) and
|
||||
result.(ParamNode).isParameterOf(c, pos)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -468,20 +482,20 @@ module Private {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a write targets `post`, which is a post-update node for the `i`th
|
||||
* parameter of `c`.
|
||||
* Holds if a write targets `post`, which is a post-update node for a
|
||||
* parameter at position `pos` in `c`.
|
||||
*/
|
||||
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, int i) {
|
||||
post = summaryNodeOutputState(c, SummaryComponentStack::argument(i))
|
||||
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
|
||||
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
|
||||
}
|
||||
|
||||
/** Holds if a parameter node is required for the `i`th parameter of `c`. */
|
||||
predicate summaryParameterNodeRange(SummarizedCallable c, int i) {
|
||||
parameterReadState(c, _, i)
|
||||
/** Holds if a parameter node at position `pos` is required for `c`. */
|
||||
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
|
||||
parameterReadState(c, _, pos)
|
||||
or
|
||||
isParameterPostUpdate(_, c, i)
|
||||
isParameterPostUpdate(_, c, pos)
|
||||
or
|
||||
c.clearsContent(i, _)
|
||||
c.clearsContent(pos, _)
|
||||
}
|
||||
|
||||
private predicate callbackOutput(
|
||||
@@ -493,10 +507,10 @@ module Private {
|
||||
}
|
||||
|
||||
private predicate callbackInput(
|
||||
SummarizedCallable c, SummaryComponentStack s, Node receiver, int i
|
||||
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
|
||||
) {
|
||||
any(SummaryNodeState state).isOutputState(c, s) and
|
||||
s.head() = TParameterSummaryComponent(i) and
|
||||
s.head() = TParameterSummaryComponent(pos) and
|
||||
receiver = summaryNodeInputState(c, s.drop(1))
|
||||
}
|
||||
|
||||
@@ -547,17 +561,17 @@ module Private {
|
||||
result = getReturnType(c, rk)
|
||||
)
|
||||
or
|
||||
exists(int i | head = TParameterSummaryComponent(i) |
|
||||
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
|
||||
result =
|
||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.drop(1))), i)
|
||||
s.drop(1))), pos)
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable c, int i, ParamNode p |
|
||||
n = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and
|
||||
p.isParameterOf(c, i) and
|
||||
exists(SummarizedCallable c, ParameterPosition pos, ParamNode p |
|
||||
n = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
||||
p.isParameterOf(c, pos) and
|
||||
result = getNodeType(p)
|
||||
)
|
||||
}
|
||||
@@ -571,10 +585,10 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if summary node `arg` is the `i`th argument of call `c`. */
|
||||
predicate summaryArgumentNode(DataFlowCall c, Node arg, int i) {
|
||||
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
|
||||
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
|
||||
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
|
||||
callbackInput(callable, s, receiver, i) and
|
||||
callbackInput(callable, s, receiver, pos) and
|
||||
arg = summaryNodeOutputState(callable, s) and
|
||||
c = summaryDataFlowCall(receiver)
|
||||
)
|
||||
@@ -582,12 +596,12 @@ module Private {
|
||||
|
||||
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
|
||||
predicate summaryPostUpdateNode(Node post, Node pre) {
|
||||
exists(SummarizedCallable c, int i |
|
||||
isParameterPostUpdate(post, c, i) and
|
||||
pre.(ParamNode).isParameterOf(c, i)
|
||||
exists(SummarizedCallable c, ParameterPosition pos |
|
||||
isParameterPostUpdate(post, c, pos) and
|
||||
pre.(ParamNode).isParameterOf(c, pos)
|
||||
or
|
||||
pre = summaryNode(c, TSummaryNodeClearsContentState(i, false)) and
|
||||
post = summaryNode(c, TSummaryNodeClearsContentState(i, true))
|
||||
pre = summaryNode(c, TSummaryNodeClearsContentState(pos, false)) and
|
||||
post = summaryNode(c, TSummaryNodeClearsContentState(pos, true))
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable callable, SummaryComponentStack s |
|
||||
@@ -610,13 +624,13 @@ module Private {
|
||||
* node, and back out to `p`.
|
||||
*/
|
||||
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
|
||||
exists(SummarizedCallable c, int i | p.isParameterOf(c, i) |
|
||||
c.clearsContent(i, _)
|
||||
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(c, ppos) |
|
||||
c.clearsContent(ppos, _)
|
||||
or
|
||||
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
|
||||
summary(c, inputContents, outputContents, _) and
|
||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i)) and
|
||||
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(i))
|
||||
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
|
||||
outputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos))
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -641,9 +655,9 @@ module Private {
|
||||
preservesValue = false and not summary(c, inputContents, outputContents, true)
|
||||
)
|
||||
or
|
||||
exists(SummarizedCallable c, int i |
|
||||
pred.(ParamNode).isParameterOf(c, i) and
|
||||
succ = summaryNode(c, TSummaryNodeClearsContentState(i, _)) and
|
||||
exists(SummarizedCallable c, ParameterPosition pos |
|
||||
pred.(ParamNode).isParameterOf(c, pos) and
|
||||
succ = summaryNode(c, TSummaryNodeClearsContentState(pos, _)) and
|
||||
preservesValue = true
|
||||
)
|
||||
}
|
||||
@@ -692,12 +706,20 @@ module Private {
|
||||
* node where field `b` is cleared).
|
||||
*/
|
||||
predicate summaryClearsContent(Node n, Content c) {
|
||||
exists(SummarizedCallable sc, int i |
|
||||
n = summaryNode(sc, TSummaryNodeClearsContentState(i, true)) and
|
||||
sc.clearsContent(i, c)
|
||||
exists(SummarizedCallable sc, ParameterPosition pos |
|
||||
n = summaryNode(sc, TSummaryNodeClearsContentState(pos, true)) and
|
||||
sc.clearsContent(pos, c)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate viableParam(
|
||||
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
|
||||
) {
|
||||
p.isParameterOf(sc, ppos) and
|
||||
sc = viableCallable(call)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared inside a
|
||||
* callable to which `arg` is an argument.
|
||||
@@ -706,18 +728,18 @@ module Private {
|
||||
* `arg` (see comment for `summaryClearsContent`).
|
||||
*/
|
||||
predicate summaryClearsContentArg(ArgNode arg, Content c) {
|
||||
exists(DataFlowCall call, int i |
|
||||
viableCallable(call).(SummarizedCallable).clearsContent(i, c) and
|
||||
arg.argumentOf(call, i)
|
||||
exists(DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, _) and
|
||||
sc.clearsContent(ppos, c)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private ParamNode summaryArgParam(ArgNode arg, ReturnKindExt rk, OutNodeExt out) {
|
||||
exists(DataFlowCall call, int pos, SummarizedCallable callable |
|
||||
arg.argumentOf(call, pos) and
|
||||
viableCallable(call) = callable and
|
||||
result.isParameterOf(callable, pos) and
|
||||
exists(DataFlowCall call, ParameterPosition ppos, SummarizedCallable sc |
|
||||
argumentPositionMatch(call, arg, ppos) and
|
||||
viableParam(call, sc, ppos, result) and
|
||||
out = rk.getAnOutNode(call)
|
||||
)
|
||||
}
|
||||
@@ -795,39 +817,33 @@ module Private {
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as parameter `n`. */
|
||||
predicate parseParam(string c, int n) {
|
||||
predicate parseParam(string c, ArgumentPosition pos) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\]", 1).toInt() = n
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
|
||||
c.regexpCapture("Parameter\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
|
||||
n = [n1 .. n2]
|
||||
)
|
||||
exists(string body |
|
||||
body = c.regexpCapture("Parameter\\[([^\\]]*)\\]", 1) and
|
||||
pos = parseParamBody(body)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as argument `n`. */
|
||||
predicate parseArg(string c, int n) {
|
||||
predicate parseArg(string c, ParameterPosition pos) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\]", 1).toInt() = n
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]", 1).toInt() = n1 and
|
||||
c.regexpCapture("Argument\\[([-0-9]+)\\.\\.([0-9]+)\\]", 2).toInt() = n2 and
|
||||
n = [n1 .. n2]
|
||||
)
|
||||
exists(string body |
|
||||
body = c.regexpCapture("Argument\\[([^\\]]*)\\]", 1) and
|
||||
pos = parseArgBody(body)
|
||||
)
|
||||
}
|
||||
|
||||
private SummaryComponent interpretComponent(string c) {
|
||||
specSplit(_, c, _) and
|
||||
(
|
||||
exists(int pos | parseArg(c, pos) and result = SummaryComponent::argument(pos))
|
||||
exists(ParameterPosition pos |
|
||||
parseArg(c, pos) and result = SummaryComponent::argument(pos)
|
||||
)
|
||||
or
|
||||
exists(int pos | parseParam(c, pos) and result = SummaryComponent::parameter(pos))
|
||||
exists(ArgumentPosition pos |
|
||||
parseParam(c, pos) and result = SummaryComponent::parameter(pos)
|
||||
)
|
||||
or
|
||||
c = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
@@ -934,14 +950,18 @@ module Private {
|
||||
interpretOutput(output, idx + 1, ref, mid) and
|
||||
specSplit(output, c, idx)
|
||||
|
|
||||
exists(int pos |
|
||||
node.asNode().(PostUpdateNode).getPreUpdateNode().(ArgNode).argumentOf(mid.asCall(), pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(PostUpdateNode).getPreUpdateNode().(ArgNode).argumentOf(mid.asCall(), apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
c = "Argument" or parseArg(c, ppos)
|
||||
)
|
||||
or
|
||||
exists(int pos | node.asNode().(ParamNode).isParameterOf(mid.asCallable(), pos) |
|
||||
c = "Parameter" or parseParam(c, pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(ParamNode).isParameterOf(mid.asCallable(), ppos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Parameter" or parseParam(c, apos)
|
||||
)
|
||||
or
|
||||
c = "ReturnValue" and
|
||||
@@ -960,8 +980,11 @@ module Private {
|
||||
interpretInput(input, idx + 1, ref, mid) and
|
||||
specSplit(input, c, idx)
|
||||
|
|
||||
exists(int pos | node.asNode().(ArgNode).argumentOf(mid.asCall(), pos) |
|
||||
c = "Argument" or parseArg(c, pos)
|
||||
exists(ArgumentPosition apos, ParameterPosition ppos |
|
||||
node.asNode().(ArgNode).argumentOf(mid.asCall(), apos) and
|
||||
parameterMatch(ppos, apos)
|
||||
|
|
||||
c = "Argument" or parseArg(c, ppos)
|
||||
)
|
||||
or
|
||||
exists(ReturnNodeExt ret |
|
||||
@@ -1117,9 +1140,9 @@ module Private {
|
||||
b.asCall() = summaryDataFlowCall(a.asNode()) and
|
||||
value = "receiver"
|
||||
or
|
||||
exists(int i |
|
||||
summaryArgumentNode(b.asCall(), a.asNode(), i) and
|
||||
value = "argument (" + i + ")"
|
||||
exists(ArgumentPosition pos |
|
||||
summaryArgumentNode(b.asCall(), a.asNode(), pos) and
|
||||
value = "argument (" + pos + ")"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,11 +13,8 @@ private import FlowSummaryImpl::Public
|
||||
private import semmle.code.csharp.Unification
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** Holds is `i` is a valid parameter position. */
|
||||
predicate parameterPosition(int i) { i in [-1 .. any(Parameter p).getPosition()] }
|
||||
|
||||
/** Gets the parameter position of the instance parameter. */
|
||||
int instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
|
||||
ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
|
||||
|
||||
/** Gets the synthesized summary data-flow node for the given values. */
|
||||
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
|
||||
@@ -32,6 +29,8 @@ DataFlowType getContentType(Content c) {
|
||||
or
|
||||
t = c.(PropertyContent).getProperty().getType()
|
||||
or
|
||||
t = c.(SyntheticFieldContent).getField().getType()
|
||||
or
|
||||
c instanceof ElementContent and
|
||||
t instanceof ObjectType // we don't know what the actual element type is
|
||||
)
|
||||
@@ -61,13 +60,14 @@ DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the `i`th parameter in a synthesized call that targets a
|
||||
* callback of type `t`.
|
||||
* Gets the type of the parameter matching arguments at position `pos` in a
|
||||
* synthesized call that targets a callback of type `t`.
|
||||
*/
|
||||
DataFlowType getCallbackParameterType(DataFlowType t, int i) {
|
||||
DataFlowType getCallbackParameterType(DataFlowType t, ArgumentPosition pos) {
|
||||
exists(SystemLinqExpressions::DelegateExtType dt |
|
||||
t = Gvn::getGlobalValueNumber(dt) and
|
||||
result = Gvn::getGlobalValueNumber(dt.getDelegateType().getParameter(i).getType())
|
||||
result =
|
||||
Gvn::getGlobalValueNumber(dt.getDelegateType().getParameter(pos.getPosition()).getType())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -136,6 +136,11 @@ SummaryComponent interpretComponentSpecific(string c) {
|
||||
c.regexpCapture("Property\\[(.+)\\]", 1) = p.getQualifiedName() and
|
||||
result = SummaryComponent::content(any(PropertyContent pc | pc.getProperty() = p))
|
||||
)
|
||||
or
|
||||
exists(SyntheticField f |
|
||||
c.regexpCapture("SyntheticField\\[(.+)\\]", 1) = f and
|
||||
result = SummaryComponent::content(any(SyntheticFieldContent sfc | sfc.getField() = f))
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the textual representation of the content in the format used for flow summaries. */
|
||||
@@ -145,6 +150,8 @@ private string getContentSpecificCsv(Content c) {
|
||||
exists(Field f | c = TFieldContent(f) and result = "Field[" + f.getQualifiedName() + "]")
|
||||
or
|
||||
exists(Property p | c = TPropertyContent(p) and result = "Property[" + p.getQualifiedName() + "]")
|
||||
or
|
||||
exists(SyntheticField f | c = TSyntheticFieldContent(f) and result = "SyntheticField[" + f + "]")
|
||||
}
|
||||
|
||||
/** Gets the textual representation of a summary component in the format used for flow summaries. */
|
||||
@@ -158,6 +165,12 @@ string getComponentSpecificCsv(SummaryComponent sc) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the textual representation of a parameter position in the format used for flow summaries. */
|
||||
string getParameterPositionCsv(ParameterPosition pos) { result = pos.toString() }
|
||||
|
||||
/** Gets the textual representation of an argument position in the format used for flow summaries. */
|
||||
string getArgumentPositionCsv(ArgumentPosition pos) { result = pos.toString() }
|
||||
|
||||
class SourceOrSinkElement = Element;
|
||||
|
||||
/** Gets the return kind corresponding to specification `"ReturnValue"`. */
|
||||
@@ -223,3 +236,22 @@ predicate interpretInputSpecific(string c, InterpretNode mid, InterpretNode n) {
|
||||
a.getUnboundDeclaration() = mid.asElement()
|
||||
)
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
private int parsePosition(string s) {
|
||||
result = s.regexpCapture("([-0-9]+)", 1).toInt()
|
||||
or
|
||||
exists(int n1, int n2 |
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 1).toInt() = n1 and
|
||||
s.regexpCapture("([-0-9]+)\\.\\.([0-9]+)", 2).toInt() = n2 and
|
||||
result in [n1 .. n2]
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the argument position obtained by parsing `X` in `Parameter[X]`. */
|
||||
bindingset[s]
|
||||
ArgumentPosition parseParamBody(string s) { result.getPosition() = parsePosition(s) }
|
||||
|
||||
/** Gets the parameter position obtained by parsing `X` in `Argument[X]`. */
|
||||
bindingset[s]
|
||||
ParameterPosition parseArgBody(string s) { result.getPosition() = parsePosition(s) }
|
||||
|
||||
@@ -8,24 +8,11 @@ import csharp
|
||||
/**
|
||||
* A callable that can be overridden or implemented.
|
||||
*
|
||||
* Unlike the class `Virtualizable`, this class only includes methods that
|
||||
* can actually be overriden/implemented. Additionally, this class includes
|
||||
* accessors whose declarations can actually be overridden/implemented.
|
||||
* Unlike the class `Overridable`, this class only includes callables that
|
||||
* can actually be overriden/implemented.
|
||||
*/
|
||||
class OverridableCallable extends Callable {
|
||||
OverridableCallable() {
|
||||
this.(Method).isOverridableOrImplementable() or
|
||||
this.(Accessor).getDeclaration().isOverridableOrImplementable()
|
||||
}
|
||||
|
||||
/** Gets a callable that immediately overrides this callable, if any. */
|
||||
Callable getAnOverrider() { none() }
|
||||
|
||||
/**
|
||||
* Gets a callable that immediately implements this interface callable,
|
||||
* if any.
|
||||
*/
|
||||
Callable getAnImplementor(ValueOrRefType t) { none() }
|
||||
class OverridableCallable extends Callable, Overridable {
|
||||
OverridableCallable() { this.isOverridableOrImplementable() }
|
||||
|
||||
/**
|
||||
* Gets a callable that immediately implements this interface member,
|
||||
@@ -68,40 +55,6 @@ class OverridableCallable extends Callable {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a callable that (transitively) implements this interface callable,
|
||||
* if any. That is, either this interface callable is immediately implemented
|
||||
* by the result, or the result overrides (transitively) another callable that
|
||||
* immediately implements this interface callable.
|
||||
*
|
||||
* Note that this is generally *not* equivalent with
|
||||
*
|
||||
* ```ql
|
||||
* result = getAnImplementor()
|
||||
* or
|
||||
* result = getAnImplementor().(OverridableCallable).getAnOverrider+()`
|
||||
* ```
|
||||
*
|
||||
* as the example below illustrates:
|
||||
*
|
||||
* ```csharp
|
||||
* interface I { void M(); }
|
||||
*
|
||||
* class A { public virtual void M() { } }
|
||||
*
|
||||
* class B : A, I { }
|
||||
*
|
||||
* class C : A { public override void M() }
|
||||
*
|
||||
* class D : B { public override void M() }
|
||||
* ```
|
||||
*
|
||||
* If this callable is `I.M` then `A.M = getAnUltimateImplementor() ` and
|
||||
* `D.M = getAnUltimateImplementor()`. However, it is *not* the case that
|
||||
* `C.M = getAnUltimateImplementor()`, because `C` is not a sub type of `I`.
|
||||
*/
|
||||
Callable getAnUltimateImplementor() { none() }
|
||||
|
||||
/**
|
||||
* Gets a callable that overrides (transitively) another callable that
|
||||
* implements this interface callable, if any.
|
||||
@@ -210,73 +163,10 @@ class OverridableCallable extends Callable {
|
||||
}
|
||||
|
||||
/** An overridable method. */
|
||||
class OverridableMethod extends Method, OverridableCallable {
|
||||
override Method getAnOverrider() { result = Method.super.getAnOverrider() }
|
||||
|
||||
override Method getAnImplementor(ValueOrRefType t) { result = Method.super.getAnImplementor(t) }
|
||||
|
||||
override Method getAnUltimateImplementor() { result = Method.super.getAnUltimateImplementor() }
|
||||
|
||||
override Method getInherited(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getInherited(t)
|
||||
}
|
||||
|
||||
override Method getAnOverrider(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getAnOverrider(t)
|
||||
}
|
||||
}
|
||||
deprecated class OverridableMethod extends Method, OverridableCallable { }
|
||||
|
||||
/** An overridable accessor. */
|
||||
class OverridableAccessor extends Accessor, OverridableCallable {
|
||||
override Accessor getAnOverrider() { overrides(result, this) }
|
||||
|
||||
override Accessor getAnImplementor(ValueOrRefType t) {
|
||||
exists(Virtualizable implementor, int kind |
|
||||
this.getAnImplementorAux(t, implementor, kind) and
|
||||
result.getDeclaration() = implementor and
|
||||
getAccessorKind(result) = kind
|
||||
)
|
||||
}
|
||||
|
||||
// predicate folding to get proper join order
|
||||
private predicate getAnImplementorAux(ValueOrRefType t, Virtualizable implementor, int kind) {
|
||||
exists(Virtualizable implementee |
|
||||
implementee = this.getDeclaration() and
|
||||
kind = getAccessorKind(this) and
|
||||
implementor = implementee.getAnImplementor(t)
|
||||
)
|
||||
}
|
||||
|
||||
override Accessor getAnUltimateImplementor() {
|
||||
exists(Virtualizable implementor, int kind |
|
||||
this.getAnUltimateImplementorAux(implementor, kind) and
|
||||
result.getDeclaration() = implementor and
|
||||
getAccessorKind(result) = kind
|
||||
)
|
||||
}
|
||||
|
||||
// predicate folding to get proper join order
|
||||
private predicate getAnUltimateImplementorAux(Virtualizable implementor, int kind) {
|
||||
exists(Virtualizable implementee |
|
||||
implementee = this.getDeclaration() and
|
||||
kind = getAccessorKind(this) and
|
||||
implementor = implementee.getAnUltimateImplementor()
|
||||
)
|
||||
}
|
||||
|
||||
override Accessor getInherited(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getInherited(t)
|
||||
}
|
||||
|
||||
override Accessor getAnOverrider(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getAnOverrider(t)
|
||||
}
|
||||
}
|
||||
|
||||
private int getAccessorKind(Accessor a) {
|
||||
accessors(a, result, _, _, _) or
|
||||
event_accessors(a, -result, _, _, _)
|
||||
}
|
||||
deprecated class OverridableAccessor extends Accessor, OverridableCallable { }
|
||||
|
||||
/** An unbound type. */
|
||||
class UnboundDeclarationType extends Type {
|
||||
|
||||
@@ -996,7 +996,7 @@ class QualifiableExpr extends Expr, @qualifiable_expr {
|
||||
*/
|
||||
predicate targetIsOverridableOrImplementable() {
|
||||
not this.getQualifier() instanceof BaseAccess and
|
||||
this.getQualifiedDeclaration().(Virtualizable).isOverridableOrImplementable()
|
||||
this.getQualifiedDeclaration().(Overridable).isOverridableOrImplementable()
|
||||
}
|
||||
|
||||
/** Holds if this expression has a conditional qualifier `?.` */
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
private import semmle.code.csharp.dataflow.LibraryTypeDataFlow
|
||||
private import semmle.code.csharp.dataflow.ExternalFlow
|
||||
|
||||
/** Definitions relating to the `Json.NET` package. */
|
||||
module JsonNET {
|
||||
@@ -31,15 +31,9 @@ module JsonNET {
|
||||
}
|
||||
|
||||
/** The class `Newtonsoft.Json.JsonConvert`. */
|
||||
class JsonConvertClass extends JsonClass, LibraryTypeDataFlow {
|
||||
class JsonConvertClass extends JsonClass {
|
||||
JsonConvertClass() { this.hasName("JsonConvert") }
|
||||
|
||||
/** Gets a `ToString` method. */
|
||||
private Method getAToStringMethod() {
|
||||
result = this.getAMethod("ToString") and
|
||||
result.isStatic()
|
||||
}
|
||||
|
||||
/** Gets a `Deserialize` method. */
|
||||
Method getADeserializeMethod() {
|
||||
result = this.getAMethod() and
|
||||
@@ -51,39 +45,73 @@ module JsonNET {
|
||||
result = this.getAMethod() and
|
||||
result.getName().matches("Serialize%")
|
||||
}
|
||||
}
|
||||
|
||||
private Method getAPopulateMethod() {
|
||||
result = this.getAMethod() and
|
||||
result.getName().matches("Populate%")
|
||||
}
|
||||
|
||||
override predicate callableFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
// ToString methods
|
||||
c = this.getAToStringMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink instanceof CallableFlowSinkReturn
|
||||
or
|
||||
// Deserialize methods
|
||||
c = this.getADeserializeMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink instanceof CallableFlowSinkReturn
|
||||
or
|
||||
// Serialize methods
|
||||
c = this.getASerializeMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink instanceof CallableFlowSinkReturn
|
||||
or
|
||||
// Populate methods
|
||||
c = this.getAPopulateMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink = any(CallableFlowSinkArg arg | arg.getArgumentIndex() = 1)
|
||||
/** Data flow for `Newtonsoft.Json.JsonConvert`. */
|
||||
private class JsonConvertClassFlowModelCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeAnonymousType<>;(System.String,T);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeAnonymousType<>;(System.String,T,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject;(System.String,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject;(System.String,System.Type);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject;(System.String,System.Type,Newtonsoft.Json.JsonConverter[]);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject;(System.String,System.Type,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject<>;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject<>;(System.String,Newtonsoft.Json.JsonConverter[]);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeObject<>;(System.String,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXNode;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXNode;(System.String,System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXNode;(System.String,System.String,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXNode;(System.String,System.String,System.Boolean,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXmlNode;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXmlNode;(System.String,System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXmlNode;(System.String,System.String,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;DeserializeXmlNode;(System.String,System.String,System.Boolean,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;PopulateObject;(System.String,System.Object);;Argument[0];Argument[1];taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;PopulateObject;(System.String,System.Object,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];Argument[1];taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,Newtonsoft.Json.Formatting);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonConverter[]);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,Newtonsoft.Json.JsonConverter[]);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,System.Type,Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeObject;(System.Object,System.Type,Newtonsoft.Json.JsonSerializerSettings);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXNode;(System.Xml.Linq.XObject);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXNode;(System.Xml.Linq.XObject,Newtonsoft.Json.Formatting);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXNode;(System.Xml.Linq.XObject,Newtonsoft.Json.Formatting,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXmlNode;(System.Xml.XmlNode);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXmlNode;(System.Xml.XmlNode,Newtonsoft.Json.Formatting);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;SerializeXmlNode;(System.Xml.XmlNode,Newtonsoft.Json.Formatting,System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Boolean);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Byte);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Char);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.DateTime);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.DateTime,Newtonsoft.Json.DateFormatHandling,Newtonsoft.Json.DateTimeZoneHandling);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.DateTimeOffset);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.DateTimeOffset,Newtonsoft.Json.DateFormatHandling);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Decimal);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Double);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Enum);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Guid);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Int16);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Int32);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Int64);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Object);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.SByte);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Single);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.String,System.Char);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.String,System.Char,Newtonsoft.Json.StringEscapeHandling);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.TimeSpan);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.UInt16);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.UInt32);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.UInt64);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonConvert;false;ToString;(System.Uri);;Argument[0];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +165,7 @@ module JsonNET {
|
||||
}
|
||||
|
||||
/** The class `NewtonSoft.Json.JsonSerializer`. */
|
||||
class JsonSerializerClass extends JsonClass, LibraryTypeDataFlow {
|
||||
class JsonSerializerClass extends JsonClass {
|
||||
JsonSerializerClass() { this.hasName("JsonSerializer") }
|
||||
|
||||
/** Gets the method for `JsonSerializer.Serialize`. */
|
||||
@@ -145,22 +173,21 @@ module JsonNET {
|
||||
|
||||
/** Gets the method for `JsonSerializer.Deserialize`. */
|
||||
Method getDeserializeMethod() { result = this.getAMethod("Deserialize") }
|
||||
}
|
||||
|
||||
override predicate callableFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
// Serialize
|
||||
c = this.getSerializeMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 1) and
|
||||
sink = any(CallableFlowSinkArg arg | arg.getArgumentIndex() = 0)
|
||||
or
|
||||
// Deserialize
|
||||
c = this.getDeserializeMethod() and
|
||||
preservesValue = false and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink instanceof CallableFlowSinkReturn
|
||||
/** Data flow for `NewtonSoft.Json.JSonSerializer`. */
|
||||
private class JsonSerializerClassFlowModelCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"Newtonsoft.Json;JsonSerializer;false;Deserialize;(Newtonsoft.Json.JsonReader);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Deserialize;(Newtonsoft.Json.JsonReader,System.Type);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Deserialize;(System.IO.TextReader,System.Type);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Serialize;(Newtonsoft.Json.JsonWriter,System.Object);;Argument[1];Argument[0];taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Serialize;(Newtonsoft.Json.JsonWriter,System.Object,System.Type);;Argument[1];Argument[0];taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Serialize;(System.IO.TextWriter,System.Object);;Argument[1];Argument[0];taint",
|
||||
"Newtonsoft.Json;JsonSerializer;false;Serialize;(System.IO.TextWriter,System.Object,System.Type);;Argument[1];Argument[0];taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,41 +223,23 @@ module JsonNET {
|
||||
LinqClass() { this.getDeclaringNamespace() instanceof LinqNamespace }
|
||||
}
|
||||
|
||||
/** The `NewtonSoft.Json.Linq.JObject` class. */
|
||||
class JObjectClass extends LinqClass, LibraryTypeDataFlow {
|
||||
JObjectClass() { this.hasName("JObject") }
|
||||
|
||||
override predicate callableFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
// ToString method
|
||||
c = this.getAMethod("ToString") and
|
||||
source instanceof CallableFlowSourceQualifier and
|
||||
sink instanceof CallableFlowSinkReturn and
|
||||
preservesValue = false
|
||||
or
|
||||
// Parse method
|
||||
c = this.getParseMethod() and
|
||||
source = any(CallableFlowSourceArg arg | arg.getArgumentIndex() = 0) and
|
||||
sink instanceof CallableFlowSinkReturn and
|
||||
preservesValue = false
|
||||
or
|
||||
// operator string
|
||||
c =
|
||||
any(Operator op |
|
||||
op.getDeclaringType() = this.getABaseType*() and op.getReturnType() instanceof StringType
|
||||
) and
|
||||
source.(CallableFlowSourceArg).getArgumentIndex() = 0 and
|
||||
sink instanceof CallableFlowSinkReturn and
|
||||
preservesValue = false
|
||||
or
|
||||
// SelectToken method
|
||||
c = this.getSelectTokenMethod() and
|
||||
source instanceof CallableFlowSourceQualifier and
|
||||
sink instanceof CallableFlowSinkReturn and
|
||||
preservesValue = false
|
||||
/** Data flow for `Newtonsoft.Json.Linq.JToken`. */
|
||||
private class JTokenClassFlowModelCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"Newtonsoft.Json.Linq;JToken;false;SelectToken;(System.String);;Argument[-1];ReturnValue;taint",
|
||||
"Newtonsoft.Json.Linq;JToken;false;SelectToken;(System.String,Newtonsoft.Json.Linq.JsonSelectSettings);;Argument[-1];ReturnValue;taint",
|
||||
"Newtonsoft.Json.Linq;JToken;false;SelectToken;(System.String,System.Boolean);;Argument[-1];ReturnValue;taint",
|
||||
"Newtonsoft.Json.Linq;JToken;false;ToString;();;Argument[-1];ReturnValue;taint",
|
||||
"Newtonsoft.Json.Linq;JToken;false;ToString;(Newtonsoft.Json.Formatting,Newtonsoft.Json.JsonConverter[]);;Argument[-1];ReturnValue;taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/** The `NewtonSoft.Json.Linq.JObject` class. */
|
||||
class JObjectClass extends LinqClass {
|
||||
JObjectClass() { this.hasName("JObject") }
|
||||
|
||||
/** Gets the `Parse` method. */
|
||||
Method getParseMethod() { result = this.getAMethod("Parse") }
|
||||
@@ -238,4 +247,15 @@ module JsonNET {
|
||||
/** Gets the `SelectToken` method. */
|
||||
Method getSelectTokenMethod() { result = this.getABaseType*().getAMethod("SelectToken") }
|
||||
}
|
||||
|
||||
/** Data flow for `NewtonSoft.Json.Linq.JObject`. */
|
||||
private class JObjectClassFlowModelCsv extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"Newtonsoft.Json.Linq;JObject;false;Parse;(System.String);;Argument[0];ReturnValue;taint",
|
||||
"Newtonsoft.Json.Linq;JObject;false;Parse;(System.String,Newtonsoft.Json.Linq.JsonLoadSettings);;Argument[0];ReturnValue;taint"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user