mirror of
https://github.com/github/codeql.git
synced 2026-05-17 04:37:07 +02:00
Compare commits
955 Commits
codeql-cli
...
remove-jav
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ee314a4dad | ||
|
|
8dcf7926de | ||
|
|
d09c3bf863 | ||
|
|
1a92fa5d92 | ||
|
|
8d2ad4ed17 | ||
|
|
5f659f6e48 | ||
|
|
ee46717c76 | ||
|
|
914e621d1b | ||
|
|
976190e84d | ||
|
|
06eb93da3f | ||
|
|
7197f41e75 | ||
|
|
5488872044 | ||
|
|
413ac4e8f4 | ||
|
|
cec6cd0830 | ||
|
|
39a12a8464 | ||
|
|
46eb27cd01 | ||
|
|
ba98c0c1cb | ||
|
|
fc8b439263 | ||
|
|
a358ea8667 | ||
|
|
c294b75f6c | ||
|
|
d5e17f9ebf | ||
|
|
c7ea7ca5cd | ||
|
|
49c656d904 | ||
|
|
79549c2285 | ||
|
|
787f36f056 | ||
|
|
b7b229d59b | ||
|
|
64fcbe05c3 | ||
|
|
31c34870ef | ||
|
|
3c17ac424d | ||
|
|
bb6c079e5a | ||
|
|
a3c1975a84 | ||
|
|
bdd78d2bc7 | ||
|
|
29db42c3cd | ||
|
|
e6df8164cf | ||
|
|
cf03bd8bd1 | ||
|
|
342c14887b | ||
|
|
e1101e582e | ||
|
|
768203bd36 | ||
|
|
c51fb00082 | ||
|
|
0a92b04c8b | ||
|
|
15161d8867 | ||
|
|
53ee465726 | ||
|
|
a20acfee25 | ||
|
|
f69787afd0 | ||
|
|
9b12980688 | ||
|
|
cb0f82c36e | ||
|
|
3b678bfbc5 | ||
|
|
e1750adc38 | ||
|
|
fd0fb9483e | ||
|
|
3d1d491e6b | ||
|
|
18020707b8 | ||
|
|
cfa0d46b73 | ||
|
|
e027d514f1 | ||
|
|
d5f675c2dc | ||
|
|
78c12dc505 | ||
|
|
ad08ccb50b | ||
|
|
95751fcc21 | ||
|
|
13417dbf14 | ||
|
|
ff21662b23 | ||
|
|
6967b06dee | ||
|
|
fc58ada92e | ||
|
|
108118afa3 | ||
|
|
d8bb5273e7 | ||
|
|
c792567904 | ||
|
|
6d9a88d1c8 | ||
|
|
3520fed752 | ||
|
|
d10dbbdd9d | ||
|
|
6bf1e87bbe | ||
|
|
91f46624b6 | ||
|
|
94f32d2985 | ||
|
|
569426b04e | ||
|
|
b0852f6c16 | ||
|
|
b985ddb868 | ||
|
|
079769ed2e | ||
|
|
fc6af0476f | ||
|
|
03bd7d7f96 | ||
|
|
92ffd8c465 | ||
|
|
b0836a620c | ||
|
|
06b36f742e | ||
|
|
c977cfe40a | ||
|
|
e0921ac983 | ||
|
|
7e7dfe2cc4 | ||
|
|
91a8b9fdd9 | ||
|
|
8debae1a3b | ||
|
|
547cbb6322 | ||
|
|
1adc5c2a5b | ||
|
|
d39df18544 | ||
|
|
e664711f47 | ||
|
|
7d3a219f63 | ||
|
|
23e4ad1abb | ||
|
|
3e1bc66984 | ||
|
|
26d2fbd217 | ||
|
|
913a679ef5 | ||
|
|
aebde189f8 | ||
|
|
66c206cc61 | ||
|
|
c9640ffdbc | ||
|
|
24214002a1 | ||
|
|
eba1b0bc15 | ||
|
|
289660067c | ||
|
|
854f2a046a | ||
|
|
69541d3628 | ||
|
|
70e1724463 | ||
|
|
cbdabe35de | ||
|
|
c9c41252e3 | ||
|
|
3437cf2909 | ||
|
|
d7afd86a27 | ||
|
|
38ca5aba98 | ||
|
|
4e6a8d991e | ||
|
|
cb0a567c03 | ||
|
|
032ac50034 | ||
|
|
3e5f7d0db5 | ||
|
|
b08eabec68 | ||
|
|
a4a9e2aa96 | ||
|
|
3189c578a4 | ||
|
|
c2b356ab08 | ||
|
|
ceb9a0bd6b | ||
|
|
a031b2a090 | ||
|
|
b52a2cd292 | ||
|
|
6be4b3bac6 | ||
|
|
4841c3037d | ||
|
|
f14e3f6007 | ||
|
|
83fb41e414 | ||
|
|
d0b9920cac | ||
|
|
51d2b5225e | ||
|
|
563e8a2bd6 | ||
|
|
a30554e97c | ||
|
|
ef6e502ff0 | ||
|
|
93daaf5b5b | ||
|
|
70489b2fc2 | ||
|
|
27c45d8dda | ||
|
|
3123abfac3 | ||
|
|
522c6e01d2 | ||
|
|
14a31a2299 | ||
|
|
35baff8bac | ||
|
|
5969c227ab | ||
|
|
8badba26b8 | ||
|
|
24e3ad4e18 | ||
|
|
a66f83644b | ||
|
|
364dab6990 | ||
|
|
b960857fc2 | ||
|
|
65d3373ad3 | ||
|
|
3108817717 | ||
|
|
d44f279339 | ||
|
|
a83bb39d0f | ||
|
|
d62f76afa6 | ||
|
|
97c2917c16 | ||
|
|
3cd675bfff | ||
|
|
478093aa89 | ||
|
|
dcae1c5c04 | ||
|
|
6e9bee1be7 | ||
|
|
25d6e00b1a | ||
|
|
a47897bdf9 | ||
|
|
2c41de6648 | ||
|
|
dd1bed02e8 | ||
|
|
bd5edc7ae5 | ||
|
|
dfe932d053 | ||
|
|
99881db8bd | ||
|
|
0c1f3ed0b3 | ||
|
|
a811ab3aff | ||
|
|
5a28a796af | ||
|
|
4adb0c75bd | ||
|
|
4a16be2cba | ||
|
|
f8e6ba633a | ||
|
|
c7c8e2f3e3 | ||
|
|
eaf05305ff | ||
|
|
044623a360 | ||
|
|
07c05528ef | ||
|
|
c72e385a47 | ||
|
|
797966fd3d | ||
|
|
82d463e86e | ||
|
|
97c0f1c7b7 | ||
|
|
64507ab316 | ||
|
|
b9c4abe7dc | ||
|
|
6d315a5d16 | ||
|
|
187b7e117c | ||
|
|
f0e7be7d56 | ||
|
|
c6c1ad1b90 | ||
|
|
07fe29cc67 | ||
|
|
4929c66e60 | ||
|
|
3ef09da1df | ||
|
|
9e41f43ee2 | ||
|
|
2cbad4aed6 | ||
|
|
3247794e2f | ||
|
|
e946f49b64 | ||
|
|
0bff1b4afb | ||
|
|
8232698254 | ||
|
|
6a78aa7840 | ||
|
|
7383988988 | ||
|
|
e906ded0d1 | ||
|
|
032a7e71fe | ||
|
|
b73a2f7d56 | ||
|
|
4d7aa5c945 | ||
|
|
af8b2b6d9c | ||
|
|
c36292bfd0 | ||
|
|
a67db45454 | ||
|
|
1111afc031 | ||
|
|
54dbd7c0bd | ||
|
|
ef5bf87672 | ||
|
|
eb45e67784 | ||
|
|
1eacbd88b8 | ||
|
|
a89bd32eb0 | ||
|
|
56a2dc632b | ||
|
|
7dded52de2 | ||
|
|
8425a94729 | ||
|
|
7bf55fbc49 | ||
|
|
39349f3763 | ||
|
|
60c6158152 | ||
|
|
225e70a8d0 | ||
|
|
338a6f2114 | ||
|
|
cd7c7c3152 | ||
|
|
84748cda76 | ||
|
|
f94a61cc8a | ||
|
|
b51ffadd27 | ||
|
|
0f2c50f1f5 | ||
|
|
c8e2b027ee | ||
|
|
839c9e35c8 | ||
|
|
46eec3c8eb | ||
|
|
6ae11b5b2c | ||
|
|
ff733e0334 | ||
|
|
693d729ec6 | ||
|
|
2150c1d58e | ||
|
|
1273b063f4 | ||
|
|
a755633405 | ||
|
|
19579f0d9a | ||
|
|
ca583bffd5 | ||
|
|
5fee6d2d19 | ||
|
|
10f0f3038c | ||
|
|
73aba09eee | ||
|
|
035d655e72 | ||
|
|
020aa4d94c | ||
|
|
58d2d5d14e | ||
|
|
1c1c46591e | ||
|
|
9f10018d48 | ||
|
|
783233dfe4 | ||
|
|
f18c163408 | ||
|
|
8022530f34 | ||
|
|
28e5dcef52 | ||
|
|
37ec83a68b | ||
|
|
94b5c4eada | ||
|
|
d3caa80274 | ||
|
|
f015cea590 | ||
|
|
05dd3fa0e7 | ||
|
|
0198cf6318 | ||
|
|
236ffc8972 | ||
|
|
563878d28d | ||
|
|
5c73fed83a | ||
|
|
080867a390 | ||
|
|
f76ce8b33b | ||
|
|
33ef634ea8 | ||
|
|
05d83e487d | ||
|
|
21079a1315 | ||
|
|
d3cf697b07 | ||
|
|
5ed9949498 | ||
|
|
2e08c5dd2b | ||
|
|
c3c73377b8 | ||
|
|
023264660b | ||
|
|
0e7cbbfeb8 | ||
|
|
e58b90ef1c | ||
|
|
e159351179 | ||
|
|
30178d4f23 | ||
|
|
90df3fa94c | ||
|
|
49c6a56f97 | ||
|
|
148443fae1 | ||
|
|
2cada386b4 | ||
|
|
905be67aae | ||
|
|
c0fd44c909 | ||
|
|
3abe1b4fc6 | ||
|
|
c4714b55a3 | ||
|
|
65f4ec403f | ||
|
|
947ab8a14d | ||
|
|
3f736d3eb8 | ||
|
|
b228398b87 | ||
|
|
8ea7a28a77 | ||
|
|
758b6bd4dd | ||
|
|
0e7afb24cf | ||
|
|
9ad51fbc02 | ||
|
|
cf149bd8c8 | ||
|
|
03db15af9a | ||
|
|
0b83d033d7 | ||
|
|
0f6e845418 | ||
|
|
01a06d1f5c | ||
|
|
e49cd83868 | ||
|
|
8485b6f0b3 | ||
|
|
220f2ded85 | ||
|
|
3f7d6e6f85 | ||
|
|
2a9e3da24f | ||
|
|
b5db4047a0 | ||
|
|
baab70bea6 | ||
|
|
b25b19f71b | ||
|
|
5a7785776c | ||
|
|
fdbf5f73b1 | ||
|
|
cc0d86403e | ||
|
|
48b763c7e9 | ||
|
|
7ce87a7118 | ||
|
|
c8c7a1f772 | ||
|
|
e3ed6c2523 | ||
|
|
23e28ae5d4 | ||
|
|
2a03a84315 | ||
|
|
68ab210dc8 | ||
|
|
ffd51e725f | ||
|
|
9585481d0b | ||
|
|
59f15eb4eb | ||
|
|
02a0eed8ee | ||
|
|
3b6c8c5191 | ||
|
|
136d04390d | ||
|
|
8fd848701e | ||
|
|
e5b84fb795 | ||
|
|
5d737934c3 | ||
|
|
367a53dd71 | ||
|
|
ca87768a93 | ||
|
|
44dca68463 | ||
|
|
406466de9a | ||
|
|
adbeba291b | ||
|
|
6cff0d0376 | ||
|
|
bc22e0d9aa | ||
|
|
4e93330cb9 | ||
|
|
abd770a027 | ||
|
|
a1ad1ddc10 | ||
|
|
d37c14880f | ||
|
|
b936a04826 | ||
|
|
c62a21e04f | ||
|
|
6d12c4aab1 | ||
|
|
26eafcb55a | ||
|
|
0640b41f00 | ||
|
|
8b7fad8595 | ||
|
|
49f5f1e2c2 | ||
|
|
6af5c5fc86 | ||
|
|
26dbf058c8 | ||
|
|
fcc0f1d5a7 | ||
|
|
e439b7d7f8 | ||
|
|
b740cf9664 | ||
|
|
097927226b | ||
|
|
f8d1e2ac11 | ||
|
|
1f7990d6bb | ||
|
|
a484e9fb06 | ||
|
|
b69033f4ff | ||
|
|
6c32b92929 | ||
|
|
98a12cef26 | ||
|
|
104873e8ee | ||
|
|
6811441459 | ||
|
|
b7fc068cee | ||
|
|
023c533745 | ||
|
|
cb8096f636 | ||
|
|
cca9ad06b4 | ||
|
|
76e4077b56 | ||
|
|
24addd5c10 | ||
|
|
e92b9cbe99 | ||
|
|
f9918cc63c | ||
|
|
e71173d953 | ||
|
|
57b5b2af2e | ||
|
|
25e1da0150 | ||
|
|
63e28c57cd | ||
|
|
199e015a06 | ||
|
|
b505662ef9 | ||
|
|
d52616b687 | ||
|
|
3f5ab60fb4 | ||
|
|
93f9097b02 | ||
|
|
2ccc6dc092 | ||
|
|
8fa3cefb8c | ||
|
|
d150c9a6be | ||
|
|
bf7c26e681 | ||
|
|
4d24be04a1 | ||
|
|
b889674486 | ||
|
|
8569d261f7 | ||
|
|
8e98dcefb1 | ||
|
|
3983aceb48 | ||
|
|
bac80bf686 | ||
|
|
f402475dd3 | ||
|
|
69fe2a36e5 | ||
|
|
ba7cdec2ea | ||
|
|
a9694bf0ef | ||
|
|
a714966e9b | ||
|
|
930a36df37 | ||
|
|
034899367d | ||
|
|
47a543e086 | ||
|
|
3bdc92ba8e | ||
|
|
122ffca049 | ||
|
|
24d740b2da | ||
|
|
bf5a46f6d8 | ||
|
|
b51ce1d2b3 | ||
|
|
7b764aec92 | ||
|
|
3c7b39f089 | ||
|
|
f202ddc5aa | ||
|
|
80f5ec29d4 | ||
|
|
1d8fae44cc | ||
|
|
b60f1cd531 | ||
|
|
9fdcacd865 | ||
|
|
ab862276fc | ||
|
|
12aeaeed56 | ||
|
|
47b5165f2a | ||
|
|
818e75bb8f | ||
|
|
8e9ac18026 | ||
|
|
902fa7d44a | ||
|
|
acd1acd869 | ||
|
|
befd1a7ccc | ||
|
|
abdd3a5dbe | ||
|
|
05cc6bcf8a | ||
|
|
f24d7c4212 | ||
|
|
487ebdf173 | ||
|
|
89a6cdc711 | ||
|
|
3404bcf265 | ||
|
|
4fbb165dce | ||
|
|
9a35a699cb | ||
|
|
68ed3250e8 | ||
|
|
1d76578202 | ||
|
|
c86311e879 | ||
|
|
342b2df93f | ||
|
|
3172d5727a | ||
|
|
d0563c80be | ||
|
|
2db039fb77 | ||
|
|
dde07fd2ee | ||
|
|
4ab9b81a9a | ||
|
|
4628f880b4 | ||
|
|
31739cdae6 | ||
|
|
2730423ab2 | ||
|
|
5d048a9518 | ||
|
|
cc1374b832 | ||
|
|
0abfb00032 | ||
|
|
26e8e89aca | ||
|
|
353c0a9ee7 | ||
|
|
3cf28ad6ce | ||
|
|
18b05bc56e | ||
|
|
54012eba23 | ||
|
|
131d63c374 | ||
|
|
d117593d72 | ||
|
|
5009ed618f | ||
|
|
edbaceceb3 | ||
|
|
fb22931e2d | ||
|
|
e8fc3c8ead | ||
|
|
9c0f18b88d | ||
|
|
95046b9bb1 | ||
|
|
451a46bf0e | ||
|
|
5e7a3ca2e6 | ||
|
|
62ecab8432 | ||
|
|
f1c3a11103 | ||
|
|
d83ed33252 | ||
|
|
9b488207eb | ||
|
|
9d31641bb1 | ||
|
|
655236c70d | ||
|
|
b47939c737 | ||
|
|
d940085384 | ||
|
|
bdd135dbff | ||
|
|
701d0bcdca | ||
|
|
4397371a50 | ||
|
|
b9b34eb0ee | ||
|
|
3b6cc97557 | ||
|
|
0ebbb333ba | ||
|
|
38cc9bef02 | ||
|
|
29028c5d46 | ||
|
|
2d03840fde | ||
|
|
2eb11731e2 | ||
|
|
02fd63ce20 | ||
|
|
5d137ce9c5 | ||
|
|
db78e3a7da | ||
|
|
b45743b562 | ||
|
|
27f2d417c1 | ||
|
|
7cfa08abc8 | ||
|
|
649c2ce188 | ||
|
|
af0b9abab7 | ||
|
|
2c93bce9ad | ||
|
|
0673355f31 | ||
|
|
b20232db3c | ||
|
|
1bbadb57a2 | ||
|
|
a756ffa3a6 | ||
|
|
296d10fe2a | ||
|
|
3b3350e648 | ||
|
|
3e17fdcaa3 | ||
|
|
32b3e416b3 | ||
|
|
97ed9edd32 | ||
|
|
5b8b27a2aa | ||
|
|
ad04099ac2 | ||
|
|
4c74709019 | ||
|
|
13c4b93d3d | ||
|
|
9d5e48430e | ||
|
|
a0bf170d02 | ||
|
|
ec3990c619 | ||
|
|
c4956a4ade | ||
|
|
270dbd2bf7 | ||
|
|
6c44b0e6e7 | ||
|
|
c0e65e71b4 | ||
|
|
eef044f4d0 | ||
|
|
abe6c90829 | ||
|
|
0a17ab9325 | ||
|
|
cc7471f37d | ||
|
|
cbb37f70c4 | ||
|
|
a1b7437f8d | ||
|
|
1fe9e9262f | ||
|
|
a173d9593b | ||
|
|
fb90bb4241 | ||
|
|
ec5435befd | ||
|
|
55c605998c | ||
|
|
96a34b6165 | ||
|
|
5d58edb3b9 | ||
|
|
44f477d552 | ||
|
|
b47507293a | ||
|
|
9ab6c29cd3 | ||
|
|
baca9edbb1 | ||
|
|
cd26d97dd7 | ||
|
|
5d37748973 | ||
|
|
67eaa1b735 | ||
|
|
db1de18cc2 | ||
|
|
ceaf2b3727 | ||
|
|
7c94dd94e9 | ||
|
|
1f6df4e70d | ||
|
|
1af39f0776 | ||
|
|
2e9876f58f | ||
|
|
f91bd91d02 | ||
|
|
2b7882e6e5 | ||
|
|
3f5b9d0f54 | ||
|
|
e93dc0b4c4 | ||
|
|
4a5f70e6c8 | ||
|
|
4e261c61ae | ||
|
|
800801177d | ||
|
|
b802d7903a | ||
|
|
ee98c0c587 | ||
|
|
1bc16fb31e | ||
|
|
81f4822b8d | ||
|
|
be1d4c04f2 | ||
|
|
726feb3f4d | ||
|
|
f90d1fd70e | ||
|
|
9e66ee1da0 | ||
|
|
3641b28c3e | ||
|
|
a6b47208e1 | ||
|
|
2d9b4b33d4 | ||
|
|
da3b7a2b69 | ||
|
|
ff73e46c95 | ||
|
|
1ead522705 | ||
|
|
efd5dc94e6 | ||
|
|
eba414e31b | ||
|
|
3bc70f0ce6 | ||
|
|
7a0fc6ae61 | ||
|
|
41891959a3 | ||
|
|
2d13906e0e | ||
|
|
24d43689b2 | ||
|
|
8830f1531f | ||
|
|
acb055400d | ||
|
|
d1a1f57e77 | ||
|
|
995a8192a9 | ||
|
|
3d4db42da4 | ||
|
|
469993f6d3 | ||
|
|
43effd2b40 | ||
|
|
bea8a457a2 | ||
|
|
1ab86892a0 | ||
|
|
5b229e9392 | ||
|
|
79c3ccd56e | ||
|
|
d7934865c9 | ||
|
|
f7ad894495 | ||
|
|
5ac32f145f | ||
|
|
22df141761 | ||
|
|
51c0ceea38 | ||
|
|
5f5285955b | ||
|
|
b99c075282 | ||
|
|
bef05f885c | ||
|
|
f6541811d2 | ||
|
|
f30dad7705 | ||
|
|
8f52089475 | ||
|
|
7ec1fa2ebe | ||
|
|
2d7d45a8ac | ||
|
|
3c3d71d4a0 | ||
|
|
81ed3e7176 | ||
|
|
1dc712f54d | ||
|
|
203ca3f91b | ||
|
|
7befdc9c5c | ||
|
|
c63fd4a254 | ||
|
|
fcd346c2af | ||
|
|
bcaf0658e4 | ||
|
|
5cecea42e4 | ||
|
|
b7206c1218 | ||
|
|
ebdda885f9 | ||
|
|
e8644f6f2a | ||
|
|
b48caaf465 | ||
|
|
8729701b66 | ||
|
|
29cb067769 | ||
|
|
ae8408bcab | ||
|
|
4998a48f99 | ||
|
|
79ff7baaf6 | ||
|
|
138a7ae67f | ||
|
|
3a9cf639bd | ||
|
|
5fa9f16c01 | ||
|
|
c7146ac10c | ||
|
|
f6366e1e1f | ||
|
|
207d8f6030 | ||
|
|
9af4d560dd | ||
|
|
5014ef2337 | ||
|
|
43ccc14162 | ||
|
|
e3a49f8213 | ||
|
|
270b56af1b | ||
|
|
39a88d2e43 | ||
|
|
648197db35 | ||
|
|
0d88d18781 | ||
|
|
bb9911e06f | ||
|
|
b28bddd22c | ||
|
|
b7f13a7e1f | ||
|
|
85e1c87d14 | ||
|
|
8d4af3ad81 | ||
|
|
ddbaf585ec | ||
|
|
e4d22ea628 | ||
|
|
5a47ddbf77 | ||
|
|
b9ef6c7e55 | ||
|
|
8b0d5a2e7b | ||
|
|
286c102358 | ||
|
|
6a47fcaf1f | ||
|
|
23d7633cd5 | ||
|
|
863eede75b | ||
|
|
4e60fd5fc7 | ||
|
|
c02a743835 | ||
|
|
ccf1a44a2b | ||
|
|
ec0066d5a4 | ||
|
|
913990bc62 | ||
|
|
c6eb795e76 | ||
|
|
51475d2fb0 | ||
|
|
f59a5b6574 | ||
|
|
ab5c1d6bdd | ||
|
|
7149ad8ac4 | ||
|
|
0dd463dd2b | ||
|
|
cd646c819d | ||
|
|
9ed14b438e | ||
|
|
35b0e83370 | ||
|
|
c20cf23c98 | ||
|
|
4b02e266fd | ||
|
|
7d3131ca49 | ||
|
|
89ce04dcb9 | ||
|
|
6e025186ab | ||
|
|
abaa0633d7 | ||
|
|
d2f833d02c | ||
|
|
2edb32f344 | ||
|
|
67df890f68 | ||
|
|
76a41146a8 | ||
|
|
6ede08e3c9 | ||
|
|
c06e37f3d9 | ||
|
|
9386a900eb | ||
|
|
8c37e90a77 | ||
|
|
f2047ee4d0 | ||
|
|
3560853f36 | ||
|
|
d962fc4ce1 | ||
|
|
c110508b4e | ||
|
|
d57bd34575 | ||
|
|
d22620f72f | ||
|
|
c259d0204a | ||
|
|
a0b712d44b | ||
|
|
d73604d1c5 | ||
|
|
f755659f5d | ||
|
|
d1ab2d2e8c | ||
|
|
fdb4a2acdb | ||
|
|
75d367a6c5 | ||
|
|
ee13efbffd | ||
|
|
dbda1bf5c0 | ||
|
|
b9afccc015 | ||
|
|
2e995839bb | ||
|
|
81a9ce2baa | ||
|
|
dbc95cadb4 | ||
|
|
9f590dbf2d | ||
|
|
414bf12f86 | ||
|
|
88c6d4bb20 | ||
|
|
29b9231f49 | ||
|
|
e8bdc8ba17 | ||
|
|
608d24f75e | ||
|
|
0a5410c2d3 | ||
|
|
474d983f8d | ||
|
|
fca561351d | ||
|
|
ac43ad6da2 | ||
|
|
e048a729db | ||
|
|
ca5c2b2acf | ||
|
|
9c4a50503c | ||
|
|
065075056b | ||
|
|
ad102e2746 | ||
|
|
b4963c7538 | ||
|
|
e4fd749a46 | ||
|
|
82f61ca015 | ||
|
|
d55f18f8e3 | ||
|
|
f1744890b1 | ||
|
|
c34d6d1162 | ||
|
|
81dbe36e99 | ||
|
|
ba99e21875 | ||
|
|
91442e100c | ||
|
|
feb2303e1f | ||
|
|
1ab04a7276 | ||
|
|
2acf518037 | ||
|
|
fe143c7dfa | ||
|
|
b39bb24fcf | ||
|
|
1ba26237a7 | ||
|
|
1e88470ad8 | ||
|
|
9f4b7255aa | ||
|
|
1ad204d89e | ||
|
|
df04c5044c | ||
|
|
c3ecae503b | ||
|
|
136c8b5192 | ||
|
|
10f6cab77e | ||
|
|
ee8958ba03 | ||
|
|
c1d34d7d6f | ||
|
|
190bf90bc8 | ||
|
|
7ddf7ff211 | ||
|
|
d178fe4e5d | ||
|
|
93bc8aa7b2 | ||
|
|
7be179cf6c | ||
|
|
3928ffd30d | ||
|
|
b7e608abc9 | ||
|
|
dab626270d | ||
|
|
5df5805d36 | ||
|
|
e0d978fd58 | ||
|
|
7310590f90 | ||
|
|
ffd2a388a9 | ||
|
|
cc838326e1 | ||
|
|
7daa6481e3 | ||
|
|
4b1f918feb | ||
|
|
dccdc3be5a | ||
|
|
cce3c0256e | ||
|
|
e9ff6e8755 | ||
|
|
a3289fabe1 | ||
|
|
537450606e | ||
|
|
ff74fe1e03 | ||
|
|
75a3f34e86 | ||
|
|
29bcd7ca6f | ||
|
|
50a9b18c92 | ||
|
|
303e02fb8a | ||
|
|
f8d46677b9 | ||
|
|
98d018ce26 | ||
|
|
21c168e229 | ||
|
|
0923d1fdc1 | ||
|
|
c92b7828cb | ||
|
|
a47efc4348 | ||
|
|
a80a367de4 | ||
|
|
d6368c3d1b | ||
|
|
49807c080b | ||
|
|
436b18a11f | ||
|
|
6bbed9d624 | ||
|
|
7156dee270 | ||
|
|
7977d9c253 | ||
|
|
b38a23daee | ||
|
|
b267d26ff8 | ||
|
|
d6ae19c87d | ||
|
|
0ba334bb22 | ||
|
|
28dce6e95a | ||
|
|
83252e5ba2 | ||
|
|
cecb6c7bdd | ||
|
|
b509627113 | ||
|
|
3d6ab81ab8 | ||
|
|
c6399dbdf4 | ||
|
|
f94d8c341d | ||
|
|
510f5abb9a | ||
|
|
5dddc48e60 | ||
|
|
c8a5397085 | ||
|
|
27f10123c7 | ||
|
|
8833ff7854 | ||
|
|
ebf17e10d6 | ||
|
|
607f2d66b8 | ||
|
|
999f22f548 | ||
|
|
9f02ae29ec | ||
|
|
7dd65d8ac6 | ||
|
|
5b0e26c814 | ||
|
|
4ff135e827 | ||
|
|
5cd0996d92 | ||
|
|
7be4b76abb | ||
|
|
0ee1e8bd97 | ||
|
|
881951368d | ||
|
|
ecda79834d | ||
|
|
e4901eda91 | ||
|
|
2a79817c3b | ||
|
|
4d4443c3cf | ||
|
|
f450476b27 | ||
|
|
cd6a60dc70 | ||
|
|
b223049682 | ||
|
|
b9d1b5584e | ||
|
|
63b7c6a8d9 | ||
|
|
f7f69dc3ab | ||
|
|
76c38a564d | ||
|
|
7fc536db15 | ||
|
|
cf9ab83dee | ||
|
|
c3e122f5fc | ||
|
|
09aaa8f78e | ||
|
|
a01fca5d48 | ||
|
|
13c5857241 | ||
|
|
a855074588 | ||
|
|
0de621edf9 | ||
|
|
789e2e48cf | ||
|
|
1903cb8f82 | ||
|
|
486b283c20 | ||
|
|
a762373ad6 | ||
|
|
f5a1a12435 | ||
|
|
b28e956dd2 | ||
|
|
adcb90aa8c | ||
|
|
23b9028d2c | ||
|
|
04e04b3031 | ||
|
|
97faeb026f | ||
|
|
119de6c60c | ||
|
|
9d66761eeb | ||
|
|
0d174f2daf | ||
|
|
81742528a2 | ||
|
|
1b6e1dbd13 | ||
|
|
285c659541 | ||
|
|
64b305cf7a | ||
|
|
2132ee52d5 | ||
|
|
abf3bbbe8d | ||
|
|
e7611ab641 | ||
|
|
ce8d14e6ef | ||
|
|
1bd5eb5120 | ||
|
|
73d6177477 | ||
|
|
2b0f6a2723 | ||
|
|
33c727e6b9 | ||
|
|
49ae549e89 | ||
|
|
097c23e437 | ||
|
|
47377c7197 | ||
|
|
786edb72df | ||
|
|
d458464e6b | ||
|
|
d834cec9b9 | ||
|
|
8614563b42 | ||
|
|
b8ce5a63c5 | ||
|
|
5bff5188ac | ||
|
|
cd40de7464 | ||
|
|
ab2bc38789 | ||
|
|
d405284d36 | ||
|
|
605bd19306 | ||
|
|
e865a290de | ||
|
|
e3765ced78 | ||
|
|
18440710b4 | ||
|
|
66bdbf4a28 | ||
|
|
dbf7487a9b | ||
|
|
e1ae531b62 | ||
|
|
34d7772a0d | ||
|
|
c4554836ca | ||
|
|
3c647c65bf | ||
|
|
21f683d531 | ||
|
|
5644514606 | ||
|
|
dcbf766217 | ||
|
|
8443d344a2 | ||
|
|
18b8244406 | ||
|
|
429decd7b6 | ||
|
|
ad2850dd5d | ||
|
|
babec9bf79 | ||
|
|
5e155d25b1 | ||
|
|
99e19e6d59 | ||
|
|
035f7b57e9 | ||
|
|
dee5535fbb | ||
|
|
1d3bcdf522 | ||
|
|
87ef540b52 | ||
|
|
89f4a35273 | ||
|
|
6be78d442c | ||
|
|
2df846ee4b | ||
|
|
54e65ce765 | ||
|
|
61bbddeb0c | ||
|
|
8aba0b04bc | ||
|
|
26ffe6c03d | ||
|
|
6287e6d8e9 | ||
|
|
ec7f4d18e1 | ||
|
|
c08f94ec04 | ||
|
|
34b054ff53 | ||
|
|
2437546009 | ||
|
|
8127f63b1e | ||
|
|
26d4269071 | ||
|
|
c48586ff80 | ||
|
|
5b55a83aaa | ||
|
|
a3bacc76f1 | ||
|
|
cf40d0ae4d | ||
|
|
489ac04f86 | ||
|
|
19bb8e8c17 | ||
|
|
e07516585a | ||
|
|
60c7003667 | ||
|
|
fda394858b | ||
|
|
8595ae71f7 | ||
|
|
3365634259 | ||
|
|
aab633eced | ||
|
|
2064915d3b | ||
|
|
0c04c9a2c2 | ||
|
|
722889e881 | ||
|
|
d9285e78c0 | ||
|
|
07303ccbb3 | ||
|
|
b9f6b60c4d | ||
|
|
32f52ac30d | ||
|
|
18e3763f90 | ||
|
|
9b6ae9029f | ||
|
|
f02b6d60a5 | ||
|
|
930d576cfb | ||
|
|
b03e75e3d1 | ||
|
|
a34d6d390e | ||
|
|
38875ca0c7 | ||
|
|
c3f942f899 | ||
|
|
6e9d9fcbbd | ||
|
|
d3163d8a76 | ||
|
|
e2d3fa7093 | ||
|
|
f5ae5a581b | ||
|
|
d2efe0b84d | ||
|
|
be1cad864b | ||
|
|
6f63c03558 | ||
|
|
7e09a1cbfd | ||
|
|
7020e4132b | ||
|
|
d388dd547e | ||
|
|
f3ce3933d1 | ||
|
|
dac71ded9d | ||
|
|
133632119d | ||
|
|
4d9c86a252 | ||
|
|
9cb4899c5c | ||
|
|
09b0c300d9 | ||
|
|
04190ea308 | ||
|
|
5f5c0b11c7 | ||
|
|
4f4dec50f2 | ||
|
|
edb273ace5 | ||
|
|
6f0a622252 | ||
|
|
7dc6518350 | ||
|
|
18c0d13efd | ||
|
|
5ec5557203 | ||
|
|
95e88c18b9 | ||
|
|
51b543c67c | ||
|
|
bced467a88 | ||
|
|
ce4b192caa | ||
|
|
6aabbf0b9a | ||
|
|
6591a86aad | ||
|
|
e53b86fbbc | ||
|
|
bbcbcefedc | ||
|
|
233ae5a54b | ||
|
|
8b3fa789da | ||
|
|
f91e826781 | ||
|
|
c6c925d67a | ||
|
|
4f3f93f267 | ||
|
|
3fd0ec74f0 | ||
|
|
04940a1105 | ||
|
|
5a9fca48e8 | ||
|
|
ec9063b4a5 | ||
|
|
c3789811c8 | ||
|
|
8b6b4dde69 | ||
|
|
df8a6b984a | ||
|
|
90633b9ce1 | ||
|
|
90fe5c5aca | ||
|
|
2e2673aff6 | ||
|
|
440793b5ff | ||
|
|
222cd41aa3 | ||
|
|
092fbd60d9 | ||
|
|
ec48d0ac29 | ||
|
|
bf2d7b3a16 | ||
|
|
13997caa32 | ||
|
|
3e889c398e | ||
|
|
858c0e67a1 | ||
|
|
957b3e1e85 | ||
|
|
3ce0a9c8c0 | ||
|
|
7de9214c99 | ||
|
|
402ed04189 | ||
|
|
059d6b0e0f | ||
|
|
563dc62c33 | ||
|
|
3f1f83f667 | ||
|
|
6d5f9035e6 | ||
|
|
7d47bffd53 | ||
|
|
d4acccb13c | ||
|
|
0a7e4b6840 | ||
|
|
4e0f3a30ee | ||
|
|
ba46eaa143 | ||
|
|
3c493511e9 | ||
|
|
12e8107492 | ||
|
|
5c7dedffb3 | ||
|
|
71a08c3237 | ||
|
|
d408ae7e10 | ||
|
|
386eb2d56b | ||
|
|
a2615339f7 | ||
|
|
cae6f91729 | ||
|
|
dbe0170249 | ||
|
|
188dbde2d6 | ||
|
|
96d11b7966 |
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -48,3 +48,6 @@
|
||||
*.gif -text
|
||||
*.dll -text
|
||||
*.pdb -text
|
||||
|
||||
java/ql/test/stubs/**/*.java linguist-generated=true
|
||||
java/ql/test/experimental/stubs/**/*.java linguist-generated=true
|
||||
11
.github/workflows/codeql-analysis.yml
vendored
11
.github/workflows/codeql-analysis.yml
vendored
@@ -11,6 +11,8 @@ on:
|
||||
- 'rc/*'
|
||||
paths:
|
||||
- 'csharp/**'
|
||||
- '.github/codeql/**'
|
||||
- '.github/workflows/codeql-analysis.yml'
|
||||
schedule:
|
||||
- cron: '0 9 * * 1'
|
||||
|
||||
@@ -38,8 +40,8 @@ jobs:
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@main
|
||||
#- name: Autobuild
|
||||
# uses: github/codeql-action/autobuild@main
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -48,9 +50,8 @@ jobs:
|
||||
# and modify them (or add more) to build your code if your project
|
||||
# uses a compiled language
|
||||
|
||||
#- run: |
|
||||
# make bootstrap
|
||||
# make release
|
||||
- run: |
|
||||
dotnet build csharp
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@main
|
||||
|
||||
2
.github/workflows/csv-coverage-update.yml
vendored
2
.github/workflows/csv-coverage-update.yml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
update:
|
||||
name: Update framework coverage report
|
||||
if: github.event.repository.fork == false
|
||||
if: github.repository == 'github/codeql'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -4,8 +4,8 @@ This open source repository contains the standard CodeQL libraries and queries t
|
||||
|
||||
## How do I learn CodeQL and run queries?
|
||||
|
||||
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed.
|
||||
There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL.
|
||||
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) extension to try out your queries on any open source project that's currently being analyzed.
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -462,4 +462,4 @@
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
2
cpp/change-notes/2021-06-22-sql-tainted.md
Normal file
2
cpp/change-notes/2021-06-22-sql-tainted.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* The 'Uncontrolled data in SQL query' (cpp/sql-injection) query now supports the `libpqxx` library.
|
||||
@@ -0,0 +1,4 @@
|
||||
lgtm,codescanning
|
||||
* The `SimpleRangeAnalysis` library includes information from the
|
||||
immediate guard for determining the upper bound of a stack
|
||||
variable for improved accuracy.
|
||||
4
cpp/change-notes/2021-09-13-overflow-static.md
Normal file
4
cpp/change-notes/2021-09-13-overflow-static.md
Normal file
@@ -0,0 +1,4 @@
|
||||
lgtm,codescanning
|
||||
* The `memberMayBeVarSize` predicate considers more fields to be variable size.
|
||||
As a result, the "Static buffer overflow" query (cpp/static-buffer-overflow)
|
||||
produces fewer false positives.
|
||||
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
3
cpp/change-notes/2021-09-27-overflow-static.md
Normal file
@@ -0,0 +1,3 @@
|
||||
lgtm,codescanning
|
||||
* Increase precision to high for the "Static buffer overflow" query
|
||||
(`cpp/static-buffer-overflow`). This means the query is run and displayed by default on Code Scanning and LGTM.
|
||||
@@ -1,3 +1,4 @@
|
||||
name: codeql-cpp-examples
|
||||
version: 0.0.0
|
||||
libraryPathDependencies: codeql/cpp-all
|
||||
name: codeql/cpp-examples
|
||||
version: 0.0.2
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
|
||||
@@ -3,3 +3,5 @@ version: 0.0.2
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
library: true
|
||||
dependencies:
|
||||
codeql/cpp-upgrades: 0.0.2
|
||||
|
||||
@@ -171,7 +171,7 @@ class Container extends Locatable, @container {
|
||||
* To get the full path, use `getAbsolutePath`.
|
||||
*/
|
||||
class Folder extends Container, @folder {
|
||||
override string getAbsolutePath() { folders(underlyingElement(this), result, _) }
|
||||
override string getAbsolutePath() { folders(underlyingElement(this), result) }
|
||||
|
||||
override Location getLocation() {
|
||||
result.getContainer() = this and
|
||||
@@ -190,7 +190,7 @@ class Folder extends Container, @folder {
|
||||
* DEPRECATED: use `getAbsolutePath` instead.
|
||||
* Gets the name of this folder.
|
||||
*/
|
||||
deprecated string getName() { folders(underlyingElement(this), result, _) }
|
||||
deprecated string getName() { folders(underlyingElement(this), result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAbsolutePath` instead.
|
||||
@@ -208,17 +208,7 @@ class Folder extends Container, @folder {
|
||||
* DEPRECATED: use `getBaseName` instead.
|
||||
* Gets the last part of the folder name.
|
||||
*/
|
||||
deprecated string getShortName() {
|
||||
exists(string longnameRaw, string longname |
|
||||
folders(underlyingElement(this), _, longnameRaw) and
|
||||
longname = longnameRaw.replaceAll("\\", "/")
|
||||
|
|
||||
exists(int index |
|
||||
result = longname.splitAt("/", index) and
|
||||
not exists(longname.splitAt("/", index + 1))
|
||||
)
|
||||
)
|
||||
}
|
||||
deprecated string getShortName() { result = this.getBaseName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getParentContainer` instead.
|
||||
@@ -242,7 +232,7 @@ class Folder extends Container, @folder {
|
||||
* `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`.
|
||||
*/
|
||||
class File extends Container, @file {
|
||||
override string getAbsolutePath() { files(underlyingElement(this), result, _, _, _) }
|
||||
override string getAbsolutePath() { files(underlyingElement(this), result) }
|
||||
|
||||
override string toString() { result = Container.super.toString() }
|
||||
|
||||
@@ -336,7 +326,13 @@ class File extends Container, @file {
|
||||
* for example, for "file.tar.gz", this predicate will have the result
|
||||
* "tar.gz", while `getExtension` will have the result "gz".
|
||||
*/
|
||||
string getExtensions() { files(underlyingElement(this), _, _, result, _) }
|
||||
string getExtensions() {
|
||||
exists(string name, int firstDotPos |
|
||||
name = this.getBaseName() and
|
||||
firstDotPos = min([name.indexOf("."), name.length() - 1]) and
|
||||
result = name.suffix(firstDotPos + 1)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the short name of this file, that is, the prefix of its base name up
|
||||
@@ -351,7 +347,16 @@ class File extends Container, @file {
|
||||
* for example, for "file.tar.gz", this predicate will have the result
|
||||
* "file", while `getStem` will have the result "file.tar".
|
||||
*/
|
||||
string getShortName() { files(underlyingElement(this), _, result, _, _) }
|
||||
string getShortName() {
|
||||
exists(string name, int firstDotPos |
|
||||
name = this.getBaseName() and
|
||||
firstDotPos = min([name.indexOf("."), name.length()]) and
|
||||
result = name.prefix(firstDotPos)
|
||||
)
|
||||
or
|
||||
this.getAbsolutePath() = "" and
|
||||
result = ""
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,53 +2,19 @@ import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
|
||||
* example:
|
||||
* Holds if `v` is a member variable of `c` that looks like it might be variable sized
|
||||
* in practice. For example:
|
||||
* ```
|
||||
* struct myStruct { // c
|
||||
* int amount;
|
||||
* char data[1]; // v
|
||||
* };
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
|
||||
* there must be at least one instance where a `c` pointer is allocated with additional space. For
|
||||
* example, holds for `c` if it occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c) + 100 * sizeof(char))
|
||||
* ```
|
||||
* but not if it only ever occurs as
|
||||
* ```
|
||||
* malloc(sizeof(c))
|
||||
* ```
|
||||
* This requires that `v` is an array of size 0 or 1.
|
||||
*/
|
||||
predicate memberMayBeVarSize(Class c, MemberVariable v) {
|
||||
exists(int i |
|
||||
// `v` is the last field in `c`
|
||||
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
|
||||
v = c.getCanonicalMember(i) and
|
||||
// v is an array of size at most 1
|
||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||
) and
|
||||
(
|
||||
exists(SizeofOperator so |
|
||||
// `sizeof(c)` is taken
|
||||
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
|
||||
so.(SizeofExprOperator).getExprOperand().getUnspecifiedType() = c
|
||||
|
|
||||
// arithmetic is performed on the result
|
||||
so.getParent*() instanceof AddExpr
|
||||
)
|
||||
or
|
||||
exists(AddressOfExpr aoe |
|
||||
// `&(c.v)` is taken
|
||||
aoe.getAddressable() = v
|
||||
)
|
||||
or
|
||||
exists(BuiltInOperationBuiltInOffsetOf oo |
|
||||
// `offsetof(c, v)` using a builtin
|
||||
oo.getAChild().(VariableAccess).getTarget() = v
|
||||
)
|
||||
)
|
||||
c = v.getDeclaringType() and
|
||||
v.getUnspecifiedType().(ArrayType).getArraySize() <= 1
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,15 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
|
||||
fc.getArgument(i) = va
|
||||
)
|
||||
or
|
||||
// String argument to a formatting function (such as `printf`)
|
||||
exists(int n, FormatLiteral fl |
|
||||
fc.(FormattingFunctionCall).getConversionArgument(n) = va and
|
||||
fl = fc.(FormattingFunctionCall).getFormat() and
|
||||
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||
)
|
||||
or
|
||||
// Call to a wrapper function that requires null termination
|
||||
// (not itself adding a null terminator)
|
||||
exists(Function wrapper, int i, Parameter p, VariableAccess use |
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -786,13 +786,18 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
* Holds if the call context `call` improves virtual dispatch in `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
predicate recordDataFlowCallSiteDispatch(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` allows us to prune unreachable nodes in `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate recordDataFlowCallSiteUnreachable(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||
}
|
||||
|
||||
@@ -846,6 +851,15 @@ private module Cached {
|
||||
TAccessPathFrontSome(AccessPathFront apf)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
*/
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
recordDataFlowCallSiteDispatch(call, callable) or
|
||||
recordDataFlowCallSiteUnreachable(call, callable)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -9,7 +9,7 @@ import semmle.code.cpp.Enum
|
||||
private import semmle.code.cpp.dataflow.EscapesTree
|
||||
|
||||
/**
|
||||
* A C/C++ access expression. This refers to a function, variable, or enum constant.
|
||||
* A C/C++ access expression. This refers to a function (excluding function references in function call expressions), variable, or enum constant.
|
||||
*/
|
||||
class Access extends Expr, NameQualifiableElement, @access {
|
||||
// As `@access` is a union type containing `@routineexpr` (which describes function accesses
|
||||
@@ -350,6 +350,15 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
* int (*myFunctionPointer)(int) = &myFunctionTarget;
|
||||
* }
|
||||
* ```
|
||||
* This excludes function accesses in function call expressions.
|
||||
* For example the access `myFunctionTarget` in `myFunction` in the following code:
|
||||
* ```
|
||||
* int myFunctionTarget(int);
|
||||
*
|
||||
* void myFunction() {
|
||||
* myFunctionTarget(1);
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class FunctionAccess extends Access, @routineexpr {
|
||||
FunctionAccess() { not iscall(underlyingElement(this), _) }
|
||||
|
||||
@@ -550,6 +550,39 @@ module TaintedWithPath {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is flow from `arg` to `out` across a call that can by summarized by the flow
|
||||
* from `par` to `ret` within it, in the graph of data flow path explanations.
|
||||
*/
|
||||
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner())
|
||||
or
|
||||
// To avoid showing trivial-looking steps, we _replace_ the last node instead
|
||||
// of adding an edge out of it.
|
||||
exists(WrapPathNode sinkNode |
|
||||
DataFlow3::PathGraph::subpaths(arg.(WrapPathNode).inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
or
|
||||
// Same for the first node
|
||||
exists(WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), out.(WrapPathNode).inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner())
|
||||
)
|
||||
or
|
||||
// Finally, handle the case where the path goes directly from a source to a
|
||||
// sink, meaning that they both need to be translated.
|
||||
exists(WrapPathNode sinkNode, WrapPathNode sourceNode |
|
||||
DataFlow3::PathGraph::subpaths(sourceNode.inner(), par.(WrapPathNode).inner(),
|
||||
ret.(WrapPathNode).inner(), sinkNode.inner()) and
|
||||
sourceNode.inner().getNode() = getNodeForExpr(arg.(InitialPathNode).inner()) and
|
||||
out.(FinalPathNode).inner() = adjustedSink(sinkNode.inner().getNode())
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
key = "semmle.label" and val = n.toString()
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -923,28 +923,29 @@ private module Stage2 {
|
||||
|
||||
ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
|
||||
|
||||
class Cc = boolean;
|
||||
class Cc = CallContext;
|
||||
|
||||
class CcCall extends Cc {
|
||||
CcCall() { this = true }
|
||||
class CcCall = CallContextCall;
|
||||
|
||||
/** Holds if this call context may be `call`. */
|
||||
predicate matchesCall(DataFlowCall call) { any() }
|
||||
}
|
||||
class CcNoCall = CallContextNoCall;
|
||||
|
||||
class CcNoCall extends Cc {
|
||||
CcNoCall() { this = false }
|
||||
}
|
||||
|
||||
Cc ccNone() { result = false }
|
||||
Cc ccNone() { result instanceof CallContextAny }
|
||||
|
||||
private class LocalCc = Unit;
|
||||
|
||||
bindingset[call, c, outercc]
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
|
||||
private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
|
||||
checkCallContextCall(outercc, call, c) and
|
||||
if recordDataFlowCallSiteDispatch(call, c)
|
||||
then result = TSpecificCall(call)
|
||||
else result = TSomeCall()
|
||||
}
|
||||
|
||||
bindingset[call, c, innercc]
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
|
||||
private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
|
||||
checkCallContextReturn(innercc, c, call) and
|
||||
if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
|
||||
}
|
||||
|
||||
bindingset[node, cc, config]
|
||||
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
|
||||
@@ -1172,7 +1173,8 @@ private module Stage2 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -1860,7 +1862,8 @@ private module Stage3 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -2117,7 +2120,7 @@ private module Stage3 {
|
||||
private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
|
||||
exists(AccessPathFront apf |
|
||||
Stage3::revFlow(node, true, _, apf, config) and
|
||||
Stage3::fwdFlow(node, true, TAccessPathFrontSome(argApf), apf, config)
|
||||
Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2618,7 +2621,8 @@ private module Stage4 {
|
||||
fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
|
||||
pragma[only_bind_into](config)) and
|
||||
fwdFlowOutFromArg(call, out, argAp0, ap, config) and
|
||||
fwdFlowIsEntered(call, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), argAp0,
|
||||
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
|
||||
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
|
||||
pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
@@ -3258,24 +3262,16 @@ class PathNode extends TPathNode {
|
||||
/** Gets the associated configuration. */
|
||||
Configuration getConfiguration() { none() }
|
||||
|
||||
private predicate isHidden() {
|
||||
hiddenNode(this.(PathNodeImpl).getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.(PathNodeImpl).getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private PathNode getASuccessorIfHidden() {
|
||||
this.isHidden() and
|
||||
this.(PathNodeImpl).isHidden() and
|
||||
result = this.(PathNodeImpl).getASuccessorImpl()
|
||||
}
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final PathNode getASuccessor() {
|
||||
result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
|
||||
not this.isHidden() and
|
||||
not result.isHidden()
|
||||
not this.(PathNodeImpl).isHidden() and
|
||||
not result.(PathNodeImpl).isHidden()
|
||||
}
|
||||
|
||||
/** Holds if this node is a source. */
|
||||
@@ -3287,6 +3283,14 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
|
||||
abstract NodeEx getNodeEx();
|
||||
|
||||
predicate isHidden() {
|
||||
hiddenNode(this.getNodeEx().asNode()) and
|
||||
not this.isSource() and
|
||||
not this instanceof PathNodeSink
|
||||
or
|
||||
this.getNodeEx() instanceof TNodeImplicitRead
|
||||
}
|
||||
|
||||
private string ppAp() {
|
||||
this instanceof PathNodeSink and result = ""
|
||||
or
|
||||
@@ -3313,10 +3317,15 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
}
|
||||
|
||||
/** Holds if `n` can reach a sink. */
|
||||
private predicate reach(PathNode n) { n instanceof PathNodeSink or reach(n.getASuccessor()) }
|
||||
private predicate directReach(PathNode n) {
|
||||
n instanceof PathNodeSink or directReach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `n1.getSucc() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and reach(n2) }
|
||||
/** Holds if `n` can reach a sink or is used in a subpath. */
|
||||
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
|
||||
|
||||
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
|
||||
private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
|
||||
|
||||
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
@@ -3325,12 +3334,14 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
|
||||
*/
|
||||
module PathGraph {
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(PathNode a, PathNode b) { pathSucc(a, b) }
|
||||
query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(PathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
query predicate subpaths = Subpaths::subpaths/4;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3622,6 +3633,87 @@ private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext c
|
||||
)
|
||||
}
|
||||
|
||||
private module Subpaths {
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths01(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
|
||||
pathIntoCallable(arg, par, _, innercc, sc, _) and
|
||||
paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _,
|
||||
unbindConf(arg.getConfiguration()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
|
||||
* `kind`, `sc`, `apout`, and `innercc`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths02(
|
||||
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
|
||||
NodeEx out, AccessPath apout
|
||||
) {
|
||||
subpaths01(arg, par, sc, innercc, kind, out, apout) and
|
||||
out.asNode() = kind.getAnOutNode(_)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate subpaths03(
|
||||
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
|
||||
) {
|
||||
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
|
||||
subpaths02(arg, par, sc, innercc, kind, out, apout) and
|
||||
ret.getNodeEx() = retnode and
|
||||
kind = retnode.getKind() and
|
||||
innercc = ret.getCallContext() and
|
||||
sc = ret.getSummaryCtx() and
|
||||
ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
|
||||
apout = ret.getAp() and
|
||||
not ret.isHidden()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
|
||||
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
|
||||
* `ret -> out` is summarized as the edge `arg -> out`.
|
||||
*/
|
||||
predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
|
||||
exists(ParamNodeEx p, NodeEx o, AccessPath apout |
|
||||
pragma[only_bind_into](arg).getASuccessor() = par and
|
||||
pragma[only_bind_into](arg).getASuccessor() = out and
|
||||
subpaths03(arg, p, ret, o, apout) and
|
||||
par.getNodeEx() = p and
|
||||
out.getNodeEx() = o and
|
||||
out.getAp() = apout
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` can reach a return node in a summarized subpath.
|
||||
*/
|
||||
predicate retReach(PathNode n) {
|
||||
subpaths(_, _, n, _)
|
||||
or
|
||||
exists(PathNode mid |
|
||||
retReach(mid) and
|
||||
n.getASuccessor() = mid and
|
||||
not subpaths(_, mid, _, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow (inter-procedurally) from `source` to `sink`.
|
||||
*
|
||||
|
||||
@@ -786,13 +786,18 @@ private module Cached {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
* Holds if the call context `call` improves virtual dispatch in `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
predicate recordDataFlowCallSiteDispatch(DataFlowCall call, DataFlowCallable callable) {
|
||||
reducedViableImplInCallContext(_, callable, call)
|
||||
or
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` allows us to prune unreachable nodes in `callable`.
|
||||
*/
|
||||
cached
|
||||
predicate recordDataFlowCallSiteUnreachable(DataFlowCall call, DataFlowCallable callable) {
|
||||
exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call))
|
||||
}
|
||||
|
||||
@@ -846,6 +851,15 @@ private module Cached {
|
||||
TAccessPathFrontSome(AccessPathFront apf)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the call context `call` either improves virtual dispatch in
|
||||
* `callable` or if it allows us to prune unreachable nodes in `callable`.
|
||||
*/
|
||||
predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
recordDataFlowCallSiteDispatch(call, callable) or
|
||||
recordDataFlowCallSiteUnreachable(call, callable)
|
||||
}
|
||||
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -1856,12 +1856,12 @@ class InitializeDynamicAllocationInstruction extends SideEffectInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of the allocation this instruction is initializing.
|
||||
* Gets the operand that represents the address of the allocation this instruction is initializing.
|
||||
*/
|
||||
final AddressOperand getAllocationAddressOperand() { result = getAnOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand for the allocation this instruction is initializing.
|
||||
* Gets the address for the allocation this instruction is initializing.
|
||||
*/
|
||||
final Instruction getAllocationAddress() { result = getAllocationAddressOperand().getDef() }
|
||||
}
|
||||
|
||||
@@ -33,3 +33,6 @@ private import implementations.Recv
|
||||
private import implementations.Accept
|
||||
private import implementations.Poll
|
||||
private import implementations.Select
|
||||
private import implementations.MySql
|
||||
private import implementations.SqLite3
|
||||
private import implementations.PostgreSql
|
||||
|
||||
32
cpp/ql/lib/semmle/code/cpp/models/implementations/MySql.qll
Normal file
32
cpp/ql/lib/semmle/code/cpp/models/implementations/MySql.qll
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the MySql C API.
|
||||
* See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
/**
|
||||
* The `mysql_query` family of functions from the MySQL C API.
|
||||
*/
|
||||
private class MySqlExecutionFunction extends SqlExecutionFunction {
|
||||
MySqlExecutionFunction() {
|
||||
this.hasName(["mysql_query", "mysql_real_query", "mysql_real_query_nonblocking"])
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The `mysql_real_escape_string` family of functions from the MySQL C API.
|
||||
*/
|
||||
private class MySqlBarrierFunction extends SqlBarrierFunction {
|
||||
MySqlBarrierFunction() {
|
||||
this.hasName(["mysql_real_escape_string", "mysql_real_escape_string_quote"])
|
||||
}
|
||||
|
||||
override predicate barrierSqlArgument(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(2) and
|
||||
output.isParameterDeref(1)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
private predicate pqxxTransactionSqlArgument(string function, int arg) {
|
||||
function = "exec" and arg = 0
|
||||
or
|
||||
function = "exec0" and arg = 0
|
||||
or
|
||||
function = "exec1" and arg = 0
|
||||
or
|
||||
function = "exec_n" and arg = 1
|
||||
or
|
||||
function = "exec_params" and arg = 0
|
||||
or
|
||||
function = "exec_params0" and arg = 0
|
||||
or
|
||||
function = "exec_params1" and arg = 0
|
||||
or
|
||||
function = "exec_params_n" and arg = 1
|
||||
or
|
||||
function = "query_value" and arg = 0
|
||||
or
|
||||
function = "stream" and arg = 0
|
||||
}
|
||||
|
||||
private predicate pqxxConnectionSqlArgument(string function, int arg) {
|
||||
function = "prepare" and arg = 1
|
||||
}
|
||||
|
||||
private predicate pqxxTransationClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in [
|
||||
"dbtransaction", "nontransaction", "basic_robusttransaction", "robusttransaction",
|
||||
"subtransaction", "transaction", "basic_transaction", "transaction_base", "work"
|
||||
]
|
||||
}
|
||||
|
||||
private predicate pqxxConnectionClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in ["connection_base", "basic_connection", "connection"]
|
||||
}
|
||||
|
||||
private predicate pqxxEscapeArgument(string function, int arg) {
|
||||
arg = 0 and
|
||||
function in ["esc", "esc_raw", "quote", "quote_raw", "quote_name", "quote_table", "esc_like"]
|
||||
}
|
||||
|
||||
private class PostgreSqlExecutionFunction extends SqlExecutionFunction {
|
||||
PostgreSqlExecutionFunction() {
|
||||
exists(Class c |
|
||||
this.getDeclaringType() = c and
|
||||
// transaction exec and connection prepare variations
|
||||
(
|
||||
pqxxTransationClassNames(c.getName(), c.getNamespace().getName()) and
|
||||
pqxxTransactionSqlArgument(this.getName(), _)
|
||||
or
|
||||
pqxxConnectionSqlArgument(this.getName(), _) and
|
||||
pqxxConnectionClassNames(c.getName(), c.getNamespace().getName())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) {
|
||||
exists(int argIndex |
|
||||
pqxxTransactionSqlArgument(this.getName(), argIndex)
|
||||
or
|
||||
pqxxConnectionSqlArgument(this.getName(), argIndex)
|
||||
|
|
||||
input.isParameterDeref(argIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class PostgreSqlBarrierFunction extends SqlBarrierFunction {
|
||||
PostgreSqlBarrierFunction() {
|
||||
exists(Class c |
|
||||
this.getDeclaringType() = c and
|
||||
// transaction and connection escape functions
|
||||
(
|
||||
pqxxTransationClassNames(c.getName(), c.getNamespace().getName()) or
|
||||
pqxxConnectionClassNames(c.getName(), c.getNamespace().getName())
|
||||
) and
|
||||
pqxxEscapeArgument(this.getName(), _)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate barrierSqlArgument(FunctionInput input, FunctionOutput output) {
|
||||
exists(int argIndex |
|
||||
input.isParameterDeref(argIndex) and
|
||||
output.isReturnValueDeref() and
|
||||
pqxxEscapeArgument(this.getName(), argIndex)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the SQLite C API.
|
||||
* See `semmle.code.cpp.models.Models` for usage information.
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.models.interfaces.Sql
|
||||
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs
|
||||
|
||||
/**
|
||||
* The `sqlite3_exec` and `sqlite3_prepare` families of functions from the SQLite C API.
|
||||
*/
|
||||
private class SqLite3ExecutionFunction extends SqlExecutionFunction {
|
||||
SqLite3ExecutionFunction() {
|
||||
this.hasName([
|
||||
"sqlite3_exec", "sqlite3_prepare", "sqlite3_prepare_v2", "sqlite3_prepare_v3",
|
||||
"sqlite3_prepare16", "sqlite3_prepare16_v2", "sqlite3_prepare16_v3"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
|
||||
}
|
||||
30
cpp/ql/lib/semmle/code/cpp/models/interfaces/Sql.qll
Normal file
30
cpp/ql/lib/semmle/code/cpp/models/interfaces/Sql.qll
Normal file
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Provides abstract classes for modeling functions that execute and escape SQL query strings.
|
||||
* To extend this QL library, create a QL class extending `SqlExecutionFunction` or `SqlEscapeFunction`
|
||||
* with a characteristic predicate that selects the function or set of functions you are modeling.
|
||||
* Within that class, override the predicates provided by the class to match the way a
|
||||
* parameter flows into the function and, in the case of `SqlEscapeFunction`, out of the function.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
|
||||
/**
|
||||
* An abstract class that represents a function that executes an SQL query.
|
||||
*/
|
||||
abstract class SqlExecutionFunction extends Function {
|
||||
/**
|
||||
* Holds if `input` to this function represents SQL code to be executed.
|
||||
*/
|
||||
abstract predicate hasSqlArgument(FunctionInput input);
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract class that represents a function that is a barrier to an SQL query string.
|
||||
*/
|
||||
abstract class SqlBarrierFunction extends Function {
|
||||
/**
|
||||
* Holds if the `output` is a barrier to the SQL input `input` such that is it safe to pass to
|
||||
* an `SqlExecutionFunction`.
|
||||
*/
|
||||
abstract predicate barrierSqlArgument(FunctionInput input, FunctionOutput output);
|
||||
}
|
||||
@@ -29,8 +29,7 @@ predicate nanExcludingComparison(ComparisonOperation guard, boolean polarity) {
|
||||
*/
|
||||
private predicate excludesNan(RangeSsaDefinition def, VariableAccess v) {
|
||||
exists(VariableAccess inCond, ComparisonOperation guard, boolean branch, StackVariable lsv |
|
||||
def.isGuardPhi(inCond, guard, branch) and
|
||||
inCond.getTarget() = lsv and
|
||||
def.isGuardPhi(lsv, inCond, guard, branch) and
|
||||
v = def.getAUse(lsv) and
|
||||
guard.getAnOperand() = inCond and
|
||||
nanExcludingComparison(guard, branch)
|
||||
|
||||
@@ -94,11 +94,21 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
predicate isPhiNode(StackVariable v) { exists(RangeSSA x | x.phi_node(v, this.(BasicBlock))) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use isGuardPhi/4 instead
|
||||
* If this definition is a phi node corresponding to a guard,
|
||||
* then return the variable and the guard.
|
||||
* then return the variable access and the guard.
|
||||
*/
|
||||
predicate isGuardPhi(VariableAccess v, Expr guard, boolean branch) {
|
||||
guard_defn(v, guard, this, branch)
|
||||
deprecated predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) {
|
||||
guard_defn(va, guard, this, branch)
|
||||
}
|
||||
|
||||
/**
|
||||
* If this definition is a phi node corresponding to a guard,
|
||||
* then return the variable guarded, the variable access and the guard.
|
||||
*/
|
||||
predicate isGuardPhi(StackVariable v, VariableAccess va, Expr guard, boolean branch) {
|
||||
guard_defn(va, guard, this, branch) and
|
||||
va.getTarget() = v
|
||||
}
|
||||
|
||||
/** Gets the primary location of this definition. */
|
||||
@@ -133,9 +143,8 @@ class RangeSsaDefinition extends ControlFlowNodeBase {
|
||||
// below excludes definitions which can only reach guard phi
|
||||
// nodes by going through the corresponding guard.
|
||||
not exists(VariableAccess access |
|
||||
v = access.getTarget() and
|
||||
pred.contains(access) and
|
||||
this.isGuardPhi(access, _, _)
|
||||
this.isGuardPhi(v, access, _, _)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -433,10 +433,7 @@ private predicate exprDependsOnDef(Expr e, RangeSsaDefinition srcDef, StackVaria
|
||||
private predicate phiDependsOnDef(
|
||||
RangeSsaDefinition phi, StackVariable v, RangeSsaDefinition srcDef, StackVariable srcVar
|
||||
) {
|
||||
exists(VariableAccess access, Expr guard |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, _)
|
||||
|
|
||||
exists(VariableAccess access, Expr guard | phi.isGuardPhi(v, access, guard, _) |
|
||||
exprDependsOnDef(guard.(ComparisonOperation).getAnOperand(), srcDef, srcVar) or
|
||||
exprDependsOnDef(access, srcDef, srcVar)
|
||||
)
|
||||
@@ -1204,8 +1201,7 @@ private float boolConversionUpperBound(Expr expr) {
|
||||
*/
|
||||
private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defLB, float guardLB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
phi.isGuardPhi(v, access, guard, branch) and
|
||||
lowerBoundFromGuard(guard, access, guardLB, branch) and
|
||||
defLB = getFullyConvertedLowerBounds(access)
|
||||
|
|
||||
@@ -1230,8 +1226,7 @@ private float getPhiLowerBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
/** See comment for `getPhiLowerBounds`, above. */
|
||||
private float getPhiUpperBounds(StackVariable v, RangeSsaDefinition phi) {
|
||||
exists(VariableAccess access, Expr guard, boolean branch, float defUB, float guardUB |
|
||||
access = v.getAnAccess() and
|
||||
phi.isGuardPhi(access, guard, branch) and
|
||||
phi.isGuardPhi(v, access, guard, branch) and
|
||||
upperBoundFromGuard(guard, access, guardUB, branch) and
|
||||
defUB = getFullyConvertedUpperBounds(access)
|
||||
|
|
||||
@@ -1493,8 +1488,7 @@ private predicate isNEPhi(
|
||||
exists(
|
||||
ComparisonOperation cmp, boolean branch, Expr linearExpr, Expr rExpr, float p, float q, float r
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
phi.isGuardPhi(v, access, cmp, branch) and
|
||||
eqOpWithSwapAndNegate(cmp, linearExpr, rExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!=` is too imprecise
|
||||
r = getValue(rExpr).toFloat() and
|
||||
@@ -1503,8 +1497,7 @@ private predicate isNEPhi(
|
||||
)
|
||||
or
|
||||
exists(Expr op, boolean branch, Expr linearExpr, float p, float q |
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, op, branch) and
|
||||
phi.isGuardPhi(v, access, op, branch) and
|
||||
eqZeroWithNegate(op, linearExpr, false, branch) and
|
||||
v.getUnspecifiedType() instanceof IntegralOrEnumType and // Float `!` is too imprecise
|
||||
linearAccess(linearExpr, access, p, q) and
|
||||
@@ -1524,12 +1517,35 @@ private predicate isUnsupportedGuardPhi(Variable v, RangeSsaDefinition phi, Vari
|
||||
or
|
||||
eqZeroWithNegate(cmp, _, false, branch)
|
||||
|
|
||||
access.getTarget() = v and
|
||||
phi.isGuardPhi(access, cmp, branch) and
|
||||
phi.isGuardPhi(v, access, cmp, branch) and
|
||||
not isNEPhi(v, phi, access, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the upper bound of the expression, if the expression is guarded.
|
||||
* An upper bound can only be found, if a guard phi node can be found, and the
|
||||
* expression has only one immediate predecessor.
|
||||
*/
|
||||
private float getGuardedUpperBound(VariableAccess guardedAccess) {
|
||||
exists(
|
||||
RangeSsaDefinition def, StackVariable v, VariableAccess guardVa, Expr guard, boolean branch
|
||||
|
|
||||
def.isGuardPhi(v, guardVa, guard, branch) and
|
||||
// If the basic block for the variable access being examined has
|
||||
// more than one predecessor, the guard phi node could originate
|
||||
// from one of the predecessors. This is because the guard phi
|
||||
// node is attached to the block at the end of the edge and not on
|
||||
// the actual edge. It is therefore not possible to determine which
|
||||
// edge the guard phi node belongs to. The predicate below ensures
|
||||
// that there is one predecessor, albeit somewhat conservative.
|
||||
exists(unique(BasicBlock b | b = def.(BasicBlock).getAPredecessor())) and
|
||||
guardedAccess = def.getAUse(v) and
|
||||
result = max(float ub | upperBoundFromGuard(guard, guardVa, ub, branch)) and
|
||||
not convertedExprMightOverflow(guard.getAChild+())
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module SimpleRangeAnalysisCached {
|
||||
/**
|
||||
@@ -1565,9 +1581,18 @@ private module SimpleRangeAnalysisCached {
|
||||
*/
|
||||
cached
|
||||
float upperBound(Expr expr) {
|
||||
// Combine the upper bounds returned by getTruncatedUpperBounds into a
|
||||
// single maximum value.
|
||||
result = max(float ub | ub = getTruncatedUpperBounds(expr) | ub)
|
||||
// Combine the upper bounds returned by getTruncatedUpperBounds and
|
||||
// getGuardedUpperBound into a single maximum value
|
||||
result = min([max(getTruncatedUpperBounds(expr)), getGuardedUpperBound(expr)])
|
||||
}
|
||||
|
||||
/** Holds if the upper bound of `expr` may have been widened. This means the the upper bound is in practice likely to be overly wide. */
|
||||
cached
|
||||
predicate upperBoundMayBeWidened(Expr e) {
|
||||
isRecursiveExpr(e) and
|
||||
// Widening is not a problem if the post-analysis in `getGuardedUpperBound` has overridden the widening.
|
||||
// Note that the RHS of `<` may be multi-valued.
|
||||
not getGuardedUpperBound(e) < getTruncatedUpperBounds(e)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,8 @@ private predicate stmtDominates(Stmt dominator, Stmt dominated) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value of `use` is guarded to be less than something.
|
||||
* Holds if the value of `use` is guarded to be less than something, and `e`
|
||||
* is in code controlled by that guard (where the guard condition held).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedLesser(Operation e, Expr use) {
|
||||
@@ -67,7 +68,8 @@ predicate guardedLesser(Operation e, Expr use) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the value of `use` is guarded to be greater than something.
|
||||
* Holds if the value of `use` is guarded to be greater than something, and `e`
|
||||
* is in code controlled by that guard (where the guard condition held).
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate guardedGreater(Operation e, Expr use) {
|
||||
@@ -120,6 +122,10 @@ predicate missingGuardAgainstOverflow(Operation e, VariableAccess use) {
|
||||
// overflow possible if large or small
|
||||
e instanceof MulExpr and
|
||||
not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))
|
||||
or
|
||||
// overflow possible if large or small
|
||||
e instanceof AssignMulExpr and
|
||||
not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -147,5 +153,9 @@ predicate missingGuardAgainstUnderflow(Operation e, VariableAccess use) {
|
||||
// underflow possible if large or small
|
||||
e instanceof MulExpr and
|
||||
not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))
|
||||
or
|
||||
// underflow possible if large or small
|
||||
e instanceof AssignMulExpr and
|
||||
not (guardedLesser(e, varUse(v)) and guardedGreater(e, varUse(v)))
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.commons.Environment
|
||||
import semmle.code.cpp.security.SecurityOptions
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.interfaces.Sql
|
||||
|
||||
/**
|
||||
* Extend this class to customize the security queries for
|
||||
@@ -34,13 +35,11 @@ class SecurityOptions extends string {
|
||||
* An argument to a function that is passed to a SQL server.
|
||||
*/
|
||||
predicate sqlArgument(string function, int arg) {
|
||||
// MySQL C API
|
||||
function = "mysql_query" and arg = 1
|
||||
or
|
||||
function = "mysql_real_query" and arg = 1
|
||||
or
|
||||
// SQLite3 C API
|
||||
function = "sqlite3_exec" and arg = 1
|
||||
exists(FunctionInput input, SqlExecutionFunction sql |
|
||||
sql.hasName(function) and
|
||||
input.isParameterDeref(arg) and
|
||||
sql.hasSqlArgument(input)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -310,23 +310,14 @@ diagnostics(
|
||||
int location: @location_default ref
|
||||
);
|
||||
|
||||
/*
|
||||
fromSource(0) = unknown,
|
||||
fromSource(1) = from source,
|
||||
fromSource(2) = from library
|
||||
*/
|
||||
files(
|
||||
unique int id: @file,
|
||||
string name: string ref,
|
||||
string simple: string ref,
|
||||
string ext: string ref,
|
||||
int fromSource: int ref
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
folders(
|
||||
unique int id: @folder,
|
||||
string name: string ref,
|
||||
string simple: string ref
|
||||
string name: string ref
|
||||
);
|
||||
|
||||
@container = @folder | @file
|
||||
|
||||
@@ -12875,18 +12875,6 @@
|
||||
<k>name</k>
|
||||
<v>59320</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>simple</k>
|
||||
<v>40580</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>ext</k>
|
||||
<v>97</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>fromSource</k>
|
||||
<v>10</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
@@ -12906,54 +12894,6 @@
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>id</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>id</src>
|
||||
<trg>ext</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>id</src>
|
||||
<trg>fromSource</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
@@ -12969,406 +12909,6 @@
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>ext</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>fromSource</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>59320</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>30814</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>6123</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>7</b>
|
||||
<v>3197</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>7</a>
|
||||
<b>42</b>
|
||||
<v>444</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>name</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>30814</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>6123</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>7</b>
|
||||
<v>3197</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>7</a>
|
||||
<b>42</b>
|
||||
<v>444</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>ext</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>36277</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>3739</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>6</b>
|
||||
<v>563</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>fromSource</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>40580</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>ext</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>15</a>
|
||||
<b>16</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>38</a>
|
||||
<b>39</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>80</a>
|
||||
<b>81</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>114</a>
|
||||
<b>115</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>441</a>
|
||||
<b>442</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>768</a>
|
||||
<b>769</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4013</a>
|
||||
<b>4014</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>ext</src>
|
||||
<trg>name</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>15</a>
|
||||
<b>16</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>38</a>
|
||||
<b>39</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>80</a>
|
||||
<b>81</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>114</a>
|
||||
<b>115</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>441</a>
|
||||
<b>442</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>768</a>
|
||||
<b>769</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4013</a>
|
||||
<b>4014</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>ext</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>15</a>
|
||||
<b>16</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>38</a>
|
||||
<b>39</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>75</a>
|
||||
<b>76</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>112</a>
|
||||
<b>113</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>428</a>
|
||||
<b>429</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>688</a>
|
||||
<b>689</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2838</a>
|
||||
<b>2839</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>ext</src>
|
||||
<trg>fromSource</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>97</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>fromSource</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>5473</a>
|
||||
<b>5474</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>fromSource</src>
|
||||
<trg>name</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>5473</a>
|
||||
<b>5474</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>fromSource</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>3744</a>
|
||||
<b>3745</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>fromSource</src>
|
||||
<trg>ext</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>9</a>
|
||||
<b>10</b>
|
||||
<v>10</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
@@ -13383,10 +12923,6 @@
|
||||
<k>name</k>
|
||||
<v>10817</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>simple</k>
|
||||
<v>3099</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
@@ -13406,22 +12942,6 @@
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>id</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10817</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
@@ -13437,94 +12957,6 @@
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>name</src>
|
||||
<trg>simple</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>10817</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>id</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1669</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>661</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>433</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>17</b>
|
||||
<v>238</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>27</a>
|
||||
<b>121</b>
|
||||
<v>97</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>simple</src>
|
||||
<trg>name</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>1669</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>2</a>
|
||||
<b>3</b>
|
||||
<v>661</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>433</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>17</b>
|
||||
<v>238</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>27</a>
|
||||
<b>121</b>
|
||||
<v>97</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @precision medium
|
||||
* @precision high
|
||||
* @id cpp/static-buffer-overflow
|
||||
* @tags reliability
|
||||
* security
|
||||
@@ -55,6 +55,8 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
|
||||
loop.counter().getAnAccess() = bufaccess.getArrayOffset() and
|
||||
// Ensure that we don't have an upper bound on the array index that's less than the buffer size.
|
||||
not upperBound(bufaccess.getArrayOffset().getFullyConverted()) < bufaccess.bufferSize() and
|
||||
// The upper bounds analysis must not have been widended
|
||||
not upperBoundMayBeWidened(bufaccess.getArrayOffset().getFullyConverted()) and
|
||||
msg =
|
||||
"Potential buffer-overflow: counter '" + loop.counter().toString() + "' <= " +
|
||||
loop.limit().toString() + " but '" + bufaccess.buffer().getName() + "' has " +
|
||||
@@ -130,11 +132,13 @@ predicate outOfBounds(BufferAccess bufaccess, string msg) {
|
||||
(
|
||||
access > size
|
||||
or
|
||||
access = size and not exists(AddressOfExpr addof | bufaccess = addof.getOperand())
|
||||
access = size and
|
||||
not exists(AddressOfExpr addof | bufaccess = addof.getOperand()) and
|
||||
not exists(BuiltInOperationBuiltInOffsetOf offsetof | offsetof.getAChild() = bufaccess)
|
||||
) and
|
||||
msg =
|
||||
"Potential buffer-overflow: '" + buf + "' has size " + size.toString() + " but '" + buf + "[" +
|
||||
access.toString() + "]' is accessed here."
|
||||
access.toString() + "]' may be accessed here."
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
12
cpp/ql/src/Metrics/Internal/DiagnosticsSumElapsedTimes.ql
Normal file
12
cpp/ql/src/Metrics/Internal/DiagnosticsSumElapsedTimes.ql
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* @name Sum of frontend and extractor time
|
||||
* @description The sum of elapsed frontend time, and the sum of elapsed extractor time.
|
||||
* This query is for internal use only and may change without notice.
|
||||
* @kind table
|
||||
* @id cpp/frontend-and-extractor-time
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
select sum(Compilation c, float seconds | compilation_time(c, _, 2, seconds) | seconds) as sum_frontend_elapsed_seconds,
|
||||
sum(Compilation c, float seconds | compilation_time(c, _, 4, seconds) | seconds) as sum_extractor_elapsed_seconds
|
||||
@@ -30,7 +30,15 @@ class Configuration extends TaintTrackingConfiguration {
|
||||
}
|
||||
|
||||
override predicate isBarrier(Expr e) {
|
||||
super.isBarrier(e) or e.getUnspecifiedType() instanceof IntegralType
|
||||
super.isBarrier(e)
|
||||
or
|
||||
e.getUnspecifiedType() instanceof IntegralType
|
||||
or
|
||||
exists(SqlBarrierFunction sql, int arg, FunctionInput input |
|
||||
e = sql.getACallToThisFunction().getArgument(arg) and
|
||||
input.isParameterDeref(arg) and
|
||||
sql.barrierSqlArgument(input, _)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
- apply: code-scanning-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql-cpp
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
- apply: lgtm-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql-cpp
|
||||
from: codeql/cpp-queries
|
||||
# These are only for IDE use.
|
||||
- exclude:
|
||||
tags contain:
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
- apply: security-and-quality-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql-cpp
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
- apply: security-extended-selectors.yml
|
||||
from: codeql/suite-helpers
|
||||
- apply: codeql-suites/exclude-slow-queries.yml
|
||||
from: codeql-cpp
|
||||
from: codeql/cpp-queries
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <pqxx/pqxx>
|
||||
|
||||
int main(int argc, char ** argv) {
|
||||
|
||||
if (argc != 2) {
|
||||
throw std::runtime_error("Give me a string!");
|
||||
}
|
||||
|
||||
pqxx::connection c;
|
||||
pqxx::work w(c);
|
||||
|
||||
// BAD
|
||||
char *userName = argv[1];
|
||||
char query1[1000] = {0};
|
||||
sprintf(query1, "SELECT UID FROM USERS where name = \"%s\"", userName);
|
||||
pqxx::row r = w.exec1(query1);
|
||||
w.commit();
|
||||
std::cout << r[0].as<int>() << std::endl;
|
||||
|
||||
// GOOD
|
||||
pqxx::result r2 = w.exec("SELECT " + w.quote(argv[1]));
|
||||
w.commit();
|
||||
std::cout << r2[0][0].c_str() << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The code passes user input as part of a SQL query without escaping special elements.
|
||||
It generates a SQL query to Postgres using <code>sprintf</code>,
|
||||
with the user-supplied data directly passed as an argument
|
||||
to <code>sprintf</code>. This leaves the code vulnerable to attack by SQL Injection.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>Use a library routine to escape characters in the user-supplied
|
||||
string before converting it to SQL. Use <code>esc</code> and <code>quote</code> pqxx library functions.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<sample src="SqlPqxxTainted.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>MSDN Library: <a href="https://docs.microsoft.com/en-us/sql/relational-databases/security/sql-injection">SQL Injection</a>.</li>
|
||||
|
||||
|
||||
<!-- LocalWords: SQL CWE
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -1,113 +0,0 @@
|
||||
/**
|
||||
* @name Uncontrolled data in SQL query to Postgres
|
||||
* @description Including user-supplied data in a SQL query to Postgres
|
||||
* without neutralizing special elements can make code
|
||||
* vulnerable to SQL Injection.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/sql-injection-via-pqxx
|
||||
* @tags security
|
||||
* external/cwe/cwe-089
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
predicate pqxxTransationClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in [
|
||||
"dbtransaction", "nontransaction", "basic_robusttransaction", "robusttransaction",
|
||||
"subtransaction", "transaction", "basic_transaction", "transaction_base", "work"
|
||||
]
|
||||
}
|
||||
|
||||
predicate pqxxConnectionClassNames(string className, string namespace) {
|
||||
namespace = "pqxx" and
|
||||
className in ["connection_base", "basic_connection", "connection"]
|
||||
}
|
||||
|
||||
predicate pqxxTransactionSqlArgument(string function, int arg) {
|
||||
function = "exec" and arg = 0
|
||||
or
|
||||
function = "exec0" and arg = 0
|
||||
or
|
||||
function = "exec1" and arg = 0
|
||||
or
|
||||
function = "exec_n" and arg = 1
|
||||
or
|
||||
function = "exec_params" and arg = 0
|
||||
or
|
||||
function = "exec_params0" and arg = 0
|
||||
or
|
||||
function = "exec_params1" and arg = 0
|
||||
or
|
||||
function = "exec_params_n" and arg = 1
|
||||
or
|
||||
function = "query_value" and arg = 0
|
||||
or
|
||||
function = "stream" and arg = 0
|
||||
}
|
||||
|
||||
predicate pqxxConnectionSqlArgument(string function, int arg) { function = "prepare" and arg = 1 }
|
||||
|
||||
Expr getPqxxSqlArgument() {
|
||||
exists(FunctionCall fc, Expr e, int argIndex, UserType t |
|
||||
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
|
||||
e = fc.getQualifier() and
|
||||
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
|
||||
// and return pointer to a connection/transation object
|
||||
e.getType().refersTo(t) and
|
||||
// transaction exec and connection prepare variations
|
||||
(
|
||||
pqxxTransationClassNames(t.getName(), t.getNamespace().getName()) and
|
||||
pqxxTransactionSqlArgument(fc.getTarget().getName(), argIndex)
|
||||
or
|
||||
pqxxConnectionClassNames(t.getName(), t.getNamespace().getName()) and
|
||||
pqxxConnectionSqlArgument(fc.getTarget().getName(), argIndex)
|
||||
) and
|
||||
result = fc.getArgument(argIndex)
|
||||
)
|
||||
}
|
||||
|
||||
predicate pqxxEscapeArgument(string function, int arg) {
|
||||
arg = 0 and
|
||||
function in ["esc", "esc_raw", "quote", "quote_raw", "quote_name", "quote_table", "esc_like"]
|
||||
}
|
||||
|
||||
predicate isEscapedPqxxArgument(Expr argExpr) {
|
||||
exists(FunctionCall fc, Expr e, int argIndex, UserType t |
|
||||
// examples: 'work' for 'work.exec(...)'; '->' for 'tx->exec()'.
|
||||
e = fc.getQualifier() and
|
||||
// to find ConnectionHandle/TransationHandle and similar classes which override '->' operator behavior
|
||||
// and return pointer to a connection/transation object
|
||||
e.getType().refersTo(t) and
|
||||
// transaction and connection escape functions
|
||||
(
|
||||
pqxxTransationClassNames(t.getName(), t.getNamespace().getName()) or
|
||||
pqxxConnectionClassNames(t.getName(), t.getNamespace().getName())
|
||||
) and
|
||||
pqxxEscapeArgument(fc.getTarget().getName(), argIndex) and
|
||||
// is escaped arg == argExpr
|
||||
argExpr = fc.getArgument(argIndex)
|
||||
)
|
||||
}
|
||||
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "SqlPqxxTainted" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isUserInput(source.asExpr(), _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink.asExpr() = getPqxxSqlArgument() }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) { isEscapedPqxxArgument(node.asExpr()) }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, Configuration config, string taintCause
|
||||
where
|
||||
config.hasFlowPath(source, sink) and
|
||||
isUserInput(source.getNode().asExpr(), taintCause)
|
||||
select sink, source, sink, "This argument to a SQL query function is derived from $@", source,
|
||||
"user input (" + taintCause + ")"
|
||||
13
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.c
Normal file
13
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.c
Normal file
@@ -0,0 +1,13 @@
|
||||
...
|
||||
fs = socket(AF_UNIX, SOCK_STREAM, 0)
|
||||
...
|
||||
close(fs);
|
||||
fs = -1; // GOOD
|
||||
...
|
||||
|
||||
...
|
||||
fs = socket(AF_UNIX, SOCK_STREAM, 0)
|
||||
...
|
||||
close(fs);
|
||||
if(fs) close(fs); // BAD
|
||||
...
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Double release of the descriptor can lead to a crash of the program. Requires the attention of developers.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>We recommend that you exclude situations of possible double release.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates an erroneous and corrected use of descriptor deallocation.</p>
|
||||
<sample src="DoubleRelease.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO46-C.+Do+not+access+a+closed+file">FIO46-C. Do not access a closed file</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
142
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql
Normal file
142
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* @name Errors When Double Release
|
||||
* @description Double release of the descriptor can lead to a crash of the program.
|
||||
* @kind problem
|
||||
* @id cpp/double-release
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags security
|
||||
* external/cwe/cwe-675
|
||||
* external/cwe/cwe-666
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.File
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.valuenumbering.HashCons
|
||||
|
||||
/**
|
||||
* A function call that potentially does not return (such as `exit`).
|
||||
*/
|
||||
class CallMayNotReturn extends FunctionCall {
|
||||
CallMayNotReturn() {
|
||||
// call that is known to not return
|
||||
not exists(this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call to another function that may not return
|
||||
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
|
||||
or
|
||||
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if there are no assignment expressions to the function argument. */
|
||||
pragma[inline]
|
||||
predicate checkChangeVariable(FunctionCall fc0, ControlFlowNode fc1, ControlFlowNode fc2) {
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp = fc0.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc0.getArgument(0).(VariableAccess).getTarget().getAnAccess()
|
||||
) and
|
||||
exptmp = fc1.getASuccessor*() and
|
||||
exptmp = fc2.getAPredecessor*()
|
||||
) and
|
||||
(
|
||||
(
|
||||
not fc0.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc0.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc0.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp =
|
||||
fc0.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc0.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAccess()
|
||||
) and
|
||||
exptmp = fc1.getASuccessor*() and
|
||||
exptmp = fc2.getAPredecessor*()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change after the call. */
|
||||
predicate closeReturn(FunctionCall fc) {
|
||||
fcloseCall(fc, _) and
|
||||
checkChangeVariable(fc, fc, fc.getEnclosingFunction())
|
||||
}
|
||||
|
||||
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change before the call. */
|
||||
predicate closeWithoutChangeBefore(FunctionCall fc) {
|
||||
fcloseCall(fc, _) and
|
||||
checkChangeVariable(fc, fc.getEnclosingFunction().getEntryPoint(), fc)
|
||||
}
|
||||
|
||||
/** Holds, if a sequential call of the specified functions is possible, via a higher-level function call. */
|
||||
predicate callInOtherFunctions(FunctionCall fc, FunctionCall fc1) {
|
||||
exists(FunctionCall fec1, FunctionCall fec2 |
|
||||
fc.getEnclosingFunction() != fc1.getEnclosingFunction() and
|
||||
fec1 = fc.getEnclosingFunction().getACallToThisFunction() and
|
||||
fec2 = fc1.getEnclosingFunction().getACallToThisFunction() and
|
||||
fec1.getASuccessor*() = fec2 and
|
||||
checkChangeVariable(fc, fec1, fec2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if successive calls to close functions are possible. */
|
||||
predicate interDoubleCloseFunctions(FunctionCall fc, FunctionCall fc1) {
|
||||
fcloseCall(fc, _) and
|
||||
fcloseCall(fc1, _) and
|
||||
fc != fc1 and
|
||||
fc.getASuccessor*() = fc1 and
|
||||
checkChangeVariable(fc, fc, fc1)
|
||||
}
|
||||
|
||||
/** Holds if the first arguments of the two functions are similar. */
|
||||
predicate similarArguments(FunctionCall fc, FunctionCall fc1) {
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fc1.getArgument(0))
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
|
||||
(
|
||||
not fc.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
|
||||
(
|
||||
fc.getArgument(0) instanceof PointerFieldAccess or
|
||||
fc.getArgument(0) instanceof ValueFieldAccess
|
||||
) and
|
||||
hashCons(fc.getArgument(0)) = hashCons(fc1.getArgument(0))
|
||||
}
|
||||
|
||||
from FunctionCall fc, FunctionCall fc1
|
||||
where
|
||||
not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and
|
||||
not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and
|
||||
(
|
||||
// detecting a repeated call situation within one function
|
||||
closeReturn(fc) and
|
||||
closeWithoutChangeBefore(fc1) and
|
||||
callInOtherFunctions(fc, fc1)
|
||||
or
|
||||
// detection of repeated call in different functions
|
||||
interDoubleCloseFunctions(fc, fc1)
|
||||
) and
|
||||
similarArguments(fc, fc1)
|
||||
select fc, "Second call to the $@ function is possible.", fc1, fc1.getTarget().getName()
|
||||
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* @name unsigned to signed used in pointer arithmetic
|
||||
* @description finds unsigned to signed conversions used in pointer arithmetic, potentially causing an out-of-bound access
|
||||
* @id cpp/sign-conversion-pointer-arithmetic
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-787
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.security.Overflow
|
||||
|
||||
from FunctionCall call, Function f, Parameter p, DataFlow::Node sink, PointerArithmeticOperation pao
|
||||
where
|
||||
f = call.getTarget() and
|
||||
p = f.getAParameter() and
|
||||
p.getUnspecifiedType().(IntegralType).isSigned() and
|
||||
call.getArgument(p.getIndex()).getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
pao.getAnOperand() = sink.asExpr() and
|
||||
not exists(Operation a | guardedLesser(a, sink.asExpr())) and
|
||||
not exists(Operation b | guardedGreater(b, call.getArgument(p.getIndex()))) and
|
||||
not call.getArgument(p.getIndex()).isConstant() and
|
||||
DataFlow::localFlow(DataFlow::parameterNode(p), sink) and
|
||||
p.getUnspecifiedType().getSize() < 8
|
||||
select call,
|
||||
"This call: $@ passes an unsigned int to a function that requires a signed int: $@. And then used in pointer arithmetic: $@",
|
||||
call, call.toString(), f, f.toString(), sink, sink.toString()
|
||||
@@ -63,6 +63,7 @@ where
|
||||
functionsMissingReturnStmt(f, blame) and
|
||||
reachable(blame) and
|
||||
not functionImperfectlyExtracted(f) and
|
||||
not f.isFromUninstantiatedTemplate(_) and
|
||||
(blame = stmt or blame.(Expr).getEnclosingStmt() = stmt) and
|
||||
msg =
|
||||
"Function " + f.getName() + " should return a value of type " + f.getType().getName() +
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.2
|
||||
dependencies:
|
||||
codeql/cpp-all: ^0.0.2
|
||||
codeql/suite-helpers: ^0.0.2
|
||||
codeql/cpp-all: "*"
|
||||
codeql/suite-helpers: "*"
|
||||
suites: codeql-suites
|
||||
extractor: cpp
|
||||
defaultSuiteFile: codeql-suites/cpp-code-scanning.qls
|
||||
|
||||
@@ -8,6 +8,7 @@ nodes
|
||||
| test.cpp:23:33:23:37 | size1 | semmle.label | size1 |
|
||||
| test.cpp:30:27:30:31 | ... * ... | semmle.label | ... * ... |
|
||||
| test.cpp:31:27:31:31 | ... * ... | semmle.label | ... * ... |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication |
|
||||
| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication |
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
edges
|
||||
| test.cpp:45:18:45:23 | buffer | test.cpp:47:10:47:15 | buffer |
|
||||
| test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp |
|
||||
| test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 |
|
||||
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer |
|
||||
| test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func |
|
||||
nodes
|
||||
| test.cpp:45:18:45:23 | buffer | semmle.label | buffer |
|
||||
| test.cpp:47:10:47:15 | buffer | semmle.label | buffer |
|
||||
| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:74:24:74:30 | medical | semmle.label | medical |
|
||||
| test.cpp:77:16:77:22 | medical | semmle.label | medical |
|
||||
@@ -12,6 +16,8 @@ nodes
|
||||
| test.cpp:82:24:82:28 | buff5 | semmle.label | buff5 |
|
||||
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
|
||||
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
|
||||
subpaths
|
||||
| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | test.cpp:47:10:47:15 | buffer | test.cpp:81:17:81:20 | call to func |
|
||||
#select
|
||||
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
|
||||
| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
edges
|
||||
| A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | Chi [c] |
|
||||
| A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | Chi [c] |
|
||||
| A.cpp:28:8:28:10 | *#this [c] | A.cpp:28:29:28:29 | Store |
|
||||
| A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:10:56:10 | b indirection [c] |
|
||||
| A.cpp:55:8:55:10 | new | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:55:8:55:10 | new | A.cpp:55:5:55:5 | set output argument [c] |
|
||||
| A.cpp:55:12:55:19 | (C *)... | A.cpp:55:8:55:10 | new |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:55:8:55:10 | new |
|
||||
| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:28:8:28:10 | *#this [c] |
|
||||
| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:10:57:25 | new indirection [c] | A.cpp:28:8:28:10 | *#this [c] |
|
||||
| A.cpp:57:10:57:25 | new indirection [c] | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:11:57:24 | B output argument [c] | A.cpp:57:10:57:25 | new indirection [c] |
|
||||
| A.cpp:57:11:57:24 | new | A.cpp:23:10:23:10 | c |
|
||||
| A.cpp:57:11:57:24 | new | A.cpp:57:11:57:24 | B output argument [c] |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | new |
|
||||
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | Chi [a] |
|
||||
@@ -14,10 +21,12 @@ edges
|
||||
| A.cpp:103:14:103:14 | *c [a] | A.cpp:107:16:107:16 | a |
|
||||
| A.cpp:126:5:126:5 | Chi [c] | A.cpp:131:8:131:8 | f7 output argument [c] |
|
||||
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:126:5:126:5 | Chi [c] |
|
||||
| A.cpp:126:8:126:10 | new | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:126:8:126:10 | new | A.cpp:126:5:126:5 | set output argument [c] |
|
||||
| A.cpp:126:12:126:18 | new | A.cpp:126:8:126:10 | new |
|
||||
| A.cpp:131:8:131:8 | Chi [c] | A.cpp:132:13:132:13 | c |
|
||||
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:131:8:131:8 | Chi [c] |
|
||||
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | Chi [b] |
|
||||
| A.cpp:142:7:142:20 | Chi [c] | A.cpp:151:18:151:18 | D output argument [c] |
|
||||
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | Chi [c] |
|
||||
| A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] |
|
||||
@@ -25,6 +34,7 @@ edges
|
||||
| A.cpp:150:12:150:18 | new | A.cpp:151:12:151:24 | b |
|
||||
| A.cpp:151:12:151:24 | Chi [b] | A.cpp:152:13:152:13 | b |
|
||||
| A.cpp:151:12:151:24 | D output argument [b] | A.cpp:151:12:151:24 | Chi [b] |
|
||||
| A.cpp:151:12:151:24 | b | A.cpp:140:13:140:13 | b |
|
||||
| A.cpp:151:12:151:24 | b | A.cpp:151:12:151:24 | D output argument [b] |
|
||||
| A.cpp:151:18:151:18 | Chi [c] | A.cpp:154:13:154:13 | c |
|
||||
| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:151:18:151:18 | Chi [c] |
|
||||
@@ -86,21 +96,49 @@ edges
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:37:24:37:27 | data |
|
||||
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | Chi [a] |
|
||||
| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | Chi [a] |
|
||||
| by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:11:20:21 | value |
|
||||
| by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | by_reference.cpp:20:5:20:8 | Chi [a] |
|
||||
| by_reference.cpp:20:11:20:21 | value | by_reference.cpp:15:26:15:30 | value |
|
||||
| by_reference.cpp:20:11:20:21 | value | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] |
|
||||
| by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:5:24:17 | value |
|
||||
| by_reference.cpp:24:5:24:17 | value | by_reference.cpp:11:48:11:52 | value |
|
||||
| by_reference.cpp:24:5:24:17 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
|
||||
| by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | by_reference.cpp:24:19:24:22 | Chi [a] |
|
||||
| by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:32:15:32:15 | Store |
|
||||
| by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:36:18:36:18 | Store |
|
||||
| by_reference.cpp:39:9:39:21 | *#this [a] | by_reference.cpp:40:12:40:15 | this indirection [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:40:18:40:28 | call to getDirectly |
|
||||
| by_reference.cpp:40:18:40:28 | call to getDirectly | by_reference.cpp:40:18:40:28 | Store |
|
||||
| by_reference.cpp:43:9:43:27 | *#this [a] | by_reference.cpp:44:26:44:29 | this indirection [a] |
|
||||
| by_reference.cpp:44:12:44:24 | call to nonMemberGetA | by_reference.cpp:44:12:44:24 | Store |
|
||||
| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] |
|
||||
| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
|
||||
| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | by_reference.cpp:51:8:51:8 | s indirection [a] |
|
||||
| by_reference.cpp:50:5:50:15 | call to user_input | by_reference.cpp:15:26:15:30 | value |
|
||||
| by_reference.cpp:50:5:50:15 | call to user_input | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:5:50:15 | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | by_reference.cpp:57:8:57:8 | s indirection [a] |
|
||||
| by_reference.cpp:56:5:56:17 | call to user_input | by_reference.cpp:19:28:19:32 | value |
|
||||
| by_reference.cpp:56:5:56:17 | call to user_input | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:5:56:17 | call to user_input |
|
||||
| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | *#this [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | by_reference.cpp:63:8:63:8 | s indirection [a] |
|
||||
| by_reference.cpp:62:5:62:23 | call to user_input | by_reference.cpp:23:34:23:38 | value |
|
||||
| by_reference.cpp:62:5:62:23 | call to user_input | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:5:62:23 | call to user_input |
|
||||
| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | *#this [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:68:3:68:15 | call to user_input | by_reference.cpp:11:48:11:52 | value |
|
||||
| by_reference.cpp:68:3:68:15 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
|
||||
| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | by_reference.cpp:69:22:69:23 | & ... indirection [a] |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:3:68:15 | call to user_input |
|
||||
| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
|
||||
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] |
|
||||
| by_reference.cpp:84:3:84:25 | Chi [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] |
|
||||
@@ -134,48 +172,73 @@ edges
|
||||
| by_reference.cpp:128:15:128:23 | Chi | by_reference.cpp:128:15:128:23 | Chi [a] |
|
||||
| by_reference.cpp:128:15:128:23 | Chi [a] | by_reference.cpp:136:16:136:16 | a |
|
||||
| by_reference.cpp:128:15:128:23 | taint_a_ref output argument [[]] | by_reference.cpp:128:15:128:23 | Chi |
|
||||
| complex.cpp:9:7:9:7 | *#this [a_] | complex.cpp:9:20:9:21 | Store |
|
||||
| complex.cpp:10:7:10:7 | *#this [b_] | complex.cpp:10:20:10:21 | Store |
|
||||
| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | Chi [a_] |
|
||||
| complex.cpp:12:8:12:11 | *#this [a_] | complex.cpp:12:22:12:27 | Chi [a_] |
|
||||
| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | Chi [b_] |
|
||||
| complex.cpp:40:17:40:17 | *b [a_] | complex.cpp:42:16:42:16 | f indirection [a_] |
|
||||
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:42:16:42:16 | f indirection [b_] |
|
||||
| complex.cpp:40:17:40:17 | *b [b_] | complex.cpp:43:16:43:16 | f indirection [b_] |
|
||||
| complex.cpp:42:16:42:16 | a output argument [b_] | complex.cpp:43:16:43:16 | f indirection [b_] |
|
||||
| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:9:7:9:7 | *#this [a_] |
|
||||
| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:42:18:42:18 | call to a |
|
||||
| complex.cpp:42:16:42:16 | f indirection [b_] | complex.cpp:9:7:9:7 | *#this [b_] |
|
||||
| complex.cpp:42:16:42:16 | f indirection [b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
|
||||
| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:10:7:10:7 | *#this [b_] |
|
||||
| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:43:18:43:18 | call to b |
|
||||
| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:59:7:59:8 | b1 indirection [a_] |
|
||||
| complex.cpp:53:14:53:17 | call to user_input | complex.cpp:11:17:11:17 | a |
|
||||
| complex.cpp:53:14:53:17 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] |
|
||||
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:14:53:17 | call to user_input |
|
||||
| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:62:7:62:8 | b2 indirection [b_] |
|
||||
| complex.cpp:54:14:54:17 | call to user_input | complex.cpp:12:17:12:17 | b |
|
||||
| complex.cpp:54:14:54:17 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] |
|
||||
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:14:54:17 | call to user_input |
|
||||
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:56:12:56:12 | f indirection [a_] |
|
||||
| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:65:7:65:8 | b3 indirection [a_] |
|
||||
| complex.cpp:55:14:55:17 | call to user_input | complex.cpp:11:17:11:17 | a |
|
||||
| complex.cpp:55:14:55:17 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] |
|
||||
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:14:55:17 | call to user_input |
|
||||
| complex.cpp:56:12:56:12 | f indirection [a_] | complex.cpp:12:8:12:11 | *#this [a_] |
|
||||
| complex.cpp:56:12:56:12 | f indirection [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
|
||||
| complex.cpp:56:12:56:12 | setB output argument [a_] | complex.cpp:65:7:65:8 | b3 indirection [a_] |
|
||||
| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:65:7:65:8 | b3 indirection [b_] |
|
||||
| complex.cpp:56:14:56:17 | call to user_input | complex.cpp:12:17:12:17 | b |
|
||||
| complex.cpp:56:14:56:17 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] |
|
||||
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:14:56:17 | call to user_input |
|
||||
| complex.cpp:59:7:59:8 | b1 indirection [a_] | complex.cpp:40:17:40:17 | *b [a_] |
|
||||
| complex.cpp:62:7:62:8 | b2 indirection [b_] | complex.cpp:40:17:40:17 | *b [b_] |
|
||||
| complex.cpp:65:7:65:8 | b3 indirection [a_] | complex.cpp:40:17:40:17 | *b [a_] |
|
||||
| complex.cpp:65:7:65:8 | b3 indirection [b_] | complex.cpp:40:17:40:17 | *b [b_] |
|
||||
| constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:22:18:23 | Store |
|
||||
| constructors.cpp:19:9:19:9 | *#this [b_] | constructors.cpp:19:22:19:23 | Store |
|
||||
| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | Chi [a_] |
|
||||
| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | Chi [b_] |
|
||||
| constructors.cpp:23:28:23:28 | Chi [a_] | constructors.cpp:23:35:23:35 | Chi [a_] |
|
||||
| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:10:28:10 | f indirection [a_] |
|
||||
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | f indirection [b_] |
|
||||
| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:10:29:10 | f indirection [b_] |
|
||||
| constructors.cpp:28:10:28:10 | a output argument [b_] | constructors.cpp:29:10:29:10 | f indirection [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:28:12:28:12 | call to a |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] |
|
||||
| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:19:9:19:9 | *#this [b_] |
|
||||
| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:29:12:29:12 | call to b |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | call to user_input |
|
||||
| constructors.cpp:34:11:34:26 | Foo output argument [a_] | constructors.cpp:40:9:40:9 | f indirection [a_] |
|
||||
| constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:23:13:23:13 | a |
|
||||
| constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:34:11:34:26 | Foo output argument [a_] |
|
||||
| constructors.cpp:35:11:35:26 | Foo output argument [b_] | constructors.cpp:43:9:43:9 | g indirection [b_] |
|
||||
| constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:23:20:23:20 | b |
|
||||
| constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:35:11:35:26 | Foo output argument [b_] |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | call to user_input |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | call to user_input |
|
||||
| constructors.cpp:36:11:36:37 | Foo output argument [a_] | constructors.cpp:46:9:46:9 | h indirection [a_] |
|
||||
| constructors.cpp:36:11:36:37 | Foo output argument [b_] | constructors.cpp:46:9:46:9 | h indirection [b_] |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:13:23:13 | a |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:20:23:20 | b |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:36:11:36:37 | Foo output argument [a_] |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:36:11:36:37 | Foo output argument [b_] |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | call to user_input |
|
||||
@@ -183,26 +246,39 @@ edges
|
||||
| constructors.cpp:43:9:43:9 | g indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] |
|
||||
| constructors.cpp:46:9:46:9 | h indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] |
|
||||
| constructors.cpp:46:9:46:9 | h indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] |
|
||||
| simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:22:18:23 | Store |
|
||||
| simple.cpp:19:9:19:9 | *#this [b_] | simple.cpp:19:22:19:23 | Store |
|
||||
| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | Chi [a_] |
|
||||
| simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:24:21:29 | Chi [a_] |
|
||||
| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | Chi [b_] |
|
||||
| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:10:28:10 | f indirection [a_] |
|
||||
| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:28:10:28:10 | f indirection [b_] |
|
||||
| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:10:29:10 | f indirection [b_] |
|
||||
| simple.cpp:28:10:28:10 | a output argument [b_] | simple.cpp:29:10:29:10 | f indirection [b_] |
|
||||
| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] |
|
||||
| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:28:12:28:12 | call to a |
|
||||
| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] |
|
||||
| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] |
|
||||
| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:19:9:19:9 | *#this [b_] |
|
||||
| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:29:12:29:12 | call to b |
|
||||
| simple.cpp:39:5:39:5 | setA output argument [a_] | simple.cpp:45:9:45:9 | f indirection [a_] |
|
||||
| simple.cpp:39:7:39:10 | call to user_input | simple.cpp:20:19:20:19 | a |
|
||||
| simple.cpp:39:7:39:10 | call to user_input | simple.cpp:39:5:39:5 | setA output argument [a_] |
|
||||
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:7:39:10 | call to user_input |
|
||||
| simple.cpp:40:5:40:5 | setB output argument [b_] | simple.cpp:48:9:48:9 | g indirection [b_] |
|
||||
| simple.cpp:40:7:40:10 | call to user_input | simple.cpp:21:19:21:19 | b |
|
||||
| simple.cpp:40:7:40:10 | call to user_input | simple.cpp:40:5:40:5 | setB output argument [b_] |
|
||||
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:7:40:10 | call to user_input |
|
||||
| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:42:5:42:5 | h indirection [a_] |
|
||||
| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:51:9:51:9 | h indirection [a_] |
|
||||
| simple.cpp:41:7:41:10 | call to user_input | simple.cpp:20:19:20:19 | a |
|
||||
| simple.cpp:41:7:41:10 | call to user_input | simple.cpp:41:5:41:5 | setA output argument [a_] |
|
||||
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:7:41:10 | call to user_input |
|
||||
| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] |
|
||||
| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] |
|
||||
| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:51:9:51:9 | h indirection [a_] |
|
||||
| simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:51:9:51:9 | h indirection [b_] |
|
||||
| simple.cpp:42:7:42:10 | call to user_input | simple.cpp:21:19:21:19 | b |
|
||||
| simple.cpp:42:7:42:10 | call to user_input | simple.cpp:42:5:42:5 | setB output argument [b_] |
|
||||
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:7:42:10 | call to user_input |
|
||||
| simple.cpp:45:9:45:9 | f indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] |
|
||||
@@ -212,8 +288,10 @@ edges
|
||||
| simple.cpp:65:5:65:22 | Store [i] | simple.cpp:66:12:66:12 | Store [i] |
|
||||
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | Store [i] |
|
||||
| simple.cpp:66:12:66:12 | Store [i] | simple.cpp:67:13:67:13 | i |
|
||||
| simple.cpp:78:9:78:15 | *#this [f1] | simple.cpp:79:19:79:20 | Store |
|
||||
| simple.cpp:83:9:83:28 | Store [f1] | simple.cpp:84:14:84:20 | this indirection [f1] |
|
||||
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | Store [f1] |
|
||||
| simple.cpp:84:14:84:20 | this indirection [f1] | simple.cpp:78:9:78:15 | *#this [f1] |
|
||||
| simple.cpp:84:14:84:20 | this indirection [f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
| simple.cpp:92:5:92:22 | Store [i] | simple.cpp:93:20:93:20 | Store [i] |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | Store [i] |
|
||||
@@ -228,6 +306,12 @@ edges
|
||||
| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:31:23:31:23 | a |
|
||||
| struct_init.c:36:10:36:24 | & ... indirection [a] | struct_init.c:14:24:14:25 | *ab [a] |
|
||||
nodes
|
||||
| A.cpp:23:10:23:10 | c | semmle.label | c |
|
||||
| A.cpp:25:7:25:17 | Chi [c] | semmle.label | Chi [c] |
|
||||
| A.cpp:27:17:27:17 | c | semmle.label | c |
|
||||
| A.cpp:27:22:27:32 | Chi [c] | semmle.label | Chi [c] |
|
||||
| A.cpp:28:8:28:10 | *#this [c] | semmle.label | *#this [c] |
|
||||
| A.cpp:28:29:28:29 | Store | semmle.label | Store |
|
||||
| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] |
|
||||
| A.cpp:55:8:55:10 | new | semmle.label | new |
|
||||
| A.cpp:55:12:55:19 | (C *)... | semmle.label | (C *)... |
|
||||
@@ -251,9 +335,11 @@ nodes
|
||||
| A.cpp:131:8:131:8 | Chi [c] | semmle.label | Chi [c] |
|
||||
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
|
||||
| A.cpp:132:13:132:13 | c | semmle.label | c |
|
||||
| A.cpp:140:13:140:13 | b | semmle.label | b |
|
||||
| A.cpp:142:7:142:20 | Chi [c] | semmle.label | Chi [c] |
|
||||
| A.cpp:142:14:142:20 | new | semmle.label | new |
|
||||
| A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] |
|
||||
| A.cpp:143:7:143:31 | Chi [b] | semmle.label | Chi [b] |
|
||||
| A.cpp:143:25:143:31 | new | semmle.label | new |
|
||||
| A.cpp:150:12:150:18 | new | semmle.label | new |
|
||||
| A.cpp:151:12:151:24 | Chi [b] | semmle.label | Chi [b] |
|
||||
@@ -336,6 +422,30 @@ nodes
|
||||
| arrays.cpp:16:8:16:13 | access to array | semmle.label | access to array |
|
||||
| arrays.cpp:36:26:36:35 | call to user_input | semmle.label | call to user_input |
|
||||
| arrays.cpp:37:24:37:27 | data | semmle.label | data |
|
||||
| by_reference.cpp:11:48:11:52 | value | semmle.label | value |
|
||||
| by_reference.cpp:12:5:12:16 | Chi [a] | semmle.label | Chi [a] |
|
||||
| by_reference.cpp:15:26:15:30 | value | semmle.label | value |
|
||||
| by_reference.cpp:16:5:16:19 | Chi [a] | semmle.label | Chi [a] |
|
||||
| by_reference.cpp:19:28:19:32 | value | semmle.label | value |
|
||||
| by_reference.cpp:20:5:20:8 | Chi [a] | semmle.label | Chi [a] |
|
||||
| by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] |
|
||||
| by_reference.cpp:20:11:20:21 | value | semmle.label | value |
|
||||
| by_reference.cpp:23:34:23:38 | value | semmle.label | value |
|
||||
| by_reference.cpp:24:5:24:17 | value | semmle.label | value |
|
||||
| by_reference.cpp:24:19:24:22 | Chi [a] | semmle.label | Chi [a] |
|
||||
| by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] |
|
||||
| by_reference.cpp:31:46:31:46 | *s [a] | semmle.label | *s [a] |
|
||||
| by_reference.cpp:32:15:32:15 | Store | semmle.label | Store |
|
||||
| by_reference.cpp:35:9:35:19 | *#this [a] | semmle.label | *#this [a] |
|
||||
| by_reference.cpp:36:18:36:18 | Store | semmle.label | Store |
|
||||
| by_reference.cpp:39:9:39:21 | *#this [a] | semmle.label | *#this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this indirection [a] | semmle.label | this indirection [a] |
|
||||
| by_reference.cpp:40:18:40:28 | Store | semmle.label | Store |
|
||||
| by_reference.cpp:40:18:40:28 | call to getDirectly | semmle.label | call to getDirectly |
|
||||
| by_reference.cpp:43:9:43:27 | *#this [a] | semmle.label | *#this [a] |
|
||||
| by_reference.cpp:44:12:44:24 | Store | semmle.label | Store |
|
||||
| by_reference.cpp:44:12:44:24 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
|
||||
| by_reference.cpp:44:26:44:29 | this indirection [a] | semmle.label | this indirection [a] |
|
||||
| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] |
|
||||
| by_reference.cpp:50:5:50:15 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
|
||||
@@ -392,6 +502,17 @@ nodes
|
||||
| by_reference.cpp:132:14:132:14 | a | semmle.label | a |
|
||||
| by_reference.cpp:134:29:134:29 | a | semmle.label | a |
|
||||
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
|
||||
| complex.cpp:9:7:9:7 | *#this [a_] | semmle.label | *#this [a_] |
|
||||
| complex.cpp:9:7:9:7 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| complex.cpp:9:20:9:21 | Store | semmle.label | Store |
|
||||
| complex.cpp:10:7:10:7 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| complex.cpp:10:20:10:21 | Store | semmle.label | Store |
|
||||
| complex.cpp:11:17:11:17 | a | semmle.label | a |
|
||||
| complex.cpp:11:22:11:27 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| complex.cpp:12:8:12:11 | *#this [a_] | semmle.label | *#this [a_] |
|
||||
| complex.cpp:12:17:12:17 | b | semmle.label | b |
|
||||
| complex.cpp:12:22:12:27 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| complex.cpp:12:22:12:27 | Chi [b_] | semmle.label | Chi [b_] |
|
||||
| complex.cpp:40:17:40:17 | *b [a_] | semmle.label | *b [a_] |
|
||||
| complex.cpp:40:17:40:17 | *b [b_] | semmle.label | *b [b_] |
|
||||
| complex.cpp:42:16:42:16 | a output argument [b_] | semmle.label | a output argument [b_] |
|
||||
@@ -418,6 +539,16 @@ nodes
|
||||
| complex.cpp:62:7:62:8 | b2 indirection [b_] | semmle.label | b2 indirection [b_] |
|
||||
| complex.cpp:65:7:65:8 | b3 indirection [a_] | semmle.label | b3 indirection [a_] |
|
||||
| complex.cpp:65:7:65:8 | b3 indirection [b_] | semmle.label | b3 indirection [b_] |
|
||||
| constructors.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] |
|
||||
| constructors.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| constructors.cpp:18:22:18:23 | Store | semmle.label | Store |
|
||||
| constructors.cpp:19:9:19:9 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| constructors.cpp:19:22:19:23 | Store | semmle.label | Store |
|
||||
| constructors.cpp:23:13:23:13 | a | semmle.label | a |
|
||||
| constructors.cpp:23:20:23:20 | b | semmle.label | b |
|
||||
| constructors.cpp:23:28:23:28 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| constructors.cpp:23:35:23:35 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| constructors.cpp:23:35:23:35 | Chi [b_] | semmle.label | Chi [b_] |
|
||||
| constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] |
|
||||
| constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] |
|
||||
| constructors.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] |
|
||||
@@ -442,6 +573,17 @@ nodes
|
||||
| constructors.cpp:43:9:43:9 | g indirection [b_] | semmle.label | g indirection [b_] |
|
||||
| constructors.cpp:46:9:46:9 | h indirection [a_] | semmle.label | h indirection [a_] |
|
||||
| constructors.cpp:46:9:46:9 | h indirection [b_] | semmle.label | h indirection [b_] |
|
||||
| simple.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] |
|
||||
| simple.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| simple.cpp:18:22:18:23 | Store | semmle.label | Store |
|
||||
| simple.cpp:19:9:19:9 | *#this [b_] | semmle.label | *#this [b_] |
|
||||
| simple.cpp:19:22:19:23 | Store | semmle.label | Store |
|
||||
| simple.cpp:20:19:20:19 | a | semmle.label | a |
|
||||
| simple.cpp:20:24:20:29 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| simple.cpp:21:10:21:13 | *#this [a_] | semmle.label | *#this [a_] |
|
||||
| simple.cpp:21:19:21:19 | b | semmle.label | b |
|
||||
| simple.cpp:21:24:21:29 | Chi [a_] | semmle.label | Chi [a_] |
|
||||
| simple.cpp:21:24:21:29 | Chi [b_] | semmle.label | Chi [b_] |
|
||||
| simple.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] |
|
||||
| simple.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] |
|
||||
| simple.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] |
|
||||
@@ -472,6 +614,8 @@ nodes
|
||||
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:66:12:66:12 | Store [i] | semmle.label | Store [i] |
|
||||
| simple.cpp:67:13:67:13 | i | semmle.label | i |
|
||||
| simple.cpp:78:9:78:15 | *#this [f1] | semmle.label | *#this [f1] |
|
||||
| simple.cpp:79:19:79:20 | Store | semmle.label | Store |
|
||||
| simple.cpp:83:9:83:28 | Store [f1] | semmle.label | Store [f1] |
|
||||
| simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 |
|
||||
@@ -490,6 +634,49 @@ nodes
|
||||
| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input |
|
||||
| struct_init.c:31:23:31:23 | a | semmle.label | a |
|
||||
| struct_init.c:36:10:36:24 | & ... indirection [a] | semmle.label | & ... indirection [a] |
|
||||
subpaths
|
||||
| A.cpp:55:8:55:10 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | Chi [c] | A.cpp:55:5:55:5 | set output argument [c] |
|
||||
| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:28:8:28:10 | *#this [c] | A.cpp:28:29:28:29 | Store | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:10:57:25 | new indirection [c] | A.cpp:28:8:28:10 | *#this [c] | A.cpp:28:29:28:29 | Store | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:11:57:24 | new | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | Chi [c] | A.cpp:57:11:57:24 | B output argument [c] |
|
||||
| A.cpp:126:8:126:10 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | Chi [c] | A.cpp:126:5:126:5 | set output argument [c] |
|
||||
| A.cpp:151:12:151:24 | b | A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | Chi [b] | A.cpp:151:12:151:24 | D output argument [b] |
|
||||
| by_reference.cpp:20:11:20:21 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | Chi [a] | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] |
|
||||
| by_reference.cpp:24:5:24:17 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | Chi [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:36:18:36:18 | Store | by_reference.cpp:40:18:40:28 | call to getDirectly |
|
||||
| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:32:15:32:15 | Store | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
|
||||
| by_reference.cpp:50:5:50:15 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | Chi [a] | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:36:18:36:18 | Store | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:56:5:56:17 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | Chi [a] | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | *#this [a] | by_reference.cpp:40:18:40:28 | Store | by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:62:5:62:23 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | Chi [a] | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | *#this [a] | by_reference.cpp:44:12:44:24 | Store | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:68:3:68:15 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | Chi [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:32:15:32:15 | Store | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
|
||||
| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:9:7:9:7 | *#this [a_] | complex.cpp:9:20:9:21 | Store | complex.cpp:42:18:42:18 | call to a |
|
||||
| complex.cpp:42:16:42:16 | f indirection [b_] | complex.cpp:9:7:9:7 | *#this [b_] | complex.cpp:9:7:9:7 | *#this [b_] | complex.cpp:42:16:42:16 | a output argument [b_] |
|
||||
| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:10:7:10:7 | *#this [b_] | complex.cpp:10:20:10:21 | Store | complex.cpp:43:18:43:18 | call to b |
|
||||
| complex.cpp:53:14:53:17 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | Chi [a_] | complex.cpp:53:12:53:12 | setA output argument [a_] |
|
||||
| complex.cpp:54:14:54:17 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | Chi [b_] | complex.cpp:54:12:54:12 | setB output argument [b_] |
|
||||
| complex.cpp:55:14:55:17 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | Chi [a_] | complex.cpp:55:12:55:12 | setA output argument [a_] |
|
||||
| complex.cpp:56:12:56:12 | f indirection [a_] | complex.cpp:12:8:12:11 | *#this [a_] | complex.cpp:12:22:12:27 | Chi [a_] | complex.cpp:56:12:56:12 | setB output argument [a_] |
|
||||
| complex.cpp:56:14:56:17 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | Chi [b_] | complex.cpp:56:12:56:12 | setB output argument [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:22:18:23 | Store | constructors.cpp:28:12:28:12 | call to a |
|
||||
| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] |
|
||||
| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:19:9:19:9 | *#this [b_] | constructors.cpp:19:22:19:23 | Store | constructors.cpp:29:12:29:12 | call to b |
|
||||
| constructors.cpp:34:11:34:26 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:35:23:35 | Chi [a_] | constructors.cpp:34:11:34:26 | Foo output argument [a_] |
|
||||
| constructors.cpp:35:11:35:26 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | Chi [b_] | constructors.cpp:35:11:35:26 | Foo output argument [b_] |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:35:23:35 | Chi [a_] | constructors.cpp:36:11:36:37 | Foo output argument [a_] |
|
||||
| constructors.cpp:36:11:36:37 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | Chi [b_] | constructors.cpp:36:11:36:37 | Foo output argument [b_] |
|
||||
| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:22:18:23 | Store | simple.cpp:28:12:28:12 | call to a |
|
||||
| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:28:10:28:10 | a output argument [b_] |
|
||||
| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:19:9:19:9 | *#this [b_] | simple.cpp:19:22:19:23 | Store | simple.cpp:29:12:29:12 | call to b |
|
||||
| simple.cpp:39:7:39:10 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | Chi [a_] | simple.cpp:39:5:39:5 | setA output argument [a_] |
|
||||
| simple.cpp:40:7:40:10 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | Chi [b_] | simple.cpp:40:5:40:5 | setB output argument [b_] |
|
||||
| simple.cpp:41:7:41:10 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | Chi [a_] | simple.cpp:41:5:41:5 | setA output argument [a_] |
|
||||
| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:24:21:29 | Chi [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] |
|
||||
| simple.cpp:42:7:42:10 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | Chi [b_] | simple.cpp:42:5:42:5 | setB output argument [b_] |
|
||||
| simple.cpp:84:14:84:20 | this indirection [f1] | simple.cpp:78:9:78:15 | *#this [f1] | simple.cpp:79:19:79:20 | Store | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
#select
|
||||
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... |
|
||||
| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new |
|
||||
|
||||
@@ -1,21 +1,46 @@
|
||||
edges
|
||||
| A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | ... = ... |
|
||||
| A.cpp:25:7:25:17 | ... = ... | A.cpp:25:7:25:10 | this [post update] [c] |
|
||||
| A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | ... = ... |
|
||||
| A.cpp:27:22:27:32 | ... = ... | A.cpp:27:22:27:25 | this [post update] [c] |
|
||||
| A.cpp:28:8:28:10 | this [c] | A.cpp:28:23:28:26 | this [c] |
|
||||
| A.cpp:28:23:28:26 | this [c] | A.cpp:28:29:28:29 | c |
|
||||
| A.cpp:29:23:29:23 | c | A.cpp:31:20:31:20 | c |
|
||||
| A.cpp:31:14:31:21 | call to B [c] | A.cpp:31:14:31:21 | new [c] |
|
||||
| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c |
|
||||
| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] |
|
||||
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... |
|
||||
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c |
|
||||
| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [c] |
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c |
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make [c] |
|
||||
| A.cpp:49:10:49:10 | b [c] | A.cpp:49:13:49:13 | c |
|
||||
| A.cpp:55:5:55:5 | ref arg b [c] | A.cpp:56:10:56:10 | b [c] |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | ref arg b [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:11:57:24 | call to B [c] | A.cpp:57:11:57:24 | new [c] |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] |
|
||||
| A.cpp:64:10:64:15 | call to setOnB [c] | A.cpp:66:10:66:11 | b2 [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c |
|
||||
| A.cpp:66:10:66:11 | b2 [c] | A.cpp:66:14:66:14 | c |
|
||||
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | A.cpp:75:10:75:11 | b2 [c] |
|
||||
| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
|
||||
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c |
|
||||
| A.cpp:75:10:75:11 | b2 [c] | A.cpp:75:14:75:14 | c |
|
||||
| A.cpp:78:27:78:27 | c | A.cpp:81:21:81:21 | c |
|
||||
| A.cpp:81:10:81:15 | call to setOnB [c] | A.cpp:82:12:82:24 | ... ? ... : ... [c] |
|
||||
| A.cpp:81:21:81:21 | c | A.cpp:81:10:81:15 | call to setOnB [c] |
|
||||
| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c |
|
||||
| A.cpp:85:26:85:26 | c | A.cpp:90:15:90:15 | c |
|
||||
| A.cpp:90:7:90:8 | ref arg b2 [c] | A.cpp:91:14:91:15 | b2 [c] |
|
||||
| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:90:15:90:15 | c | A.cpp:90:7:90:8 | ref arg b2 [c] |
|
||||
| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | ... = ... |
|
||||
| A.cpp:100:5:100:6 | c1 [post update] [a] | A.cpp:101:8:101:9 | c1 [a] |
|
||||
| A.cpp:100:5:100:13 | ... = ... | A.cpp:100:5:100:6 | c1 [post update] [a] |
|
||||
@@ -25,9 +50,11 @@ edges
|
||||
| A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a |
|
||||
| A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a |
|
||||
| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:131:8:131:8 | ref arg b [c] |
|
||||
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | ref arg b [c] |
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] |
|
||||
| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c |
|
||||
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:143:7:143:31 | ... = ... [c] |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:151:18:151:18 | ref arg b [c] |
|
||||
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | b [post update] [c] |
|
||||
@@ -35,11 +62,13 @@ edges
|
||||
| A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
|
||||
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] |
|
||||
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] |
|
||||
| A.cpp:143:7:143:31 | ... = ... [c] | A.cpp:143:7:143:10 | this [post update] [b, c] |
|
||||
| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | ... = ... |
|
||||
| A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b |
|
||||
| A.cpp:151:12:151:24 | call to D [b, c] | A.cpp:153:10:153:10 | d [b, c] |
|
||||
| A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | d [b] |
|
||||
| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b |
|
||||
| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] |
|
||||
| A.cpp:151:18:151:18 | ref arg b [c] | A.cpp:154:10:154:10 | b [c] |
|
||||
| A.cpp:152:10:152:10 | d [b] | A.cpp:152:13:152:13 | b |
|
||||
@@ -49,11 +78,14 @@ edges
|
||||
| A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b |
|
||||
| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 [head] |
|
||||
| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] |
|
||||
| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead |
|
||||
| A.cpp:161:18:161:40 | call to MyList [next, head] | A.cpp:162:38:162:39 | l2 [next, head] |
|
||||
| A.cpp:161:38:161:39 | l1 [head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
|
||||
| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] |
|
||||
| A.cpp:162:18:162:40 | call to MyList [next, next, head] | A.cpp:165:10:165:11 | l3 [next, next, head] |
|
||||
| A.cpp:162:18:162:40 | call to MyList [next, next, head] | A.cpp:167:44:167:44 | l [next, next, head] |
|
||||
| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, head] |
|
||||
| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] |
|
||||
| A.cpp:165:10:165:11 | l3 [next, next, head] | A.cpp:165:14:165:17 | next [next, head] |
|
||||
| A.cpp:165:14:165:17 | next [next, head] | A.cpp:165:20:165:23 | next [head] |
|
||||
| A.cpp:165:20:165:23 | next [head] | A.cpp:165:26:165:29 | head |
|
||||
@@ -62,20 +94,38 @@ edges
|
||||
| A.cpp:167:47:167:50 | next [head] | A.cpp:169:12:169:12 | l [head] |
|
||||
| A.cpp:167:47:167:50 | next [next, head] | A.cpp:167:44:167:44 | l [next, head] |
|
||||
| A.cpp:169:12:169:12 | l [head] | A.cpp:169:15:169:18 | head |
|
||||
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... |
|
||||
| A.cpp:181:32:181:35 | next [head] | A.cpp:184:7:184:23 | ... = ... [head] |
|
||||
| A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:7:184:23 | ... = ... [next, head] |
|
||||
| A.cpp:183:7:183:20 | ... = ... | A.cpp:183:7:183:10 | this [post update] [head] |
|
||||
| A.cpp:184:7:184:23 | ... = ... [head] | A.cpp:184:7:184:10 | this [post update] [next, head] |
|
||||
| A.cpp:184:7:184:23 | ... = ... [next, head] | A.cpp:184:7:184:10 | this [post update] [next, next, head] |
|
||||
| B.cpp:6:15:6:24 | new | B.cpp:7:25:7:25 | e |
|
||||
| B.cpp:7:16:7:35 | call to Box1 [elem1] | B.cpp:8:25:8:26 | b1 [elem1] |
|
||||
| B.cpp:7:25:7:25 | e | B.cpp:7:16:7:35 | call to Box1 [elem1] |
|
||||
| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 |
|
||||
| B.cpp:8:16:8:27 | call to Box2 [box1, elem1] | B.cpp:9:10:9:11 | b2 [box1, elem1] |
|
||||
| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
|
||||
| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] |
|
||||
| B.cpp:9:10:9:11 | b2 [box1, elem1] | B.cpp:9:14:9:17 | box1 [elem1] |
|
||||
| B.cpp:9:14:9:17 | box1 [elem1] | B.cpp:9:20:9:24 | elem1 |
|
||||
| B.cpp:15:15:15:27 | new | B.cpp:16:37:16:37 | e |
|
||||
| B.cpp:16:16:16:38 | call to Box1 [elem2] | B.cpp:17:25:17:26 | b1 [elem2] |
|
||||
| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] |
|
||||
| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 |
|
||||
| B.cpp:17:16:17:27 | call to Box2 [box1, elem2] | B.cpp:19:10:19:11 | b2 [box1, elem2] |
|
||||
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
|
||||
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] |
|
||||
| B.cpp:19:10:19:11 | b2 [box1, elem2] | B.cpp:19:14:19:17 | box1 [elem2] |
|
||||
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 |
|
||||
| B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:22 | ... = ... |
|
||||
| B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:22 | ... = ... |
|
||||
| B.cpp:35:7:35:22 | ... = ... | B.cpp:35:7:35:10 | this [post update] [elem1] |
|
||||
| B.cpp:36:7:36:22 | ... = ... | B.cpp:36:7:36:10 | this [post update] [elem2] |
|
||||
| B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:7:46:21 | ... = ... [elem1] |
|
||||
| B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:7:46:21 | ... = ... [elem2] |
|
||||
| B.cpp:46:7:46:21 | ... = ... [elem1] | B.cpp:46:7:46:10 | this [post update] [box1, elem1] |
|
||||
| B.cpp:46:7:46:21 | ... = ... [elem2] | B.cpp:46:7:46:10 | this [post update] [box1, elem2] |
|
||||
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] |
|
||||
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] |
|
||||
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] |
|
||||
@@ -89,8 +139,16 @@ edges
|
||||
| C.cpp:27:8:27:11 | this [s3] | C.cpp:31:10:31:11 | this [s3] |
|
||||
| C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 |
|
||||
| C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 |
|
||||
| D.cpp:10:11:10:17 | this [elem] | D.cpp:10:30:10:33 | this [elem] |
|
||||
| D.cpp:10:30:10:33 | this [elem] | D.cpp:10:30:10:33 | elem |
|
||||
| D.cpp:11:24:11:24 | e | D.cpp:11:29:11:36 | ... = ... |
|
||||
| D.cpp:11:29:11:36 | ... = ... | D.cpp:11:29:11:32 | this [post update] [elem] |
|
||||
| D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:30:17:32 | this [box, elem] |
|
||||
| D.cpp:17:30:17:32 | this [box, elem] | D.cpp:17:30:17:32 | box [elem] |
|
||||
| D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:25:22:31 | call to getElem |
|
||||
| D.cpp:28:15:28:24 | new | D.cpp:30:5:30:20 | ... = ... |
|
||||
| D.cpp:30:5:30:5 | b [post update] [box, elem] | D.cpp:31:14:31:14 | b [box, elem] |
|
||||
@@ -100,6 +158,7 @@ edges
|
||||
| D.cpp:35:15:35:24 | new | D.cpp:37:21:37:21 | e |
|
||||
| D.cpp:37:5:37:5 | b [post update] [box, elem] | D.cpp:38:14:38:14 | b [box, elem] |
|
||||
| D.cpp:37:8:37:10 | ref arg box [elem] | D.cpp:37:5:37:5 | b [post update] [box, elem] |
|
||||
| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e |
|
||||
| D.cpp:37:21:37:21 | e | D.cpp:37:8:37:10 | ref arg box [elem] |
|
||||
| D.cpp:38:14:38:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
|
||||
| D.cpp:42:15:42:24 | new | D.cpp:44:5:44:26 | ... = ... |
|
||||
@@ -110,6 +169,7 @@ edges
|
||||
| D.cpp:49:15:49:24 | new | D.cpp:51:27:51:27 | e |
|
||||
| D.cpp:51:5:51:5 | ref arg b [box, elem] | D.cpp:52:14:52:14 | b [box, elem] |
|
||||
| D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] | D.cpp:51:5:51:5 | ref arg b [box, elem] |
|
||||
| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e |
|
||||
| D.cpp:51:27:51:27 | e | D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] |
|
||||
| D.cpp:52:14:52:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] |
|
||||
| D.cpp:56:15:56:24 | new | D.cpp:58:5:58:27 | ... = ... |
|
||||
@@ -223,17 +283,45 @@ edges
|
||||
| arrays.cpp:44:8:44:25 | access to array [data] | arrays.cpp:44:27:44:30 | data |
|
||||
| arrays.cpp:44:10:44:17 | indirect [arr, data] | arrays.cpp:44:20:44:22 | arr [data] |
|
||||
| arrays.cpp:44:20:44:22 | arr [data] | arrays.cpp:44:8:44:25 | access to array [data] |
|
||||
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... |
|
||||
| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:5:12:5 | s [post update] [a] |
|
||||
| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | ... = ... |
|
||||
| by_reference.cpp:16:5:16:19 | ... = ... | by_reference.cpp:16:5:16:8 | this [post update] [a] |
|
||||
| by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:23:20:27 | value |
|
||||
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value |
|
||||
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:20:5:20:8 | ref arg this [a] |
|
||||
| by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:25:24:29 | value |
|
||||
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value |
|
||||
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:24:19:24:22 | ref arg this [a] |
|
||||
| by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:12:32:12 | s [a] |
|
||||
| by_reference.cpp:32:12:32:12 | s [a] | by_reference.cpp:32:15:32:15 | a |
|
||||
| by_reference.cpp:35:9:35:19 | this [a] | by_reference.cpp:36:12:36:15 | this [a] |
|
||||
| by_reference.cpp:36:12:36:15 | this [a] | by_reference.cpp:36:18:36:18 | a |
|
||||
| by_reference.cpp:39:9:39:21 | this [a] | by_reference.cpp:40:12:40:15 | this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this [a] | by_reference.cpp:35:9:35:19 | this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this [a] | by_reference.cpp:40:18:40:28 | call to getDirectly |
|
||||
| by_reference.cpp:43:9:43:27 | this [a] | by_reference.cpp:44:26:44:29 | this [a] |
|
||||
| by_reference.cpp:44:26:44:29 | this [a] | by_reference.cpp:31:46:31:46 | s [a] |
|
||||
| by_reference.cpp:44:26:44:29 | this [a] | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
|
||||
| by_reference.cpp:50:3:50:3 | ref arg s [a] | by_reference.cpp:51:8:51:8 | s [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | ref arg s [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:35:9:35:19 | this [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:56:3:56:3 | ref arg s [a] | by_reference.cpp:57:8:57:8 | s [a] |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | ref arg s [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:39:9:39:21 | this [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:62:3:62:3 | ref arg s [a] | by_reference.cpp:63:8:63:8 | s [a] |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | ref arg s [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:43:9:43:27 | this [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:68:17:68:18 | ref arg & ... [a] | by_reference.cpp:69:22:69:23 | & ... [a] |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:31:46:31:46 | s [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
|
||||
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] |
|
||||
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] |
|
||||
@@ -308,29 +396,43 @@ edges
|
||||
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] |
|
||||
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a |
|
||||
| by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a |
|
||||
| complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | this [a_] |
|
||||
| complex.cpp:9:20:9:21 | this [a_] | complex.cpp:9:20:9:21 | a_ |
|
||||
| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [b_] |
|
||||
| complex.cpp:10:20:10:21 | this [b_] | complex.cpp:10:20:10:21 | b_ |
|
||||
| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | ... = ... |
|
||||
| complex.cpp:11:22:11:27 | ... = ... | complex.cpp:11:22:11:23 | this [post update] [a_] |
|
||||
| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | ... = ... |
|
||||
| complex.cpp:12:22:12:27 | ... = ... | complex.cpp:12:22:12:23 | this [post update] [b_] |
|
||||
| complex.cpp:40:17:40:17 | b [inner, f, a_] | complex.cpp:42:8:42:8 | b [inner, f, a_] |
|
||||
| complex.cpp:40:17:40:17 | b [inner, f, b_] | complex.cpp:43:8:43:8 | b [inner, f, b_] |
|
||||
| complex.cpp:42:8:42:8 | b [inner, f, a_] | complex.cpp:42:10:42:14 | inner [f, a_] |
|
||||
| complex.cpp:42:10:42:14 | inner [f, a_] | complex.cpp:42:16:42:16 | f [a_] |
|
||||
| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:9:7:9:7 | this [a_] |
|
||||
| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:42:18:42:18 | call to a |
|
||||
| complex.cpp:43:8:43:8 | b [inner, f, b_] | complex.cpp:43:10:43:14 | inner [f, b_] |
|
||||
| complex.cpp:43:10:43:14 | inner [f, b_] | complex.cpp:43:16:43:16 | f [b_] |
|
||||
| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:10:7:10:7 | this [b_] |
|
||||
| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:43:18:43:18 | call to b |
|
||||
| complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | complex.cpp:59:7:59:8 | b1 [inner, f, a_] |
|
||||
| complex.cpp:53:6:53:10 | inner [post update] [f, a_] | complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] |
|
||||
| complex.cpp:53:12:53:12 | ref arg f [a_] | complex.cpp:53:6:53:10 | inner [post update] [f, a_] |
|
||||
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a |
|
||||
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | ref arg f [a_] |
|
||||
| complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | complex.cpp:62:7:62:8 | b2 [inner, f, b_] |
|
||||
| complex.cpp:54:6:54:10 | inner [post update] [f, b_] | complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] |
|
||||
| complex.cpp:54:12:54:12 | ref arg f [b_] | complex.cpp:54:6:54:10 | inner [post update] [f, b_] |
|
||||
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b |
|
||||
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | ref arg f [b_] |
|
||||
| complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | complex.cpp:65:7:65:8 | b3 [inner, f, a_] |
|
||||
| complex.cpp:55:6:55:10 | inner [post update] [f, a_] | complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] |
|
||||
| complex.cpp:55:12:55:12 | ref arg f [a_] | complex.cpp:55:6:55:10 | inner [post update] [f, a_] |
|
||||
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a |
|
||||
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | ref arg f [a_] |
|
||||
| complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | complex.cpp:65:7:65:8 | b3 [inner, f, b_] |
|
||||
| complex.cpp:56:6:56:10 | inner [post update] [f, b_] | complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] |
|
||||
| complex.cpp:56:12:56:12 | ref arg f [b_] | complex.cpp:56:6:56:10 | inner [post update] [f, b_] |
|
||||
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b |
|
||||
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | ref arg f [b_] |
|
||||
| complex.cpp:59:7:59:8 | b1 [inner, f, a_] | complex.cpp:40:17:40:17 | b [inner, f, a_] |
|
||||
| complex.cpp:62:7:62:8 | b2 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] |
|
||||
@@ -357,22 +459,43 @@ edges
|
||||
| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:3:60:28 | ... = ... |
|
||||
| conflated.cpp:61:8:61:9 | ll [next, y] | conflated.cpp:61:12:61:15 | next [y] |
|
||||
| conflated.cpp:61:12:61:15 | next [y] | conflated.cpp:61:18:61:18 | y |
|
||||
| constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:22:18:23 | this [a_] |
|
||||
| constructors.cpp:18:22:18:23 | this [a_] | constructors.cpp:18:22:18:23 | a_ |
|
||||
| constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | this [b_] |
|
||||
| constructors.cpp:19:22:19:23 | this [b_] | constructors.cpp:19:22:19:23 | b_ |
|
||||
| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | a |
|
||||
| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | b |
|
||||
| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] |
|
||||
| constructors.cpp:23:35:23:35 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] |
|
||||
| constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] |
|
||||
| constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:18:9:18:9 | this [a_] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:28:12:28:12 | call to a |
|
||||
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] |
|
||||
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:29:12:29:12 | call to b |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:26 | call to Foo [a_] |
|
||||
| constructors.cpp:34:11:34:26 | call to Foo [a_] | constructors.cpp:40:9:40:9 | f [a_] |
|
||||
| constructors.cpp:35:11:35:26 | call to Foo [b_] | constructors.cpp:43:9:43:9 | g [b_] |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:11:35:26 | call to Foo [b_] |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [a_] |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [a_] | constructors.cpp:46:9:46:9 | h [a_] |
|
||||
| constructors.cpp:36:11:36:37 | call to Foo [b_] | constructors.cpp:46:9:46:9 | h [b_] |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:11:36:37 | call to Foo [b_] |
|
||||
| constructors.cpp:40:9:40:9 | f [a_] | constructors.cpp:26:15:26:15 | f [a_] |
|
||||
| constructors.cpp:43:9:43:9 | g [b_] | constructors.cpp:26:15:26:15 | f [b_] |
|
||||
| constructors.cpp:46:9:46:9 | h [a_] | constructors.cpp:26:15:26:15 | f [a_] |
|
||||
| constructors.cpp:46:9:46:9 | h [b_] | constructors.cpp:26:15:26:15 | f [b_] |
|
||||
| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:44 | ... = ... |
|
||||
| qualifiers.cpp:9:30:9:44 | ... = ... | qualifiers.cpp:9:30:9:33 | this [post update] [a] |
|
||||
| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:64 | ... = ... |
|
||||
| qualifiers.cpp:12:49:12:64 | ... = ... | qualifiers.cpp:12:49:12:53 | inner [post update] [a] |
|
||||
| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:65 | ... = ... |
|
||||
| qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:13:29:13:33 | inner [a] |
|
||||
| qualifiers.cpp:13:51:13:65 | ... = ... | qualifiers.cpp:13:51:13:55 | inner [post update] [a] |
|
||||
| qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] | qualifiers.cpp:23:10:23:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:22:5:22:38 | ... = ... | qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] |
|
||||
| qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] | qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] |
|
||||
@@ -381,17 +504,20 @@ edges
|
||||
| qualifiers.cpp:23:16:23:20 | inner [a] | qualifiers.cpp:23:23:23:23 | a |
|
||||
| qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] | qualifiers.cpp:28:10:28:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] | qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value |
|
||||
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:28:10:28:14 | outer [inner, a] | qualifiers.cpp:28:16:28:20 | inner [a] |
|
||||
| qualifiers.cpp:28:16:28:20 | inner [a] | qualifiers.cpp:28:23:28:23 | a |
|
||||
| qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] | qualifiers.cpp:33:10:33:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] | qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value |
|
||||
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:33:10:33:14 | outer [inner, a] | qualifiers.cpp:33:16:33:20 | inner [a] |
|
||||
| qualifiers.cpp:33:16:33:20 | inner [a] | qualifiers.cpp:33:23:33:23 | a |
|
||||
| qualifiers.cpp:37:19:37:35 | ref arg * ... [a] | qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] |
|
||||
| qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] | qualifiers.cpp:38:10:38:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] | qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value |
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
|
||||
| qualifiers.cpp:38:10:38:14 | outer [inner, a] | qualifiers.cpp:38:16:38:20 | inner [a] |
|
||||
| qualifiers.cpp:38:16:38:20 | inner [a] | qualifiers.cpp:38:23:38:23 | a |
|
||||
@@ -420,17 +546,31 @@ edges
|
||||
| realistic.cpp:61:25:61:27 | bar [baz, userInput, bufferLen] | realistic.cpp:61:21:61:30 | access to array [baz, userInput, bufferLen] |
|
||||
| realistic.cpp:61:32:61:34 | baz [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput [bufferLen] |
|
||||
| realistic.cpp:61:37:61:45 | userInput [bufferLen] | realistic.cpp:61:47:61:55 | bufferLen |
|
||||
| simple.cpp:18:9:18:9 | this [a_] | simple.cpp:18:22:18:23 | this [a_] |
|
||||
| simple.cpp:18:22:18:23 | this [a_] | simple.cpp:18:22:18:23 | a_ |
|
||||
| simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | this [b_] |
|
||||
| simple.cpp:19:22:19:23 | this [b_] | simple.cpp:19:22:19:23 | b_ |
|
||||
| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | ... = ... |
|
||||
| simple.cpp:20:24:20:29 | ... = ... | simple.cpp:20:24:20:25 | this [post update] [a_] |
|
||||
| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | ... = ... |
|
||||
| simple.cpp:21:24:21:29 | ... = ... | simple.cpp:21:24:21:25 | this [post update] [b_] |
|
||||
| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:10:28:10 | f [a_] |
|
||||
| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:10:29:10 | f [b_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:18:9:18:9 | this [a_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:28:12:28:12 | call to a |
|
||||
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:19:9:19:9 | this [b_] |
|
||||
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:29:12:29:12 | call to b |
|
||||
| simple.cpp:39:5:39:5 | ref arg f [a_] | simple.cpp:45:9:45:9 | f [a_] |
|
||||
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a |
|
||||
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | ref arg f [a_] |
|
||||
| simple.cpp:40:5:40:5 | ref arg g [b_] | simple.cpp:48:9:48:9 | g [b_] |
|
||||
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b |
|
||||
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | ref arg g [b_] |
|
||||
| simple.cpp:41:5:41:5 | ref arg h [a_] | simple.cpp:51:9:51:9 | h [a_] |
|
||||
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a |
|
||||
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | ref arg h [a_] |
|
||||
| simple.cpp:42:5:42:5 | ref arg h [b_] | simple.cpp:51:9:51:9 | h [b_] |
|
||||
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b |
|
||||
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | ref arg h [b_] |
|
||||
| simple.cpp:45:9:45:9 | f [a_] | simple.cpp:26:15:26:15 | f [a_] |
|
||||
| simple.cpp:48:9:48:9 | g [b_] | simple.cpp:26:15:26:15 | f [b_] |
|
||||
@@ -440,10 +580,14 @@ edges
|
||||
| simple.cpp:65:5:65:22 | ... = ... | simple.cpp:65:5:65:5 | a [post update] [i] |
|
||||
| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | ... = ... |
|
||||
| simple.cpp:67:10:67:11 | a2 [i] | simple.cpp:67:13:67:13 | i |
|
||||
| simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:79:16:79:17 | this [f2, f1] |
|
||||
| simple.cpp:79:16:79:17 | f2 [f1] | simple.cpp:79:19:79:20 | f1 |
|
||||
| simple.cpp:79:16:79:17 | this [f2, f1] | simple.cpp:79:16:79:17 | f2 [f1] |
|
||||
| simple.cpp:83:9:83:10 | f2 [post update] [f1] | simple.cpp:83:9:83:10 | this [post update] [f2, f1] |
|
||||
| simple.cpp:83:9:83:10 | this [post update] [f2, f1] | simple.cpp:84:14:84:20 | this [f2, f1] |
|
||||
| simple.cpp:83:9:83:28 | ... = ... | simple.cpp:83:9:83:10 | f2 [post update] [f1] |
|
||||
| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | ... = ... |
|
||||
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] |
|
||||
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
| simple.cpp:92:5:92:5 | a [post update] [i] | simple.cpp:94:10:94:11 | a2 [i] |
|
||||
| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:5:92:5 | a [post update] [i] |
|
||||
@@ -477,6 +621,19 @@ edges
|
||||
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | struct_init.c:46:16:46:24 | pointerAB [a] |
|
||||
| struct_init.c:46:16:46:24 | pointerAB [a] | struct_init.c:14:24:14:25 | ab [a] |
|
||||
nodes
|
||||
| A.cpp:23:10:23:10 | c | semmle.label | c |
|
||||
| A.cpp:25:7:25:10 | this [post update] [c] | semmle.label | this [post update] [c] |
|
||||
| A.cpp:25:7:25:17 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:27:17:27:17 | c | semmle.label | c |
|
||||
| A.cpp:27:22:27:25 | this [post update] [c] | semmle.label | this [post update] [c] |
|
||||
| A.cpp:27:22:27:32 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:28:8:28:10 | this [c] | semmle.label | this [c] |
|
||||
| A.cpp:28:23:28:26 | this [c] | semmle.label | this [c] |
|
||||
| A.cpp:28:29:28:29 | c | semmle.label | c |
|
||||
| A.cpp:29:23:29:23 | c | semmle.label | c |
|
||||
| A.cpp:31:14:31:21 | call to B [c] | semmle.label | call to B [c] |
|
||||
| A.cpp:31:14:31:21 | new [c] | semmle.label | new [c] |
|
||||
| A.cpp:31:20:31:20 | c | semmle.label | c |
|
||||
| A.cpp:41:15:41:21 | new | semmle.label | new |
|
||||
| A.cpp:43:10:43:12 | & ... | semmle.label | & ... |
|
||||
| A.cpp:47:12:47:18 | new | semmle.label | new |
|
||||
@@ -500,6 +657,14 @@ nodes
|
||||
| A.cpp:73:25:73:32 | new | semmle.label | new |
|
||||
| A.cpp:75:10:75:11 | b2 [c] | semmle.label | b2 [c] |
|
||||
| A.cpp:75:14:75:14 | c | semmle.label | c |
|
||||
| A.cpp:78:27:78:27 | c | semmle.label | c |
|
||||
| A.cpp:81:10:81:15 | call to setOnB [c] | semmle.label | call to setOnB [c] |
|
||||
| A.cpp:81:21:81:21 | c | semmle.label | c |
|
||||
| A.cpp:82:12:82:24 | ... ? ... : ... [c] | semmle.label | ... ? ... : ... [c] |
|
||||
| A.cpp:85:26:85:26 | c | semmle.label | c |
|
||||
| A.cpp:90:7:90:8 | ref arg b2 [c] | semmle.label | ref arg b2 [c] |
|
||||
| A.cpp:90:15:90:15 | c | semmle.label | c |
|
||||
| A.cpp:91:14:91:15 | b2 [c] | semmle.label | b2 [c] |
|
||||
| A.cpp:98:12:98:18 | new | semmle.label | new |
|
||||
| A.cpp:100:5:100:6 | c1 [post update] [a] | semmle.label | c1 [post update] [a] |
|
||||
| A.cpp:100:5:100:13 | ... = ... | semmle.label | ... = ... |
|
||||
@@ -514,11 +679,14 @@ nodes
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] | semmle.label | ref arg b [c] |
|
||||
| A.cpp:132:10:132:10 | b [c] | semmle.label | b [c] |
|
||||
| A.cpp:132:13:132:13 | c | semmle.label | c |
|
||||
| A.cpp:140:13:140:13 | b | semmle.label | b |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c] | semmle.label | b [post update] [c] |
|
||||
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:142:14:142:20 | new | semmle.label | new |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b, c] | semmle.label | this [post update] [b, c] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b] | semmle.label | this [post update] [b] |
|
||||
| A.cpp:143:7:143:10 | this [post update] [b] | semmle.label | this [post update] [b] |
|
||||
| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:143:7:143:31 | ... = ... [c] | semmle.label | ... = ... [c] |
|
||||
| A.cpp:143:25:143:31 | new | semmle.label | new |
|
||||
@@ -551,6 +719,15 @@ nodes
|
||||
| A.cpp:167:47:167:50 | next [next, head] | semmle.label | next [next, head] |
|
||||
| A.cpp:169:12:169:12 | l [head] | semmle.label | l [head] |
|
||||
| A.cpp:169:15:169:18 | head | semmle.label | head |
|
||||
| A.cpp:181:15:181:21 | newHead | semmle.label | newHead |
|
||||
| A.cpp:181:32:181:35 | next [head] | semmle.label | next [head] |
|
||||
| A.cpp:181:32:181:35 | next [next, head] | semmle.label | next [next, head] |
|
||||
| A.cpp:183:7:183:10 | this [post update] [head] | semmle.label | this [post update] [head] |
|
||||
| A.cpp:183:7:183:20 | ... = ... | semmle.label | ... = ... |
|
||||
| A.cpp:184:7:184:10 | this [post update] [next, head] | semmle.label | this [post update] [next, head] |
|
||||
| A.cpp:184:7:184:10 | this [post update] [next, next, head] | semmle.label | this [post update] [next, next, head] |
|
||||
| A.cpp:184:7:184:23 | ... = ... [head] | semmle.label | ... = ... [head] |
|
||||
| A.cpp:184:7:184:23 | ... = ... [next, head] | semmle.label | ... = ... [next, head] |
|
||||
| B.cpp:6:15:6:24 | new | semmle.label | new |
|
||||
| B.cpp:7:16:7:35 | call to Box1 [elem1] | semmle.label | call to Box1 [elem1] |
|
||||
| B.cpp:7:25:7:25 | e | semmle.label | e |
|
||||
@@ -567,6 +744,18 @@ nodes
|
||||
| B.cpp:19:10:19:11 | b2 [box1, elem2] | semmle.label | b2 [box1, elem2] |
|
||||
| B.cpp:19:14:19:17 | box1 [elem2] | semmle.label | box1 [elem2] |
|
||||
| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 |
|
||||
| B.cpp:33:16:33:17 | e1 | semmle.label | e1 |
|
||||
| B.cpp:33:26:33:27 | e2 | semmle.label | e2 |
|
||||
| B.cpp:35:7:35:10 | this [post update] [elem1] | semmle.label | this [post update] [elem1] |
|
||||
| B.cpp:35:7:35:22 | ... = ... | semmle.label | ... = ... |
|
||||
| B.cpp:36:7:36:10 | this [post update] [elem2] | semmle.label | this [post update] [elem2] |
|
||||
| B.cpp:36:7:36:22 | ... = ... | semmle.label | ... = ... |
|
||||
| B.cpp:44:16:44:17 | b1 [elem1] | semmle.label | b1 [elem1] |
|
||||
| B.cpp:44:16:44:17 | b1 [elem2] | semmle.label | b1 [elem2] |
|
||||
| B.cpp:46:7:46:10 | this [post update] [box1, elem1] | semmle.label | this [post update] [box1, elem1] |
|
||||
| B.cpp:46:7:46:10 | this [post update] [box1, elem2] | semmle.label | this [post update] [box1, elem2] |
|
||||
| B.cpp:46:7:46:21 | ... = ... [elem1] | semmle.label | ... = ... [elem1] |
|
||||
| B.cpp:46:7:46:21 | ... = ... [elem2] | semmle.label | ... = ... [elem2] |
|
||||
| C.cpp:18:12:18:18 | call to C [s1] | semmle.label | call to C [s1] |
|
||||
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
|
||||
| C.cpp:19:5:19:5 | c [s1] | semmle.label | c [s1] |
|
||||
@@ -582,6 +771,15 @@ nodes
|
||||
| C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] |
|
||||
| C.cpp:31:10:31:11 | s3 | semmle.label | s3 |
|
||||
| C.cpp:31:10:31:11 | this [s3] | semmle.label | this [s3] |
|
||||
| D.cpp:10:11:10:17 | this [elem] | semmle.label | this [elem] |
|
||||
| D.cpp:10:30:10:33 | elem | semmle.label | elem |
|
||||
| D.cpp:10:30:10:33 | this [elem] | semmle.label | this [elem] |
|
||||
| D.cpp:11:24:11:24 | e | semmle.label | e |
|
||||
| D.cpp:11:29:11:32 | this [post update] [elem] | semmle.label | this [post update] [elem] |
|
||||
| D.cpp:11:29:11:36 | ... = ... | semmle.label | ... = ... |
|
||||
| D.cpp:17:11:17:17 | this [box, elem] | semmle.label | this [box, elem] |
|
||||
| D.cpp:17:30:17:32 | box [elem] | semmle.label | box [elem] |
|
||||
| D.cpp:17:30:17:32 | this [box, elem] | semmle.label | this [box, elem] |
|
||||
| D.cpp:21:30:21:31 | b2 [box, elem] | semmle.label | b2 [box, elem] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | semmle.label | b2 [box, elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | semmle.label | call to getBox1 [elem] |
|
||||
@@ -729,6 +927,30 @@ nodes
|
||||
| arrays.cpp:44:10:44:17 | indirect [arr, data] | semmle.label | indirect [arr, data] |
|
||||
| arrays.cpp:44:20:44:22 | arr [data] | semmle.label | arr [data] |
|
||||
| arrays.cpp:44:27:44:30 | data | semmle.label | data |
|
||||
| by_reference.cpp:11:48:11:52 | value | semmle.label | value |
|
||||
| by_reference.cpp:12:5:12:5 | s [post update] [a] | semmle.label | s [post update] [a] |
|
||||
| by_reference.cpp:12:5:12:16 | ... = ... | semmle.label | ... = ... |
|
||||
| by_reference.cpp:15:26:15:30 | value | semmle.label | value |
|
||||
| by_reference.cpp:16:5:16:8 | this [post update] [a] | semmle.label | this [post update] [a] |
|
||||
| by_reference.cpp:16:5:16:19 | ... = ... | semmle.label | ... = ... |
|
||||
| by_reference.cpp:19:28:19:32 | value | semmle.label | value |
|
||||
| by_reference.cpp:20:5:20:8 | ref arg this [a] | semmle.label | ref arg this [a] |
|
||||
| by_reference.cpp:20:23:20:27 | value | semmle.label | value |
|
||||
| by_reference.cpp:23:34:23:38 | value | semmle.label | value |
|
||||
| by_reference.cpp:24:19:24:22 | ref arg this [a] | semmle.label | ref arg this [a] |
|
||||
| by_reference.cpp:24:25:24:29 | value | semmle.label | value |
|
||||
| by_reference.cpp:31:46:31:46 | s [a] | semmle.label | s [a] |
|
||||
| by_reference.cpp:32:12:32:12 | s [a] | semmle.label | s [a] |
|
||||
| by_reference.cpp:32:15:32:15 | a | semmle.label | a |
|
||||
| by_reference.cpp:35:9:35:19 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:36:12:36:15 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:36:18:36:18 | a | semmle.label | a |
|
||||
| by_reference.cpp:39:9:39:21 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:40:18:40:28 | call to getDirectly | semmle.label | call to getDirectly |
|
||||
| by_reference.cpp:43:9:43:27 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:44:12:44:24 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
|
||||
| by_reference.cpp:44:26:44:29 | this [a] | semmle.label | this [a] |
|
||||
| by_reference.cpp:50:3:50:3 | ref arg s [a] | semmle.label | ref arg s [a] |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | semmle.label | s [a] |
|
||||
@@ -818,6 +1040,18 @@ nodes
|
||||
| by_reference.cpp:135:27:135:27 | a | semmle.label | a |
|
||||
| by_reference.cpp:136:8:136:13 | pouter [a] | semmle.label | pouter [a] |
|
||||
| by_reference.cpp:136:16:136:16 | a | semmle.label | a |
|
||||
| complex.cpp:9:7:9:7 | this [a_] | semmle.label | this [a_] |
|
||||
| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ |
|
||||
| complex.cpp:9:20:9:21 | this [a_] | semmle.label | this [a_] |
|
||||
| complex.cpp:10:7:10:7 | this [b_] | semmle.label | this [b_] |
|
||||
| complex.cpp:10:20:10:21 | b_ | semmle.label | b_ |
|
||||
| complex.cpp:10:20:10:21 | this [b_] | semmle.label | this [b_] |
|
||||
| complex.cpp:11:17:11:17 | a | semmle.label | a |
|
||||
| complex.cpp:11:22:11:23 | this [post update] [a_] | semmle.label | this [post update] [a_] |
|
||||
| complex.cpp:11:22:11:27 | ... = ... | semmle.label | ... = ... |
|
||||
| complex.cpp:12:17:12:17 | b | semmle.label | b |
|
||||
| complex.cpp:12:22:12:23 | this [post update] [b_] | semmle.label | this [post update] [b_] |
|
||||
| complex.cpp:12:22:12:27 | ... = ... | semmle.label | ... = ... |
|
||||
| complex.cpp:40:17:40:17 | b [inner, f, a_] | semmle.label | b [inner, f, a_] |
|
||||
| complex.cpp:40:17:40:17 | b [inner, f, b_] | semmle.label | b [inner, f, b_] |
|
||||
| complex.cpp:42:8:42:8 | b [inner, f, a_] | semmle.label | b [inner, f, a_] |
|
||||
@@ -874,6 +1108,18 @@ nodes
|
||||
| conflated.cpp:61:8:61:9 | ll [next, y] | semmle.label | ll [next, y] |
|
||||
| conflated.cpp:61:12:61:15 | next [y] | semmle.label | next [y] |
|
||||
| conflated.cpp:61:18:61:18 | y | semmle.label | y |
|
||||
| constructors.cpp:18:9:18:9 | this [a_] | semmle.label | this [a_] |
|
||||
| constructors.cpp:18:22:18:23 | a_ | semmle.label | a_ |
|
||||
| constructors.cpp:18:22:18:23 | this [a_] | semmle.label | this [a_] |
|
||||
| constructors.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] |
|
||||
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
|
||||
| constructors.cpp:19:22:19:23 | this [b_] | semmle.label | this [b_] |
|
||||
| constructors.cpp:23:13:23:13 | a | semmle.label | a |
|
||||
| constructors.cpp:23:20:23:20 | b | semmle.label | b |
|
||||
| constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | semmle.label | constructor init of field a_ [post-this] [a_] |
|
||||
| constructors.cpp:23:28:23:28 | a | semmle.label | a |
|
||||
| constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | semmle.label | constructor init of field b_ [post-this] [b_] |
|
||||
| constructors.cpp:23:35:23:35 | b | semmle.label | b |
|
||||
| constructors.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
|
||||
| constructors.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
|
||||
@@ -892,6 +1138,16 @@ nodes
|
||||
| constructors.cpp:43:9:43:9 | g [b_] | semmle.label | g [b_] |
|
||||
| constructors.cpp:46:9:46:9 | h [a_] | semmle.label | h [a_] |
|
||||
| constructors.cpp:46:9:46:9 | h [b_] | semmle.label | h [b_] |
|
||||
| qualifiers.cpp:9:21:9:25 | value | semmle.label | value |
|
||||
| qualifiers.cpp:9:30:9:33 | this [post update] [a] | semmle.label | this [post update] [a] |
|
||||
| qualifiers.cpp:9:30:9:44 | ... = ... | semmle.label | ... = ... |
|
||||
| qualifiers.cpp:12:40:12:44 | value | semmle.label | value |
|
||||
| qualifiers.cpp:12:49:12:53 | inner [post update] [a] | semmle.label | inner [post update] [a] |
|
||||
| qualifiers.cpp:12:49:12:64 | ... = ... | semmle.label | ... = ... |
|
||||
| qualifiers.cpp:13:29:13:33 | inner [a] | semmle.label | inner [a] |
|
||||
| qualifiers.cpp:13:42:13:46 | value | semmle.label | value |
|
||||
| qualifiers.cpp:13:51:13:55 | inner [post update] [a] | semmle.label | inner [post update] [a] |
|
||||
| qualifiers.cpp:13:51:13:65 | ... = ... | semmle.label | ... = ... |
|
||||
| qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] | semmle.label | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:22:5:22:38 | ... = ... | semmle.label | ... = ... |
|
||||
| qualifiers.cpp:22:11:22:18 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] |
|
||||
@@ -946,6 +1202,18 @@ nodes
|
||||
| realistic.cpp:61:32:61:34 | baz [userInput, bufferLen] | semmle.label | baz [userInput, bufferLen] |
|
||||
| realistic.cpp:61:37:61:45 | userInput [bufferLen] | semmle.label | userInput [bufferLen] |
|
||||
| realistic.cpp:61:47:61:55 | bufferLen | semmle.label | bufferLen |
|
||||
| simple.cpp:18:9:18:9 | this [a_] | semmle.label | this [a_] |
|
||||
| simple.cpp:18:22:18:23 | a_ | semmle.label | a_ |
|
||||
| simple.cpp:18:22:18:23 | this [a_] | semmle.label | this [a_] |
|
||||
| simple.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] |
|
||||
| simple.cpp:19:22:19:23 | b_ | semmle.label | b_ |
|
||||
| simple.cpp:19:22:19:23 | this [b_] | semmle.label | this [b_] |
|
||||
| simple.cpp:20:19:20:19 | a | semmle.label | a |
|
||||
| simple.cpp:20:24:20:25 | this [post update] [a_] | semmle.label | this [post update] [a_] |
|
||||
| simple.cpp:20:24:20:29 | ... = ... | semmle.label | ... = ... |
|
||||
| simple.cpp:21:19:21:19 | b | semmle.label | b |
|
||||
| simple.cpp:21:24:21:25 | this [post update] [b_] | semmle.label | this [post update] [b_] |
|
||||
| simple.cpp:21:24:21:29 | ... = ... | semmle.label | ... = ... |
|
||||
| simple.cpp:26:15:26:15 | f [a_] | semmle.label | f [a_] |
|
||||
| simple.cpp:26:15:26:15 | f [b_] | semmle.label | f [b_] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | semmle.label | f [a_] |
|
||||
@@ -969,6 +1237,10 @@ nodes
|
||||
| simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:67:10:67:11 | a2 [i] | semmle.label | a2 [i] |
|
||||
| simple.cpp:67:13:67:13 | i | semmle.label | i |
|
||||
| simple.cpp:78:9:78:15 | this [f2, f1] | semmle.label | this [f2, f1] |
|
||||
| simple.cpp:79:16:79:17 | f2 [f1] | semmle.label | f2 [f1] |
|
||||
| simple.cpp:79:16:79:17 | this [f2, f1] | semmle.label | this [f2, f1] |
|
||||
| simple.cpp:79:19:79:20 | f1 | semmle.label | f1 |
|
||||
| simple.cpp:83:9:83:10 | f2 [post update] [f1] | semmle.label | f2 [post update] [f1] |
|
||||
| simple.cpp:83:9:83:10 | this [post update] [f2, f1] | semmle.label | this [post update] [f2, f1] |
|
||||
| simple.cpp:83:9:83:28 | ... = ... | semmle.label | ... = ... |
|
||||
@@ -1008,6 +1280,65 @@ nodes
|
||||
| struct_init.c:43:5:43:7 | & ... [a] | semmle.label | & ... [a] |
|
||||
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | semmle.label | outer [pointerAB, a] |
|
||||
| struct_init.c:46:16:46:24 | pointerAB [a] | semmle.label | pointerAB [a] |
|
||||
subpaths
|
||||
| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:31:14:31:21 | call to B [c] |
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:31:14:31:21 | new [c] | A.cpp:48:12:48:18 | call to make [c] |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:55:5:55:5 | ref arg b [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:29:28:29 | c | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:29:28:29 | c | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:57:11:57:24 | call to B [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:91:14:91:15 | b2 [c] | A.cpp:64:10:64:15 | call to setOnB [c] |
|
||||
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | A.cpp:82:12:82:24 | ... ? ... : ... [c] | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
|
||||
| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | A.cpp:91:14:91:15 | b2 [c] | A.cpp:81:10:81:15 | call to setOnB [c] |
|
||||
| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:90:7:90:8 | ref arg b2 [c] |
|
||||
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:126:5:126:5 | ref arg b [c] |
|
||||
| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
|
||||
| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | this [post update] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
|
||||
| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] | A.cpp:184:7:184:10 | this [post update] [next, head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
|
||||
| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:7:184:10 | this [post update] [next, next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, head] |
|
||||
| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:10 | this [post update] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] |
|
||||
| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:7:46:10 | this [post update] [box1, elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
|
||||
| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:10 | this [post update] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] |
|
||||
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:7:46:10 | this [post update] [box1, elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:30:17:32 | box [elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:30:10:33 | elem | D.cpp:22:25:22:31 | call to getElem |
|
||||
| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this [post update] [elem] | D.cpp:37:8:37:10 | ref arg box [elem] |
|
||||
| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this [post update] [elem] | D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] |
|
||||
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | this [post update] [a] | by_reference.cpp:20:5:20:8 | ref arg this [a] |
|
||||
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:24:19:24:22 | ref arg this [a] |
|
||||
| by_reference.cpp:40:12:40:15 | this [a] | by_reference.cpp:35:9:35:19 | this [a] | by_reference.cpp:36:18:36:18 | a | by_reference.cpp:40:18:40:28 | call to getDirectly |
|
||||
| by_reference.cpp:44:26:44:29 | this [a] | by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:15:32:15 | a | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | this [post update] [a] | by_reference.cpp:50:3:50:3 | ref arg s [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:35:9:35:19 | this [a] | by_reference.cpp:36:18:36:18 | a | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | ref arg this [a] | by_reference.cpp:56:3:56:3 | ref arg s [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:39:9:39:21 | this [a] | by_reference.cpp:40:18:40:28 | call to getDirectly | by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | ref arg this [a] | by_reference.cpp:62:3:62:3 | ref arg s [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:43:9:43:27 | this [a] | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:15:32:15 | a | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
|
||||
| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | a_ | complex.cpp:42:18:42:18 | call to a |
|
||||
| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | b_ | complex.cpp:43:18:43:18 | call to b |
|
||||
| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:53:12:53:12 | ref arg f [a_] |
|
||||
| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:54:12:54:12 | ref arg f [b_] |
|
||||
| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:55:12:55:12 | ref arg f [a_] |
|
||||
| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:56:12:56:12 | ref arg f [b_] |
|
||||
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:22:18:23 | a_ | constructors.cpp:28:12:28:12 | call to a |
|
||||
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | b_ | constructors.cpp:29:12:29:12 | call to b |
|
||||
| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | constructors.cpp:34:11:34:26 | call to Foo [a_] |
|
||||
| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | constructors.cpp:35:11:35:26 | call to Foo [b_] |
|
||||
| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | constructors.cpp:36:11:36:37 | call to Foo [a_] |
|
||||
| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | constructors.cpp:36:11:36:37 | call to Foo [b_] |
|
||||
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:33 | this [post update] [a] | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:53 | inner [post update] [a] | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | inner [a] | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
|
||||
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:18:9:18:9 | this [a_] | simple.cpp:18:22:18:23 | a_ | simple.cpp:28:12:28:12 | call to a |
|
||||
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | b_ | simple.cpp:29:12:29:12 | call to b |
|
||||
| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:39:5:39:5 | ref arg f [a_] |
|
||||
| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:40:5:40:5 | ref arg g [b_] |
|
||||
| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:41:5:41:5 | ref arg h [a_] |
|
||||
| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:42:5:42:5 | ref arg h [b_] |
|
||||
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:79:19:79:20 | f1 | simple.cpp:84:14:84:20 | call to getf2f1 |
|
||||
#select
|
||||
| A.cpp:43:10:43:12 | & ... | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... | & ... flows from $@ | A.cpp:41:15:41:21 | new | new |
|
||||
| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new |
|
||||
|
||||
@@ -594,6 +594,15 @@
|
||||
| test.c:659:9:659:9 | u | 0 |
|
||||
| test.c:664:12:664:12 | s | -2147483648 |
|
||||
| test.c:665:7:665:8 | s2 | -4 |
|
||||
| test.c:670:7:670:7 | x | -2147483648 |
|
||||
| test.c:671:9:671:9 | y | -2147483648 |
|
||||
| test.c:675:7:675:7 | y | -2147483648 |
|
||||
| test.c:684:7:684:7 | x | -2147483648 |
|
||||
| test.c:689:7:689:7 | x | -2147483648 |
|
||||
| test.c:696:8:696:8 | x | 2147483647 |
|
||||
| test.c:696:12:696:12 | y | 256 |
|
||||
| test.c:697:9:697:9 | x | 2147483647 |
|
||||
| test.c:698:9:698:9 | y | 256 |
|
||||
| test.cpp:10:7:10:7 | b | -2147483648 |
|
||||
| test.cpp:11:5:11:5 | x | -2147483648 |
|
||||
| test.cpp:13:10:13:10 | x | -2147483648 |
|
||||
@@ -647,16 +656,18 @@
|
||||
| test.cpp:97:10:97:10 | i | -2147483648 |
|
||||
| test.cpp:97:22:97:22 | i | -2147483648 |
|
||||
| test.cpp:98:5:98:5 | i | -2147483648 |
|
||||
| test.cpp:105:7:105:7 | n | -32768 |
|
||||
| test.cpp:108:7:108:7 | n | 0 |
|
||||
| test.cpp:109:5:109:5 | n | 1 |
|
||||
| test.cpp:111:5:111:5 | n | 0 |
|
||||
| test.cpp:114:8:114:8 | n | 0 |
|
||||
| test.cpp:115:5:115:5 | n | 0 |
|
||||
| test.cpp:117:5:117:5 | n | 1 |
|
||||
| test.cpp:120:3:120:3 | n | 0 |
|
||||
| test.cpp:120:8:120:8 | n | 1 |
|
||||
| test.cpp:120:12:120:12 | n | 0 |
|
||||
| test.cpp:121:4:121:4 | n | 0 |
|
||||
| test.cpp:121:8:121:8 | n | 0 |
|
||||
| test.cpp:121:12:121:12 | n | 1 |
|
||||
| test.cpp:98:9:98:9 | i | -2147483648 |
|
||||
| test.cpp:99:5:99:5 | i | -2147483648 |
|
||||
| test.cpp:106:7:106:7 | n | -32768 |
|
||||
| test.cpp:109:7:109:7 | n | 0 |
|
||||
| test.cpp:110:5:110:5 | n | 1 |
|
||||
| test.cpp:112:5:112:5 | n | 0 |
|
||||
| test.cpp:115:8:115:8 | n | 0 |
|
||||
| test.cpp:116:5:116:5 | n | 0 |
|
||||
| test.cpp:118:5:118:5 | n | 1 |
|
||||
| test.cpp:121:3:121:3 | n | 0 |
|
||||
| test.cpp:121:8:121:8 | n | 1 |
|
||||
| test.cpp:121:12:121:12 | n | 0 |
|
||||
| test.cpp:122:4:122:4 | n | 0 |
|
||||
| test.cpp:122:8:122:8 | n | 0 |
|
||||
| test.cpp:122:12:122:12 | n | 1 |
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
| test.c:394:20:394:36 | ... ? ... : ... | 0.0 | 0.0 | 100.0 |
|
||||
| test.c:606:5:606:14 | ... ? ... : ... | 0.0 | 1.0 | 0.0 |
|
||||
| test.c:607:5:607:14 | ... ? ... : ... | 0.0 | 0.0 | 1.0 |
|
||||
| test.cpp:120:3:120:12 | ... ? ... : ... | 0.0 | 1.0 | 0.0 |
|
||||
| test.cpp:121:3:121:12 | ... ? ... : ... | 0.0 | 0.0 | 1.0 |
|
||||
| test.cpp:121:3:121:12 | ... ? ... : ... | 0.0 | 1.0 | 0.0 |
|
||||
| test.cpp:122:3:122:12 | ... ? ... : ... | 0.0 | 0.0 | 1.0 |
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
| test.c:394:20:394:36 | ... ? ... : ... | 100.0 | 99.0 | 100.0 |
|
||||
| test.c:606:5:606:14 | ... ? ... : ... | 32767.0 | 32767.0 | 0.0 |
|
||||
| test.c:607:5:607:14 | ... ? ... : ... | 32767.0 | 0.0 | 32767.0 |
|
||||
| test.cpp:120:3:120:12 | ... ? ... : ... | 32767.0 | 32767.0 | 0.0 |
|
||||
| test.cpp:121:3:121:12 | ... ? ... : ... | 32767.0 | 0.0 | 32767.0 |
|
||||
| test.cpp:121:3:121:12 | ... ? ... : ... | 32767.0 | 32767.0 | 0.0 |
|
||||
| test.cpp:122:3:122:12 | ... ? ... : ... | 32767.0 | 0.0 | 32767.0 |
|
||||
|
||||
@@ -664,3 +664,37 @@ void test_mod(int s) {
|
||||
int s2 = s % 5;
|
||||
out(s2); // -4 .. 4
|
||||
}
|
||||
|
||||
void exit(int);
|
||||
void guard_with_exit(int x, int y) {
|
||||
if (x) {
|
||||
if (y != 0) {
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
out(y); // ..
|
||||
|
||||
// This test ensures that we correctly identify
|
||||
// that the upper bound for y is max_int when calling `out(y)`.
|
||||
// The RangeSsa will place guardPhy on `out(y)`, and consequently there is no
|
||||
// frontier phi node at out(y).
|
||||
}
|
||||
|
||||
void test(int x) {
|
||||
if (x >= 10) {
|
||||
return;
|
||||
}
|
||||
// The basic below has two predecessors.
|
||||
label:
|
||||
out(x);
|
||||
goto label;
|
||||
}
|
||||
|
||||
void test_overflow() {
|
||||
const int x = 2147483647; // 2^31-1
|
||||
const int y = 256;
|
||||
if ((x + y) <= 512) {
|
||||
out(x);
|
||||
out(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ int ref_to_number(int &i, const int &ci, int &aliased) {
|
||||
return alias;
|
||||
|
||||
for (; i <= 12345; i++) { // test that widening works for references
|
||||
i = i;
|
||||
i;
|
||||
}
|
||||
|
||||
|
||||
@@ -584,9 +584,9 @@
|
||||
| test.c:639:9:639:10 | ss | 2 |
|
||||
| test.c:645:8:645:8 | s | 2147483647 |
|
||||
| test.c:645:15:645:15 | s | 127 |
|
||||
| test.c:645:23:645:23 | s | 15 |
|
||||
| test.c:646:18:646:18 | s | 15 |
|
||||
| test.c:646:22:646:22 | s | 15 |
|
||||
| test.c:645:23:645:23 | s | 9 |
|
||||
| test.c:646:18:646:18 | s | 9 |
|
||||
| test.c:646:22:646:22 | s | 9 |
|
||||
| test.c:647:9:647:14 | result | 127 |
|
||||
| test.c:653:7:653:7 | i | 0 |
|
||||
| test.c:654:9:654:9 | i | 2147483647 |
|
||||
@@ -594,6 +594,15 @@
|
||||
| test.c:659:9:659:9 | u | 4294967295 |
|
||||
| test.c:664:12:664:12 | s | 2147483647 |
|
||||
| test.c:665:7:665:8 | s2 | 4 |
|
||||
| test.c:670:7:670:7 | x | 2147483647 |
|
||||
| test.c:671:9:671:9 | y | 2147483647 |
|
||||
| test.c:675:7:675:7 | y | 2147483647 |
|
||||
| test.c:684:7:684:7 | x | 2147483647 |
|
||||
| test.c:689:7:689:7 | x | 15 |
|
||||
| test.c:696:8:696:8 | x | 2147483647 |
|
||||
| test.c:696:12:696:12 | y | 256 |
|
||||
| test.c:697:9:697:9 | x | 2147483647 |
|
||||
| test.c:698:9:698:9 | y | 256 |
|
||||
| test.cpp:10:7:10:7 | b | 2147483647 |
|
||||
| test.cpp:11:5:11:5 | x | 2147483647 |
|
||||
| test.cpp:13:10:13:10 | x | 2147483647 |
|
||||
@@ -646,17 +655,19 @@
|
||||
| test.cpp:95:12:95:16 | alias | 2147483647 |
|
||||
| test.cpp:97:10:97:10 | i | 65535 |
|
||||
| test.cpp:97:22:97:22 | i | 32767 |
|
||||
| test.cpp:98:5:98:5 | i | 32767 |
|
||||
| test.cpp:105:7:105:7 | n | 32767 |
|
||||
| test.cpp:108:7:108:7 | n | 32767 |
|
||||
| test.cpp:109:5:109:5 | n | 32767 |
|
||||
| test.cpp:111:5:111:5 | n | 0 |
|
||||
| test.cpp:114:8:114:8 | n | 32767 |
|
||||
| test.cpp:115:5:115:5 | n | 0 |
|
||||
| test.cpp:117:5:117:5 | n | 32767 |
|
||||
| test.cpp:120:3:120:3 | n | 32767 |
|
||||
| test.cpp:120:8:120:8 | n | 32767 |
|
||||
| test.cpp:120:12:120:12 | n | 0 |
|
||||
| test.cpp:121:4:121:4 | n | 32767 |
|
||||
| test.cpp:121:8:121:8 | n | 0 |
|
||||
| test.cpp:121:12:121:12 | n | 32767 |
|
||||
| test.cpp:98:5:98:5 | i | 2147483647 |
|
||||
| test.cpp:98:9:98:9 | i | 12345 |
|
||||
| test.cpp:99:5:99:5 | i | 32767 |
|
||||
| test.cpp:106:7:106:7 | n | 32767 |
|
||||
| test.cpp:109:7:109:7 | n | 32767 |
|
||||
| test.cpp:110:5:110:5 | n | 32767 |
|
||||
| test.cpp:112:5:112:5 | n | 0 |
|
||||
| test.cpp:115:8:115:8 | n | 32767 |
|
||||
| test.cpp:116:5:116:5 | n | 0 |
|
||||
| test.cpp:118:5:118:5 | n | 32767 |
|
||||
| test.cpp:121:3:121:3 | n | 32767 |
|
||||
| test.cpp:121:8:121:8 | n | 32767 |
|
||||
| test.cpp:121:12:121:12 | n | 0 |
|
||||
| test.cpp:122:4:122:4 | n | 32767 |
|
||||
| test.cpp:122:8:122:8 | n | 0 |
|
||||
| test.cpp:122:12:122:12 | n | 32767 |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql-cpp-tests
|
||||
version: 0.0.0
|
||||
name: codeql/cpp-tests
|
||||
version: 0.0.2
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
codeql/cpp-queries: "*"
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
| test2.c:33:26:33:27 | 46 | Potential buffer-overflow: 'buffer' has size 40 not 46. |
|
||||
| test2.c:34:22:34:23 | 47 | Potential buffer-overflow: 'buffer' has size 40 not 47. |
|
||||
| test2.c:35:23:35:24 | 48 | Potential buffer-overflow: 'buffer' has size 40 not 48. |
|
||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' is accessed here. |
|
||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' is accessed here. |
|
||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' is accessed here. |
|
||||
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' is accessed here. |
|
||||
| test.c:14:9:14:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[5]' may be accessed here. |
|
||||
| test.c:15:9:15:13 | access to array | Potential buffer-overflow: 'xs' has size 5 but 'xs[6]' may be accessed here. |
|
||||
| test.c:20:9:20:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[5]' may be accessed here. |
|
||||
| test.c:21:9:21:18 | access to array | Potential buffer-overflow: 'ys' has size 5 but 'ys[6]' may be accessed here. |
|
||||
| test.cpp:19:3:19:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer1' has 3 elements. |
|
||||
| test.cpp:20:3:20:12 | access to array | Potential buffer-overflow: counter 'i' <= 3 but 'buffer2' has 3 elements. |
|
||||
| test.cpp:24:27:24:27 | 4 | Potential buffer-overflow: 'buffer1' has size 3 not 4. |
|
||||
|
||||
@@ -27,3 +27,47 @@ void f(void) {
|
||||
c = stru.zs[6]; // GOOD (zs is variable size)
|
||||
}
|
||||
|
||||
void* malloc(long unsigned int);
|
||||
void test_buffer_sentinal() {
|
||||
struct { char len; char buf[1]; } *b = malloc(10); // len(buf.buffer) effectively 8
|
||||
b->buf[0] = 0; // GOOD
|
||||
b->buf[7] = 0; // GOOD
|
||||
b->buf[8] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
union u {
|
||||
unsigned long value;
|
||||
char ptr[1];
|
||||
};
|
||||
|
||||
void union_test() {
|
||||
union u u;
|
||||
u.ptr[0] = 0; // GOOD
|
||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_struct_union() {
|
||||
struct { union u u; } v;
|
||||
v.u.ptr[0] = 0; // GOOD
|
||||
v.u.ptr[sizeof(union u)-1] = 0; // GOOD
|
||||
v.u.ptr[sizeof(union u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void union_test2() {
|
||||
union { char ptr[1]; unsigned long value; } u;
|
||||
u.ptr[0] = 0; // GOOD
|
||||
u.ptr[sizeof(u)-1] = 0; // GOOD
|
||||
u.ptr[sizeof(u)] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char len;
|
||||
char buf[1];
|
||||
} var_buf;
|
||||
|
||||
void test_alloc() {
|
||||
// Special case of taking sizeof without any addition or multiplications
|
||||
var_buf *b = malloc(sizeof(var_buf));
|
||||
b->buf[1] = 0; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
@@ -46,3 +46,13 @@ void f2(char *src)
|
||||
ptr = &(buffer[1]);
|
||||
memcpy(ptr, src, 100); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void f3() {
|
||||
int i;
|
||||
char buffer[5];
|
||||
for (i=0; i<10; i++) {
|
||||
if (i < 5) {
|
||||
buffer[i] = 0; // GOOD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ int twoReasons(int a, int b) {
|
||||
if (a <= 0 && b > 5) {
|
||||
return a < b;
|
||||
}
|
||||
if (a <= 100 && b > 105) {
|
||||
if (a <= 100 && b > 105) { // BUG [Not detected - this clause is always false]
|
||||
return a > b;
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -34,6 +34,7 @@ nodes
|
||||
| test.cpp:88:21:88:22 | d2 | semmle.label | d2 |
|
||||
| test.cpp:95:21:95:21 | d | semmle.label | d |
|
||||
| test.cpp:96:21:96:23 | dss | semmle.label | dss |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:57:19:57:19 | d | here |
|
||||
| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | Pointer arithmetic here may be done with the wrong type because of the cast $@. | test.cpp:74:19:74:21 | dss | here |
|
||||
|
||||
@@ -11,4 +11,17 @@
|
||||
| test.cpp:130:14:130:19 | buffer | Variable $@ may not be null terminated. | test.cpp:127:7:127:12 | buffer | buffer |
|
||||
| test.cpp:139:10:139:15 | buffer | Variable $@ may not be null terminated. | test.cpp:136:8:136:13 | buffer | buffer |
|
||||
| test.cpp:147:14:147:19 | buffer | Variable $@ may not be null terminated. | test.cpp:143:8:143:13 | buffer | buffer |
|
||||
| test.cpp:170:10:170:15 | buffer | Variable $@ may not be null terminated. | test.cpp:166:8:166:13 | buffer | buffer |
|
||||
| test.cpp:182:10:182:15 | buffer | Variable $@ may not be null terminated. | test.cpp:178:8:178:13 | buffer | buffer |
|
||||
| test.cpp:234:10:234:15 | buffer | Variable $@ may not be null terminated. | test.cpp:232:8:232:13 | buffer | buffer |
|
||||
| test.cpp:262:10:262:15 | buffer | Variable $@ may not be null terminated. | test.cpp:259:8:259:13 | buffer | buffer |
|
||||
| test.cpp:283:10:283:15 | buffer | Variable $@ may not be null terminated. | test.cpp:280:8:280:13 | buffer | buffer |
|
||||
| test.cpp:300:10:300:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:295:8:295:14 | buffer2 | buffer2 |
|
||||
| test.cpp:312:10:312:15 | buffer | Variable $@ may not be null terminated. | test.cpp:308:8:308:13 | buffer | buffer |
|
||||
| test.cpp:327:18:327:23 | buffer | Variable $@ may not be null terminated. | test.cpp:326:8:326:13 | buffer | buffer |
|
||||
| test.cpp:346:11:346:16 | buffer | Variable $@ may not be null terminated. | test.cpp:341:8:341:13 | buffer | buffer |
|
||||
| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer |
|
||||
| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 |
|
||||
| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer |
|
||||
| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer |
|
||||
| test.cpp:444:10:444:15 | buffer | Variable $@ may not be null terminated. | test.cpp:442:8:442:13 | buffer | buffer |
|
||||
| test.cpp:450:16:450:21 | buffer | Variable $@ may not be null terminated. | test.cpp:448:8:448:13 | buffer | buffer |
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
| test.cpp:410:10:410:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:409:18:409:23 | buffer | User-provided value |
|
||||
| test.cpp:425:10:425:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:424:9:424:14 | buffer | User-provided value |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-170/ImproperNullTerminationTainted.ql
|
||||
@@ -1,16 +1,16 @@
|
||||
|
||||
typedef unsigned int size_t;
|
||||
typedef signed int ssize_t;
|
||||
typedef struct {} FILE;
|
||||
|
||||
size_t strlen(const char *s);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
char *strcat(char *s1, const char *s2);
|
||||
char *strdup(const char *s1);
|
||||
|
||||
void *malloc(size_t size);
|
||||
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memcpy(void *s1, const void *s2, size_t n);
|
||||
|
||||
void read(int src, void *out, int num);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
ssize_t readlink(const char *path, char *buffer, size_t buffer_size);
|
||||
ssize_t readlinkat(int fd, const char *path, char *buffer, size_t buffer_size);
|
||||
|
||||
@@ -154,6 +154,18 @@ void test_readlink(int fd, const char *path, size_t sz)
|
||||
strdup(buffer); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
ssize_t len;
|
||||
|
||||
len = readlink(path, buffer, sizeof(buffer));
|
||||
if (len >= 0)
|
||||
{
|
||||
buffer[len - 1] = 0;
|
||||
strdup(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
@@ -209,3 +221,248 @@ void test_readlink(int fd, const char *path, size_t sz)
|
||||
strdup(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void doNothing(char *data) { };
|
||||
void doNothing2(const char *data);
|
||||
void clearBuffer(char *data, size_t size);
|
||||
|
||||
void test_strcat()
|
||||
{
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strcat(buffer, "content"); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
buffer[0] = 0;
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
buffer[10] = 0;
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
buffer[0] = '\0';
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
buffer[0] = 'a';
|
||||
strcat(buffer, "content"); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
*buffer = 0;
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strcpy(buffer, "con");
|
||||
strcat(buffer, "tent"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
doNothing(buffer);
|
||||
strcat(buffer, "content"); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
doNothing2(buffer);
|
||||
strcat(buffer, "content"); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
{
|
||||
char buffer1[1024];
|
||||
char buffer2[1024];
|
||||
char *buffer_ptr = buffer1;
|
||||
|
||||
*buffer_ptr = 0;
|
||||
strcat(buffer1, "content"); // GOOD
|
||||
strcat(buffer2, "content"); // BAD
|
||||
strcat(buffer_ptr, "content"); // GOOD
|
||||
|
||||
buffer_ptr = buffer2;
|
||||
strcat(buffer_ptr, "content"); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
char *buffer_ptr = buffer;
|
||||
|
||||
*buffer_ptr = 'a';
|
||||
strcat(buffer, "content"); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
clearBuffer(buffer, 1024);
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void test_strlen(bool cond1, bool cond2)
|
||||
{
|
||||
{
|
||||
char buffer[1024];
|
||||
int i = strlen(buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024] = {0};
|
||||
int i = strlen(buffer); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char *ptr = "content";
|
||||
int i = strlen(ptr); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
if (cond1)
|
||||
buffer[0] = 0;
|
||||
if (cond1)
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
if (cond1)
|
||||
buffer[0] = 0;
|
||||
if (cond2)
|
||||
strlen(buffer); // BAD
|
||||
}
|
||||
}
|
||||
|
||||
void test_strcpy()
|
||||
{
|
||||
{
|
||||
char buffer1[1024];
|
||||
char buffer2[1024];
|
||||
|
||||
strcpy(buffer1, buffer2); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer1[1024];
|
||||
char buffer2[1024];
|
||||
|
||||
strcpy(buffer2, "content"); // GOOD
|
||||
strcpy(buffer1, buffer2); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void strcatWrapper(char *data, const char *with)
|
||||
{
|
||||
strcat(data, with);
|
||||
}
|
||||
|
||||
void strcatWrapper2(char *data, const char *with)
|
||||
{
|
||||
strcatWrapper(data, with);
|
||||
}
|
||||
|
||||
void test_wrappers()
|
||||
{
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strcatWrapper(buffer, "content"); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
strcatWrapper2(buffer, "content"); // BAD
|
||||
}
|
||||
}
|
||||
|
||||
void test_read_fread(int read_src, FILE *s)
|
||||
{
|
||||
const size_t buffer_size = 80;
|
||||
|
||||
{
|
||||
char buffer[buffer_size];
|
||||
|
||||
read(read_src, buffer, buffer_size * sizeof(char));
|
||||
strlen(buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[buffer_size];
|
||||
|
||||
read(read_src, buffer, buffer_size * sizeof(char));
|
||||
buffer[buffer_size - 1] = 0;
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[buffer_size];
|
||||
|
||||
fread(buffer, sizeof(char), buffer_size, s);
|
||||
strlen(buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[buffer_size];
|
||||
|
||||
fread(buffer, sizeof(char), buffer_size, s);
|
||||
buffer[buffer_size - 1] = 0;
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
void test_printf(char *str)
|
||||
{
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
printf(buffer, ""); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
printf("%s", buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char *copied_str = (char *)malloc(len);
|
||||
|
||||
memcpy(copied_str, str, len);
|
||||
printf("%s", copied_str); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
char *copied_str = (char *)malloc(len + 1);
|
||||
|
||||
memcpy(copied_str, str, len + 1);
|
||||
printf("%s", copied_str); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* This test case is closely based on CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp
|
||||
* from the SAMATE Juliet test suite.
|
||||
*/
|
||||
|
||||
#define NULL (0)
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef size_t time_t;
|
||||
time_t time(time_t *timer);
|
||||
|
||||
typedef struct {} FILE;
|
||||
extern FILE *stdin;
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
int fclose(FILE *stream);
|
||||
#define FILENAME_MAX (4096)
|
||||
|
||||
typedef unsigned long size_t;
|
||||
size_t strlen(const char *s);
|
||||
char *strcat(char *s1, const char *s2);
|
||||
char *fgets(char *s, int n, FILE *stream);
|
||||
|
||||
int globalReturnsTrue()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int globalReturnsFalse()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void printLine(const char *str);
|
||||
|
||||
#define BASEPATH "c:\\temp\\"
|
||||
#define FOPEN fopen
|
||||
|
||||
namespace CWE23_Relative_Path_Traversal__char_console_fopen_11
|
||||
{
|
||||
|
||||
void bad()
|
||||
{
|
||||
char * data;
|
||||
char dataBuffer[FILENAME_MAX] = BASEPATH;
|
||||
data = dataBuffer;
|
||||
if(globalReturnsTrue())
|
||||
{
|
||||
{
|
||||
/* Read input from the console */
|
||||
size_t dataLen = strlen(data);
|
||||
/* if there is room in data, read into it from the console */
|
||||
if (FILENAME_MAX-dataLen > 1)
|
||||
{
|
||||
/* POTENTIAL FLAW: Read data from the console */
|
||||
if (fgets(data+dataLen, (int)(FILENAME_MAX-dataLen), stdin) != NULL)
|
||||
{
|
||||
/* The next few lines remove the carriage return from the string that is
|
||||
* inserted by fgets() */
|
||||
dataLen = strlen(data);
|
||||
if (dataLen > 0 && data[dataLen-1] == '\n')
|
||||
{
|
||||
data[dataLen-1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printLine("fgets() failed");
|
||||
/* Restore NUL terminator if fgets fails */
|
||||
data[dataLen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
|
||||
pFile = FOPEN(data, "wb+");
|
||||
if (pFile != NULL)
|
||||
{
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* goodG2B1() - use goodsource and badsink by changing the globalReturnsTrue() to globalReturnsFalse() */
|
||||
static void goodG2B1()
|
||||
{
|
||||
char * data;
|
||||
char dataBuffer[FILENAME_MAX] = BASEPATH;
|
||||
data = dataBuffer;
|
||||
if(globalReturnsFalse())
|
||||
{
|
||||
/* INCIDENTAL: CWE 561 Dead Code, the code below will never run */
|
||||
printLine("Benign, fixed string");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIX: Use a fixed file name */
|
||||
strcat(data, "file.txt");
|
||||
}
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
|
||||
pFile = FOPEN(data, "wb+");
|
||||
if (pFile != NULL)
|
||||
{
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* goodG2B2() - use goodsource and badsink by reversing the blocks in the if statement */
|
||||
static void goodG2B2()
|
||||
{
|
||||
char * data;
|
||||
char dataBuffer[FILENAME_MAX] = BASEPATH;
|
||||
data = dataBuffer;
|
||||
if(globalReturnsTrue())
|
||||
{
|
||||
/* FIX: Use a fixed file name */
|
||||
strcat(data, "file.txt");
|
||||
}
|
||||
{
|
||||
FILE *pFile = NULL;
|
||||
/* POTENTIAL FLAW: Possibly opening a file without validating the file name or path */
|
||||
pFile = FOPEN(data, "wb+");
|
||||
if (pFile != NULL)
|
||||
{
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
edges
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | semmle.label | ... + ... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | semmle.label | fgets output argument |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection |
|
||||
#select
|
||||
| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | This argument to a file access function is derived from $@ and then passed to fopen(filename) | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | user input (fgets) |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-022/TaintedPath.ql
|
||||
@@ -5,6 +5,7 @@ edges
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName |
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection |
|
||||
| test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.c:9:23:9:26 | argv | semmle.label | argv |
|
||||
| test.c:9:23:9:26 | argv | semmle.label | argv |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| tests.cpp:53:16:53:19 | data | This argument to an OS command is derived from $@ and then passed to system(string) | tests.cpp:33:34:33:39 | call to getenv | user input (getenv) |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-078/ExecTainted.ql
|
||||
@@ -0,0 +1,58 @@
|
||||
//semmle-extractor-options: --edg --target --edg win64
|
||||
|
||||
// A selection of tests from the SAMATE Juliet framework for rule CWE-78.
|
||||
|
||||
// library types, functions etc
|
||||
#define NULL (0)
|
||||
typedef unsigned long size_t;
|
||||
size_t strlen(const char *s);
|
||||
char *strncat(char *s1, const char *s2, size_t n);
|
||||
char *getenv(const char *name);
|
||||
int system(const char *string);
|
||||
void exit(int status);
|
||||
|
||||
#define FULL_COMMAND "dir "
|
||||
#define ENV_VARIABLE "ADD"
|
||||
#define GETENV getenv
|
||||
#define SYSTEM system
|
||||
|
||||
void printLine(const char *str);
|
||||
|
||||
// ----------
|
||||
|
||||
/* The static variable below is used to drive control flow in the source function */
|
||||
static int badStatic = 0;
|
||||
|
||||
static char * badSource(char * data)
|
||||
{
|
||||
if(badStatic)
|
||||
{
|
||||
{
|
||||
/* Append input from an environment variable to data */
|
||||
size_t dataLen = strlen(data);
|
||||
char * environment = GETENV(ENV_VARIABLE);
|
||||
/* If there is data in the environment variable */
|
||||
if (environment != NULL)
|
||||
{
|
||||
/* POTENTIAL FLAW: Read data from an environment variable */
|
||||
strncat(data+dataLen, environment, 100-dataLen-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
void CWE78_OS_Command_Injection__char_environment_system_21_bad()
|
||||
{
|
||||
char * data;
|
||||
char data_buf[100] = FULL_COMMAND;
|
||||
data = data_buf;
|
||||
badStatic = 1; /* true */
|
||||
data = badSource(data);
|
||||
/* POTENTIAL FLAW: Execute command in data possibly leading to command injection [NOT DETECTED] */
|
||||
if (SYSTEM(data) != 0)
|
||||
{
|
||||
printLine("command execution failed!");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ edges
|
||||
| search.c:55:17:55:25 | raw_query indirection | search.c:14:24:14:28 | *query |
|
||||
| search.c:57:5:57:15 | raw_query | search.c:22:24:22:28 | query |
|
||||
| search.c:57:17:57:25 | raw_query indirection | search.c:22:24:22:28 | *query |
|
||||
subpaths
|
||||
nodes
|
||||
| search.c:14:24:14:28 | *query | semmle.label | *query |
|
||||
| search.c:14:24:14:28 | query | semmle.label | query |
|
||||
|
||||
@@ -5,6 +5,15 @@ edges
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 |
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection |
|
||||
| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection |
|
||||
| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.c:15:20:15:23 | argv | semmle.label | argv |
|
||||
| test.c:15:20:15:23 | argv | semmle.label | argv |
|
||||
@@ -13,5 +22,15 @@ nodes
|
||||
| test.c:21:18:21:23 | query1 | semmle.label | query1 |
|
||||
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection |
|
||||
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
|
||||
| test.cpp:43:27:43:30 | argv | semmle.label | argv |
|
||||
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array | semmle.label | access to array |
|
||||
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
|
||||
| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection |
|
||||
#select
|
||||
| test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg) | test.c:15:20:15:23 | argv | user input (argv) |
|
||||
| test.cpp:43:27:43:33 | access to array | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)) | test.cpp:43:27:43:30 | argv | user input (argv) |
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
int sprintf(char* str, const char* format, ...);
|
||||
|
||||
namespace std
|
||||
{
|
||||
template<class charT> struct char_traits;
|
||||
|
||||
template <class T> class allocator {
|
||||
public:
|
||||
allocator() throw();
|
||||
};
|
||||
|
||||
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> >
|
||||
class basic_string {
|
||||
public:
|
||||
explicit basic_string(const Allocator& a = Allocator());
|
||||
basic_string(const charT* s, const Allocator& a = Allocator());
|
||||
|
||||
const charT* c_str() const;
|
||||
};
|
||||
|
||||
typedef basic_string<char> string;
|
||||
}
|
||||
|
||||
namespace pqxx {
|
||||
struct connection {};
|
||||
|
||||
struct row {};
|
||||
struct result {};
|
||||
|
||||
struct work {
|
||||
work(connection&);
|
||||
|
||||
row exec1(const char*);
|
||||
result exec(const std::string&);
|
||||
std::string quote(const char*);
|
||||
};
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
pqxx::connection c;
|
||||
pqxx::work w(c);
|
||||
|
||||
pqxx::row r = w.exec1(argv[1]); // BAD
|
||||
|
||||
pqxx::result r2 = w.exec(w.quote(argv[1])); // GOOD
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
edges
|
||||
| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | (LPCSTR)... |
|
||||
| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | data indirection |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | (LPCSTR)... |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data |
|
||||
| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:17:73:22 | data |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection |
|
||||
| test.cpp:73:17:73:22 | data | test.cpp:37:73:37:76 | data |
|
||||
| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | *data |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:37:73:37:76 | *data | semmle.label | *data |
|
||||
| test.cpp:37:73:37:76 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
|
||||
| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... |
|
||||
| test.cpp:43:32:43:35 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | data | semmle.label | data |
|
||||
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv |
|
||||
| test.cpp:73:17:73:22 | data | semmle.label | data |
|
||||
| test.cpp:73:24:73:27 | data indirection | semmle.label | data indirection |
|
||||
#select
|
||||
| test.cpp:43:32:43:35 | data | test.cpp:64:30:64:35 | call to getenv | test.cpp:43:32:43:35 | data | The value of this argument may come from $@ and is being passed to LoadLibraryA | test.cpp:64:30:64:35 | call to getenv | call to getenv |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-114/UncontrolledProcessOperation.ql
|
||||
@@ -0,0 +1,132 @@
|
||||
// Some SAMATE Juliet test cases for CWE-114.
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef unsigned int BOOL;
|
||||
typedef const char *LPCSTR;
|
||||
typedef void *HMODULE;
|
||||
#define NULL (0)
|
||||
|
||||
size_t strlen(const char *s);
|
||||
char *strncat(char *s1, const char *s2, size_t n);
|
||||
|
||||
HMODULE LoadLibraryA(LPCSTR libname);
|
||||
BOOL FreeLibrary(HMODULE hModule);
|
||||
|
||||
char *getenv(const char *name);
|
||||
|
||||
#define GETENV getenv
|
||||
#define ENV_VARIABLE "ADD"
|
||||
|
||||
void printLine(const char *msg);
|
||||
|
||||
// --- CWE114_Process_Control__w32_char_environment_82 ---
|
||||
|
||||
class CWE114_Process_Control__w32_char_environment_82_base
|
||||
{
|
||||
public:
|
||||
/* pure virtual function */
|
||||
virtual void action(char * data) = 0;
|
||||
};
|
||||
|
||||
class CWE114_Process_Control__w32_char_environment_82_bad : public CWE114_Process_Control__w32_char_environment_82_base
|
||||
{
|
||||
public:
|
||||
void action(char * data);
|
||||
};
|
||||
|
||||
void CWE114_Process_Control__w32_char_environment_82_bad::action(char * data)
|
||||
{
|
||||
{
|
||||
HMODULE hModule;
|
||||
/* POTENTIAL FLAW: If the path to the library is not specified, an attacker may be able to
|
||||
* replace his own file with the intended library */
|
||||
hModule = LoadLibraryA(data);
|
||||
if (hModule != NULL)
|
||||
{
|
||||
FreeLibrary(hModule);
|
||||
printLine("Library loaded and freed successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
printLine("Unable to load library");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bad()
|
||||
{
|
||||
char * data;
|
||||
char dataBuffer[100] = "";
|
||||
data = dataBuffer;
|
||||
{
|
||||
/* Append input from an environment variable to data */
|
||||
size_t dataLen = strlen(data);
|
||||
char * environment = GETENV(ENV_VARIABLE);
|
||||
/* If there is data in the environment variable */
|
||||
if (environment != NULL)
|
||||
{
|
||||
/* POTENTIAL FLAW: Read data from an environment variable */
|
||||
strncat(data+dataLen, environment, 100-dataLen-1);
|
||||
}
|
||||
}
|
||||
CWE114_Process_Control__w32_char_environment_82_base* baseObject = new CWE114_Process_Control__w32_char_environment_82_bad;
|
||||
baseObject->action(data);
|
||||
delete baseObject;
|
||||
}
|
||||
|
||||
// --- CWE114_Process_Control__w32_char_console_33 ---
|
||||
|
||||
typedef struct {} FILE;
|
||||
char *fgets(char *s, int n, FILE *stream);
|
||||
FILE *stdin;
|
||||
|
||||
void CWE114_Process_Control__w32_char_console_33_bad()
|
||||
{
|
||||
char * data;
|
||||
char * &dataRef = data;
|
||||
char dataBuffer[100] = "";
|
||||
data = dataBuffer;
|
||||
{
|
||||
/* Read input from the console */
|
||||
size_t dataLen = strlen(data);
|
||||
/* if there is room in data, read into it from the console */
|
||||
if (100-dataLen > 1)
|
||||
{
|
||||
/* POTENTIAL FLAW: Read data from the console [NOT DETECTED] */
|
||||
if (fgets(data+dataLen, (int)(100-dataLen), stdin) != NULL)
|
||||
{
|
||||
/* The next few lines remove the carriage return from the string that is
|
||||
* inserted by fgets() */
|
||||
dataLen = strlen(data);
|
||||
if (dataLen > 0 && data[dataLen-1] == '\n')
|
||||
{
|
||||
data[dataLen-1] = '\0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printLine("fgets() failed");
|
||||
/* Restore NUL terminator if fgets fails */
|
||||
data[dataLen] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
char * data = dataRef;
|
||||
{
|
||||
HMODULE hModule;
|
||||
/* POTENTIAL FLAW: If the path to the library is not specified, an attacker may be able to
|
||||
* replace his own file with the intended library */
|
||||
hModule = LoadLibraryA(data);
|
||||
if (hModule != NULL)
|
||||
{
|
||||
FreeLibrary(hModule);
|
||||
printLine("Library loaded and freed successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
printLine("Unable to load library");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ edges
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | (const char *)... |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer |
|
||||
| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection |
|
||||
subpaths
|
||||
nodes
|
||||
| test.cpp:24:30:24:36 | *command | semmle.label | *command |
|
||||
| test.cpp:24:30:24:36 | command | semmle.label | command |
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
| tests.cpp:350:13:350:19 | call to strncat | This 'call to strncat' operation is limited to 100 bytes but the destination is only 50 bytes. |
|
||||
| tests.cpp:452:9:452:15 | call to wcsncpy | This 'call to wcsncpy' operation is limited to 396 bytes but the destination is only 200 bytes. |
|
||||
| tests.cpp:481:9:481:16 | call to swprintf | This 'call to swprintf' operation is limited to 400 bytes but the destination is only 200 bytes. |
|
||||
| tests.cpp:630:13:630:20 | call to swprintf | This 'call to swprintf' operation is limited to 400 bytes but the destination is only 200 bytes. |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-120/BadlyBoundedWrite.ql
|
||||
@@ -0,0 +1 @@
|
||||
Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql
|
||||
@@ -0,0 +1,19 @@
|
||||
| tests.cpp:45:9:45:14 | call to memcpy | This 'memcpy' operation accesses 32 bytes but the $@ is only 16 bytes. | tests.cpp:32:10:32:18 | charFirst | destination buffer |
|
||||
| tests.cpp:60:9:60:14 | call to memcpy | This 'memcpy' operation accesses 32 bytes but the $@ is only 16 bytes. | tests.cpp:32:10:32:18 | charFirst | destination buffer |
|
||||
| tests.cpp:171:9:171:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | destination buffer |
|
||||
| tests.cpp:172:9:172:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | array |
|
||||
| tests.cpp:192:9:192:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | destination buffer |
|
||||
| tests.cpp:192:9:192:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:185:12:185:24 | dataBadBuffer | destination buffer |
|
||||
| tests.cpp:193:9:193:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | array |
|
||||
| tests.cpp:193:9:193:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:185:12:185:24 | dataBadBuffer | array |
|
||||
| tests.cpp:212:9:212:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | destination buffer |
|
||||
| tests.cpp:212:9:212:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:205:12:205:24 | dataBadBuffer | destination buffer |
|
||||
| tests.cpp:213:9:213:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | array |
|
||||
| tests.cpp:213:9:213:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:205:12:205:24 | dataBadBuffer | array |
|
||||
| tests.cpp:237:9:237:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:221:36:221:41 | call to alloca | array |
|
||||
| tests.cpp:237:9:237:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:225:12:225:24 | dataBadBuffer | array |
|
||||
| tests.cpp:261:9:261:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:245:10:245:22 | dataBadBuffer | array |
|
||||
| tests.cpp:261:9:261:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:249:12:249:24 | dataBadBuffer | array |
|
||||
| tests.cpp:384:9:384:14 | call to memcpy | This 'memcpy' operation accesses 40 bytes but the $@ is only 10 bytes. | tests.cpp:380:19:380:24 | call to alloca | destination buffer |
|
||||
| tests.cpp:434:9:434:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:422:12:422:26 | new[] | array |
|
||||
| tests.cpp:453:9:453:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:445:12:445:26 | new[] | array |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-119/OverflowBuffer.ql
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user