mirror of
https://github.com/github/codeql.git
synced 2026-05-24 08:07:07 +02:00
Compare commits
639 Commits
mbg/csharp
...
redsun82/j
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
513305b11d | ||
|
|
62c8112388 | ||
|
|
6b266badc6 | ||
|
|
2d76b41293 | ||
|
|
9a1156dd62 | ||
|
|
43d002e6b5 | ||
|
|
16a7e39e95 | ||
|
|
17ab87d1fc | ||
|
|
dc8dc61196 | ||
|
|
ab34bd232e | ||
|
|
9e97e0433e | ||
|
|
102221d0aa | ||
|
|
c6d1ec5f64 | ||
|
|
21ea7ebe40 | ||
|
|
18a25c5071 | ||
|
|
ceec44b819 | ||
|
|
d2839f4ee4 | ||
|
|
2bde364bdd | ||
|
|
5122f7cf92 | ||
|
|
afd33e4dcd | ||
|
|
29500c7eb7 | ||
|
|
2a54dce5cb | ||
|
|
056be6d504 | ||
|
|
71b38b71bf | ||
|
|
cd7bb54039 | ||
|
|
3c78d8a737 | ||
|
|
b83d4e010b | ||
|
|
40366042a5 | ||
|
|
095a9cbc73 | ||
|
|
5db069eb56 | ||
|
|
9f27a5278f | ||
|
|
9247e6af0c | ||
|
|
29768bbed4 | ||
|
|
78c0c7cb76 | ||
|
|
503c15334a | ||
|
|
599b7a6653 | ||
|
|
9cb8edb41a | ||
|
|
eb35fa0d5e | ||
|
|
6692f23cbd | ||
|
|
8349bd50ba | ||
|
|
59eec7ffa2 | ||
|
|
ce6e6d5db3 | ||
|
|
898d12b0be | ||
|
|
e6adfbca77 | ||
|
|
b595a70384 | ||
|
|
938039d82c | ||
|
|
f5cfc5e282 | ||
|
|
58218ee630 | ||
|
|
2b8558706f | ||
|
|
ea9b99f67c | ||
|
|
0c5e89a68e | ||
|
|
da4a2238bc | ||
|
|
a9449cc991 | ||
|
|
a8b52acaa9 | ||
|
|
0f8e39a236 | ||
|
|
c07a814515 | ||
|
|
8fc914f636 | ||
|
|
7e1ad825c3 | ||
|
|
f897575d3f | ||
|
|
55b95d22e9 | ||
|
|
73360eefb3 | ||
|
|
08e115056d | ||
|
|
c4c363d4e5 | ||
|
|
56153d583e | ||
|
|
1a4f333c4a | ||
|
|
8a99ef4531 | ||
|
|
21ecf230ce | ||
|
|
7a4b88fadc | ||
|
|
de4fe6d25c | ||
|
|
d69bcca687 | ||
|
|
fe565baf06 | ||
|
|
64a52ba07f | ||
|
|
a5be35170b | ||
|
|
6769f08f93 | ||
|
|
c66679c03b | ||
|
|
41bb349a9b | ||
|
|
805c2c3c3c | ||
|
|
8382a352d4 | ||
|
|
b2d9a600e5 | ||
|
|
a6377145ac | ||
|
|
4748c4a4f5 | ||
|
|
a5f27b8f19 | ||
|
|
a402ce59f4 | ||
|
|
94ad234a28 | ||
|
|
970b57cbe7 | ||
|
|
fb011842c9 | ||
|
|
ab1f0c13e5 | ||
|
|
ef780c15fb | ||
|
|
346ab9d623 | ||
|
|
147ac37fec | ||
|
|
29acd6960f | ||
|
|
09a2dd4a2e | ||
|
|
6c52de9234 | ||
|
|
c579ec9ea7 | ||
|
|
898713538f | ||
|
|
fba4a83dc8 | ||
|
|
f25d7456da | ||
|
|
851315fb93 | ||
|
|
6295f57a87 | ||
|
|
8cf0954796 | ||
|
|
bedfe1e755 | ||
|
|
0ed037d667 | ||
|
|
dad517ff5e | ||
|
|
db7c61969d | ||
|
|
49c5cc05ac | ||
|
|
8cb5380d84 | ||
|
|
ddc407257f | ||
|
|
0f44d6a780 | ||
|
|
4a637cbe0a | ||
|
|
b554d7dd16 | ||
|
|
f3fc80a080 | ||
|
|
22eda4ef0a | ||
|
|
e986d8922a | ||
|
|
b91a52a050 | ||
|
|
9e60e1217f | ||
|
|
09f930f4e8 | ||
|
|
68039ecd68 | ||
|
|
59c27a2196 | ||
|
|
07603a835a | ||
|
|
5aabd90eff | ||
|
|
d96e8cb704 | ||
|
|
a900fe8657 | ||
|
|
3d2d09d0bc | ||
|
|
96f55fbdf1 | ||
|
|
55516342b2 | ||
|
|
51673312c5 | ||
|
|
149df86ce2 | ||
|
|
569e33b407 | ||
|
|
e2afb000b2 | ||
|
|
2a78183238 | ||
|
|
327757dbcb | ||
|
|
b426c6fb39 | ||
|
|
c8169f576f | ||
|
|
14b3f6211e | ||
|
|
059693ce89 | ||
|
|
70d8c1c76e | ||
|
|
f245da1e52 | ||
|
|
7e6319d648 | ||
|
|
93231794ee | ||
|
|
5762191832 | ||
|
|
fd8821fcb5 | ||
|
|
cc99867969 | ||
|
|
2e76f3471a | ||
|
|
19424627c1 | ||
|
|
680ea0b960 | ||
|
|
a5763303fc | ||
|
|
8d16a2b4fa | ||
|
|
97ebc0e839 | ||
|
|
d82fc67b36 | ||
|
|
ac48eca916 | ||
|
|
93e35661e6 | ||
|
|
a276f721f7 | ||
|
|
1ffcdc9293 | ||
|
|
56c83e250e | ||
|
|
5859590b5d | ||
|
|
8cebf510dc | ||
|
|
b5723bd75d | ||
|
|
fef314e27f | ||
|
|
1363c54a9f | ||
|
|
09caeca7e9 | ||
|
|
c67122b3f1 | ||
|
|
0d0d34cc71 | ||
|
|
be245357cc | ||
|
|
ee00b98476 | ||
|
|
6ae32f22a8 | ||
|
|
a59c865328 | ||
|
|
d0c48893f5 | ||
|
|
d99247cf13 | ||
|
|
a9eb801fea | ||
|
|
9a4bc69843 | ||
|
|
d4fef1c68e | ||
|
|
d2fcced5ad | ||
|
|
093c27955f | ||
|
|
f99f26f908 | ||
|
|
434b3973eb | ||
|
|
3584ad1905 | ||
|
|
50b3b7ee1f | ||
|
|
fa8e4f7314 | ||
|
|
c04b615a07 | ||
|
|
283231bdbc | ||
|
|
025a7d0cca | ||
|
|
8cfdea2001 | ||
|
|
e860d706c9 | ||
|
|
3d20050c0a | ||
|
|
b57e92164c | ||
|
|
cd92162920 | ||
|
|
33ed6034f6 | ||
|
|
1dcc76996d | ||
|
|
f4841e1f39 | ||
|
|
f6c81ff30a | ||
|
|
4b364639a2 | ||
|
|
bde9378cee | ||
|
|
769b3a6aae | ||
|
|
7d65baccb2 | ||
|
|
77cb35380c | ||
|
|
c5457d3e30 | ||
|
|
2f0d3288ce | ||
|
|
93c656065d | ||
|
|
e86ce8feed | ||
|
|
d3177b9e82 | ||
|
|
f4550544ce | ||
|
|
f9521e9e88 | ||
|
|
f342bae962 | ||
|
|
bceab0b44e | ||
|
|
02f8984aff | ||
|
|
b63e34d467 | ||
|
|
ec726f5941 | ||
|
|
208ae7aa01 | ||
|
|
be746b775b | ||
|
|
bc518c08c7 | ||
|
|
06ea72ccc7 | ||
|
|
57086f60b9 | ||
|
|
6452cc549f | ||
|
|
f59bacab30 | ||
|
|
356905ba36 | ||
|
|
dc291ffad7 | ||
|
|
d191d09c55 | ||
|
|
9c6276ef48 | ||
|
|
21f2c81f24 | ||
|
|
d30aab47ea | ||
|
|
fef758998c | ||
|
|
b9592fef2d | ||
|
|
7a33e2f539 | ||
|
|
34101b5ca0 | ||
|
|
07db9cf3c4 | ||
|
|
92c9a8e146 | ||
|
|
21cb11ea5d | ||
|
|
4c525ce7ab | ||
|
|
0f794b57ed | ||
|
|
2e987f8d78 | ||
|
|
2139b97628 | ||
|
|
7fc1d53ede | ||
|
|
50d83ada95 | ||
|
|
10678d3a42 | ||
|
|
7d538988a6 | ||
|
|
7f17b7716d | ||
|
|
b57fa1bffa | ||
|
|
662b1e7df6 | ||
|
|
750f1ae8e9 | ||
|
|
e0b06c8e72 | ||
|
|
8d6aceb008 | ||
|
|
3fad6bdc0c | ||
|
|
518d170acd | ||
|
|
b9ad36c11d | ||
|
|
4ca071210b | ||
|
|
1ddf81c58c | ||
|
|
c155394f25 | ||
|
|
2c76e6e637 | ||
|
|
2ff5c2c234 | ||
|
|
98d8cd1d6d | ||
|
|
e8e46accc0 | ||
|
|
06f0c1189f | ||
|
|
082dc61620 | ||
|
|
2e7da72277 | ||
|
|
5b17d8cf76 | ||
|
|
f2a0724620 | ||
|
|
b8222167d2 | ||
|
|
6efd844180 | ||
|
|
34f405f465 | ||
|
|
d4a0846c6c | ||
|
|
d180900ab4 | ||
|
|
97670b3674 | ||
|
|
ff48ac5434 | ||
|
|
af63e63686 | ||
|
|
19faf8f30b | ||
|
|
3aaee9d981 | ||
|
|
8e19b05a25 | ||
|
|
1ac9e5a2a4 | ||
|
|
3f9ad14473 | ||
|
|
9cb1c89a02 | ||
|
|
a57f803b37 | ||
|
|
1130870168 | ||
|
|
8ddfee9971 | ||
|
|
8df4dfb585 | ||
|
|
2f7526d70b | ||
|
|
eeb09ae389 | ||
|
|
3c4a386f3f | ||
|
|
e3dbf5b022 | ||
|
|
72534e882b | ||
|
|
a99b3f2c3b | ||
|
|
92718a98d0 | ||
|
|
e70727524a | ||
|
|
d6055754b6 | ||
|
|
c24b43d01e | ||
|
|
179a4cd41a | ||
|
|
a929c0bf24 | ||
|
|
427ccee3b9 | ||
|
|
22f16dda85 | ||
|
|
db0a3e38e2 | ||
|
|
e7edf15031 | ||
|
|
4c77e0f315 | ||
|
|
7124cd4e6e | ||
|
|
c076992b83 | ||
|
|
659d8e7c90 | ||
|
|
1e8de0511b | ||
|
|
bce0a4d2a7 | ||
|
|
2160910d56 | ||
|
|
a5c8a5b5f8 | ||
|
|
f8a3ce7bf8 | ||
|
|
f9f1d9eecc | ||
|
|
d3066af2e2 | ||
|
|
8c03136c25 | ||
|
|
d52e9bc18c | ||
|
|
b8b841cfba | ||
|
|
df9f8ee386 | ||
|
|
99f4930e24 | ||
|
|
e9df9147ad | ||
|
|
f32f85399a | ||
|
|
c56feb7644 | ||
|
|
7ef60a8649 | ||
|
|
ca2838b361 | ||
|
|
7a6ab70091 | ||
|
|
7d6e08ecf1 | ||
|
|
dfa6d20072 | ||
|
|
821cc0e875 | ||
|
|
7094fb07a4 | ||
|
|
52809133f5 | ||
|
|
056aa342fe | ||
|
|
f58a6e5d3a | ||
|
|
f11815c633 | ||
|
|
52cfd49087 | ||
|
|
8c1c039edf | ||
|
|
c9e0927992 | ||
|
|
d5f667e585 | ||
|
|
b758732a28 | ||
|
|
ba3fadbf20 | ||
|
|
d7d1554461 | ||
|
|
12e0f3f359 | ||
|
|
0bb6ff58cc | ||
|
|
b9c0aca11a | ||
|
|
ee3674cb80 | ||
|
|
3ee369b710 | ||
|
|
e16bb226c0 | ||
|
|
48bf4fd82a | ||
|
|
c271755985 | ||
|
|
a16c43881b | ||
|
|
39e0382089 | ||
|
|
22e012c6f4 | ||
|
|
1b6f3a43ef | ||
|
|
b8c44be599 | ||
|
|
84d1828a9c | ||
|
|
ca7017f3d7 | ||
|
|
f2e7dca65c | ||
|
|
b9b3b3a0b5 | ||
|
|
6c792e69b3 | ||
|
|
4a39055322 | ||
|
|
6552c849f0 | ||
|
|
00d8a10051 | ||
|
|
da7da80b2b | ||
|
|
5db30c9947 | ||
|
|
6fb10555ff | ||
|
|
bbd02b855b | ||
|
|
48a03e2a04 | ||
|
|
a92d97744f | ||
|
|
ef6c1a9968 | ||
|
|
72142b51f7 | ||
|
|
c06d4d2647 | ||
|
|
4a001f960f | ||
|
|
1253553aec | ||
|
|
68dfa5c83b | ||
|
|
25a20f74f0 | ||
|
|
5a65282241 | ||
|
|
2e04d4b888 | ||
|
|
79499c240a | ||
|
|
267a46d01b | ||
|
|
341059d2d0 | ||
|
|
79841bbc00 | ||
|
|
3c3c58b0a9 | ||
|
|
9bf1072a01 | ||
|
|
a5f23ade8c | ||
|
|
017b6f2e44 | ||
|
|
6a6bb5ebf9 | ||
|
|
15f7a95209 | ||
|
|
b631138b63 | ||
|
|
093d36ebe6 | ||
|
|
c7349740f0 | ||
|
|
efa797a21d | ||
|
|
77d4f5a2dc | ||
|
|
edf88b34da | ||
|
|
0215ea3ee3 | ||
|
|
35ac66d3aa | ||
|
|
219fe03637 | ||
|
|
b7a5b08d61 | ||
|
|
87ec22db65 | ||
|
|
f52195e96d | ||
|
|
430ed055bc | ||
|
|
8e85c4c0ea | ||
|
|
017822b872 | ||
|
|
eea61ea821 | ||
|
|
b289266398 | ||
|
|
f5545516db | ||
|
|
216bc76694 | ||
|
|
5921dacf52 | ||
|
|
ca44c777f0 | ||
|
|
5283413055 | ||
|
|
dbb8bb86ba | ||
|
|
afb2243984 | ||
|
|
a7e426d89f | ||
|
|
fde51e0c29 | ||
|
|
69ed88bccd | ||
|
|
97e1c96200 | ||
|
|
46ba1f9160 | ||
|
|
5d74ad5bc6 | ||
|
|
4013f00b19 | ||
|
|
e0e5319b11 | ||
|
|
d8007a85e6 | ||
|
|
512e27187e | ||
|
|
f2bad1e6e1 | ||
|
|
c5360ba46c | ||
|
|
be9c1d074f | ||
|
|
097681e705 | ||
|
|
63e8061917 | ||
|
|
8bbb0ec954 | ||
|
|
d81b9aa5fd | ||
|
|
fd7093e74d | ||
|
|
a6de855549 | ||
|
|
3b9eba2afc | ||
|
|
4dca9aa958 | ||
|
|
84bef5d4bc | ||
|
|
da99d3660d | ||
|
|
7f6fd34d46 | ||
|
|
d23a3f821e | ||
|
|
2340369e2d | ||
|
|
70c1b58492 | ||
|
|
f3dc0412b5 | ||
|
|
a3e9aed00a | ||
|
|
e96ba4806b | ||
|
|
76346eccd8 | ||
|
|
feb45e5731 | ||
|
|
66ca10c338 | ||
|
|
fa61f6f3df | ||
|
|
0561a63003 | ||
|
|
ff41917147 | ||
|
|
838f3b90e7 | ||
|
|
3c36a9e308 | ||
|
|
eb81743fb5 | ||
|
|
d9ef9f82e1 | ||
|
|
92a719092a | ||
|
|
ffa5110522 | ||
|
|
c9fa7fa283 | ||
|
|
8ef4be49aa | ||
|
|
e6996ea29a | ||
|
|
579c871b69 | ||
|
|
63c71b418c | ||
|
|
3e7a966c0d | ||
|
|
926725a87f | ||
|
|
9bf4262dbb | ||
|
|
c82f75604a | ||
|
|
ea77c0d86c | ||
|
|
ec1d034ee0 | ||
|
|
37a8fc85eb | ||
|
|
b5bf1c578c | ||
|
|
f3898329d6 | ||
|
|
acd6f4156b | ||
|
|
e22d3a1074 | ||
|
|
212374b94b | ||
|
|
aa7a730041 | ||
|
|
1c5afb2306 | ||
|
|
5b30e945ef | ||
|
|
2b3111441d | ||
|
|
99a4fe4828 | ||
|
|
aa28c94562 | ||
|
|
501485b9f6 | ||
|
|
db491fc985 | ||
|
|
1950fd33db | ||
|
|
91b6801db1 | ||
|
|
ea30f02271 | ||
|
|
f41c30e335 | ||
|
|
ddebdad9e1 | ||
|
|
f8f8991d36 | ||
|
|
3c129fcd23 | ||
|
|
6001c735ff | ||
|
|
5a97348e78 | ||
|
|
0eccd902c2 | ||
|
|
45eb14975a | ||
|
|
badfa1a5c5 | ||
|
|
b475f14575 | ||
|
|
d4ba2d68f9 | ||
|
|
05a77a2005 | ||
|
|
ef345a3279 | ||
|
|
2357ef07cc | ||
|
|
088913d925 | ||
|
|
83155df1f7 | ||
|
|
b7992ed8cd | ||
|
|
219ea28217 | ||
|
|
fbf40ef02a | ||
|
|
370c5157f1 | ||
|
|
2782d90d0f | ||
|
|
ad5ab9f270 | ||
|
|
4474e252fe | ||
|
|
18d2f586b3 | ||
|
|
189c16095d | ||
|
|
a604a68fe9 | ||
|
|
4e2a93df55 | ||
|
|
6a904eddd4 | ||
|
|
fe032a5834 | ||
|
|
cfd4be6b4e | ||
|
|
93a28cbfaf | ||
|
|
13ce515aab | ||
|
|
8807217e49 | ||
|
|
daefd5988e | ||
|
|
d9ea78bfb8 | ||
|
|
f02abb3e93 | ||
|
|
a2f45f1b5b | ||
|
|
bb5bfda14b | ||
|
|
e152f08468 | ||
|
|
16cd3a8bc0 | ||
|
|
7d30e3ca5e | ||
|
|
319e3d1ba4 | ||
|
|
8380474acd | ||
|
|
a3d15dbaa3 | ||
|
|
ec7e6e8e03 | ||
|
|
4e63b83fd3 | ||
|
|
ea1fc43732 | ||
|
|
13959ab91e | ||
|
|
df7379c0d2 | ||
|
|
7795badd18 | ||
|
|
e695477f4f | ||
|
|
627654cff9 | ||
|
|
f2cc0da936 | ||
|
|
bd0d69ffca | ||
|
|
97ed67e284 | ||
|
|
db33dadb8e | ||
|
|
1139059d77 | ||
|
|
92f26027e1 | ||
|
|
85875c2879 | ||
|
|
17e6fd2fe9 | ||
|
|
5d75b255a8 | ||
|
|
26e8701ae3 | ||
|
|
cdb41588a9 | ||
|
|
1eccb8ea93 | ||
|
|
66611323e2 | ||
|
|
d804fc5168 | ||
|
|
f223c957ba | ||
|
|
86bd0c0dc3 | ||
|
|
6e0c5615fe | ||
|
|
edde4149aa | ||
|
|
87478d016a | ||
|
|
09d74a3b3e | ||
|
|
271a759490 | ||
|
|
b9595d985e | ||
|
|
ab94524328 | ||
|
|
155e21e729 | ||
|
|
d440b5fa85 | ||
|
|
47895b3334 | ||
|
|
71fb6bf915 | ||
|
|
c673bd9151 | ||
|
|
0f2de46648 | ||
|
|
f0f58dacb3 | ||
|
|
4a3b86c652 | ||
|
|
062fbf2b3c | ||
|
|
ec0b90f4b4 | ||
|
|
96a06bed8d | ||
|
|
f2dc585751 | ||
|
|
478f56b82f | ||
|
|
78f855d7e3 | ||
|
|
75ffb5fc4c | ||
|
|
75fea4245a | ||
|
|
5c108e5c12 | ||
|
|
53e886380c | ||
|
|
97f7a26e11 | ||
|
|
1213369d75 | ||
|
|
e0ab5ce49b | ||
|
|
06a8fd0e4a | ||
|
|
113565ba76 | ||
|
|
ae5ab9c67c | ||
|
|
884c61604e | ||
|
|
c5e1f0ccc9 | ||
|
|
94121f19ca | ||
|
|
2b8e719034 | ||
|
|
bdbbd45909 | ||
|
|
0d0711f2a7 | ||
|
|
d4873dd35e | ||
|
|
f7317b6a2b | ||
|
|
352b3711f6 | ||
|
|
eb37c413f2 | ||
|
|
106a9d479f | ||
|
|
d84e0e262d | ||
|
|
8b0dd7b866 | ||
|
|
b798bc2c8f | ||
|
|
a72cf56a05 | ||
|
|
4d9c0e0c26 | ||
|
|
a6ee1df567 | ||
|
|
581679d27d | ||
|
|
fc8b7c04cf | ||
|
|
ccd28ff66a | ||
|
|
a844d60174 | ||
|
|
6ac8c4f544 | ||
|
|
e0eb653dcc | ||
|
|
fb2799bd47 | ||
|
|
12b9999289 | ||
|
|
7871cd74f6 | ||
|
|
1e9dcea88b | ||
|
|
6fbdb2c52b | ||
|
|
48e3724299 | ||
|
|
0c9931ff8a | ||
|
|
48d7d9cedb | ||
|
|
4a97a449fc | ||
|
|
2e987343dd | ||
|
|
723a896b99 | ||
|
|
0f28502e68 | ||
|
|
469d09c9af | ||
|
|
9d52a08793 | ||
|
|
db83285c9f | ||
|
|
15e8e4803d | ||
|
|
c67e1230b6 | ||
|
|
f1febac3ec | ||
|
|
4284d66afb | ||
|
|
0e3ee6efd7 | ||
|
|
365b2ebd6d | ||
|
|
f2a6503efe | ||
|
|
7e7afbabcd | ||
|
|
103745b5d2 | ||
|
|
92672836dc | ||
|
|
c51f2f8780 | ||
|
|
c9cda74195 | ||
|
|
bd003c58a8 | ||
|
|
08097157fd | ||
|
|
b8b01ce71c | ||
|
|
7f72f87204 | ||
|
|
aa09288462 | ||
|
|
8ba7efd455 | ||
|
|
bb467d4abf | ||
|
|
d987aa67ec | ||
|
|
e8bcbbd6df | ||
|
|
acc7e3f32d | ||
|
|
c4305151c3 | ||
|
|
fba96c4eae | ||
|
|
cb652f3dc8 | ||
|
|
6e14111337 | ||
|
|
d7d7cf920a | ||
|
|
a4acf0890e | ||
|
|
812fc2349b | ||
|
|
5b9436a95f | ||
|
|
4768ebabee | ||
|
|
9e31fb50c8 | ||
|
|
2dea9da38c | ||
|
|
1202af1c5c | ||
|
|
9c284b1778 |
2
.github/dependabot.yml
vendored
2
.github/dependabot.yml
vendored
@@ -45,3 +45,5 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
||||
exclude-paths:
|
||||
- "misc/bazel/registry/**"
|
||||
|
||||
78
.github/workflows/compile-queries.yml
vendored
78
.github/workflows/compile-queries.yml
vendored
@@ -1,78 +0,0 @@
|
||||
name: "Compile all queries using the latest stable CodeQL CLI"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: # makes sure the cache gets populated - running on the branches people tend to merge into.
|
||||
- main
|
||||
- "rc/*"
|
||||
- "codeql-cli-*"
|
||||
pull_request:
|
||||
paths:
|
||||
- '**.ql'
|
||||
- '**.qll'
|
||||
- '**/qlpack.yml'
|
||||
- '**.dbscheme'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
languages: ${{ steps.detect.outputs.languages }}
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Detect changed languages
|
||||
id: detect
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "pull_request" ]]; then
|
||||
# For PRs, detect which languages have changes
|
||||
changed_files=$(gh pr view ${{ github.event.pull_request.number }} --json files --jq '.files.[].path')
|
||||
languages=()
|
||||
for lang in actions cpp csharp go java javascript python ql ruby rust swift; do
|
||||
if echo "$changed_files" | grep -qE "^($lang/|shared/)" ; then
|
||||
languages+=("$lang")
|
||||
fi
|
||||
done
|
||||
echo "languages=$(jq -c -n '$ARGS.positional' --args "${languages[@]}")" >> $GITHUB_OUTPUT
|
||||
else
|
||||
# For pushes to main/rc branches, run all languages
|
||||
echo 'languages=["actions","cpp","csharp","go","java","javascript","python","ql","ruby","rust","swift"]' >> $GITHUB_OUTPUT
|
||||
fi
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
|
||||
compile-queries:
|
||||
needs: detect-changes
|
||||
if: github.repository_owner == 'github' && needs.detect-changes.outputs.languages != '[]'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: ${{ fromJson(needs.detect-changes.outputs.languages) }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Setup CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
with:
|
||||
channel: 'release'
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: ${{ matrix.language }}-queries
|
||||
- name: check formatting
|
||||
run: find shared ${{ matrix.language }}/ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
|
||||
- name: compile queries - check-only
|
||||
# run with --check-only if running in a PR (github.sha != main)
|
||||
if : ${{ github.event_name == 'pull_request' }}
|
||||
shell: bash
|
||||
run: codeql query compile -q -j0 ${{ matrix.language }}/ql/{src,examples} --keep-going --warnings=error --check-only --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000
|
||||
- name: compile queries - full
|
||||
# do full compile if running on main - this populates the cache
|
||||
if : ${{ github.event_name != 'pull_request' }}
|
||||
shell: bash
|
||||
run: codeql query compile -q -j0 ${{ matrix.language }}/ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500 --ram=56000
|
||||
236
.github/workflows/ruby-build.yml
vendored
236
.github/workflows/ruby-build.yml
vendored
@@ -1,236 +0,0 @@
|
||||
name: "Ruby: Build"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-build.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- .github/workflows/ruby-build.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Version tag to create"
|
||||
required: false
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Install GNU tar
|
||||
if: runner.os == 'macOS'
|
||||
run: |
|
||||
brew install gnu-tar
|
||||
echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH
|
||||
- name: Prepare Windows
|
||||
if: runner.os == 'Windows'
|
||||
shell: powershell
|
||||
run: |
|
||||
git config --global core.longpaths true
|
||||
- uses: ./.github/actions/os-version
|
||||
id: os_version
|
||||
- name: Cache entire extractor
|
||||
uses: actions/cache@v3
|
||||
id: cache-extractor
|
||||
with:
|
||||
path: |
|
||||
target/release/codeql-extractor-ruby
|
||||
target/release/codeql-extractor-ruby.exe
|
||||
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
- uses: actions/cache@v3
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
with:
|
||||
path: |
|
||||
~/.cargo/registry
|
||||
~/.cargo/git
|
||||
target
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/**/Cargo.lock') }}
|
||||
- name: Check formatting
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo fmt -- --check
|
||||
- name: Build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo build --verbose
|
||||
- name: Run tests
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo test --verbose
|
||||
- name: Release build
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
run: cd extractor && cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
run: ../target/release/codeql-extractor-ruby generate --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: ruby.dbscheme
|
||||
path: ruby/ql/lib/ruby.dbscheme
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
name: TreeSitter.qll
|
||||
path: ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: extractor-${{ matrix.os }}
|
||||
path: |
|
||||
target/release/codeql-extractor-ruby
|
||||
target/release/codeql-extractor-ruby.exe
|
||||
retention-days: 1
|
||||
compile-queries:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: ruby-build
|
||||
- name: Build Query Pack
|
||||
run: |
|
||||
PACKS=${{ runner.temp }}/query-packs
|
||||
rm -rf $PACKS
|
||||
codeql pack create ../misc/suite-helpers --output "$PACKS"
|
||||
codeql pack create ../shared/regex --output "$PACKS"
|
||||
codeql pack create ../shared/ssa --output "$PACKS"
|
||||
codeql pack create ../shared/tutorial --output "$PACKS"
|
||||
codeql pack create ql/lib --output "$PACKS"
|
||||
codeql pack create -j0 ql/src --output "$PACKS" --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
PACK_FOLDER=$(readlink -f "$PACKS"/codeql/ruby-queries/*)
|
||||
codeql generate query-help --format=sarifv2.1.0 --output="${PACK_FOLDER}/rules.sarif" ql/src
|
||||
(cd ql/src; find queries \( -name '*.qhelp' -o -name '*.rb' -o -name '*.erb' \) -exec bash -c 'mkdir -p "'"${PACK_FOLDER}"'/$(dirname "{}")"' \; -exec cp "{}" "${PACK_FOLDER}/{}" \;)
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: codeql-ruby-queries
|
||||
path: |
|
||||
${{ runner.temp }}/query-packs/*
|
||||
retention-days: 1
|
||||
include-hidden-files: true
|
||||
|
||||
package:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build, compile-queries]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ruby.dbscheme
|
||||
path: ruby/ruby
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: extractor-ubuntu-latest
|
||||
path: ruby/linux64
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: extractor-windows-latest
|
||||
path: ruby/win64
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: extractor-macos-latest
|
||||
path: ruby/osx64
|
||||
- run: |
|
||||
mkdir -p ruby
|
||||
cp -r codeql-extractor.yml tools ql/lib/ruby.dbscheme.stats ruby/
|
||||
mkdir -p ruby/tools/{linux64,osx64,win64}
|
||||
cp linux64/codeql-extractor-ruby ruby/tools/linux64/extractor
|
||||
cp osx64/codeql-extractor-ruby ruby/tools/osx64/extractor
|
||||
cp win64/codeql-extractor-ruby.exe ruby/tools/win64/extractor.exe
|
||||
chmod +x ruby/tools/{linux64,osx64}/extractor
|
||||
zip -rq codeql-ruby.zip ruby
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: codeql-ruby-pack
|
||||
path: ruby/codeql-ruby.zip
|
||||
retention-days: 1
|
||||
include-hidden-files: true
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: codeql-ruby-queries
|
||||
path: ruby/qlpacks
|
||||
- run: |
|
||||
echo '{
|
||||
"provide": [
|
||||
"ruby/codeql-extractor.yml",
|
||||
"qlpacks/*/*/*/qlpack.yml"
|
||||
]
|
||||
}' > .codeqlmanifest.json
|
||||
zip -rq codeql-ruby-bundle.zip .codeqlmanifest.json ruby qlpacks
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: codeql-ruby-bundle
|
||||
path: ruby/codeql-ruby-bundle.zip
|
||||
retention-days: 1
|
||||
include-hidden-files: true
|
||||
|
||||
test:
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ${{ github.workspace }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: [package]
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Fetch CodeQL
|
||||
uses: ./.github/actions/fetch-codeql
|
||||
|
||||
- name: Download Ruby bundle
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: codeql-ruby-bundle
|
||||
path: ${{ runner.temp }}
|
||||
- name: Unzip Ruby bundle
|
||||
shell: bash
|
||||
run: unzip -q -d "${{ runner.temp }}/ruby-bundle" "${{ runner.temp }}/codeql-ruby-bundle.zip"
|
||||
|
||||
- name: Run QL test
|
||||
shell: bash
|
||||
run: |
|
||||
codeql test run --search-path "${{ runner.temp }}/ruby-bundle" --additional-packs "${{ runner.temp }}/ruby-bundle" ruby/ql/test/library-tests/ast/constants/
|
||||
- name: Create database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database create --search-path "${{ runner.temp }}/ruby-bundle" --language ruby --source-root ruby/ql/test/library-tests/ast/constants/ ../database
|
||||
- name: Analyze database
|
||||
shell: bash
|
||||
run: |
|
||||
codeql database analyze --search-path "${{ runner.temp }}/ruby-bundle" --format=sarifv2.1.0 --output=out.sarif ../database ruby-code-scanning.qls
|
||||
75
.github/workflows/ruby-dataset-measure.yml
vendored
75
.github/workflows/ruby-dataset-measure.yml
vendored
@@ -1,75 +0,0 @@
|
||||
name: "Ruby: Collect database stats"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
paths:
|
||||
- ruby/ql/lib/ruby.dbscheme
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
paths:
|
||||
- ruby/ql/lib/ruby.dbscheme
|
||||
- .github/workflows/ruby-dataset-measure.yml
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
measure:
|
||||
env:
|
||||
CODEQL_THREADS: 4 # TODO: remove this once it's set by the CLI
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
repo: [rails/rails, discourse/discourse, spree/spree, ruby/ruby]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
|
||||
- name: Checkout ${{ matrix.repo }}
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
repository: ${{ matrix.repo }}
|
||||
path: ${{ github.workspace }}/repo
|
||||
- name: Create database
|
||||
run: |
|
||||
codeql database create \
|
||||
--search-path "${{ github.workspace }}" \
|
||||
--threads 4 \
|
||||
--language ruby --source-root "${{ github.workspace }}/repo" \
|
||||
"${{ runner.temp }}/database"
|
||||
- name: Measure database
|
||||
run: |
|
||||
mkdir -p "stats/${{ matrix.repo }}"
|
||||
codeql dataset measure --threads 4 --output "stats/${{ matrix.repo }}/stats.xml" "${{ runner.temp }}/database/db-ruby"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: measurements-${{ hashFiles('stats/**') }}
|
||||
path: stats
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs: measure
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: stats
|
||||
- run: |
|
||||
python -m pip install --user lxml
|
||||
find stats -name 'stats.xml' | sort | xargs python ruby/scripts/merge_stats.py --output ruby/ql/lib/ruby.dbscheme.stats --normalise ruby_tokeninfo
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ruby.dbscheme.stats
|
||||
path: ruby/ql/lib/ruby.dbscheme.stats
|
||||
40
.github/workflows/ruby-qltest-rtjo.yml
vendored
40
.github/workflows/ruby-qltest-rtjo.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: "Ruby: Run RTJO Language Tests"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- reopened
|
||||
- labeled
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qltest-rtjo:
|
||||
if: "github.repository_owner == 'github' && github.event.label.name == 'Run: RTJO Language Tests'"
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: ruby-qltest
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --dynamic-join-order-mode=all --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-diff-informed --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
73
.github/workflows/ruby-qltest.yml
vendored
73
.github/workflows/ruby-qltest.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: "Ruby: Run QL Tests"
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/ruby-build.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "ruby/**"
|
||||
- "shared/**"
|
||||
- .github/workflows/ruby-qltest.yml
|
||||
- .github/actions/fetch-codeql/action.yml
|
||||
- codeql-workspace.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ruby
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
qlupgrade:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- name: Check DB upgrade scripts
|
||||
run: |
|
||||
echo >empty.trap
|
||||
codeql dataset import -S ql/lib/upgrades/initial/ruby.dbscheme testdb empty.trap
|
||||
codeql dataset upgrade testdb --additional-packs ql/lib
|
||||
diff -q testdb/ruby.dbscheme ql/lib/ruby.dbscheme
|
||||
- name: Check DB downgrade scripts
|
||||
run: |
|
||||
echo >empty.trap
|
||||
rm -rf testdb; codeql dataset import -S ql/lib/ruby.dbscheme testdb empty.trap
|
||||
codeql resolve upgrades --format=lines --allow-downgrades --additional-packs downgrades \
|
||||
--dbscheme=ql/lib/ruby.dbscheme --target-dbscheme=downgrades/initial/ruby.dbscheme |
|
||||
xargs codeql execute upgrades testdb
|
||||
diff -q testdb/ruby.dbscheme downgrades/initial/ruby.dbscheme
|
||||
qltest:
|
||||
if: github.repository_owner == 'github'
|
||||
runs-on: ubuntu-latest-xl
|
||||
strategy:
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: ./.github/actions/fetch-codeql
|
||||
- uses: ./ruby/actions/create-extractor-pack
|
||||
- name: Cache compilation cache
|
||||
id: query-cache
|
||||
uses: ./.github/actions/cache-query-compilation
|
||||
with:
|
||||
key: ruby-qltest
|
||||
- name: Run QL tests
|
||||
run: |
|
||||
codeql test run --threads=0 --ram 50000 --search-path "${{ github.workspace }}" --check-databases --check-diff-informed --check-undefined-labels --check-unused-labels --check-repeated-labels --check-redefined-labels --check-use-before-definition --consistency-queries ql/consistency-queries ql/test --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
22
MODULE.bazel
22
MODULE.bazel
@@ -15,23 +15,23 @@ local_path_override(
|
||||
# see https://registry.bazel.build/ for a list of available packages
|
||||
|
||||
bazel_dep(name = "platforms", version = "1.0.0")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.16")
|
||||
bazel_dep(name = "rules_go", version = "0.59.0")
|
||||
bazel_dep(name = "rules_java", version = "9.0.3")
|
||||
bazel_dep(name = "rules_pkg", version = "1.0.1")
|
||||
bazel_dep(name = "rules_cc", version = "0.2.17")
|
||||
bazel_dep(name = "rules_go", version = "0.60.0")
|
||||
bazel_dep(name = "rules_java", version = "9.6.1")
|
||||
bazel_dep(name = "rules_pkg", version = "1.2.0")
|
||||
bazel_dep(name = "rules_nodejs", version = "6.7.3")
|
||||
bazel_dep(name = "rules_python", version = "0.40.0")
|
||||
bazel_dep(name = "rules_shell", version = "0.5.0")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.8.1")
|
||||
bazel_dep(name = "abseil-cpp", version = "20240116.1", repo_name = "absl")
|
||||
bazel_dep(name = "rules_python", version = "1.9.0")
|
||||
bazel_dep(name = "rules_shell", version = "0.7.1")
|
||||
bazel_dep(name = "bazel_skylib", version = "1.9.0")
|
||||
bazel_dep(name = "abseil-cpp", version = "20260107.1", repo_name = "absl")
|
||||
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
|
||||
bazel_dep(name = "fmt", version = "12.1.0-codeql.1")
|
||||
bazel_dep(name = "rules_kotlin", version = "2.2.2-codeql.1")
|
||||
bazel_dep(name = "gazelle", version = "0.47.0")
|
||||
bazel_dep(name = "rules_dotnet", version = "0.21.5-codeql.1")
|
||||
bazel_dep(name = "googletest", version = "1.14.0.bcr.1")
|
||||
bazel_dep(name = "rules_rust", version = "0.68.1.codeql.1")
|
||||
bazel_dep(name = "zstd", version = "1.5.5.bcr.1")
|
||||
bazel_dep(name = "googletest", version = "1.17.0.bcr.2")
|
||||
bazel_dep(name = "rules_rust", version = "0.69.0")
|
||||
bazel_dep(name = "zstd", version = "1.5.7.bcr.1")
|
||||
|
||||
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
|
||||
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## 0.4.32
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.31
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.30
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.29
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.28
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
actions/ql/lib/change-notes/released/0.4.29.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.29.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.29
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/lib/change-notes/released/0.4.30.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.30.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.30
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/lib/change-notes/released/0.4.31.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.31.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.31
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/lib/change-notes/released/0.4.32.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.32.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.32
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.28
|
||||
lastReleaseVersion: 0.4.32
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.29-dev
|
||||
version: 0.4.33-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
## 0.6.24
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.23
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.22
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.21
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.20
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
actions/ql/src/change-notes/released/0.6.21.md
Normal file
3
actions/ql/src/change-notes/released/0.6.21.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.21
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/src/change-notes/released/0.6.22.md
Normal file
3
actions/ql/src/change-notes/released/0.6.22.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.22
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/src/change-notes/released/0.6.23.md
Normal file
3
actions/ql/src/change-notes/released/0.6.23.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.23
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/src/change-notes/released/0.6.24.md
Normal file
3
actions/ql/src/change-notes/released/0.6.24.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.24
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.20
|
||||
lastReleaseVersion: 0.6.24
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.21-dev
|
||||
version: 0.6.25-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -199,6 +199,7 @@ def annotate_as_appropriate(filename, lines):
|
||||
# as overlay[local?]. It is not clear that these heuristics are exactly what we want,
|
||||
# but they seem to work well enough for now (as determined by speed and accuracy numbers).
|
||||
if (filename.endswith("Test.qll") or
|
||||
re.search(r"go/ql/lib/semmle/go/security/[^/]+[.]qll$", filename.replace(os.sep, "/")) or
|
||||
((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and
|
||||
any("implements DataFlow::ConfigSig" in line for line in lines))):
|
||||
return None
|
||||
|
||||
@@ -172,10 +172,6 @@
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll"
|
||||
],
|
||||
"C# ControlFlowReachability": [
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/ControlFlowReachability.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/ControlFlowReachability.qll"
|
||||
],
|
||||
"C++ ExternalAPIs": [
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll",
|
||||
"cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Trap extends @trap {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Tag extends @tag {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Element e, Trap trap
|
||||
where
|
||||
in_trap_or_tag(e, trap)
|
||||
or
|
||||
exists(Tag tag |
|
||||
in_trap_or_tag(e, tag) and
|
||||
trap_uses_tag(trap, tag)
|
||||
)
|
||||
select e, trap
|
||||
2545
cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/old.dbscheme
Normal file
2545
cpp/downgrades/770002bb02322e04fa25345838ce6e82af285a0b/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,13 @@
|
||||
class SourceFile extends @source_file {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Trap extends @trap {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from SourceFile source_file, string name, Trap trap
|
||||
where
|
||||
source_file_uses_trap(source_file, trap) and
|
||||
source_file_name(source_file, name)
|
||||
select name, trap
|
||||
@@ -0,0 +1,8 @@
|
||||
description: Add source_file_name
|
||||
compatibility: backwards
|
||||
source_file_uses_trap.rel: run source_file_uses_trap.ql
|
||||
source_file_name.rel: delete
|
||||
tag_name.rel: delete
|
||||
trap_uses_tag.rel: delete
|
||||
in_trap.rel: run in_trap.ql
|
||||
in_trap_or_tag.rel: delete
|
||||
8
cpp/justfile
Normal file
8
cpp/justfile
Normal file
@@ -0,0 +1,8 @@
|
||||
import '../lib.just'
|
||||
import? '../../cpp-coding-standards.just'
|
||||
|
||||
[group('build')]
|
||||
build: (_build_dist "cpp")
|
||||
|
||||
[group('test')]
|
||||
language-tests *EXTRA_ARGS: (_language_tests EXTRA_ARGS source_dir() 'ql/test' '../../semmlecode-cpp-tests')
|
||||
9
cpp/ql/consistency-queries/badLocations.ql
Normal file
9
cpp/ql/consistency-queries/badLocations.ql
Normal file
@@ -0,0 +1,9 @@
|
||||
import cpp
|
||||
|
||||
// Locations should either be :0:0:0:0 locations (UnknownLocation, or
|
||||
// a whole file), or all 4 fields should be positive.
|
||||
from Location l
|
||||
where
|
||||
[l.getStartLine(), l.getEndLine(), l.getStartColumn(), l.getEndColumn()] != 0 and
|
||||
[l.getStartLine(), l.getEndLine(), l.getStartColumn(), l.getEndColumn()] < 1
|
||||
select l
|
||||
5
cpp/ql/consistency-queries/nullInToString.ql
Normal file
5
cpp/ql/consistency-queries/nullInToString.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Element e
|
||||
where e.toString().matches("%(null)%")
|
||||
select e
|
||||
5
cpp/ql/consistency-queries/qlpack.yml
Normal file
5
cpp/ql/consistency-queries/qlpack.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
name: codeql/cpp-consistency-queries
|
||||
groups: [cpp, test, consistency-queries]
|
||||
dependencies:
|
||||
codeql/cpp-all: ${workspace}
|
||||
extractor: cpp
|
||||
10
cpp/ql/consistency-queries/unusedLocations.ql
Normal file
10
cpp/ql/consistency-queries/unusedLocations.ql
Normal file
@@ -0,0 +1,10 @@
|
||||
import cpp
|
||||
|
||||
from Location l
|
||||
where
|
||||
not any(Element e).getLocation() = l and
|
||||
not any(LambdaCapture lc).getLocation() = l and
|
||||
not any(MacroAccess ma).getActualLocation() = l and
|
||||
not any(NamespaceDeclarationEntry nde).getBodyLocation() = l and
|
||||
not any(XmlLocatable xml).getLocation() = l
|
||||
select l
|
||||
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from VariableDeclarationEntry i
|
||||
where not exists(i.getType())
|
||||
select i
|
||||
5
cpp/ql/consistency-queries/variablesWithoutTypes.ql
Normal file
5
cpp/ql/consistency-queries/variablesWithoutTypes.ql
Normal file
@@ -0,0 +1,5 @@
|
||||
import cpp
|
||||
|
||||
from Variable i
|
||||
where not exists(i.getType())
|
||||
select i
|
||||
@@ -52,5 +52,6 @@ ql/cpp/ql/src/Summary/LinesOfUserCode.ql
|
||||
ql/cpp/ql/src/Telemetry/CompilerErrors.ql
|
||||
ql/cpp/ql/src/Telemetry/DatabaseQuality.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractorInformation.ql
|
||||
ql/cpp/ql/src/Telemetry/MissingIncludes.ql
|
||||
ql/cpp/ql/src/Telemetry/SucceededIncludes.ql
|
||||
|
||||
@@ -160,6 +160,7 @@ ql/cpp/ql/src/Summary/LinesOfUserCode.ql
|
||||
ql/cpp/ql/src/Telemetry/CompilerErrors.ql
|
||||
ql/cpp/ql/src/Telemetry/DatabaseQuality.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractorInformation.ql
|
||||
ql/cpp/ql/src/Telemetry/MissingIncludes.ql
|
||||
ql/cpp/ql/src/Telemetry/SucceededIncludes.ql
|
||||
ql/cpp/ql/src/jsf/4.06 Pre-Processing Directives/AV Rule 32.ql
|
||||
|
||||
@@ -93,5 +93,6 @@ ql/cpp/ql/src/Summary/LinesOfUserCode.ql
|
||||
ql/cpp/ql/src/Telemetry/CompilerErrors.ql
|
||||
ql/cpp/ql/src/Telemetry/DatabaseQuality.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractionMetrics.ql
|
||||
ql/cpp/ql/src/Telemetry/ExtractorInformation.ql
|
||||
ql/cpp/ql/src/Telemetry/MissingIncludes.ql
|
||||
ql/cpp/ql/src/Telemetry/SucceededIncludes.ql
|
||||
|
||||
6
cpp/ql/justfile
Normal file
6
cpp/ql/justfile
Normal file
@@ -0,0 +1,6 @@
|
||||
import "../../lib.just"
|
||||
|
||||
[no-cd]
|
||||
format *ARGS=".": (_format_ql ARGS)
|
||||
|
||||
consistency_queries := source_dir() / "consistency-queries"
|
||||
@@ -1,3 +1,32 @@
|
||||
## 8.0.3
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 8.0.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 8.0.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol.
|
||||
|
||||
## 8.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.
|
||||
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.
|
||||
|
||||
## 7.1.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: fix
|
||||
---
|
||||
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* CodeQL version 2.24.2 accidentially introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a class `IndirectUninitializedNode` to represent the indirection of an uninitialized local variable as a dataflow node.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a class `DataFlow::IndirectParameterNode` to represent the indirection of a parameter as a dataflow node.
|
||||
* Added a predicate `Node::asIndirectInstruction` which returns the `Instruction` that defines the indirect dataflow node, if any.
|
||||
5
cpp/ql/lib/change-notes/2026-03-24-field-init.md
Normal file
5
cpp/ql/lib/change-notes/2026-03-24-field-init.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a class `ConstructorDirectFieldInit` to represent field initializations that occur in member initializer lists.
|
||||
* Added a class `ConstructorDefaultFieldInit` to represent default field initializations.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The `SourceModelCsv`, `SinkModelCsv`, and `SummaryModelCsv` classes and the associated CSV parsing infrastructure have been removed from `ExternalFlow.qll`. New models should be added as `.model.yml` files in the `ext/` directory.
|
||||
4
cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md
Normal file
4
cpp/ql/lib/change-notes/2026-03-30-nsdmi-dataflow.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added dataflow through members initialized via non-static data member initialization (NSDMI).
|
||||
4
cpp/ql/lib/change-notes/2026-03-31-http-flow-sources.md
Normal file
4
cpp/ql/lib/change-notes/2026-03-31-http-flow-sources.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added `HttpReceiveHttpRequest`, `HttpReceiveRequestEntityBody`, and `HttpReceiveClientCertificate` from Win32's `http.h` as remote flow sources.
|
||||
4
cpp/ql/lib/change-notes/2026-03-31-meson.md
Normal file
4
cpp/ql/lib/change-notes/2026-03-31-meson.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added a subclass `MesonPrivateTestFile` of `ConfigurationTestFile` that represents files created by Meson to test the build configuration.
|
||||
14
cpp/ql/lib/change-notes/released/8.0.0.md
Normal file
14
cpp/ql/lib/change-notes/released/8.0.0.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## 8.0.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* CodeQL version 2.24.2 accidentally introduced a syntactical breaking change to `BarrierGuard<...>::getAnIndirectBarrierNode` and `InstructionBarrierGuard<...>::getAnIndirectBarrierNode`. These breaking changes have now been reverted so that the original code compiles again.
|
||||
* `MustFlow`, the inter-procedural must-flow data flow analysis library, has been re-worked to use parameterized modules. Like in the case of data flow and taint tracking, instead of extending the `MustFlowConfiguration` class, the user should now implement a module with the `MustFlow::ConfigSig` signature, and instantiate the `MustFlow::Global` parameterized module with the implemented module.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Refactored the "Year field changed using an arithmetic operation without checking for leap year" query (`cpp/leap-year/unchecked-after-arithmetic-year-modification`) to address large numbers of false positive results.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* The `allowInterproceduralFlow` predicate of must-flow data flow configurations now correctly handles direct recursion.
|
||||
5
cpp/ql/lib/change-notes/released/8.0.1.md
Normal file
5
cpp/ql/lib/change-notes/released/8.0.1.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 8.0.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Inline expectations test comments, which are of the form `// $ tag` or `// $ tag=value`, are now parsed more strictly and will not be recognized if there isn't a space after the `$` symbol.
|
||||
3
cpp/ql/lib/change-notes/released/8.0.2.md
Normal file
3
cpp/ql/lib/change-notes/released/8.0.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 8.0.2
|
||||
|
||||
No user-facing changes.
|
||||
3
cpp/ql/lib/change-notes/released/8.0.3.md
Normal file
3
cpp/ql/lib/change-notes/released/8.0.3.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 8.0.3
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 7.1.1
|
||||
lastReleaseVersion: 8.0.3
|
||||
|
||||
@@ -31,6 +31,9 @@ extensions:
|
||||
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*5]", "remote", "manual"]
|
||||
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[*6]", "remote", "manual"]
|
||||
- ["", "", False, "WinHttpQueryHeadersEx", "", "", "Argument[**8]", "remote", "manual"]
|
||||
- ["", "", False, "HttpReceiveHttpRequest", "", "", "Argument[*3]", "remote", "manual"]
|
||||
- ["", "", False, "HttpReceiveRequestEntityBody", "", "", "Argument[*3]", "remote", "manual"]
|
||||
- ["", "", False, "HttpReceiveClientCertificate", "", "", "Argument[*3]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
|
||||
22
cpp/ql/lib/ext/ZMQ.model.yml
Normal file
22
cpp/ql/lib/ext/ZMQ.model.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
# ZeroMQ networking library models
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sourceModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||
- ["", "", False, "zmq_recv", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- ["", "", False, "zmq_recvmsg", "", "", "Argument[*1]", "remote", "manual"]
|
||||
- ["", "", False, "zmq_msg_recv", "", "", "Argument[*0]", "remote", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sinkModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, kind, provenance
|
||||
- ["", "", False, "zmq_send", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||
- ["", "", False, "zmq_sendmsg", "", "", "Argument[*1]", "remote-sink", "manual"]
|
||||
- ["", "", False, "zmq_msg_send", "", "", "Argument[*0]", "remote-sink", "manual"]
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: summaryModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, input, output, kind, provenance
|
||||
- ["", "", False, "zmq_msg_init_data", "", "", "Argument[*1]", "Argument[*0]", "taint", "manual"]
|
||||
- ["", "", False, "zmq_msg_data", "", "", "Argument[*0]", "ReturnValue[*]", "taint", "manual"]
|
||||
19
cpp/ql/lib/ext/getc.model.yml
Normal file
19
cpp/ql/lib/ext/getc.model.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
# Models for getc and similar character-reading functions
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/cpp-all
|
||||
extensible: sourceModel
|
||||
data: # namespace, type, subtypes, name, signature, ext, output, kind, provenance
|
||||
- ["", "", False, "getc", "", "", "ReturnValue", "remote", "manual"]
|
||||
- ["", "", False, "getwc", "", "", "ReturnValue", "remote", "manual"]
|
||||
- ["", "", False, "_getc_nolock", "", "", "ReturnValue", "remote", "manual"]
|
||||
- ["", "", False, "_getwc_nolock", "", "", "ReturnValue", "remote", "manual"]
|
||||
- ["", "", False, "getch", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getch", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getwch", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getch_nolock", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getwch_nolock", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "getchar", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "getwchar", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getchar_nolock", "", "", "ReturnValue", "local", "manual"]
|
||||
- ["", "", False, "_getwchar_nolock", "", "", "ReturnValue", "local", "manual"]
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 7.1.2-dev
|
||||
version: 8.0.4-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -26,3 +26,19 @@ class CmakeTryCompileFile extends ConfigurationTestFile {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A file created by Meson to test the system configuration.
|
||||
*/
|
||||
class MesonPrivateTestFile extends ConfigurationTestFile {
|
||||
MesonPrivateTestFile() {
|
||||
this.getBaseName() = "testfile.c" and
|
||||
exists(Folder folder, Folder parent |
|
||||
folder = this.getParentContainer() and
|
||||
parent = folder.getParentContainer()
|
||||
|
|
||||
folder.getBaseName().matches("tmp%") and
|
||||
parent.getBaseName() = "meson-private"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -524,6 +524,12 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
|
||||
not exists(NewOrNewArrayExpr new | e = new.getAllocatorCall().getArgument(0))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this function has an ambiguous return type, meaning that zero or multiple return
|
||||
* types for this function are present in the database (this can occur in `build-mode: none`).
|
||||
*/
|
||||
predicate hasAmbiguousReturnType() { count(this.getType()) != 1 }
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -163,12 +163,23 @@ predicate primitiveVariadicFormatter(
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function call whose target is a variadic formatter with the given
|
||||
* `type`, `format` parameter index and `output` parameter index.
|
||||
*
|
||||
* Join-order helper for `callsVariadicFormatter`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate callsVariadicFormatterCall(FunctionCall fc, string type, int format, int output) {
|
||||
variadicFormatter(fc.getTarget(), type, format, output)
|
||||
}
|
||||
|
||||
private predicate callsVariadicFormatter(
|
||||
Function f, string type, int formatParamIndex, int outputParamIndex
|
||||
) {
|
||||
// calls a variadic formatter with `formatParamIndex`, `outputParamIndex` linked
|
||||
exists(FunctionCall fc, int format, int output |
|
||||
variadicFormatter(pragma[only_bind_into](fc.getTarget()), type, format, output) and
|
||||
callsVariadicFormatterCall(fc, type, format, output) and
|
||||
fc.getEnclosingFunction() = f and
|
||||
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
||||
fc.getArgument(output) = f.getParameter(outputParamIndex).getAnAccess()
|
||||
@@ -176,7 +187,7 @@ private predicate callsVariadicFormatter(
|
||||
or
|
||||
// calls a variadic formatter with only `formatParamIndex` linked
|
||||
exists(FunctionCall fc, string calledType, int format, int output |
|
||||
variadicFormatter(pragma[only_bind_into](fc.getTarget()), calledType, format, output) and
|
||||
callsVariadicFormatterCall(fc, calledType, format, output) and
|
||||
fc.getEnclosingFunction() = f and
|
||||
fc.getArgument(format) = f.getParameter(formatParamIndex).getAnAccess() and
|
||||
not fc.getArgument(output) = f.getParameter(_).getAnAccess() and
|
||||
|
||||
@@ -1663,7 +1663,7 @@ private module Cached {
|
||||
private predicate compares_ge(
|
||||
ValueNumber test, Operand left, Operand right, int k, boolean isGe, GuardValue value
|
||||
) {
|
||||
exists(int onemk | k = 1 - onemk | compares_lt(test, right, left, onemk, isGe, value))
|
||||
compares_lt(test, right, left, 1 - k, isGe, value)
|
||||
}
|
||||
|
||||
/** Rearrange various simple comparisons into `left < right + k` form. */
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/**
|
||||
* INTERNAL use only. This is an experimental API subject to change without notice.
|
||||
*
|
||||
* Provides classes and predicates for dealing with flow models specified in CSV format.
|
||||
* Provides classes and predicates for dealing with flow models specified
|
||||
* in data extension files.
|
||||
*
|
||||
* The CSV specification has the following columns:
|
||||
* The extensible relations have the following columns:
|
||||
* - Sources:
|
||||
* `namespace; type; subtypes; name; signature; ext; output; kind`
|
||||
* - Sinks:
|
||||
@@ -104,117 +105,9 @@ private import internal.FlowSummaryImpl::Private
|
||||
private import internal.FlowSummaryImpl::Private::External
|
||||
private import internal.ExternalFlowExtensions::Extensions as Extensions
|
||||
private import codeql.mad.ModelValidation as SharedModelVal
|
||||
private import codeql.util.Unit
|
||||
private import codeql.mad.static.ModelsAsData as SharedMaD
|
||||
|
||||
/**
|
||||
* A unit class for adding additional source model rows.
|
||||
*
|
||||
* Extend this class to add additional source definitions.
|
||||
*/
|
||||
class SourceModelCsv extends Unit {
|
||||
/** Holds if `row` specifies a source definition. */
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional sink model rows.
|
||||
*
|
||||
* Extend this class to add additional sink definitions.
|
||||
*/
|
||||
class SinkModelCsv extends Unit {
|
||||
/** Holds if `row` specifies a sink definition. */
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional summary model rows.
|
||||
*
|
||||
* Extend this class to add additional flow summary definitions.
|
||||
*/
|
||||
class SummaryModelCsv extends Unit {
|
||||
/** Holds if `row` specifies a summary definition. */
|
||||
abstract predicate row(string row);
|
||||
}
|
||||
|
||||
/** Holds if `row` is a source model. */
|
||||
predicate sourceModel(string row) { any(SourceModelCsv s).row(row) }
|
||||
|
||||
/** Holds if `row` is a sink model. */
|
||||
predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
|
||||
|
||||
/** Holds if `row` is a summary model. */
|
||||
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
|
||||
|
||||
private module MadInput implements SharedMaD::InputSig {
|
||||
/** Holds if a source model exists for the given parameters. */
|
||||
predicate additionalSourceModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string output, string kind, string provenance, string model
|
||||
) {
|
||||
exists(string row |
|
||||
sourceModel(row) and
|
||||
row.splitAt(";", 0) = namespace and
|
||||
row.splitAt(";", 1) = type and
|
||||
row.splitAt(";", 2) = subtypes.toString() and
|
||||
subtypes = [true, false] and
|
||||
row.splitAt(";", 3) = name and
|
||||
row.splitAt(";", 4) = signature and
|
||||
row.splitAt(";", 5) = ext and
|
||||
row.splitAt(";", 6) = output and
|
||||
row.splitAt(";", 7) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
}
|
||||
|
||||
/** Holds if a sink model exists for the given parameters. */
|
||||
predicate additionalSinkModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string kind, string provenance, string model
|
||||
) {
|
||||
exists(string row |
|
||||
sinkModel(row) and
|
||||
row.splitAt(";", 0) = namespace and
|
||||
row.splitAt(";", 1) = type and
|
||||
row.splitAt(";", 2) = subtypes.toString() and
|
||||
subtypes = [true, false] and
|
||||
row.splitAt(";", 3) = name and
|
||||
row.splitAt(";", 4) = signature and
|
||||
row.splitAt(";", 5) = ext and
|
||||
row.splitAt(";", 6) = input and
|
||||
row.splitAt(";", 7) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a summary model exists for the given parameters.
|
||||
*
|
||||
* This predicate does not expand `@` to `*`s.
|
||||
*/
|
||||
predicate additionalSummaryModel(
|
||||
string namespace, string type, boolean subtypes, string name, string signature, string ext,
|
||||
string input, string output, string kind, string provenance, string model
|
||||
) {
|
||||
exists(string row |
|
||||
summaryModel(row) and
|
||||
row.splitAt(";", 0) = namespace and
|
||||
row.splitAt(";", 1) = type and
|
||||
row.splitAt(";", 2) = subtypes.toString() and
|
||||
subtypes = [true, false] and
|
||||
row.splitAt(";", 3) = name and
|
||||
row.splitAt(";", 4) = signature and
|
||||
row.splitAt(";", 5) = ext and
|
||||
row.splitAt(";", 6) = input and
|
||||
row.splitAt(";", 7) = output and
|
||||
row.splitAt(";", 8) = kind
|
||||
) and
|
||||
provenance = "manual" and
|
||||
model = ""
|
||||
}
|
||||
|
||||
string namespaceSegmentSeparator() { result = "::" }
|
||||
}
|
||||
|
||||
@@ -250,8 +143,8 @@ predicate summaryModel(
|
||||
)
|
||||
}
|
||||
|
||||
/** Provides a query predicate to check the CSV data for validation errors. */
|
||||
module CsvValidation {
|
||||
/** Provides a query predicate to check the data for validation errors. */
|
||||
module ModelValidation {
|
||||
private string getInvalidModelInput() {
|
||||
exists(string pred, AccessPath input, string part |
|
||||
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
|
||||
@@ -294,40 +187,6 @@ module CsvValidation {
|
||||
|
||||
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
|
||||
|
||||
private string getInvalidModelSubtype() {
|
||||
exists(string pred, string row |
|
||||
sourceModel(row) and pred = "source"
|
||||
or
|
||||
sinkModel(row) and pred = "sink"
|
||||
or
|
||||
summaryModel(row) and pred = "summary"
|
||||
|
|
||||
exists(string b |
|
||||
b = row.splitAt(";", 2) and
|
||||
not b = ["true", "false"] and
|
||||
result = "Invalid boolean \"" + b + "\" in " + pred + " model."
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private string getInvalidModelColumnCount() {
|
||||
exists(string pred, string row, int expect |
|
||||
sourceModel(row) and expect = 8 and pred = "source"
|
||||
or
|
||||
sinkModel(row) and expect = 8 and pred = "sink"
|
||||
or
|
||||
summaryModel(row) and expect = 9 and pred = "summary"
|
||||
|
|
||||
exists(int cols |
|
||||
cols = 1 + max(int n | exists(row.splitAt(";", n))) and
|
||||
cols != expect and
|
||||
result =
|
||||
"Wrong number of columns in " + pred + " model row, expected " + expect + ", got " + cols +
|
||||
"."
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private string getInvalidModelSignature() {
|
||||
exists(string pred, string namespace, string type, string name, string signature, string ext |
|
||||
sourceModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "source"
|
||||
@@ -353,12 +212,25 @@ module CsvValidation {
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if some row in a CSV-based flow model appears to contain typos. */
|
||||
private string getIncorrectConstructorSummaryOutput() {
|
||||
exists(string namespace, string type, string name, string output |
|
||||
type = name or
|
||||
type = name + "<" + any(string s)
|
||||
|
|
||||
summaryModel(namespace, type, _, name, _, _, _, output, _, _, _) and
|
||||
output.matches("ReturnValue%") and
|
||||
result =
|
||||
"Constructor model for " + namespace + "." + type +
|
||||
" should use `Argument[this]` in the output, not `ReturnValue`."
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if some row in a MaD flow model appears to contain typos. */
|
||||
query predicate invalidModelRow(string msg) {
|
||||
msg =
|
||||
[
|
||||
getInvalidModelSignature(), getInvalidModelInput(), getInvalidModelOutput(),
|
||||
getInvalidModelSubtype(), getInvalidModelColumnCount(), KindVal::getInvalidModelKind()
|
||||
KindVal::getInvalidModelKind(), getIncorrectConstructorSummaryOutput()
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -555,6 +427,7 @@ private Locatable getSupportedFunctionTemplateArgument(Function templateFunction
|
||||
* Normalize the `n`'th parameter of `f` by replacing template names
|
||||
* with `func:N` (where `N` is the index of the template).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private string getTypeNameWithoutFunctionTemplates(Function f, int n, int remaining) {
|
||||
exists(Function templateFunction |
|
||||
templateFunction = getFullyTemplatedFunction(f) and
|
||||
@@ -1011,7 +884,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a source with the given kind in a CSV flow
|
||||
* Holds if `node` is specified as a source with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
@@ -1022,7 +895,7 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `node` is specified as a sink with the given kind in a CSV flow
|
||||
* Holds if `node` is specified as a sink with the given kind in a MaD flow
|
||||
* model.
|
||||
*/
|
||||
cached
|
||||
|
||||
@@ -201,7 +201,7 @@ module SourceSinkInterpretationInput implements
|
||||
string toString() {
|
||||
result = this.asElement().toString()
|
||||
or
|
||||
result = this.asNode().toString()
|
||||
result = this.asNode().toStringImpl()
|
||||
or
|
||||
result = this.asCall().toString()
|
||||
}
|
||||
|
||||
@@ -585,12 +585,15 @@ class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit
|
||||
|
||||
/**
|
||||
* An initialization of a member variable performed as part of a
|
||||
* constructor's explicit initializer list or implicit actions.
|
||||
* constructor's initializer list or by default initialization.
|
||||
*
|
||||
* In the example below, member variable `b` is being initialized by
|
||||
* constructor parameter `a`:
|
||||
* constructor parameter `a`, and `c` is initialized by default
|
||||
* initialization:
|
||||
* ```
|
||||
* struct S {
|
||||
* int b;
|
||||
* int c = 3;
|
||||
* S(int a): b(a) {}
|
||||
* } s(2);
|
||||
* ```
|
||||
@@ -616,6 +619,28 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
|
||||
override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An initialization of a member variable performed as part of a
|
||||
* constructor's explicit initializer list.
|
||||
*/
|
||||
class ConstructorDirectFieldInit extends ConstructorFieldInit {
|
||||
ConstructorDirectFieldInit() { exists(this.getChild(0)) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDirectFieldInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An initialization of a member variable performed by default
|
||||
* initialization.
|
||||
*/
|
||||
class ConstructorDefaultFieldInit extends ConstructorFieldInit {
|
||||
ConstructorDefaultFieldInit() {
|
||||
not exists(this.getChild(0)) and exists(this.getTarget().getInitializer())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConstructorDefaultFieldInit" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a destructor of a base class or field as part of a destructor's
|
||||
* compiler-generated actions.
|
||||
|
||||
@@ -6,117 +6,67 @@ private import OverlayXml
|
||||
|
||||
/**
|
||||
* Holds always for the overlay variant and never for the base variant.
|
||||
* This local predicate is used to define local predicates that behave
|
||||
* differently for the base and overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
|
||||
|
||||
overlay[local]
|
||||
private string getLocationFilePath(@location_default loc) {
|
||||
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path for an element with a single location.
|
||||
* Holds if the TRAP file or tag `t` is reachable from source file `sourceFile`
|
||||
* in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant.
|
||||
*/
|
||||
overlay[local]
|
||||
private string getSingleLocationFilePath(@element e) {
|
||||
exists(@location_default loc |
|
||||
var_decls(e, _, _, _, loc)
|
||||
or
|
||||
fun_decls(e, _, _, _, loc)
|
||||
or
|
||||
type_decls(e, _, loc)
|
||||
or
|
||||
namespace_decls(e, _, loc, _)
|
||||
or
|
||||
macroinvocations(e, _, loc, _)
|
||||
or
|
||||
preprocdirects(e, _, loc)
|
||||
or
|
||||
diagnostics(e, _, _, _, _, loc)
|
||||
or
|
||||
usings(e, _, loc, _)
|
||||
or
|
||||
static_asserts(e, _, _, loc, _)
|
||||
or
|
||||
derivations(e, _, _, _, loc)
|
||||
or
|
||||
frienddecls(e, _, _, loc)
|
||||
or
|
||||
comments(e, _, loc)
|
||||
or
|
||||
exprs(e, _, loc)
|
||||
or
|
||||
stmts(e, _, loc)
|
||||
or
|
||||
initialisers(e, _, _, loc)
|
||||
or
|
||||
attributes(e, _, _, _, loc)
|
||||
or
|
||||
attribute_args(e, _, _, _, loc)
|
||||
or
|
||||
namequalifiers(e, _, _, loc)
|
||||
or
|
||||
enumconstants(e, _, _, _, _, loc)
|
||||
or
|
||||
type_mentions(e, _, loc, _)
|
||||
or
|
||||
lambda_capture(e, _, _, _, _, _, loc)
|
||||
or
|
||||
concept_templates(e, _, loc)
|
||||
|
|
||||
result = getLocationFilePath(loc)
|
||||
private predicate locallyReachableTrapOrTag(
|
||||
boolean isOverlayVariant, string sourceFile, @trap_or_tag t
|
||||
) {
|
||||
exists(@source_file sf, @trap trap |
|
||||
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
|
||||
source_file_uses_trap(sf, trap) and
|
||||
source_file_name(sf, sourceFile) and
|
||||
(t = trap or trap_uses_tag(trap, t))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the file path for an element with potentially multiple locations.
|
||||
* Holds if element `e` is in TRAP file or tag `t`
|
||||
* in the base (isOverlayVariant=false) or overlay (isOverlayVariant=true) variant.
|
||||
*/
|
||||
overlay[local]
|
||||
private string getMultiLocationFilePath(@element e) {
|
||||
exists(@location_default loc |
|
||||
var_decls(_, e, _, _, loc)
|
||||
or
|
||||
fun_decls(_, e, _, _, loc)
|
||||
or
|
||||
type_decls(_, e, loc)
|
||||
or
|
||||
namespace_decls(_, e, loc, _)
|
||||
|
|
||||
result = getLocationFilePath(loc)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A local helper predicate that holds in the base variant and never in the
|
||||
* overlay variant.
|
||||
*/
|
||||
overlay[local]
|
||||
private predicate isBase() { not isOverlay() }
|
||||
|
||||
/**
|
||||
* Holds if `path` was extracted in the overlay database.
|
||||
*/
|
||||
overlay[local]
|
||||
private predicate overlayHasFile(string path) {
|
||||
isOverlay() and
|
||||
files(_, path) and
|
||||
path != ""
|
||||
private predicate locallyInTrapOrTag(boolean isOverlayVariant, @element e, @trap_or_tag t) {
|
||||
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
|
||||
in_trap_or_tag(e, t)
|
||||
}
|
||||
|
||||
/**
|
||||
* Discards an element from the base variant if:
|
||||
* - It has a single location in a file extracted in the overlay, or
|
||||
* - All of its locations are in files extracted in the overlay.
|
||||
* - We have knowledge about what TRAP file or tag it is in (in the base).
|
||||
* - It is not in any overlay TRAP file or tag that is reachable from an overlay source file.
|
||||
* - For every base TRAP file or tag that contains it and is reachable from a base source file,
|
||||
* either the source file has changed, or the overlay has redefined the TRAP file or tag,
|
||||
* or the overlay runner has re-extracted the same source file.
|
||||
*/
|
||||
overlay[discard_entity]
|
||||
private predicate discardElement(@element e) {
|
||||
isBase() and
|
||||
(
|
||||
overlayHasFile(getSingleLocationFilePath(e))
|
||||
or
|
||||
forex(string path | path = getMultiLocationFilePath(e) | overlayHasFile(path))
|
||||
// If we don't have any knowledge about what TRAP file something
|
||||
// is in, then we don't want to discard it, so we only consider
|
||||
// entities that are known to be in a base TRAP file or tag.
|
||||
locallyInTrapOrTag(false, e, _) and
|
||||
// Anything that is reachable from an overlay source file should
|
||||
// not be discarded.
|
||||
not exists(@trap_or_tag t | locallyInTrapOrTag(true, e, t) |
|
||||
locallyReachableTrapOrTag(true, _, t)
|
||||
) and
|
||||
// Finally, we have to make sure the base variant does not retain it.
|
||||
// If it is reachable from a base source file, then that is
|
||||
// sufficient unless either the base source file has changed (in
|
||||
// particular, been deleted), or the overlay has redefined the TRAP
|
||||
// file or tag it is in, or the overlay runner has re-extracted the same
|
||||
// source file (e.g. because a header it includes has changed).
|
||||
forall(@trap_or_tag t, string sourceFile |
|
||||
locallyInTrapOrTag(false, e, t) and
|
||||
locallyReachableTrapOrTag(false, sourceFile, t)
|
||||
|
|
||||
overlayChangedFiles(sourceFile) or
|
||||
locallyReachableTrapOrTag(true, _, t) or
|
||||
locallyReachableTrapOrTag(true, sourceFile, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -238,7 +238,12 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {
|
||||
|
||||
private import TypeTracking<Location, TtInput>::TypeTrack<qualifierSource/1>::Graph<qualifierOfVirtualCall/1>
|
||||
|
||||
private predicate edgePlus(PathNode n1, PathNode n2) = fastTC(edges/2)(n1, n2)
|
||||
private predicate isSource(PathNode n) { n.isSource() }
|
||||
|
||||
private predicate isSink(PathNode n) { n.isSink() }
|
||||
|
||||
private predicate edgePlus(PathNode n1, PathNode n2) =
|
||||
doublyBoundedFastTC(edges/2, isSource/1, isSink/1)(n1, n2)
|
||||
|
||||
/**
|
||||
* Gets the most specific implementation of `mf` that may be called when the
|
||||
@@ -255,6 +260,15 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private MemberFunction mostSpecificForSource(PathNode p1, MemberFunction mf) {
|
||||
p1.isSource() and
|
||||
exists(Class derived |
|
||||
qualifierSourceImpl(p1.getNode(), derived) and
|
||||
result = mostSpecific(mf, derived)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a possible pair of end-points `(p1, p2)` where:
|
||||
* - `p1` is a derived-to-base conversion that converts from some
|
||||
@@ -264,16 +278,16 @@ private module TrackVirtualDispatch<methodDispatchSig/1 virtualDispatch0> {
|
||||
* - `callable` is the most specific implementation that may be called when
|
||||
* the qualifier has type `derived`.
|
||||
*/
|
||||
bindingset[p1, p2]
|
||||
pragma[inline_late]
|
||||
private predicate pairCand(
|
||||
PathNode p1, PathNode p2, DataFlowPrivate::DataFlowCallable callable,
|
||||
DataFlowPrivate::DataFlowCall call
|
||||
) {
|
||||
exists(Class derived, MemberFunction mf |
|
||||
qualifierSourceImpl(p1.getNode(), derived) and
|
||||
p2.isSink() and
|
||||
exists(MemberFunction mf |
|
||||
qualifierOfVirtualCallImpl(p2.getNode(), call.asCallInstruction(), mf) and
|
||||
p1.isSource() and
|
||||
p2.isSink() and
|
||||
callable.asSourceCallable() = mostSpecific(mf, derived)
|
||||
callable.asSourceCallable() = mostSpecificForSource(p1, mf)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
1881
cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll
Normal file
1881
cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
private import cpp as Cpp
|
||||
private import DataFlowUtil
|
||||
private import DataFlowNodes
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import DataFlowDispatch
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
@@ -16,28 +17,42 @@ private import semmle.code.cpp.dataflow.ExternalFlow as External
|
||||
cached
|
||||
private module Cached {
|
||||
cached
|
||||
module Nodes0 {
|
||||
cached
|
||||
newtype TIRDataFlowNode0 =
|
||||
TInstructionNode0(Instruction i) {
|
||||
not Ssa::ignoreInstruction(i) and
|
||||
not exists(Operand op |
|
||||
not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op)
|
||||
) and
|
||||
// We exclude `void`-typed instructions because they cannot contain data.
|
||||
// However, if the instruction is a glvalue, and their type is `void`, then the result
|
||||
// type of the instruction is really `void*`, and thus we still want to have a dataflow
|
||||
// node for it.
|
||||
(not i.getResultType() instanceof VoidType or i.isGLValue())
|
||||
} or
|
||||
TMultipleUseOperandNode0(Operand op) {
|
||||
not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op))
|
||||
} or
|
||||
TSingleUseOperandNode0(Operand op) {
|
||||
not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op))
|
||||
}
|
||||
newtype TIRDataFlowNode0 =
|
||||
TInstructionNode0(Instruction i) {
|
||||
not Ssa::ignoreInstruction(i) and
|
||||
not exists(Operand op |
|
||||
not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op)
|
||||
) and
|
||||
// We exclude `void`-typed instructions because they cannot contain data.
|
||||
// However, if the instruction is a glvalue, and their type is `void`, then the result
|
||||
// type of the instruction is really `void*`, and thus we still want to have a dataflow
|
||||
// node for it.
|
||||
(not i.getResultType() instanceof VoidType or i.isGLValue())
|
||||
} or
|
||||
TMultipleUseOperandNode0(Operand op) {
|
||||
not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op))
|
||||
} or
|
||||
TSingleUseOperandNode0(Operand op) {
|
||||
not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op))
|
||||
}
|
||||
|
||||
cached
|
||||
string toStringCached(Node n) {
|
||||
result = toExprString(n)
|
||||
or
|
||||
not exists(toExprString(n)) and
|
||||
result = n.toStringImpl()
|
||||
}
|
||||
|
||||
cached
|
||||
Location getLocationCached(Node n) { result = n.getLocationImpl() }
|
||||
|
||||
cached
|
||||
newtype TContentApprox =
|
||||
TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or
|
||||
TUnionApproxContent(string s) { unionHasApproxName(_, s) } or
|
||||
TElementApproxContent()
|
||||
|
||||
/**
|
||||
* Gets an additional term that is added to the `join` and `branch` computations to reflect
|
||||
* an additional forward or backwards branching factor that is not taken into account
|
||||
@@ -59,38 +74,174 @@ private module Cached {
|
||||
result = countNumberOfBranchesUsingParameter(switch, p)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
private import Nodes0
|
||||
cached
|
||||
newtype TDataFlowCallable =
|
||||
TSourceCallable(Cpp::Declaration decl) or
|
||||
TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c)
|
||||
|
||||
/**
|
||||
* A module for calculating the number of stars (i.e., `*`s) needed for various
|
||||
* dataflow node `toString` predicates.
|
||||
*/
|
||||
module NodeStars {
|
||||
private int getNumberOfIndirections(Node n) {
|
||||
result = n.(RawIndirectOperand).getIndirectionIndex()
|
||||
cached
|
||||
newtype TDataFlowCall =
|
||||
TNormalCall(CallInstruction call) or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
) {
|
||||
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that loses the
|
||||
* calling context. For example, this would happen with flow through a
|
||||
* global or static variable.
|
||||
*/
|
||||
cached
|
||||
predicate jumpStep(Node n1, Node n2) {
|
||||
exists(GlobalLikeVariable v |
|
||||
exists(Ssa::GlobalUse globalUse |
|
||||
v = globalUse.getVariable() and
|
||||
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
||||
|
|
||||
globalUse.getIndirection() = getMinIndirectionForGlobalUse(globalUse) and
|
||||
v = n2.asVariable()
|
||||
or
|
||||
v = n2.asIndirectVariable(globalUse.getIndirection())
|
||||
)
|
||||
or
|
||||
exists(Ssa::GlobalDef globalDef |
|
||||
v = globalDef.getVariable() and
|
||||
n2.(InitialGlobalValue).getGlobalDef() = globalDef
|
||||
|
|
||||
globalDef.getIndirection() = getMinIndirectionForGlobalDef(globalDef) and
|
||||
v = n1.asVariable()
|
||||
or
|
||||
v = n1.asIndirectVariable(globalDef.getIndirection())
|
||||
)
|
||||
)
|
||||
or
|
||||
result = n.(RawIndirectInstruction).getIndirectionIndex()
|
||||
or
|
||||
result = n.(VariableNode).getIndirectionIndex()
|
||||
or
|
||||
result = n.(PostUpdateNodeImpl).getIndirectionIndex()
|
||||
or
|
||||
result = n.(FinalParameterNode).getIndirectionIndex()
|
||||
or
|
||||
result = n.(BodyLessParameterNodeImpl).getIndirectionIndex()
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(),
|
||||
n2.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of stars (i.e., `*`s) needed to produce the `toString`
|
||||
* output for `n`.
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*
|
||||
* The boolean `certain` is true if the destination address does not involve
|
||||
* any pointer arithmetic, and false otherwise.
|
||||
*/
|
||||
string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) }
|
||||
cached
|
||||
predicate storeStepImpl(Node node1, Content c, Node node2, boolean certain) {
|
||||
exists(
|
||||
PostFieldUpdateNode postFieldUpdate, int indirectionIndex1, int numberOfLoads,
|
||||
StoreInstruction store, FieldContent fc
|
||||
|
|
||||
postFieldUpdate = node2 and
|
||||
fc = c and
|
||||
nodeHasInstruction(node1, pragma[only_bind_into](store),
|
||||
pragma[only_bind_into](indirectionIndex1)) and
|
||||
postFieldUpdate.getIndirectionIndex() = 1 and
|
||||
numberOfLoadsFromOperand(postFieldUpdate.getFieldAddress(),
|
||||
store.getDestinationAddressOperand(), numberOfLoads, certain) and
|
||||
fc.getAField() = postFieldUpdate.getUpdatedField() and
|
||||
getIndirectionIndexLate(fc) = 1 + indirectionIndex1 + numberOfLoads
|
||||
)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode()) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*/
|
||||
cached
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepImpl(node1, c, node2, _) }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a read of `f`.
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
cached
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(
|
||||
FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2, FieldContent fc
|
||||
|
|
||||
fc = c and
|
||||
nodeHasOperand(node2, operand, indirectionIndex2) and
|
||||
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
|
||||
// in `storeStep`.
|
||||
nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and
|
||||
numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _) and
|
||||
fc.getAField() = fa1.getField() and
|
||||
getIndirectionIndexLate(fc) = indirectionIndex2 + numberOfLoads
|
||||
)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
cached
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
n =
|
||||
any(PostUpdateNode pun, Content d |
|
||||
d.impliesClearOf(c) and storeStepImpl(_, d, pun, true)
|
||||
|
|
||||
pun
|
||||
).getPreUpdateNode() and
|
||||
(
|
||||
not exists(Operand op, Cpp::Operation p |
|
||||
n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and
|
||||
(
|
||||
p instanceof Cpp::AssignPointerAddExpr or
|
||||
p instanceof Cpp::AssignPointerSubExpr or
|
||||
p instanceof Cpp::CrementOperation
|
||||
)
|
||||
|
|
||||
p.getAnOperand() = op.getUse().getAst()
|
||||
)
|
||||
or
|
||||
forex(PostUpdateNode pun, Content d |
|
||||
pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and
|
||||
storeStepImpl(_, d, pun, true) and
|
||||
pun.getPreUpdateNode() = n
|
||||
|
|
||||
c.(Content).getIndirectionIndex() = d.getIndirectionIndex()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
import NodeStars
|
||||
import Cached
|
||||
|
||||
private int getNumberOfIndirections(Node n) {
|
||||
result = n.(RawIndirectOperand).getIndirectionIndex()
|
||||
or
|
||||
result = n.(RawIndirectInstruction).getIndirectionIndex()
|
||||
or
|
||||
result = n.(VariableNode).getIndirectionIndex()
|
||||
or
|
||||
result = n.(PostUpdateNodeImpl).getIndirectionIndex()
|
||||
or
|
||||
result = n.(FinalParameterNode).getIndirectionIndex()
|
||||
or
|
||||
result = n.(BodyLessParameterNodeImpl).getIndirectionIndex()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of stars (i.e., `*`s) needed to produce the `toString`
|
||||
* output for `n`.
|
||||
*/
|
||||
string stars(Node n) { result = repeatStars(getNumberOfIndirections(n)) }
|
||||
|
||||
/**
|
||||
* A cut-down `DataFlow::Node` class that does not depend on the output of SSA.
|
||||
@@ -828,85 +979,10 @@ private int getMinIndirectionForGlobalDef(Ssa::GlobalDef def) {
|
||||
result = getMinIndirectionsForType(def.getUnspecifiedType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that loses the
|
||||
* calling context. For example, this would happen with flow through a
|
||||
* global or static variable.
|
||||
*/
|
||||
predicate jumpStep(Node n1, Node n2) {
|
||||
exists(GlobalLikeVariable v |
|
||||
exists(Ssa::GlobalUse globalUse |
|
||||
v = globalUse.getVariable() and
|
||||
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
||||
|
|
||||
globalUse.getIndirection() = getMinIndirectionForGlobalUse(globalUse) and
|
||||
v = n2.asVariable()
|
||||
or
|
||||
v = n2.asIndirectVariable(globalUse.getIndirection())
|
||||
)
|
||||
or
|
||||
exists(Ssa::GlobalDef globalDef |
|
||||
v = globalDef.getVariable() and
|
||||
n2.(InitialGlobalValue).getGlobalDef() = globalDef
|
||||
|
|
||||
globalDef.getIndirection() = getMinIndirectionForGlobalDef(globalDef) and
|
||||
v = n1.asVariable()
|
||||
or
|
||||
v = n1.asIndirectVariable(globalDef.getIndirection())
|
||||
)
|
||||
)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(),
|
||||
n2.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
bindingset[c]
|
||||
pragma[inline_late]
|
||||
private int getIndirectionIndexLate(Content c) { result = c.getIndirectionIndex() }
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*
|
||||
* The boolean `certain` is true if the destination address does not involve
|
||||
* any pointer arithmetic, and false otherwise. This has to do with whether a
|
||||
* store step can be used to clear a field (see `clearsContent`).
|
||||
*/
|
||||
predicate storeStepImpl(Node node1, Content c, Node node2, boolean certain) {
|
||||
exists(
|
||||
PostFieldUpdateNode postFieldUpdate, int indirectionIndex1, int numberOfLoads,
|
||||
StoreInstruction store, FieldContent fc
|
||||
|
|
||||
postFieldUpdate = node2 and
|
||||
fc = c and
|
||||
nodeHasInstruction(node1, pragma[only_bind_into](store),
|
||||
pragma[only_bind_into](indirectionIndex1)) and
|
||||
postFieldUpdate.getIndirectionIndex() = 1 and
|
||||
numberOfLoadsFromOperand(postFieldUpdate.getFieldAddress(),
|
||||
store.getDestinationAddressOperand(), numberOfLoads, certain) and
|
||||
fc.getAField() = postFieldUpdate.getUpdatedField() and
|
||||
getIndirectionIndexLate(fc) = 1 + indirectionIndex1 + numberOfLoads
|
||||
)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode()) and
|
||||
certain = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
|
||||
* Thus, `node2` references an object with a field `f` that contains the
|
||||
* value of `node1`.
|
||||
*/
|
||||
predicate storeStep(Node node1, ContentSet c, Node node2) { storeStepImpl(node1, c, node2, _) }
|
||||
|
||||
/**
|
||||
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
|
||||
* operations and exactly `n` `LoadInstruction` operations.
|
||||
*/
|
||||
private predicate numberOfLoadsFromOperandRec(
|
||||
Operand operandFrom, Operand operandTo, int ind, boolean certain
|
||||
) {
|
||||
@@ -957,63 +1033,6 @@ predicate nodeHasInstruction(Node node, Instruction instr, int indirectionIndex)
|
||||
hasInstructionAndIndex(node, instr, indirectionIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a read of `f`.
|
||||
* Thus, `node1` references an object with a field `f` whose value ends up in
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, ContentSet c, Node node2) {
|
||||
exists(
|
||||
FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2, FieldContent fc
|
||||
|
|
||||
fc = c and
|
||||
nodeHasOperand(node2, operand, indirectionIndex2) and
|
||||
// The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct
|
||||
// in `storeStep`.
|
||||
nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and
|
||||
numberOfLoadsFromOperand(fa1, operand, numberOfLoads, _) and
|
||||
fc.getAField() = fa1.getField() and
|
||||
getIndirectionIndexLate(fc) = indirectionIndex2 + numberOfLoads
|
||||
)
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
|
||||
node2.(FlowSummaryNode).getSummaryNode())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at node `n`.
|
||||
*/
|
||||
predicate clearsContent(Node n, ContentSet c) {
|
||||
n =
|
||||
any(PostUpdateNode pun, Content d | d.impliesClearOf(c) and storeStepImpl(_, d, pun, true) | pun)
|
||||
.getPreUpdateNode() and
|
||||
(
|
||||
// The crement operations and pointer addition and subtraction self-assign. We do not
|
||||
// want to clear the contents if it is indirectly pointed at by any of these operations,
|
||||
// as part of the contents might still be accessible afterwards. If there is no such
|
||||
// indirection clearing the contents is safe.
|
||||
not exists(Operand op, Cpp::Operation p |
|
||||
n.(IndirectOperand).hasOperandAndIndirectionIndex(op, _) and
|
||||
(
|
||||
p instanceof Cpp::AssignPointerAddExpr or
|
||||
p instanceof Cpp::AssignPointerSubExpr or
|
||||
p instanceof Cpp::CrementOperation
|
||||
)
|
||||
|
|
||||
p.getAnOperand() = op.getUse().getAst()
|
||||
)
|
||||
or
|
||||
forex(PostUpdateNode pun, Content d |
|
||||
pragma[only_bind_into](d).impliesClearOf(pragma[only_bind_into](c)) and
|
||||
storeStepImpl(_, d, pun, true) and
|
||||
pun.getPreUpdateNode() = n
|
||||
|
|
||||
c.(Content).getIndirectionIndex() = d.getIndirectionIndex()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value that is being tracked is expected to be stored inside content `c`
|
||||
* at node `n`.
|
||||
@@ -1046,11 +1065,6 @@ class CastNode extends Node {
|
||||
CastNode() { none() } // stub implementation
|
||||
}
|
||||
|
||||
cached
|
||||
private newtype TDataFlowCallable =
|
||||
TSourceCallable(Cpp::Declaration decl) or
|
||||
TSummarizedCallable(FlowSummaryImpl::Public::SummarizedCallable c)
|
||||
|
||||
/**
|
||||
* A callable, which may be:
|
||||
* - a function (that may contain code)
|
||||
@@ -1134,15 +1148,6 @@ class DataFlowType extends TypeFinal {
|
||||
string toString() { result = "" }
|
||||
}
|
||||
|
||||
cached
|
||||
private newtype TDataFlowCall =
|
||||
TNormalCall(CallInstruction call) or
|
||||
TSummaryCall(
|
||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||
) {
|
||||
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
|
||||
}
|
||||
|
||||
private predicate summarizedCallableIsManual(SummarizedCallable sc) {
|
||||
sc.asSummarizedCallable().hasManualModel()
|
||||
}
|
||||
@@ -1165,7 +1170,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
Function getStaticCallSourceTarget() { none() }
|
||||
Declaration getStaticCallSourceTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the target of this call. We use the following strategy for deciding
|
||||
@@ -1177,7 +1182,7 @@ class DataFlowCall extends TDataFlowCall {
|
||||
* whether is it manual or generated.
|
||||
*/
|
||||
final DataFlowCallable getStaticCallTarget() {
|
||||
exists(Function target | target = this.getStaticCallSourceTarget() |
|
||||
exists(Declaration target | target = this.getStaticCallSourceTarget() |
|
||||
// Don't use the source callable if there is a manual model for the
|
||||
// target
|
||||
not exists(SummarizedCallable sc |
|
||||
@@ -1237,7 +1242,7 @@ private class NormalCall extends DataFlowCall, TNormalCall {
|
||||
|
||||
override CallTargetOperand getCallTargetOperand() { result = call.getCallTargetOperand() }
|
||||
|
||||
override Function getStaticCallSourceTarget() { result = call.getStaticCallTarget() }
|
||||
override Declaration getStaticCallSourceTarget() { result = call.getStaticCallTarget() }
|
||||
|
||||
override ArgumentOperand getArgumentOperand(int index) { result = call.getArgumentOperand(index) }
|
||||
|
||||
@@ -1523,12 +1528,6 @@ private predicate fieldHasApproxName(Field f, string s) {
|
||||
|
||||
private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().charAt(0) }
|
||||
|
||||
cached
|
||||
private newtype TContentApprox =
|
||||
TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or
|
||||
TUnionApproxContent(string s) { unionHasApproxName(_, s) } or
|
||||
TElementApproxContent()
|
||||
|
||||
/** An approximated `Content`. */
|
||||
class ContentApprox extends TContentApprox {
|
||||
string toString() { none() } // overridden in subclasses
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,8 +6,8 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import DataFlowUtil
|
||||
private import DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
|
||||
private import DataFlowNodes
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
@@ -73,17 +73,9 @@ private module Cached {
|
||||
// a result for `getConvertedResultExpression`. We remap this here so that
|
||||
// this `ConvertInstruction` maps to the result of the expression that
|
||||
// represents the extent.
|
||||
exists(TranslatedNonConstantAllocationSize tas |
|
||||
result = tas.getExtent().getExpr() and
|
||||
instr = tas.getInstruction(AllocationExtentConvertTag())
|
||||
)
|
||||
result = IRConstruction::Raw::getAllocationExtentConvertExpr(instr)
|
||||
or
|
||||
// There's no instruction that returns `ParenthesisExpr`, but some queries
|
||||
// expect this
|
||||
exists(TranslatedTransparentConversion ttc |
|
||||
result = ttc.getExpr().(ParenthesisExpr) and
|
||||
instr = ttc.getResult()
|
||||
)
|
||||
result = IRConstruction::Raw::getTransparentConversionParenthesisExpr(instr)
|
||||
or
|
||||
// Certain expressions generate `CopyValueInstruction`s only when they
|
||||
// are needed. Examples of this include crement operations and compound
|
||||
@@ -112,10 +104,10 @@ private module Cached {
|
||||
// needed, and in that case the only value that will propagate forward in
|
||||
// the program is the value that's been updated. So in those cases we just
|
||||
// use the result of `node.asDefinition()` as the result of `node.asExpr()`.
|
||||
exists(TranslatedCoreExpr tco |
|
||||
tco.getInstruction(_) = instr and
|
||||
tco.producesExprResult() and
|
||||
result = asDefinitionImpl0(instr)
|
||||
exists(StoreInstruction store |
|
||||
store = instr and
|
||||
IRConstruction::Raw::instructionProducesExprResult(store) and
|
||||
result = asDefinitionImpl0(store)
|
||||
)
|
||||
or
|
||||
// IR construction breaks an array aggregate literal `{1, 2, 3}` into a
|
||||
@@ -145,18 +137,9 @@ private module Cached {
|
||||
// For an expression such as `i += 2` we pretend that the generated
|
||||
// `StoreInstruction` contains the result of the expression even though
|
||||
// this isn't totally aligned with the C/C++ standard.
|
||||
exists(TranslatedAssignOperation tao |
|
||||
store = tao.getInstruction(AssignmentStoreTag()) and
|
||||
result = tao.getExpr()
|
||||
)
|
||||
result = IRConstruction::Raw::getAssignOperationStoreExpr(store)
|
||||
or
|
||||
// Similarly for `i++` and `++i` we pretend that the generated
|
||||
// `StoreInstruction` contains the result of the expression even though
|
||||
// this isn't totally aligned with the C/C++ standard.
|
||||
exists(TranslatedCrementOperation tco |
|
||||
store = tco.getInstruction(CrementStoreTag()) and
|
||||
result = tco.getExpr()
|
||||
)
|
||||
result = IRConstruction::Raw::getCrementOperationStoreExpr(store)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,11 +149,7 @@ private module Cached {
|
||||
*/
|
||||
private predicate excludeAsDefinitionResult(StoreInstruction store) {
|
||||
// Exclude the store to the temporary generated by a ternary expression.
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
store = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
store = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
)
|
||||
IRConstruction::Raw::isConditionalExprTempStore(store)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
private import DataFlowUtil
|
||||
private import DataFlowNodes
|
||||
private import DataFlowPrivate
|
||||
private import SsaImpl as Ssa
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
|
||||
private import PrintIRUtilities
|
||||
|
||||
/** A property provider for local IR dataflow store steps. */
|
||||
|
||||
@@ -2,6 +2,7 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
|
||||
private import SsaImpl as Ssa
|
||||
private import PrintIRUtilities
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowNodes
|
||||
|
||||
private Instruction getInstruction(Node n, string stars) {
|
||||
result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and
|
||||
|
||||
@@ -10,8 +10,9 @@ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
|
||||
private import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedInitialization
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowNodes
|
||||
import SsaImplCommon
|
||||
|
||||
private module SourceVariables {
|
||||
@@ -438,10 +439,7 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
|
||||
* initialize `v`.
|
||||
*/
|
||||
private Instruction getInitializationTargetAddress(IRVariable v) {
|
||||
exists(TranslatedVariableInitialization init |
|
||||
init.getIRVariable() = v and
|
||||
result = init.getTargetAddress()
|
||||
)
|
||||
result = IRConstruction::Raw::getInitializationTargetAddress(v)
|
||||
}
|
||||
|
||||
/** An initial definition of an SSA variable address. */
|
||||
|
||||
@@ -4,75 +4,25 @@ import semmle.code.cpp.ir.internal.IRCppLanguage
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import DataFlowUtil
|
||||
private import DataFlowNodes
|
||||
private import semmle.code.cpp.models.interfaces.PointerWrapper
|
||||
private import DataFlowPrivate
|
||||
private import TypeFlow
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
/**
|
||||
* Holds if `operand` is an operand that is not used by the dataflow library.
|
||||
* Ignored operands are not recognized as uses by SSA, and they don't have a
|
||||
* corresponding `(Indirect)OperandNode`.
|
||||
*/
|
||||
predicate ignoreOperand(Operand operand) {
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or
|
||||
operand instanceof MemoryOperand
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an instruction that is not used by the dataflow library.
|
||||
* Ignored instructions are not recognized as reads/writes by SSA, and they
|
||||
* don't have a corresponding `(Indirect)InstructionNode`.
|
||||
*/
|
||||
predicate ignoreInstruction(Instruction instr) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
(
|
||||
instr instanceof CallSideEffectInstruction or
|
||||
instr instanceof CallReadSideEffectInstruction or
|
||||
instr instanceof ExitFunctionInstruction or
|
||||
instr instanceof EnterFunctionInstruction or
|
||||
instr instanceof WriteSideEffectInstruction or
|
||||
instr instanceof PhiInstruction or
|
||||
instr instanceof ReadSideEffectInstruction or
|
||||
instr instanceof ChiInstruction or
|
||||
instr instanceof InitializeIndirectionInstruction or
|
||||
instr instanceof AliasedDefinitionInstruction or
|
||||
instr instanceof AliasedUseInstruction or
|
||||
instr instanceof InitializeNonLocalInstruction or
|
||||
instr instanceof ReturnIndirectionInstruction or
|
||||
instr instanceof UninitializedGroupInstruction
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the C++ type of `this` in the member function `f`.
|
||||
* Gets the C++ type of `this` in an `IRFunction` generated from `f`.
|
||||
* The result is a glvalue if `isGLValue` is true, and
|
||||
* a prvalue if `isGLValue` is false.
|
||||
*/
|
||||
bindingset[isGLValue]
|
||||
private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) {
|
||||
result.hasType(f.getTypeOfThis(), isGLValue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the C++ type of the instruction `i`.
|
||||
*
|
||||
* This is equivalent to `i.getResultLanguageType()` with the exception
|
||||
* of instructions that directly references a `this` IRVariable. In this
|
||||
* case, `i.getResultLanguageType()` gives an unknown type, whereas the
|
||||
* predicate gives the expected type (i.e., a potentially cv-qualified
|
||||
* type `A*` where `A` is the declaring type of the member function that
|
||||
* contains `i`).
|
||||
*/
|
||||
cached
|
||||
CppType getResultLanguageType(Instruction i) {
|
||||
if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable
|
||||
then
|
||||
if i.isGLValue()
|
||||
then result = getThisType(i.getEnclosingFunction(), true)
|
||||
else result = getThisType(i.getEnclosingFunction(), false)
|
||||
else result = i.getResultLanguageType()
|
||||
private CppType getThisType(Cpp::Declaration f, boolean isGLValue) {
|
||||
result.hasType(f.(Cpp::MemberFunction).getTypeOfThis(), isGLValue)
|
||||
or
|
||||
exists(Cpp::PointerType pt |
|
||||
pt.getBaseType() = f.(Cpp::Field).getDeclaringType() and
|
||||
result.hasType(pt, isGLValue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -230,7 +180,8 @@ private class PointerWrapperTypeIndirection extends Indirection instanceof Point
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
this = call.getStaticCallTarget().getClassAndName(["operator*", "operator->", "get"]) and
|
||||
this =
|
||||
call.getStaticCallTarget().(Function).getClassAndName(["operator*", "operator->", "get"]) and
|
||||
address = call.getThisArgumentOperand()
|
||||
)
|
||||
}
|
||||
@@ -249,7 +200,7 @@ private module IteratorIndirections {
|
||||
|
||||
override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
|
||||
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
|
||||
this = call.getStaticCallTarget().getClassAndName("operator=") and
|
||||
this = call.getStaticCallTarget().(Function).getClassAndName("operator=") and
|
||||
address = call.getThisArgumentOperand() and
|
||||
certain = false
|
||||
)
|
||||
@@ -347,10 +298,6 @@ predicate isWrite(Node0Impl value, Operand address, boolean certain) {
|
||||
)
|
||||
}
|
||||
|
||||
predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
|
||||
any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo)
|
||||
}
|
||||
|
||||
newtype TBaseSourceVariable =
|
||||
// Each IR variable gets its own source variable
|
||||
TBaseIRVariable(IRVariable var) or
|
||||
@@ -572,6 +519,69 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* Holds if `operand` is an operand that is not used by the dataflow library.
|
||||
* Ignored operands are not recognized as uses by SSA, and they don't have a
|
||||
* corresponding `(Indirect)OperandNode`.
|
||||
*/
|
||||
cached
|
||||
predicate ignoreOperand(Operand operand) {
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or
|
||||
operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or
|
||||
operand instanceof MemoryOperand
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an instruction that is not used by the dataflow library.
|
||||
* Ignored instructions are not recognized as reads/writes by SSA, and they
|
||||
* don't have a corresponding `(Indirect)InstructionNode`.
|
||||
*/
|
||||
cached
|
||||
predicate ignoreInstruction(Instruction instr) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
(
|
||||
instr instanceof CallSideEffectInstruction or
|
||||
instr instanceof CallReadSideEffectInstruction or
|
||||
instr instanceof ExitFunctionInstruction or
|
||||
instr instanceof EnterFunctionInstruction or
|
||||
instr instanceof WriteSideEffectInstruction or
|
||||
instr instanceof PhiInstruction or
|
||||
instr instanceof ReadSideEffectInstruction or
|
||||
instr instanceof ChiInstruction or
|
||||
instr instanceof InitializeIndirectionInstruction or
|
||||
instr instanceof AliasedDefinitionInstruction or
|
||||
instr instanceof AliasedUseInstruction or
|
||||
instr instanceof InitializeNonLocalInstruction or
|
||||
instr instanceof ReturnIndirectionInstruction or
|
||||
instr instanceof UninitializedGroupInstruction
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
|
||||
any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the C++ type of the instruction `i`.
|
||||
*
|
||||
* This is equivalent to `i.getResultLanguageType()` with the exception
|
||||
* of instructions that directly references a `this` IRVariable. In this
|
||||
* case, `i.getResultLanguageType()` gives an unknown type, whereas the
|
||||
* predicate gives the expected type (i.e., a potentially cv-qualified
|
||||
* type `A*` where `A` is the declaring type of the member function that
|
||||
* contains `i`).
|
||||
*/
|
||||
cached
|
||||
CppType getResultLanguageType(Instruction i) {
|
||||
if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable
|
||||
then
|
||||
if i.isGLValue()
|
||||
then result = getThisType(i.getEnclosingFunction(), true)
|
||||
else result = getThisType(i.getEnclosingFunction(), false)
|
||||
else result = i.getResultLanguageType()
|
||||
}
|
||||
|
||||
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
|
||||
private predicate isConversion(Operand op) {
|
||||
exists(Instruction def, Operand use |
|
||||
|
||||
@@ -5,64 +5,81 @@ private import semmle.code.cpp.models.interfaces.DataFlow
|
||||
private import semmle.code.cpp.models.interfaces.SideEffect
|
||||
private import DataFlowUtil
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowNodes
|
||||
private import SsaImpl as Ssa
|
||||
private import semmle.code.cpp.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
|
||||
private import semmle.code.cpp.ir.dataflow.FlowSteps
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step. This relation is only used for local taint flow
|
||||
* (for example `TaintTracking::localTaint(source, sink)`) so it may contain
|
||||
* special cases that should only apply to local taint flow.
|
||||
*/
|
||||
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// dataflow step
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// taint flow step
|
||||
localAdditionalTaintStep(nodeFrom, nodeTo, _)
|
||||
or
|
||||
// models-as-data summarized flow for local data flow (i.e. special case for flow
|
||||
// through calls to modeled functions, without relying on global dataflow to join
|
||||
// the dots).
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
|
||||
cached
|
||||
private module Cached {
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/**
|
||||
* This predicate exists to collapse the `cached` predicates in this module with the
|
||||
* `cached` predicates in other C/C++ dataflow files, which is then collapsed
|
||||
* with the `cached` predicates in `DataFlowImplCommon.qll`.
|
||||
*/
|
||||
cached
|
||||
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
* (intra-procedural) step. This relation is only used for local taint flow
|
||||
* (for example `TaintTracking::localTaint(source, sink)`) so it may contain
|
||||
* special cases that should only apply to local taint flow.
|
||||
*/
|
||||
cached
|
||||
predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
// dataflow step
|
||||
DataFlow::localFlowStep(nodeFrom, nodeTo)
|
||||
or
|
||||
// taint flow step
|
||||
localAdditionalTaintStep(nodeFrom, nodeTo, _)
|
||||
or
|
||||
// models-as-data summarized flow for local data flow (i.e. special case for flow
|
||||
// through calls to modeled functions, without relying on global dataflow to join
|
||||
// the dots).
|
||||
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(nodeFrom, nodeTo, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||
* different objects.
|
||||
*/
|
||||
cached
|
||||
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
|
||||
operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and
|
||||
model = ""
|
||||
or
|
||||
modeledTaintStep(nodeFrom, nodeTo, model)
|
||||
or
|
||||
// Flow from (the indirection of) an operand of a pointer arithmetic instruction to the
|
||||
// indirection of the pointer arithmetic instruction. This provides flow from `source`
|
||||
// in `x[source]` to the result of the associated load instruction.
|
||||
exists(PointerArithmeticInstruction pai, int indirectionIndex |
|
||||
nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and
|
||||
model = ""
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
// object->field conflation for content that is a `TaintInheritingContent`.
|
||||
exists(DataFlow::ContentSet f |
|
||||
readStep(nodeFrom, f, nodeTo) and
|
||||
f.getAReadContent() instanceof TaintInheritingContent
|
||||
) and
|
||||
model = ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||
* different objects.
|
||||
*/
|
||||
cached
|
||||
predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, string model) {
|
||||
operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) and
|
||||
model = ""
|
||||
or
|
||||
modeledTaintStep(nodeFrom, nodeTo, model)
|
||||
or
|
||||
// Flow from (the indirection of) an operand of a pointer arithmetic instruction to the
|
||||
// indirection of the pointer arithmetic instruction. This provides flow from `source`
|
||||
// in `x[source]` to the result of the associated load instruction.
|
||||
exists(PointerArithmeticInstruction pai, int indirectionIndex |
|
||||
nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1)
|
||||
) and
|
||||
model = ""
|
||||
or
|
||||
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) and
|
||||
model = ""
|
||||
or
|
||||
// models-as-data summarized flow
|
||||
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
|
||||
nodeTo.(FlowSummaryNode).getSummaryNode(), false, model)
|
||||
or
|
||||
// object->field conflation for content that is a `TaintInheritingContent`.
|
||||
exists(DataFlow::ContentSet f |
|
||||
readStep(nodeFrom, f, nodeTo) and
|
||||
f.getAReadContent() instanceof TaintInheritingContent
|
||||
) and
|
||||
model = ""
|
||||
}
|
||||
import Cached
|
||||
|
||||
/**
|
||||
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
|
||||
@@ -196,7 +213,7 @@ predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut, string
|
||||
// Taint flow from a pointer argument to an output, when the model specifies flow from the deref
|
||||
// to that output, but the deref is not modeled in the IR for the caller.
|
||||
exists(
|
||||
CallInstruction call, DataFlow::SideEffectOperandNode indirectArgument, Function func,
|
||||
CallInstruction call, SideEffectOperandNode indirectArgument, Function func,
|
||||
FunctionInput modelIn, FunctionOutput modelOut
|
||||
|
|
||||
indirectArgument = callInput(call, modelIn) and
|
||||
|
||||
@@ -495,7 +495,7 @@ class FieldInstruction extends Instruction {
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
Language::Declaration funcSymbol;
|
||||
|
||||
FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) }
|
||||
|
||||
@@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
final Language::Declaration getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
final Language::Function getStaticCallTarget() {
|
||||
final Language::Declaration getStaticCallTarget() {
|
||||
result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
|
||||
@@ -495,7 +495,7 @@ class FieldInstruction extends Instruction {
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
Language::Declaration funcSymbol;
|
||||
|
||||
FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) }
|
||||
|
||||
@@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
final Language::Declaration getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
final Language::Function getStaticCallTarget() {
|
||||
final Language::Declaration getStaticCallTarget() {
|
||||
result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ private import TranslatedCall
|
||||
private import TranslatedStmt
|
||||
private import TranslatedFunction
|
||||
private import TranslatedGlobalVar
|
||||
private import TranslatedNonStaticDataMember
|
||||
private import TranslatedInitialization
|
||||
|
||||
TranslatedElement getInstructionTranslatedElement(Instruction instruction) {
|
||||
instruction = TRawInstruction(result, _)
|
||||
@@ -44,6 +46,9 @@ module Raw {
|
||||
or
|
||||
not var.isFromUninstantiatedTemplate(_) and
|
||||
var instanceof StaticInitializedStaticLocalVariable
|
||||
or
|
||||
not var.isFromUninstantiatedTemplate(_) and
|
||||
var instanceof Field
|
||||
) and
|
||||
var.hasInitializer() and
|
||||
(
|
||||
@@ -63,6 +68,8 @@ module Raw {
|
||||
getTranslatedFunction(decl).hasUserVariable(var, type)
|
||||
or
|
||||
getTranslatedVarInit(decl).hasUserVariable(var, type)
|
||||
or
|
||||
getTranslatedFieldInit(decl).hasUserVariable(var, type)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -109,7 +116,7 @@ module Raw {
|
||||
}
|
||||
|
||||
cached
|
||||
Function getInstructionFunction(Instruction instruction) {
|
||||
Declaration getInstructionFunction(Instruction instruction) {
|
||||
result =
|
||||
getInstructionTranslatedElement(instruction)
|
||||
.getInstructionFunction(getInstructionTag(instruction))
|
||||
@@ -194,6 +201,89 @@ module Raw {
|
||||
Expr getInstructionUnconvertedResultExpression(Instruction instruction) {
|
||||
result = getInstructionConvertedResultExpression(instruction).getUnconverted()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression associated with the instruction `instr` that computes
|
||||
* the `Convert` instruction on the extent expression of an allocation.
|
||||
*/
|
||||
cached
|
||||
Expr getAllocationExtentConvertExpr(Instruction instr) {
|
||||
exists(TranslatedNonConstantAllocationSize tas |
|
||||
instr = tas.getInstruction(AllocationExtentConvertTag()) and
|
||||
result = tas.getExtent().getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `ParenthesisExpr` associated with a transparent conversion
|
||||
* instruction, if any.
|
||||
*/
|
||||
cached
|
||||
ParenthesisExpr getTransparentConversionParenthesisExpr(Instruction instr) {
|
||||
exists(TranslatedTransparentConversion ttc |
|
||||
result = ttc.getExpr() and
|
||||
instr = ttc.getResult()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` belongs to a `TranslatedCoreExpr` that produces an
|
||||
* expression result. This indicates that the instruction represents a
|
||||
* definition whose result should be mapped back to the expression.
|
||||
*/
|
||||
cached
|
||||
predicate instructionProducesExprResult(Instruction instr) {
|
||||
exists(TranslatedCoreExpr tco |
|
||||
tco.getInstruction(_) = instr and
|
||||
tco.producesExprResult()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression associated with a `StoreInstruction` generated
|
||||
* by an `TranslatedAssignOperation`.
|
||||
*/
|
||||
cached
|
||||
Expr getAssignOperationStoreExpr(StoreInstruction store) {
|
||||
exists(TranslatedAssignOperation tao |
|
||||
store = tao.getInstruction(AssignmentStoreTag()) and
|
||||
result = tao.getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the expression associated with a `StoreInstruction` generated
|
||||
* by an `TranslatedCrementOperation`.
|
||||
*/
|
||||
cached
|
||||
Expr getCrementOperationStoreExpr(StoreInstruction store) {
|
||||
exists(TranslatedCrementOperation tco |
|
||||
store = tco.getInstruction(CrementStoreTag()) and
|
||||
result = tco.getExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `store` is a `StoreInstruction` that defines the temporary
|
||||
* `IRVariable` generated as part of the translation of a ternary expression.
|
||||
*/
|
||||
cached
|
||||
predicate isConditionalExprTempStore(StoreInstruction store) {
|
||||
exists(TranslatedConditionalExpr tce |
|
||||
store = tce.getInstruction(ConditionValueFalseStoreTag())
|
||||
or
|
||||
store = tce.getInstruction(ConditionValueTrueStoreTag())
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the instruction that computes the address used to initialize `v`. */
|
||||
cached
|
||||
Instruction getInitializationTargetAddress(IRVariable v) {
|
||||
exists(TranslatedVariableInitialization init |
|
||||
init.getIRVariable() = v and
|
||||
result = init.getTargetAddress()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class TStageInstruction = TRawInstruction or TRawUnreachedInstruction;
|
||||
|
||||
@@ -130,27 +130,31 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Call` or `NewOrNewArrayExpr` or `DeleteOrDeleteArrayExpr`.
|
||||
* An expression that can have call side effects.
|
||||
*
|
||||
* All kinds of expression invoke a function as part of their evaluation. This class provides a
|
||||
* way to treat both kinds of function similarly, and to get the invoked `Function`.
|
||||
* All kinds of expressions invoke a function as part of their evaluation. This class provides a
|
||||
* way to treat those expressions similarly, and to get the invoked `Declaration`.
|
||||
*/
|
||||
class CallOrAllocationExpr extends Expr {
|
||||
CallOrAllocationExpr() {
|
||||
class ExprWithCallSideEffects extends Expr {
|
||||
ExprWithCallSideEffects() {
|
||||
this instanceof Call
|
||||
or
|
||||
this instanceof NewOrNewArrayExpr
|
||||
or
|
||||
this instanceof DeleteOrDeleteArrayExpr
|
||||
or
|
||||
this instanceof ConstructorDefaultFieldInit
|
||||
}
|
||||
|
||||
/** Gets the `Function` invoked by this expression, if known. */
|
||||
final Function getTarget() {
|
||||
/** Gets the `Declaration` invoked by this expression, if known. */
|
||||
final Declaration getTarget() {
|
||||
result = this.(Call).getTarget()
|
||||
or
|
||||
result = this.(NewOrNewArrayExpr).getAllocator()
|
||||
or
|
||||
result = this.(DeleteOrDeleteArrayExpr).getDeallocator()
|
||||
or
|
||||
result = this.(ConstructorDefaultFieldInit).getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,7 +162,7 @@ class CallOrAllocationExpr extends Expr {
|
||||
* Returns the side effect opcode, if any, that represents any side effects not specifically modeled
|
||||
* by an argument side effect.
|
||||
*/
|
||||
Opcode getCallSideEffectOpcode(CallOrAllocationExpr expr) {
|
||||
Opcode getCallSideEffectOpcode(ExprWithCallSideEffects expr) {
|
||||
not exists(expr.getTarget().(SideEffectFunction)) and result instanceof Opcode::CallSideEffect
|
||||
or
|
||||
exists(SideEffectFunction sideEffectFunction |
|
||||
@@ -175,7 +179,7 @@ Opcode getCallSideEffectOpcode(CallOrAllocationExpr expr) {
|
||||
/**
|
||||
* Returns a side effect opcode for parameter index `i` of the specified call.
|
||||
*
|
||||
* This predicate will return at most two results: one read side effect, and one write side effect.
|
||||
* This predicate will yield at most two results: one read side effect, and one write side effect.
|
||||
*/
|
||||
Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
|
||||
exists(boolean buffer |
|
||||
@@ -228,3 +232,14 @@ Opcode getASideEffectOpcode(Call call, ParameterIndex i) {
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a side effect opcode for a default field initialization.
|
||||
*
|
||||
* This predicate will yield two results: one read side effect, and one write side effect.
|
||||
*/
|
||||
Opcode getDefaultFieldInitSideEffectOpcode() {
|
||||
result instanceof Opcode::IndirectReadSideEffect
|
||||
or
|
||||
result instanceof Opcode::IndirectMayWriteSideEffect
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ private import SideEffects
|
||||
private import TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import TranslatedFunction
|
||||
private import TranslatedInitialization
|
||||
private import DefaultOptions as DefaultOptions
|
||||
|
||||
/**
|
||||
@@ -348,7 +349,7 @@ class TranslatedExprCall extends TranslatedCallExpr {
|
||||
class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
|
||||
override FunctionCall expr;
|
||||
|
||||
override Function getInstructionFunction(InstructionTag tag) {
|
||||
override Declaration getInstructionFunction(InstructionTag tag) {
|
||||
tag = CallTargetTag() and result = expr.getTarget()
|
||||
}
|
||||
|
||||
@@ -429,6 +430,9 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi
|
||||
or
|
||||
expr instanceof DeleteOrDeleteArrayExpr and
|
||||
result = getTranslatedDeleteOrDeleteArray(expr).getInstruction(CallTag())
|
||||
or
|
||||
expr instanceof ConstructorDefaultFieldInit and
|
||||
result = getTranslatedConstructorFieldInitialization(expr).getInstruction(CallTag())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,11 +508,25 @@ abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
abstract predicate sideEffectInstruction(Opcode opcode, CppType type);
|
||||
}
|
||||
|
||||
private class CallOrDefaultFieldInit extends Expr {
|
||||
CallOrDefaultFieldInit() {
|
||||
this instanceof Call
|
||||
or
|
||||
this instanceof ConstructorDefaultFieldInit
|
||||
}
|
||||
|
||||
Declaration getTarget() {
|
||||
result = this.(Call).getTarget()
|
||||
or
|
||||
result = this.(ConstructorDefaultFieldInit).getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of a single argument side effect for a call.
|
||||
*/
|
||||
abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
Call call;
|
||||
CallOrDefaultFieldInit callOrInit;
|
||||
int index;
|
||||
SideEffectOpcode sideEffectOpcode;
|
||||
|
||||
@@ -524,7 +542,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
result = "(read side effect for " + this.getArgString() + ")"
|
||||
}
|
||||
|
||||
override Call getPrimaryExpr() { result = call }
|
||||
override Expr getPrimaryExpr() { result = callOrInit }
|
||||
|
||||
override predicate sortOrder(int group, int indexInGroup) {
|
||||
indexInGroup = index and
|
||||
@@ -586,9 +604,10 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandTag instanceof BufferSizeOperandTag and
|
||||
result =
|
||||
getTranslatedExpr(call.getArgument(call.getTarget()
|
||||
.(SideEffectFunction)
|
||||
.getParameterSizeIndex(index)).getFullyConverted()).getResult()
|
||||
getTranslatedExpr(callOrInit
|
||||
.(Call)
|
||||
.getArgument(callOrInit.getTarget().(SideEffectFunction).getParameterSizeIndex(index))
|
||||
.getFullyConverted()).getResult()
|
||||
}
|
||||
|
||||
/** Holds if this side effect is a write side effect, rather than a read side effect. */
|
||||
@@ -616,7 +635,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
Expr arg;
|
||||
|
||||
TranslatedArgumentExprSideEffect() {
|
||||
this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode)
|
||||
this = TTranslatedArgumentExprSideEffect(callOrInit, arg, index, sideEffectOpcode)
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = arg }
|
||||
@@ -640,28 +659,31 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
* The IR translation of an argument side effect for `*this` on a call, where there is no `Expr`
|
||||
* object that represents the `this` argument.
|
||||
*
|
||||
* The applies only to constructor calls, as the AST has exploit qualifier `Expr`s for all other
|
||||
* calls to non-static member functions.
|
||||
* This applies to constructor calls and default field initializations, as the AST has explicit
|
||||
* qualifier `Expr`s for all other calls to non-static member functions.
|
||||
*/
|
||||
class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect,
|
||||
TTranslatedStructorQualifierSideEffect
|
||||
class TranslatedImplicitThisQualifierSideEffect extends TranslatedArgumentSideEffect,
|
||||
TTranslatedImplicitThisQualifierSideEffect
|
||||
{
|
||||
TranslatedStructorQualifierSideEffect() {
|
||||
this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and
|
||||
TranslatedImplicitThisQualifierSideEffect() {
|
||||
this = TTranslatedImplicitThisQualifierSideEffect(callOrInit, sideEffectOpcode) and
|
||||
index = -1
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = call }
|
||||
final override Locatable getAst() { result = callOrInit }
|
||||
|
||||
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
|
||||
final override Type getIndirectionType() { result = callOrInit.getTarget().getDeclaringType() }
|
||||
|
||||
final override string getArgString() { result = "this" }
|
||||
|
||||
final override Instruction getArgInstruction() {
|
||||
exists(TranslatedStructorCall structorCall |
|
||||
structorCall.getExpr() = call and
|
||||
structorCall.getExpr() = callOrInit and
|
||||
result = structorCall.getQualifierResult()
|
||||
)
|
||||
or
|
||||
callOrInit instanceof ConstructorDefaultFieldInit and
|
||||
result = getTranslatedFunction(callOrInit.getEnclosingFunction()).getLoadThisInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,8 @@ abstract class TranslatedCondition extends TranslatedElement {
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) or
|
||||
result = getEnclosingVariable(expr).(Field)
|
||||
}
|
||||
|
||||
final Type getResultType() { result = expr.getUnspecifiedType() }
|
||||
|
||||
@@ -34,8 +34,11 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
or
|
||||
result = entry.getDeclaration().(GlobalOrNamespaceVariable)
|
||||
or
|
||||
result = entry.getDeclaration().(Field)
|
||||
or
|
||||
not entry.getDeclaration() instanceof StaticInitializedStaticLocalVariable and
|
||||
not entry.getDeclaration() instanceof GlobalOrNamespaceVariable and
|
||||
not entry.getDeclaration() instanceof Field and
|
||||
result = stmt.getEnclosingFunction()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -767,7 +767,7 @@ newtype TTranslatedElement =
|
||||
expr = initList.getFieldExpr(field, position).getFullyConverted()
|
||||
)
|
||||
or
|
||||
exists(ConstructorFieldInit init |
|
||||
exists(ConstructorDirectFieldInit init |
|
||||
not ignoreExpr(init) and
|
||||
ast = init and
|
||||
field = init.getTarget() and
|
||||
@@ -775,6 +775,14 @@ newtype TTranslatedElement =
|
||||
position = -1
|
||||
)
|
||||
} or
|
||||
// The initialization of a field via a default member initializer.
|
||||
TTranslatedDefaultFieldInitialization(Expr ast, Field field) {
|
||||
exists(ConstructorDefaultFieldInit init |
|
||||
not ignoreExpr(init) and
|
||||
ast = init and
|
||||
field = init.getTarget()
|
||||
)
|
||||
} or
|
||||
// The value initialization of a field due to an omitted member of an
|
||||
// initializer list.
|
||||
TTranslatedFieldValueInitialization(Expr ast, Field field) {
|
||||
@@ -871,7 +879,7 @@ newtype TTranslatedElement =
|
||||
// The declaration/initialization part of a `ConditionDeclExpr`
|
||||
TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or
|
||||
// The side effects of a `Call`
|
||||
TTranslatedCallSideEffects(CallOrAllocationExpr expr) {
|
||||
TTranslatedCallSideEffects(ExprWithCallSideEffects expr) {
|
||||
not ignoreExpr(expr) and
|
||||
not ignoreSideEffects(expr)
|
||||
} or
|
||||
@@ -910,15 +918,23 @@ newtype TTranslatedElement =
|
||||
} or
|
||||
// Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects
|
||||
// on `*this` without an `Expr`.
|
||||
TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) {
|
||||
TTranslatedImplicitThisQualifierSideEffect(ExprWithCallSideEffects call, SideEffectOpcode opcode) {
|
||||
not ignoreExpr(call) and
|
||||
not ignoreSideEffects(call) and
|
||||
call instanceof ConstructorCall and
|
||||
opcode = getASideEffectOpcode(call, -1)
|
||||
(
|
||||
call instanceof ConstructorCall and
|
||||
opcode = getASideEffectOpcode(call, -1)
|
||||
or
|
||||
call instanceof ConstructorFieldInit and
|
||||
opcode = getDefaultFieldInitSideEffectOpcode()
|
||||
)
|
||||
} or
|
||||
// The side effect that initializes newly-allocated memory.
|
||||
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
|
||||
TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } or
|
||||
TTranslatedStaticStorageDurationVarInit(Variable var) {
|
||||
Raw::varHasIRFunc(var) and not var instanceof Field
|
||||
} or
|
||||
TTranslatedNonStaticDataMemberVarInit(Field var) { Raw::varHasIRFunc(var) } or
|
||||
TTranslatedAssertionOperand(MacroInvocation mi, int index) { hasAssertionOperand(mi, index) }
|
||||
|
||||
/**
|
||||
@@ -1179,7 +1195,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* If the instruction specified by `tag` is a `FunctionInstruction`, gets the
|
||||
* `Function` for that instruction.
|
||||
*/
|
||||
Function getInstructionFunction(InstructionTag tag) { none() }
|
||||
Declaration getInstructionFunction(InstructionTag tag) { none() }
|
||||
|
||||
/**
|
||||
* If the instruction specified by `tag` is a `VariableInstruction`, gets the
|
||||
@@ -1297,5 +1313,7 @@ abstract class TranslatedRootElement extends TranslatedElement {
|
||||
this instanceof TTranslatedFunction
|
||||
or
|
||||
this instanceof TTranslatedStaticStorageDurationVarInit
|
||||
or
|
||||
this instanceof TTranslatedNonStaticDataMemberVarInit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ private import TranslatedFunction
|
||||
private import TranslatedInitialization
|
||||
private import TranslatedStmt
|
||||
private import TranslatedGlobalVar
|
||||
private import TranslatedNonStaticDataMember
|
||||
private import IRConstruction
|
||||
import TranslatedCall
|
||||
|
||||
@@ -138,6 +139,8 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
result = getTranslatedFunction(getEnclosingFunction(expr))
|
||||
or
|
||||
result = getTranslatedVarInit(getEnclosingVariable(expr))
|
||||
or
|
||||
result = getTranslatedFieldInit(getEnclosingVariable(expr))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +156,10 @@ Declaration getEnclosingDeclaration0(Expr e) {
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
if
|
||||
v instanceof StaticInitializedStaticLocalVariable or
|
||||
v instanceof GlobalOrNamespaceVariable or
|
||||
v instanceof Field
|
||||
then result = v
|
||||
else result = e.getEnclosingDeclaration()
|
||||
)
|
||||
@@ -173,7 +179,10 @@ Variable getEnclosingVariable0(Expr e) {
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
if
|
||||
v instanceof StaticInitializedStaticLocalVariable or
|
||||
v instanceof GlobalOrNamespaceVariable or
|
||||
v instanceof Field
|
||||
then result = v
|
||||
else result = e.getEnclosingVariable()
|
||||
)
|
||||
@@ -826,6 +835,46 @@ class TranslatedPostfixCrementOperation extends TranslatedCrementOperation {
|
||||
override Instruction getResult() { result = this.getLoadedOperand().getResult() }
|
||||
}
|
||||
|
||||
class TranslatedParamAccessForType extends TranslatedNonConstantExpr {
|
||||
override ParamAccessForType expr;
|
||||
|
||||
TranslatedParamAccessForType() {
|
||||
// Currently only needed for this parameter accesses.
|
||||
expr.isThisAccess()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(OnlyInstructionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override TranslatedElement getChildInternal(int id) { none() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
opcode instanceof Opcode::CopyValue and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result =
|
||||
this.getEnclosingFunction().(TranslatedNonStaticDataMemberVarInit).getLoadThisInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* IR translation of an array access expression (e.g. `a[i]`). The array being accessed will either
|
||||
* be a prvalue of pointer type (possibly due to an implicit array-to-pointer conversion), or a
|
||||
@@ -1215,7 +1264,7 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
|
||||
resultType = this.getResultType()
|
||||
}
|
||||
|
||||
override Function getInstructionFunction(InstructionTag tag) {
|
||||
override Declaration getInstructionFunction(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = expr.getTarget()
|
||||
}
|
||||
@@ -2498,7 +2547,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
|
||||
any()
|
||||
}
|
||||
|
||||
override Function getInstructionFunction(InstructionTag tag) {
|
||||
override Declaration getInstructionFunction(InstructionTag tag) {
|
||||
tag = CallTargetTag() and result = expr.getAllocator()
|
||||
}
|
||||
|
||||
@@ -2581,7 +2630,7 @@ class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, Trans
|
||||
result = this.getFirstArgumentOrCallInstruction(kind)
|
||||
}
|
||||
|
||||
override Function getInstructionFunction(InstructionTag tag) {
|
||||
override Declaration getInstructionFunction(InstructionTag tag) {
|
||||
tag = CallTargetTag() and result = expr.getDeallocator()
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +148,8 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) or
|
||||
result = getEnclosingVariable(expr).(Field)
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = expr }
|
||||
@@ -514,8 +515,8 @@ TranslatedFieldInitialization getTranslatedConstructorFieldInitialization(Constr
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of a field from an
|
||||
* element of an initializer list.
|
||||
* The IR translation of the initialization of a field from an element of
|
||||
* an initializer list.
|
||||
*/
|
||||
abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
Expr ast;
|
||||
@@ -528,13 +529,11 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(ast) or
|
||||
result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable)
|
||||
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable) or
|
||||
result = getEnclosingVariable(ast).(Field)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(this.getFieldAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
final Field getField() { result = field }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index describing the order in which this field is to be
|
||||
@@ -542,6 +541,20 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
*/
|
||||
final int getOrder() { result = field.getInitializationOrder() }
|
||||
|
||||
/** Gets the position in the initializer list, or `-1` if the initialization is implicit. */
|
||||
int getPosition() { result = -1 }
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of the initialization of a field from an element of an initializer
|
||||
* list where default initialization is not used.
|
||||
*/
|
||||
abstract class TranslatedNonDefaultFieldInitialization extends TranslatedFieldInitialization {
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(this.getFieldAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
@@ -559,18 +572,13 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
}
|
||||
|
||||
final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() }
|
||||
|
||||
final Field getField() { result = field }
|
||||
|
||||
/** Gets the position in the initializer list, or `-1` if the initialization is implicit. */
|
||||
int getPosition() { result = -1 }
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of a field from an
|
||||
* explicit element in an initializer list.
|
||||
* The IR translation of the initialization of a field from an explicit element in
|
||||
* an initializer list.
|
||||
*/
|
||||
class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization,
|
||||
class TranslatedExplicitFieldInitialization extends TranslatedNonDefaultFieldInitialization,
|
||||
InitializationContext, TTranslatedExplicitFieldInitialization
|
||||
{
|
||||
Expr expr;
|
||||
@@ -610,15 +618,81 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
override int getPosition() { result = position }
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of the initialization of a field from an element of an initializer
|
||||
* list where default initialization is used.
|
||||
*/
|
||||
class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization,
|
||||
TTranslatedDefaultFieldInitialization
|
||||
{
|
||||
TranslatedDefaultFieldInitialization() {
|
||||
this = TTranslatedDefaultFieldInitialization(ast, field)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(CallTargetTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getSideEffects().getALastInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getLastChild() { result = this.getSideEffects() }
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CallTargetTag() and
|
||||
result = this.getInstruction(CallTag())
|
||||
or
|
||||
tag = CallTag() and
|
||||
result = this.getSideEffects().getFirstInstruction(kind)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getSideEffects() and
|
||||
result = this.getParent().getChildSuccessor(this, kind)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTargetTag() and
|
||||
opcode instanceof Opcode::FunctionAddress and
|
||||
resultType = getFunctionGLValueType()
|
||||
or
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = CallTag() and
|
||||
(
|
||||
operandTag instanceof CallTargetOperandTag and
|
||||
result = this.getInstruction(CallTargetTag())
|
||||
or
|
||||
operandTag instanceof ThisArgumentOperandTag and
|
||||
result = getTranslatedFunction(this.getFunction()).getLoadThisInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
override Declaration getInstructionFunction(InstructionTag tag) {
|
||||
tag = CallTargetTag() and
|
||||
result = field
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getSideEffects() }
|
||||
|
||||
final TranslatedSideEffects getSideEffects() { result.getExpr() = ast }
|
||||
}
|
||||
|
||||
private string getZeroValue(Type type) {
|
||||
if type instanceof FloatingPointType then result = "0.0" else result = "0"
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of a field without a
|
||||
* corresponding element in the initializer list.
|
||||
* The IR translation of the initialization of a field without a corresponding
|
||||
* element in the initializer list.
|
||||
*/
|
||||
class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
class TranslatedFieldValueInitialization extends TranslatedNonDefaultFieldInitialization,
|
||||
TTranslatedFieldValueInitialization
|
||||
{
|
||||
TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) }
|
||||
@@ -628,7 +702,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
TranslatedNonDefaultFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
@@ -659,7 +733,8 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
result =
|
||||
TranslatedNonDefaultFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
(
|
||||
@@ -683,8 +758,8 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of an array element from
|
||||
* an element of an initializer list.
|
||||
* The IR translation of the initialization of an array element from an element
|
||||
* of an initializer list.
|
||||
*/
|
||||
abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
ArrayOrVectorAggregateLiteral initList;
|
||||
@@ -701,6 +776,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
result = getEnclosingVariable(initList).(GlobalOrNamespaceVariable)
|
||||
or
|
||||
result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable)
|
||||
or
|
||||
result = getEnclosingVariable(initList).(Field)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
@@ -759,8 +836,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of an array element from
|
||||
* an explicit element in an initializer list.
|
||||
* The IR translation of the initialization of an array element from an explicit
|
||||
* element in an initializer list.
|
||||
*/
|
||||
class TranslatedExplicitElementInitialization extends TranslatedElementInitialization,
|
||||
TTranslatedExplicitElementInitialization, InitializationContext
|
||||
@@ -808,8 +885,8 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the IR translation of the initialization of a range of array
|
||||
* elements without corresponding elements in the initializer list.
|
||||
* The IR translation of the initialization of a range of array elements without
|
||||
* corresponding elements in the initializer list.
|
||||
*/
|
||||
class TranslatedElementValueInitialization extends TranslatedElementInitialization,
|
||||
TTranslatedElementValueInitialization
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import TranslatedInitialization
|
||||
private import InstructionTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
|
||||
class TranslatedNonStaticDataMemberVarInit extends TranslatedRootElement,
|
||||
TTranslatedNonStaticDataMemberVarInit, InitializationContext
|
||||
{
|
||||
Field field;
|
||||
Class cls;
|
||||
|
||||
TranslatedNonStaticDataMemberVarInit() {
|
||||
this = TTranslatedNonStaticDataMemberVarInit(field) and
|
||||
cls.getAMember() = field
|
||||
}
|
||||
|
||||
override string toString() { result = cls.toString() + "::" + field.toString() }
|
||||
|
||||
final override Field getAst() { result = field }
|
||||
|
||||
final override Declaration getFunction() { result = field }
|
||||
|
||||
override Instruction getFirstInstruction(EdgeKind kind) {
|
||||
result = this.getInstruction(EnterFunctionTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getALastInstructionInternal() {
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int n) {
|
||||
n = 1 and
|
||||
result = getTranslatedInitialization(field.getInitializer().getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode op, InstructionTag tag, CppType type) {
|
||||
op instanceof Opcode::EnterFunction and
|
||||
tag = EnterFunctionTag() and
|
||||
type = getVoidType()
|
||||
or
|
||||
op instanceof Opcode::AliasedDefinition and
|
||||
tag = AliasedDefinitionTag() and
|
||||
type = getUnknownType()
|
||||
or
|
||||
op instanceof Opcode::InitializeNonLocal and
|
||||
tag = InitializeNonLocalTag() and
|
||||
type = getUnknownType()
|
||||
or
|
||||
tag = ThisAddressTag() and
|
||||
op instanceof Opcode::VariableAddress and
|
||||
type = getTypeForGLValue(any(UnknownType t))
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
op instanceof Opcode::InitializeParameter and
|
||||
type = this.getThisType()
|
||||
or
|
||||
tag = ThisLoadTag() and
|
||||
op instanceof Opcode::Load and
|
||||
type = this.getThisType()
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
op instanceof Opcode::InitializeIndirection and
|
||||
type = getTypeForPRValue(cls)
|
||||
or
|
||||
op instanceof Opcode::FieldAddress and
|
||||
tag = InitializerFieldAddressTag() and
|
||||
type = getTypeForGLValue(field.getType())
|
||||
or
|
||||
op instanceof Opcode::ReturnVoid and
|
||||
tag = ReturnTag() and
|
||||
type = getVoidType()
|
||||
or
|
||||
op instanceof Opcode::AliasedUse and
|
||||
tag = AliasedUseTag() and
|
||||
type = getVoidType()
|
||||
or
|
||||
op instanceof Opcode::ExitFunction and
|
||||
tag = ExitFunctionTag() and
|
||||
type = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
result = this.getInstruction(AliasedDefinitionTag())
|
||||
or
|
||||
tag = AliasedDefinitionTag() and
|
||||
result = this.getInstruction(InitializeNonLocalTag())
|
||||
or
|
||||
tag = InitializeNonLocalTag() and
|
||||
result = this.getInstruction(ThisAddressTag())
|
||||
or
|
||||
tag = ThisAddressTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getInstruction(ThisLoadTag())
|
||||
or
|
||||
tag = ThisLoadTag() and
|
||||
result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
result = this.getInstruction(InitializerFieldAddressTag())
|
||||
)
|
||||
or
|
||||
tag = InitializerFieldAddressTag() and
|
||||
result = this.getChild(1).getFirstInstruction(kind)
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = ReturnTag() and
|
||||
result = this.getInstruction(AliasedUseTag())
|
||||
or
|
||||
tag = AliasedUseTag() and
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
|
||||
child = this.getChild(1) and
|
||||
result = this.getInstruction(ReturnTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override CppType getInstructionMemoryOperandType(
|
||||
InstructionTag tag, TypedOperandTag operandTag
|
||||
) {
|
||||
tag = AliasedUseTag() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
result = getUnknownType()
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
(
|
||||
tag = ThisAddressTag() or
|
||||
tag = InitializerStoreTag() or
|
||||
tag = InitializerIndirectStoreTag()
|
||||
) and
|
||||
result = getIRTempVariable(field, ThisTempVar())
|
||||
}
|
||||
|
||||
override Field getInstructionField(InstructionTag tag) {
|
||||
tag = InitializerFieldAddressTag() and
|
||||
result = field
|
||||
}
|
||||
|
||||
override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ThisTempVar() and
|
||||
type = this.getThisType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this variable defines or accesses variable `var` with type `type`. This includes all
|
||||
* parameters and local variables, plus any global variables or static data members that are
|
||||
* directly accessed by the function.
|
||||
*/
|
||||
final predicate hasUserVariable(Variable varUsed, CppType type) {
|
||||
(
|
||||
(
|
||||
varUsed instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
varUsed instanceof StaticLocalVariable
|
||||
or
|
||||
varUsed instanceof MemberVariable and not varUsed instanceof Field
|
||||
) and
|
||||
exists(VariableAccess access |
|
||||
access.getTarget() = varUsed and
|
||||
getEnclosingVariable(access) = field
|
||||
)
|
||||
or
|
||||
field = varUsed
|
||||
or
|
||||
varUsed.(LocalScopeVariable).getEnclosingElement*() = field
|
||||
or
|
||||
varUsed.(Parameter).getCatchBlock().getEnclosingElement*() = field
|
||||
) and
|
||||
type = getTypeForPRValue(getVariableType(varUsed))
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
(
|
||||
tag = InitializerStoreTag()
|
||||
or
|
||||
tag = ThisLoadTag()
|
||||
) and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(ThisAddressTag())
|
||||
or
|
||||
(
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
operandTag instanceof AddressOperandTag
|
||||
or
|
||||
tag = InitializerFieldAddressTag() and
|
||||
operandTag instanceof UnaryOperandTag
|
||||
) and
|
||||
result = this.getInstruction(ThisLoadTag())
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(InitializerFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
final Instruction getLoadThisInstruction() { result = this.getInstruction(ThisLoadTag()) }
|
||||
|
||||
private CppType getThisType() { result = getTypeForGLValue(cls) }
|
||||
}
|
||||
|
||||
TranslatedNonStaticDataMemberVarInit getTranslatedFieldInit(Field field) { result.getAst() = field }
|
||||
@@ -495,7 +495,7 @@ class FieldInstruction extends Instruction {
|
||||
* `FunctionAddress` instruction.
|
||||
*/
|
||||
class FunctionInstruction extends Instruction {
|
||||
Language::Function funcSymbol;
|
||||
Language::Declaration funcSymbol;
|
||||
|
||||
FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) }
|
||||
|
||||
@@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the function that this instruction references.
|
||||
*/
|
||||
final Language::Function getFunctionSymbol() { result = funcSymbol }
|
||||
final Language::Declaration getFunctionSymbol() { result = funcSymbol }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction {
|
||||
/**
|
||||
* Gets the `Function` that the call targets, if this is statically known.
|
||||
*/
|
||||
final Language::Function getStaticCallTarget() {
|
||||
final Language::Declaration getStaticCallTarget() {
|
||||
result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol()
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ private import implementations.SqLite3
|
||||
private import implementations.PostgreSql
|
||||
private import implementations.System
|
||||
private import implementations.StructuredExceptionHandling
|
||||
private import implementations.ZMQ
|
||||
private import implementations.Win32CommandExecution
|
||||
private import implementations.CA2AEX
|
||||
private import implementations.CComBSTR
|
||||
@@ -58,3 +57,4 @@ private import implementations.CAtlFileMapping
|
||||
private import implementations.CAtlTemporaryFile
|
||||
private import implementations.CRegKey
|
||||
private import implementations.WinHttp
|
||||
private import implementations.Http
|
||||
|
||||
@@ -112,21 +112,3 @@ private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunctio
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
}
|
||||
|
||||
/**
|
||||
* A model for `getc` and similar functions that are flow sources.
|
||||
*/
|
||||
private class GetcSource extends SourceModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
";;false;getc;;;ReturnValue;remote", ";;false;getwc;;;ReturnValue;remote",
|
||||
";;false;_getc_nolock;;;ReturnValue;remote", ";;false;_getwc_nolock;;;ReturnValue;remote",
|
||||
";;false;getch;;;ReturnValue;local", ";;false;_getch;;;ReturnValue;local",
|
||||
";;false;_getwch;;;ReturnValue;local", ";;false;_getch_nolock;;;ReturnValue;local",
|
||||
";;false;_getwch_nolock;;;ReturnValue;local", ";;false;getchar;;;ReturnValue;local",
|
||||
";;false;getwchar;;;ReturnValue;local", ";;false;_getchar_nolock;;;ReturnValue;local",
|
||||
";;false;_getwchar_nolock;;;ReturnValue;local",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
193
cpp/ql/lib/semmle/code/cpp/models/implementations/Http.qll
Normal file
193
cpp/ql/lib/semmle/code/cpp/models/implementations/Http.qll
Normal file
@@ -0,0 +1,193 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.dataflow.FlowSteps
|
||||
private import semmle.code.cpp.dataflow.new.DataFlow
|
||||
|
||||
private class HttpRequest extends Class {
|
||||
HttpRequest() { this.hasGlobalName("_HTTP_REQUEST_V1") }
|
||||
}
|
||||
|
||||
private class HttpRequestInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
HttpRequestInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpRequest and
|
||||
(
|
||||
this.getAField().hasName("pRawUrl") and
|
||||
this.getIndirectionIndex() = 2
|
||||
or
|
||||
this.getAField().hasName("CookedUrl") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("Headers") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("pEntityChunks") and
|
||||
this.getIndirectionIndex() = 2
|
||||
or
|
||||
this.getAField().hasName("pSslInfo") and
|
||||
this.getIndirectionIndex() = 2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpCookedUrl extends Class {
|
||||
HttpCookedUrl() { this.hasGlobalName("_HTTP_COOKED_URL") }
|
||||
}
|
||||
|
||||
private class HttpCookedUrlInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
HttpCookedUrlInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpCookedUrl and
|
||||
this.getAField().hasName(["pFullUrl", "pHost", "pAbsPath", "pQueryString"]) and
|
||||
this.getIndirectionIndex() = 2
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpRequestHeaders extends Class {
|
||||
HttpRequestHeaders() { this.hasGlobalName("_HTTP_REQUEST_HEADERS") }
|
||||
}
|
||||
|
||||
private class HttpRequestHeadersInheritingContent extends TaintInheritingContent,
|
||||
DataFlow::FieldContent
|
||||
{
|
||||
HttpRequestHeadersInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpRequestHeaders and
|
||||
(
|
||||
this.getAField().hasName("KnownHeaders") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("pUnknownHeaders") and
|
||||
this.getIndirectionIndex() = 2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpKnownHeader extends Class {
|
||||
HttpKnownHeader() { this.hasGlobalName("_HTTP_KNOWN_HEADER") }
|
||||
}
|
||||
|
||||
private class HttpKnownHeaderInheritingContent extends TaintInheritingContent,
|
||||
DataFlow::FieldContent
|
||||
{
|
||||
HttpKnownHeaderInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpKnownHeader and
|
||||
this.getAField().hasName("pRawValue") and
|
||||
this.getIndirectionIndex() = 2
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpUnknownHeader extends Class {
|
||||
HttpUnknownHeader() { this.hasGlobalName("_HTTP_UNKNOWN_HEADER") }
|
||||
}
|
||||
|
||||
private class HttpUnknownHeaderInheritingContent extends TaintInheritingContent,
|
||||
DataFlow::FieldContent
|
||||
{
|
||||
HttpUnknownHeaderInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpUnknownHeader and
|
||||
this.getAField().hasName(["pName", "pRawValue"]) and
|
||||
this.getIndirectionIndex() = 2
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpDataChunk extends Class {
|
||||
HttpDataChunk() { this.hasGlobalName("_HTTP_DATA_CHUNK") }
|
||||
}
|
||||
|
||||
private class HttpDataChunkInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
HttpDataChunkInheritingContent() {
|
||||
this.getAField().getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
|
||||
(
|
||||
this.getAField().hasName("FromMemory") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("FromFileHandle") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("FromFragmentCache") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("FromFragmentCacheEx") and
|
||||
this.getIndirectionIndex() = 1
|
||||
or
|
||||
this.getAField().hasName("Trailers") and
|
||||
this.getIndirectionIndex() = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class FromMemory extends Class {
|
||||
FromMemory() {
|
||||
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
|
||||
this.getAField().hasName("pBuffer")
|
||||
}
|
||||
}
|
||||
|
||||
private class FromMemoryInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
FromMemoryInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof FromMemory and
|
||||
this.getAField().hasName("pBuffer") and
|
||||
this.getIndirectionIndex() = 2
|
||||
}
|
||||
}
|
||||
|
||||
private class FromFileHandle extends Class {
|
||||
FromFileHandle() {
|
||||
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
|
||||
this.getAField().hasName("FileHandle")
|
||||
}
|
||||
}
|
||||
|
||||
private class FromFileHandleInheritingContent extends TaintInheritingContent, DataFlow::FieldContent
|
||||
{
|
||||
FromFileHandleInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof FromFileHandle and
|
||||
this.getIndirectionIndex() = 1 and
|
||||
this.getAField().hasName("FileHandle")
|
||||
}
|
||||
}
|
||||
|
||||
private class FromFragmentCacheOrCacheEx extends Class {
|
||||
FromFragmentCacheOrCacheEx() {
|
||||
this.getDeclaringType().(Union).getDeclaringType() instanceof HttpDataChunk and
|
||||
this.getAField().hasName("pFragmentName")
|
||||
}
|
||||
}
|
||||
|
||||
private class FromFragmentCacheInheritingContent extends TaintInheritingContent,
|
||||
DataFlow::FieldContent
|
||||
{
|
||||
FromFragmentCacheInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof FromFragmentCacheOrCacheEx and
|
||||
this.getIndirectionIndex() = 2 and
|
||||
this.getAField().hasName("pFragmentName")
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpSslInfo extends Class {
|
||||
HttpSslInfo() { this.hasGlobalName("_HTTP_SSL_INFO") }
|
||||
}
|
||||
|
||||
private class HttpSslInfoInheritingContent extends TaintInheritingContent, DataFlow::FieldContent {
|
||||
HttpSslInfoInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpSslInfo and
|
||||
this.getAField().hasName(["pServerCertIssuer", "pServerCertSubject", "pClientCertInfo"]) and
|
||||
this.getIndirectionIndex() = 2
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpSslClientCertInfo extends Class {
|
||||
HttpSslClientCertInfo() { this.hasGlobalName("_HTTP_SSL_CLIENT_CERT_INFO") }
|
||||
}
|
||||
|
||||
private class HttpSslClientCertInfoInheritingContent extends TaintInheritingContent,
|
||||
DataFlow::FieldContent
|
||||
{
|
||||
HttpSslClientCertInfoInheritingContent() {
|
||||
this.getAField().getDeclaringType() instanceof HttpSslClientCertInfo and
|
||||
(
|
||||
this.getAField().hasName("pCertEncoded") and
|
||||
this.getIndirectionIndex() = 2
|
||||
or
|
||||
this.getAField().hasName("Token") and
|
||||
this.getIndirectionIndex() = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the ZeroMQ networking library.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
|
||||
/**
|
||||
* Remote flow sources.
|
||||
*/
|
||||
private class ZmqSource extends SourceModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
";;false;zmq_recv;;;Argument[*1];remote", ";;false;zmq_recvmsg;;;Argument[*1];remote",
|
||||
";;false;zmq_msg_recv;;;Argument[*0];remote",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remote flow sinks.
|
||||
*/
|
||||
private class ZmqSinks extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
";;false;zmq_send;;;Argument[*1];remote-sink",
|
||||
";;false;zmq_sendmsg;;;Argument[*1];remote-sink",
|
||||
";;false;zmq_msg_send;;;Argument[*0];remote-sink",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow steps.
|
||||
*/
|
||||
private class ZmqSummaries extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
";;false;zmq_msg_init_data;;;Argument[*1];Argument[*0];taint",
|
||||
";;false;zmq_msg_data;;;Argument[*0];ReturnValue[*];taint",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -245,6 +245,25 @@ trap_filename(
|
||||
string filename: string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* Gives the tag name for `tag`.
|
||||
* For debugging only.
|
||||
*/
|
||||
tag_name(
|
||||
int tag: @tag,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@trap_or_tag = @tag | @trap;
|
||||
|
||||
/**
|
||||
* Gives the name for the source file.
|
||||
*/
|
||||
source_file_name(
|
||||
int sf: @source_file,
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
/**
|
||||
* In `build-mode: none` overlay mode, indicates that `source_file`
|
||||
* (`/path/to/foo.c`) uses the TRAP file `trap_file`; i.e. it is the
|
||||
@@ -252,16 +271,25 @@ trap_filename(
|
||||
* includes, or a template instantiation it transitively uses.
|
||||
*/
|
||||
source_file_uses_trap(
|
||||
string source_file: string ref,
|
||||
int source_file: @source_file ref,
|
||||
int trap_file: @trap ref
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if there is a definition of `element` in TRAP file `trap_file`.
|
||||
* In `build-mode: none` overlay mode, indicates that the TRAP file
|
||||
* `trap_file` uses tag `tag`.
|
||||
*/
|
||||
in_trap(
|
||||
trap_uses_tag(
|
||||
int trap_file: @trap ref,
|
||||
int tag: @tag ref
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if there is a definition of `element` in TRAP file or tag `t`.
|
||||
*/
|
||||
in_trap_or_tag(
|
||||
int element: @element ref,
|
||||
int trap_file: @trap ref
|
||||
int t: @trap_or_tag ref
|
||||
);
|
||||
|
||||
pch_uses(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
class Element extends @element {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
class Trap extends @trap {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from Element e, Trap trap
|
||||
where in_trap(e, trap)
|
||||
select e, trap
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user