mirror of
https://github.com/github/codeql.git
synced 2026-06-03 04:40:14 +02:00
Compare commits
753 Commits
max-schaef
...
criemen/cs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a98dbf55e | ||
|
|
b63294764b | ||
|
|
5a9867c5b0 | ||
|
|
1c8f474848 | ||
|
|
2787f0a0fc | ||
|
|
a04830b8b2 | ||
|
|
b2512eb212 | ||
|
|
dc8ca70ab5 | ||
|
|
697a7b8a60 | ||
|
|
af7b295c59 | ||
|
|
9dca6697fb | ||
|
|
5220a8d3f8 | ||
|
|
ccaa792343 | ||
|
|
e8a466a02c | ||
|
|
a0e73eaab0 | ||
|
|
a17cd9bc1c | ||
|
|
4ce8d953d2 | ||
|
|
cff9bcfabc | ||
|
|
4e70e674fd | ||
|
|
ae21bbf0b2 | ||
|
|
3465c34cb6 | ||
|
|
4455ed982d | ||
|
|
84594e66bc | ||
|
|
e0c89a700f | ||
|
|
426bdc0011 | ||
|
|
d38fa13299 | ||
|
|
e91987b1a9 | ||
|
|
d544f47746 | ||
|
|
e4f6b1ac27 | ||
|
|
77e48f72ec | ||
|
|
9ec5e6e35e | ||
|
|
424046d238 | ||
|
|
80c4b7357a | ||
|
|
31c2a3be98 | ||
|
|
decbaa9dc7 | ||
|
|
3f0be47c7b | ||
|
|
49428c4585 | ||
|
|
43f1d092f1 | ||
|
|
d86293f9b4 | ||
|
|
ff30308a2b | ||
|
|
4b9430d59e | ||
|
|
cd2eec0aa0 | ||
|
|
f6ae7523b5 | ||
|
|
12cd1c1011 | ||
|
|
4e214e1c7c | ||
|
|
c6193ebc0c | ||
|
|
838a00bbc9 | ||
|
|
2abdf7dbbd | ||
|
|
602d16d73f | ||
|
|
b99e44c3ca | ||
|
|
4bcf9e50a0 | ||
|
|
467854ba4b | ||
|
|
2d9ff85753 | ||
|
|
3e3ea51e69 | ||
|
|
2a33a86c9d | ||
|
|
aa521ecd59 | ||
|
|
abcb5a7a95 | ||
|
|
e621d208e4 | ||
|
|
55ec27f47f | ||
|
|
e90b630c9b | ||
|
|
c6bc1a3f3a | ||
|
|
07eba4e3b1 | ||
|
|
041dc19055 | ||
|
|
989a546796 | ||
|
|
d0ca7045d4 | ||
|
|
a59ed5bc49 | ||
|
|
06191922c3 | ||
|
|
71ad6a8262 | ||
|
|
0d7943031c | ||
|
|
f969274a29 | ||
|
|
245f475fdb | ||
|
|
df4f2a367b | ||
|
|
31f602cd47 | ||
|
|
4689bdb468 | ||
|
|
1054e7a4ee | ||
|
|
003166af13 | ||
|
|
e7e6529df6 | ||
|
|
8d3ed68b68 | ||
|
|
49add7d8ce | ||
|
|
eb228b6e68 | ||
|
|
62dd86bacb | ||
|
|
7b91be6c52 | ||
|
|
11505d6842 | ||
|
|
56a70da28f | ||
|
|
70996a4c7e | ||
|
|
576eda3ec6 | ||
|
|
4cebb7e848 | ||
|
|
f8d427336e | ||
|
|
7bbf1a24d4 | ||
|
|
c6c00e7179 | ||
|
|
3a7df994cb | ||
|
|
387a241efd | ||
|
|
506b911767 | ||
|
|
4009f03087 | ||
|
|
9807a8e1d3 | ||
|
|
af524f0043 | ||
|
|
894f9ab8fa | ||
|
|
7082efa037 | ||
|
|
c34ad25cf9 | ||
|
|
13e60d7b11 | ||
|
|
132cc03e3b | ||
|
|
679d64f0e8 | ||
|
|
30a512c96b | ||
|
|
81d77bf37c | ||
|
|
947e0274c7 | ||
|
|
f404d7a5f8 | ||
|
|
392b2af923 | ||
|
|
b82dfa9a21 | ||
|
|
5487b404ed | ||
|
|
0bf2d77a7e | ||
|
|
a161d6e666 | ||
|
|
9ea6ef06ef | ||
|
|
f2b52650d5 | ||
|
|
a35bda2946 | ||
|
|
f82f1df5d6 | ||
|
|
7bf271fb6c | ||
|
|
a9e2f55b61 | ||
|
|
484d0fe4cd | ||
|
|
12d856737a | ||
|
|
8f4509f434 | ||
|
|
431d9d58f1 | ||
|
|
242399817a | ||
|
|
fd757b0089 | ||
|
|
58bf70d61b | ||
|
|
613831b2e1 | ||
|
|
c937230f1a | ||
|
|
c26c68c286 | ||
|
|
7c3684dbb7 | ||
|
|
400910e4d3 | ||
|
|
155073c498 | ||
|
|
727a7e804c | ||
|
|
f8ab64dff0 | ||
|
|
c717e346fb | ||
|
|
ac115e0a6f | ||
|
|
bb2bbd2d4d | ||
|
|
f6794fe859 | ||
|
|
8e9aa5b560 | ||
|
|
a7f3ef1a6c | ||
|
|
8e2b17cd86 | ||
|
|
6d859daf3d | ||
|
|
b54b5ae0a9 | ||
|
|
b3fa59d94b | ||
|
|
3c86aad16d | ||
|
|
4ce1b680c2 | ||
|
|
048a7c4e42 | ||
|
|
48291dd32d | ||
|
|
0b45b63bd2 | ||
|
|
0c5b528d54 | ||
|
|
1366247f4c | ||
|
|
f7a8a8ae19 | ||
|
|
9736936e54 | ||
|
|
ddb145f15f | ||
|
|
38b811b050 | ||
|
|
1ec1dd368d | ||
|
|
6e385cabd8 | ||
|
|
37a536baf9 | ||
|
|
3478890090 | ||
|
|
b79a5fee14 | ||
|
|
b9ac038de2 | ||
|
|
ceb3d14fe0 | ||
|
|
07ded4278f | ||
|
|
051a77fd79 | ||
|
|
18c8d90a1a | ||
|
|
688afddaf2 | ||
|
|
8f58685b38 | ||
|
|
567aa1102a | ||
|
|
bc34374075 | ||
|
|
e25a655509 | ||
|
|
b9dfeb3aac | ||
|
|
34b9791e46 | ||
|
|
322e6c91be | ||
|
|
8b6c940e76 | ||
|
|
6d6f89e71e | ||
|
|
a39a94ca8e | ||
|
|
19644a8f07 | ||
|
|
7f6ae8b2ab | ||
|
|
11152deeb5 | ||
|
|
f76cde36bb | ||
|
|
e1f7f3cbd4 | ||
|
|
e75562e508 | ||
|
|
5cc94e1105 | ||
|
|
21b7a51d0a | ||
|
|
1479509d93 | ||
|
|
377da9fa66 | ||
|
|
4a1bf95a87 | ||
|
|
e8c18a3883 | ||
|
|
98032d58b8 | ||
|
|
5b17066e6c | ||
|
|
ea04b500a3 | ||
|
|
b841d5f923 | ||
|
|
81b3ff2bb8 | ||
|
|
79e1aa0498 | ||
|
|
05a4c7fdc1 | ||
|
|
66f4eccc30 | ||
|
|
5407b57261 | ||
|
|
aac6cf60ee | ||
|
|
ffff10a7e8 | ||
|
|
7bae2d9192 | ||
|
|
6b031a4623 | ||
|
|
785175e77f | ||
|
|
bfd852aacd | ||
|
|
ec72150893 | ||
|
|
435b7df764 | ||
|
|
8913638b25 | ||
|
|
b259a0ff6a | ||
|
|
c8706e2ad7 | ||
|
|
65081a9a1f | ||
|
|
08b528b5c4 | ||
|
|
0837e400a2 | ||
|
|
efe064284b | ||
|
|
86fe5b47db | ||
|
|
2b939fdf08 | ||
|
|
f81a3ec464 | ||
|
|
375f0ea8b6 | ||
|
|
1e699ec0e5 | ||
|
|
c8edf3151b | ||
|
|
c233094846 | ||
|
|
fa3d401226 | ||
|
|
7cf5210063 | ||
|
|
9a95b9bcda | ||
|
|
c09df2e3f1 | ||
|
|
8f115bfd06 | ||
|
|
91d224eea5 | ||
|
|
fb0f9ec601 | ||
|
|
b8d45ae927 | ||
|
|
e2ef0dc71d | ||
|
|
d46442245b | ||
|
|
435638a5bb | ||
|
|
954b0612d5 | ||
|
|
14db0dfcc7 | ||
|
|
c040d4847b | ||
|
|
dc9f171ee6 | ||
|
|
b4958e7d58 | ||
|
|
a077b70d66 | ||
|
|
535d1e2565 | ||
|
|
55df481e5c | ||
|
|
083be305e1 | ||
|
|
38ecde0cc1 | ||
|
|
78fcbd07d6 | ||
|
|
3a9ffe189e | ||
|
|
4641990021 | ||
|
|
9e2f0b5ed0 | ||
|
|
c4521a30aa | ||
|
|
4e08ba6820 | ||
|
|
bf3fb685ad | ||
|
|
b9c89750b9 | ||
|
|
14cfb82a8c | ||
|
|
342b3d7733 | ||
|
|
1929dead39 | ||
|
|
c1ecd5a0da | ||
|
|
57cbacb495 | ||
|
|
ce0104799a | ||
|
|
60f3598da9 | ||
|
|
e25c0498d4 | ||
|
|
8937e0b313 | ||
|
|
cb1cd5ed2a | ||
|
|
28eb2caacb | ||
|
|
33494fe9e1 | ||
|
|
e4683449cb | ||
|
|
8bf8888c24 | ||
|
|
6538a7645d | ||
|
|
6062fbb475 | ||
|
|
572cec2c55 | ||
|
|
43e8b900bf | ||
|
|
2a552d9721 | ||
|
|
d6b6c432d9 | ||
|
|
d534c93ff1 | ||
|
|
f6ac63b259 | ||
|
|
12201d2e8e | ||
|
|
6ad5c9542b | ||
|
|
b18a6d5e0b | ||
|
|
ce471105e2 | ||
|
|
4aed638066 | ||
|
|
1f8a51cffe | ||
|
|
e745df6478 | ||
|
|
c1a1ebfb60 | ||
|
|
e9cb272396 | ||
|
|
6ad8a4db1c | ||
|
|
cf958f0828 | ||
|
|
10c657bc23 | ||
|
|
0cf702a74f | ||
|
|
0818354ad7 | ||
|
|
00ba7e42b1 | ||
|
|
c7be5ac527 | ||
|
|
1db622e740 | ||
|
|
68999f3cef | ||
|
|
9b150e4ea9 | ||
|
|
a5a7d27c4b | ||
|
|
3c5b9ce0cd | ||
|
|
3c9783c7c9 | ||
|
|
b41ec37993 | ||
|
|
ee5c014382 | ||
|
|
581305b234 | ||
|
|
8beacb8d4a | ||
|
|
9cae488ef4 | ||
|
|
65e13aa5ed | ||
|
|
93234c0b5c | ||
|
|
9e2dd09ddc | ||
|
|
0f4ea10638 | ||
|
|
776e35279d | ||
|
|
e4276f7adb | ||
|
|
b106db6fda | ||
|
|
9769953669 | ||
|
|
52a0fdabcf | ||
|
|
08d6379563 | ||
|
|
abc16abf6f | ||
|
|
135923c9c1 | ||
|
|
63525a9d9e | ||
|
|
e6e87a44a3 | ||
|
|
d2afb20f3f | ||
|
|
a5bfeb68a8 | ||
|
|
9800458467 | ||
|
|
927eb8424d | ||
|
|
8d9e4d391f | ||
|
|
55ec9d0a91 | ||
|
|
5a1a3f0727 | ||
|
|
86ba75cadf | ||
|
|
6203887645 | ||
|
|
784bb72b33 | ||
|
|
b451adabfc | ||
|
|
896a3c65be | ||
|
|
570ca3b6fe | ||
|
|
24946c0dfd | ||
|
|
fef2932f56 | ||
|
|
773f46d3b4 | ||
|
|
30ecb4b0c8 | ||
|
|
867a39083e | ||
|
|
302199a74a | ||
|
|
abef8483bd | ||
|
|
96a37f3a3c | ||
|
|
2ad121a8a5 | ||
|
|
dcc778520a | ||
|
|
50041f07a3 | ||
|
|
35f6e6ebb4 | ||
|
|
aff848b038 | ||
|
|
dbb4167f80 | ||
|
|
0ed01453b9 | ||
|
|
2c7291336d | ||
|
|
bb146a1758 | ||
|
|
2465cc20f0 | ||
|
|
64004926bc | ||
|
|
903f376620 | ||
|
|
b1d4ca505d | ||
|
|
bbc3cfba6f | ||
|
|
a2e3b37847 | ||
|
|
8198898d73 | ||
|
|
39eeed9238 | ||
|
|
5fe6a5a730 | ||
|
|
4dca4a7389 | ||
|
|
ec58b209e3 | ||
|
|
21e4a5b2d5 | ||
|
|
29d57d82b7 | ||
|
|
9d90c24006 | ||
|
|
f288ddc3d5 | ||
|
|
d923784ae4 | ||
|
|
90c63ab6b0 | ||
|
|
2fb4dfeb90 | ||
|
|
665b140a8a | ||
|
|
700201556c | ||
|
|
58dae6d1c6 | ||
|
|
2a91743477 | ||
|
|
a28f19c857 | ||
|
|
c689065f83 | ||
|
|
855d96db66 | ||
|
|
d85284da55 | ||
|
|
02c98fae5f | ||
|
|
1ad06f3293 | ||
|
|
9c15cf18e8 | ||
|
|
3b0b5e403c | ||
|
|
a2bcc97a74 | ||
|
|
743814a234 | ||
|
|
c2d072e3f8 | ||
|
|
22d968fba3 | ||
|
|
31b069041f | ||
|
|
a8eb95a688 | ||
|
|
64d23d4f9b | ||
|
|
5b2d226c35 | ||
|
|
1edca19419 | ||
|
|
24c809b3b5 | ||
|
|
72a1289eba | ||
|
|
c6641dfbf3 | ||
|
|
a85df81b67 | ||
|
|
0612b3795a | ||
|
|
3ee0fa9bc4 | ||
|
|
b77b3763be | ||
|
|
8eeb861963 | ||
|
|
2f53adf2c2 | ||
|
|
dbb5aa9aad | ||
|
|
083a5068c3 | ||
|
|
886c85ddc1 | ||
|
|
958c6ff289 | ||
|
|
ee6cb96d07 | ||
|
|
3219edc603 | ||
|
|
6b94b77a0a | ||
|
|
f8c3b2977a | ||
|
|
f783ca7940 | ||
|
|
96d6ecb108 | ||
|
|
35e19eac96 | ||
|
|
4f8908106b | ||
|
|
f7c07d55ed | ||
|
|
49218cdbfb | ||
|
|
18661eee77 | ||
|
|
66486b08dc | ||
|
|
4aec302fb7 | ||
|
|
c7b9e405b7 | ||
|
|
2cfca032de | ||
|
|
82b92c38f9 | ||
|
|
bfd150a1d3 | ||
|
|
ff15b73250 | ||
|
|
4a08ca39d6 | ||
|
|
16c5edd3ca | ||
|
|
11194e574c | ||
|
|
354983087e | ||
|
|
be494b73d4 | ||
|
|
951b6beeb1 | ||
|
|
990d7161b2 | ||
|
|
78e08cf63c | ||
|
|
6882504397 | ||
|
|
5ded55cd9f | ||
|
|
283d6efdf8 | ||
|
|
75a1173d63 | ||
|
|
dc512728fa | ||
|
|
4ea5c13390 | ||
|
|
7124a53c9c | ||
|
|
53d92d58fc | ||
|
|
b3e5b86f0a | ||
|
|
05385eb704 | ||
|
|
27646ce971 | ||
|
|
fb470e4140 | ||
|
|
bf503849ea | ||
|
|
bf6e6a1e68 | ||
|
|
a3d53ba9ec | ||
|
|
7029f14651 | ||
|
|
2592c94c54 | ||
|
|
36082808d3 | ||
|
|
c1c4a5bfcf | ||
|
|
cd44d67529 | ||
|
|
06fe10bbe9 | ||
|
|
7b214a24df | ||
|
|
232c147f6b | ||
|
|
ec39de20d8 | ||
|
|
38274db205 | ||
|
|
169ba03778 | ||
|
|
aed830cf1b | ||
|
|
a245d0019e | ||
|
|
032572b924 | ||
|
|
f54379d096 | ||
|
|
9196939384 | ||
|
|
4920c7f8b0 | ||
|
|
cffcc7334d | ||
|
|
0f2db1bcdb | ||
|
|
3eeb6ffec4 | ||
|
|
44c87561b3 | ||
|
|
c240c1b3f5 | ||
|
|
6cbadece0e | ||
|
|
bf20b8e5a5 | ||
|
|
8a5f3e4825 | ||
|
|
7c053ed428 | ||
|
|
021ed88a0a | ||
|
|
12d0f1a84b | ||
|
|
33f10d8d19 | ||
|
|
790615fbc2 | ||
|
|
5fd56ce866 | ||
|
|
121fd0896b | ||
|
|
42a2ec9891 | ||
|
|
06b1cd939c | ||
|
|
d2d70cc782 | ||
|
|
79f675cdb7 | ||
|
|
a5206028b0 | ||
|
|
30610c9a3f | ||
|
|
3bcee63980 | ||
|
|
862de152a1 | ||
|
|
6f37d7c374 | ||
|
|
9652679c6f | ||
|
|
e97456f5fc | ||
|
|
56b49a4de3 | ||
|
|
3d5098aaeb | ||
|
|
1c298e6001 | ||
|
|
310ebe47b3 | ||
|
|
42c343e820 | ||
|
|
92d3d9d83f | ||
|
|
4205f1bd03 | ||
|
|
b849a66c97 | ||
|
|
9dbf7e818d | ||
|
|
9de3cc703a | ||
|
|
5418d39a0d | ||
|
|
af49a3aa64 | ||
|
|
8115774a7a | ||
|
|
4e1b44a059 | ||
|
|
21a369de13 | ||
|
|
c04654d8f9 | ||
|
|
95a7d6559c | ||
|
|
3253c0425c | ||
|
|
050b8e682f | ||
|
|
ba67217b44 | ||
|
|
06238dd5f6 | ||
|
|
011666b48c | ||
|
|
d3063e849e | ||
|
|
ede17585a6 | ||
|
|
e3edea2a5f | ||
|
|
eb97ce3294 | ||
|
|
efb63aada3 | ||
|
|
3627eb2bcf | ||
|
|
e8c9708282 | ||
|
|
09e83d1173 | ||
|
|
ac38d4c9c6 | ||
|
|
59a49eef0b | ||
|
|
f552a15aae | ||
|
|
f597f0272a | ||
|
|
26f767073d | ||
|
|
a10731c591 | ||
|
|
1fce26534f | ||
|
|
4e823b4306 | ||
|
|
4cf40ed259 | ||
|
|
67ed12c916 | ||
|
|
b107c4c641 | ||
|
|
c0b04eac7c | ||
|
|
26b0363707 | ||
|
|
2f0ee12584 | ||
|
|
f22d60f011 | ||
|
|
140ff723e4 | ||
|
|
3f11d83b7b | ||
|
|
02a2debe94 | ||
|
|
cd10dc8a27 | ||
|
|
e301223644 | ||
|
|
743be92624 | ||
|
|
5ba0e0ffce | ||
|
|
d4af05cbf9 | ||
|
|
ed6a068ebc | ||
|
|
4e99266b65 | ||
|
|
7cc20587ad | ||
|
|
b89088737a | ||
|
|
319b799f95 | ||
|
|
687ecffe71 | ||
|
|
b46174f464 | ||
|
|
76a9b71231 | ||
|
|
1d7c2f4799 | ||
|
|
f0c0bbf4c8 | ||
|
|
6c10ba2fb1 | ||
|
|
9ba32a0440 | ||
|
|
de85f2bbf8 | ||
|
|
8054a5d086 | ||
|
|
3f1e145d2c | ||
|
|
0ba0063e6d | ||
|
|
f562d5319f | ||
|
|
26634a3266 | ||
|
|
d816035da6 | ||
|
|
13a9e83e6a | ||
|
|
c92519ed6b | ||
|
|
da68153a96 | ||
|
|
5d729616cd | ||
|
|
58fe66f5a8 | ||
|
|
ee813c1e61 | ||
|
|
46aa712c28 | ||
|
|
1b9b6ae5b5 | ||
|
|
a4ef183a2e | ||
|
|
36f1070b93 | ||
|
|
fc1fc05d16 | ||
|
|
ee4a9c3f8d | ||
|
|
6e29b70100 | ||
|
|
9263cfdf56 | ||
|
|
15e9838f16 | ||
|
|
fb1b41b649 | ||
|
|
c268163804 | ||
|
|
910b2a98f1 | ||
|
|
bd7de83aab | ||
|
|
07eb60d044 | ||
|
|
712f7758cf | ||
|
|
e19ebf9ca8 | ||
|
|
563805ff0c | ||
|
|
a3cecd178f | ||
|
|
fbfafbfdd4 | ||
|
|
2a1ca637fd | ||
|
|
5cd732b3c6 | ||
|
|
67601b5312 | ||
|
|
0ab159f803 | ||
|
|
2c99e2f3d5 | ||
|
|
836bb6006c | ||
|
|
0bfa53cfd6 | ||
|
|
4feda50add | ||
|
|
b5cbd909f7 | ||
|
|
35702a9fdf | ||
|
|
a972d0943a | ||
|
|
2a64552979 | ||
|
|
7e71d9e619 | ||
|
|
bec3e62771 | ||
|
|
23c6027386 | ||
|
|
8b8a2726d4 | ||
|
|
554087161b | ||
|
|
5036135f01 | ||
|
|
0fceecee6d | ||
|
|
e271c7e5e7 | ||
|
|
91a98f3512 | ||
|
|
231e9ef098 | ||
|
|
a6dae91215 | ||
|
|
3202bcce70 | ||
|
|
c60cb136bb | ||
|
|
4339e18ed6 | ||
|
|
2b541b78ac | ||
|
|
049ba54948 | ||
|
|
daca5121f6 | ||
|
|
2af1302a4a | ||
|
|
86336565eb | ||
|
|
065353667f | ||
|
|
da44b13fd4 | ||
|
|
d55289bf68 | ||
|
|
4246ebf9e0 | ||
|
|
771b5eca47 | ||
|
|
10e9c6defd | ||
|
|
df191e4b6d | ||
|
|
7f97492580 | ||
|
|
a36d432184 | ||
|
|
c04546da98 | ||
|
|
308d027d1e | ||
|
|
44e214b933 | ||
|
|
eb3e140008 | ||
|
|
f6b1d66167 | ||
|
|
1b1a78bf04 | ||
|
|
342f4f867b | ||
|
|
9d2e21e470 | ||
|
|
ff3d4b8b40 | ||
|
|
3b6c43c9a1 | ||
|
|
8812567c69 | ||
|
|
0d36d918c9 | ||
|
|
d4cbb8cb22 | ||
|
|
9a91145d7e | ||
|
|
efe7153ac2 | ||
|
|
9ad461daa0 | ||
|
|
59b26c0dad | ||
|
|
b71248face | ||
|
|
dc77614bd1 | ||
|
|
56a1a7cc4d | ||
|
|
f3dd2ebe7d | ||
|
|
16fbffe47b | ||
|
|
51cf400669 | ||
|
|
02e3d2704c | ||
|
|
e6ae3ffe7a | ||
|
|
d21943137f | ||
|
|
bddd448fdf | ||
|
|
6472ed7fe0 | ||
|
|
c51efb1477 | ||
|
|
bd811f25da | ||
|
|
8dcd8b9e5b | ||
|
|
70aa490bbd | ||
|
|
15afc3ed64 | ||
|
|
b93442a2b6 | ||
|
|
ab891465a4 | ||
|
|
53e80e0f27 | ||
|
|
c8e8ac0b55 | ||
|
|
9a6fc967db | ||
|
|
17ee7c2352 | ||
|
|
c4075b3ec7 | ||
|
|
d390b6235b | ||
|
|
8ed5bfb27d | ||
|
|
0a71705dfe | ||
|
|
2fcf0abb7f | ||
|
|
c5307bed2b | ||
|
|
d6ccd63ed2 | ||
|
|
3de32e813b | ||
|
|
bbf9bcde2a | ||
|
|
e264bddb25 | ||
|
|
fa3053f7fa | ||
|
|
401639e10b | ||
|
|
057172c391 | ||
|
|
aa418dc7d0 | ||
|
|
9a2c1daebe | ||
|
|
75a8f01f65 | ||
|
|
4ecda9cccd | ||
|
|
3145c53a19 | ||
|
|
bd77f572f1 | ||
|
|
0a96eb0a40 | ||
|
|
2679d1fdb5 | ||
|
|
451d779f4a | ||
|
|
459b006244 | ||
|
|
8e890571ed | ||
|
|
3b3c036626 | ||
|
|
efb04f6db4 | ||
|
|
d0ec2fd643 | ||
|
|
0a0ce1f202 | ||
|
|
c65d407937 | ||
|
|
d08ee76b16 | ||
|
|
26a665369b | ||
|
|
05162c68ec | ||
|
|
aade79f723 | ||
|
|
1f92267786 | ||
|
|
890b9d59ed | ||
|
|
225a9fe2d8 | ||
|
|
0e1da37379 | ||
|
|
39a6375606 | ||
|
|
613c7b24b5 | ||
|
|
0bc24b8641 | ||
|
|
c6f2a2936b | ||
|
|
dcba1b9913 | ||
|
|
7fbba3a659 | ||
|
|
8f985e0045 | ||
|
|
0510b0c825 | ||
|
|
3356261031 | ||
|
|
e2ac3769bc | ||
|
|
aa0db1426d | ||
|
|
d0f214a9a7 | ||
|
|
9097d93ac7 | ||
|
|
b832fc8e32 | ||
|
|
140ff537c0 | ||
|
|
4e29ed5ff0 | ||
|
|
228aaee0bf | ||
|
|
9e473ebda4 | ||
|
|
da14f428e2 | ||
|
|
192c16bbb3 | ||
|
|
552221868f | ||
|
|
791a6422b3 | ||
|
|
e730815f41 | ||
|
|
dd71204128 | ||
|
|
bcde466d6c | ||
|
|
1bbf88f208 | ||
|
|
782ecd77b7 | ||
|
|
6865ce56bc | ||
|
|
a4117538ab | ||
|
|
3ac3169278 | ||
|
|
484d020c39 | ||
|
|
dab9a859f3 | ||
|
|
30a9656ebb | ||
|
|
cb749bd973 | ||
|
|
661da76838 | ||
|
|
9ad1749957 | ||
|
|
76db1c5c8b | ||
|
|
b0c7964ea6 | ||
|
|
b3185e9519 | ||
|
|
e225ea6bef | ||
|
|
dcd88100f0 | ||
|
|
446416f1ab | ||
|
|
a1512c8af0 | ||
|
|
9bdddabd8a | ||
|
|
fddda0368c | ||
|
|
fa10dbea9f | ||
|
|
a052a4e385 | ||
|
|
cdc0d1fff1 | ||
|
|
fe4ef48844 | ||
|
|
b5ff104a00 | ||
|
|
5263cccefc | ||
|
|
24c385b1da | ||
|
|
177db998c7 | ||
|
|
ed3ffde5e6 | ||
|
|
be506c64ba | ||
|
|
4f35a62583 | ||
|
|
d9854eb409 | ||
|
|
1d4832cbfe | ||
|
|
362cf107a4 | ||
|
|
bb1720d50a | ||
|
|
936f846b09 | ||
|
|
0cb00c9091 | ||
|
|
93c39c5fdd | ||
|
|
b8d29e8fc1 | ||
|
|
aeeafd75bf |
9
.github/dependabot.yml
vendored
9
.github/dependabot.yml
vendored
@@ -31,3 +31,12 @@ updates:
|
||||
- "golang.org/x/*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "go/ql/test"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
32
.github/workflows/check-change-note.yml
vendored
32
.github/workflows/check-change-note.yml
vendored
@@ -9,26 +9,42 @@ on:
|
||||
- "*/ql/lib/**/*.ql"
|
||||
- "*/ql/lib/**/*.qll"
|
||||
- "*/ql/lib/**/*.yml"
|
||||
- "shared/**/*.ql"
|
||||
- "shared/**/*.qll"
|
||||
- "!**/experimental/**"
|
||||
- "!ql/**"
|
||||
- ".github/workflows/check-change-note.yml"
|
||||
|
||||
jobs:
|
||||
check-change-note:
|
||||
env:
|
||||
REPO: ${{ github.repository }}
|
||||
PULL_REQUEST_NUMBER: ${{ github.event.number }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Fail if no change note found. To fix, either add one, or add the `no-change-note-required` label.
|
||||
if: |
|
||||
github.event.pull_request.draft == false &&
|
||||
!contains(github.event.pull_request.labels.*.name, 'no-change-note-required')
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
|
||||
grep true -c
|
||||
change_note_files=$(gh api "repos/$REPO/pulls/$PULL_REQUEST_NUMBER/files" --paginate --jq '.[].filename | select(test("/change-notes/.*[.]md$"))')
|
||||
|
||||
if [ -z "$change_note_files" ]; then
|
||||
echo "No change note found. Either add one, or add the 'no-change-note-required' label."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Change notes found:"
|
||||
echo "$change_note_files"
|
||||
|
||||
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md', 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text, or released/x.y.z.md for released change-notes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
|
||||
grep true -c
|
||||
bad_change_note_file_names=$(gh api "repos/$REPO/pulls/$PULL_REQUEST_NUMBER/files" --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))][] | select((test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$")) | not)')
|
||||
|
||||
if [ -n "$bad_change_note_file_names" ]; then
|
||||
echo "The following change note file names are invalid:"
|
||||
echo "$bad_change_note_file_names"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
2
.github/workflows/csharp-qltest.yml
vendored
2
.github/workflows/csharp-qltest.yml
vendored
@@ -91,7 +91,7 @@ jobs:
|
||||
run: |
|
||||
# Generate (Asp)NetCore stubs
|
||||
STUBS_PATH=stubs_output
|
||||
python3 ql/src/Stubs/make_stubs_nuget.py webapp Swashbuckle.AspNetCore.Swagger 6.5.0 "$STUBS_PATH"
|
||||
python3 scripts/stubs/make_stubs_nuget.py webapp Swashbuckle.AspNetCore.Swagger 6.5.0 "$STUBS_PATH"
|
||||
rm -rf ql/test/resources/stubs/_frameworks
|
||||
# Update existing stubs in the repo with the freshly generated ones
|
||||
mv "$STUBS_PATH/output/stubs/_frameworks" ql/test/resources/stubs/
|
||||
|
||||
25
.github/workflows/csv-coverage-pr-artifacts.yml
vendored
25
.github/workflows/csv-coverage-pr-artifacts.yml
vendored
@@ -89,9 +89,32 @@ jobs:
|
||||
- name: Save PR number
|
||||
run: |
|
||||
mkdir -p pr
|
||||
echo ${{ github.event.pull_request.number }} > pr/NR
|
||||
echo ${PR_NUMBER} > pr/NR
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
- name: Upload PR number
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: pr
|
||||
path: pr/
|
||||
- name: Save comment ID (if it exists)
|
||||
run: |
|
||||
# Find the latest comment starting with COMMENT_PREFIX
|
||||
COMMENT_PREFIX=":warning: The head of this PR and the base branch were compared for differences in the framework coverage reports."
|
||||
COMMENT_ID=$(gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/comments" --paginate | jq --arg prefix "${COMMENT_PREFIX}" 'map(select(.body|startswith($prefix)) | .id) | max // empty')
|
||||
if [[ -z ${COMMENT_ID} ]]
|
||||
then
|
||||
echo "Comment not found. Not uploading 'comment/ID' artifact."
|
||||
else
|
||||
mkdir -p comment
|
||||
echo ${COMMENT_ID} > comment/ID
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||
- name: Upload comment ID (if it exists)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: comment
|
||||
path: comment/
|
||||
if-no-files-found: ignore
|
||||
|
||||
@@ -6,7 +6,7 @@ provide:
|
||||
- "*/ql/consistency-queries/qlpack.yml"
|
||||
- "*/ql/automodel/src/qlpack.yml"
|
||||
- "*/ql/automodel/test/qlpack.yml"
|
||||
- "shared/*/qlpack.yml"
|
||||
- "shared/**/qlpack.yml"
|
||||
- "cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/qlpack.yml"
|
||||
- "go/ql/config/legacy-support/qlpack.yml"
|
||||
- "go/build/codeql-extractor-go/codeql-extractor.yml"
|
||||
@@ -29,6 +29,7 @@ provide:
|
||||
- "swift/extractor-pack/codeql-extractor.yml"
|
||||
- "swift/integration-tests/qlpack.yml"
|
||||
- "ql/extractor-pack/codeql-extractor.yml"
|
||||
- ".github/codeql/extensions/**/codeql-pack.yml"
|
||||
|
||||
versionPolicies:
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
class BuiltinType extends @builtintype {
|
||||
string toString() { none() }
|
||||
}
|
||||
|
||||
from BuiltinType type, string name, int kind, int kind_new, int size, int sign, int alignment
|
||||
where
|
||||
builtintypes(type, name, kind, size, sign, alignment) and
|
||||
if
|
||||
type instanceof @fp16 or
|
||||
type instanceof @std_bfloat16 or
|
||||
type instanceof @std_float16 or
|
||||
type instanceof @complex_std_float32 or
|
||||
type instanceof @complex_float32x or
|
||||
type instanceof @complex_std_float64 or
|
||||
type instanceof @complex_float64x or
|
||||
type instanceof @complex_std_float128
|
||||
then kind_new = 2
|
||||
else kind_new = kind
|
||||
select type, name, kind_new, size, sign, alignment
|
||||
2221
cpp/downgrades/5b388693c66db1e7dc2e76a90aa67a2b6eb74f0f/old.dbscheme
Normal file
2221
cpp/downgrades/5b388693c66db1e7dc2e76a90aa67a2b6eb74f0f/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Introduce new floating-point types from C23 and C++23
|
||||
compatibility: backwards
|
||||
builtintypes.rel: run builtintypes.qlo
|
||||
2231
cpp/downgrades/8cba93a44180e0d50a80a660950800d822b981fc/old.dbscheme
Normal file
2231
cpp/downgrades/8cba93a44180e0d50a80a660950800d822b981fc/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Removed @assignpaddexpr and @assignpsubexpr from @assign_bitwise_expr
|
||||
compatibility: full
|
||||
2226
cpp/downgrades/f79ce79e3b751aeeed59e594633ba5c07a27ef3e/old.dbscheme
Normal file
2226
cpp/downgrades/f79ce79e3b751aeeed59e594633ba5c07a27ef3e/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
description: Introduce extractor version numbers
|
||||
compatibility: breaking
|
||||
extractor_version.rel: delete
|
||||
@@ -1,3 +1,25 @@
|
||||
## 0.11.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `Container` and `Folder` classes now derive from `ElementBase` instead of `Locatable`, and no longer expose the `getLocation` predicate. Use `getURL` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new class `AdditionalCallTarget` for specifying additional call targets.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* More field accesses are identified as `ImplicitThisFieldAccess`.
|
||||
* Added support for new floating-point types in C23 and C++23.
|
||||
|
||||
## 0.10.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `AnalysedString` class, use the new name `AnalyzedString`.
|
||||
* Deleted the deprecated `isBarrierGuard` predicate from the dataflow library and its uses, use `isBarrier` and the `BarrierGuard` module instead.
|
||||
|
||||
## 0.10.0
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
4
cpp/ql/lib/change-notes/2023-10-30-realloc-flow.md
Normal file
4
cpp/ql/lib/change-notes/2023-10-30-realloc-flow.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added taint models for `realloc` and related functions.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The expressions `AssignPointerAddExpr` and `AssignPointerSubExpr` are no longer subtypes of `AssignBitwiseOperation`.
|
||||
@@ -1,5 +1,6 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
## 0.10.1
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `AnalysedString` class, use the new name `AnalyzedString`.
|
||||
* Deleted the deprecated `isBarrierGuard` predicate from the dataflow library and its uses, use `isBarrier` and the `BarrierGuard` module instead.
|
||||
14
cpp/ql/lib/change-notes/released/0.11.0.md
Normal file
14
cpp/ql/lib/change-notes/released/0.11.0.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## 0.11.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
* The `Container` and `Folder` classes now derive from `ElementBase` instead of `Locatable`, and no longer expose the `getLocation` predicate. Use `getURL` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a new class `AdditionalCallTarget` for specifying additional call targets.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* More field accesses are identified as `ImplicitThisFieldAccess`.
|
||||
* Added support for new floating-point types in C23 and C++23.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.10.0
|
||||
lastReleaseVersion: 0.11.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.10.1-dev
|
||||
version: 0.11.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
@@ -7,6 +7,7 @@ library: true
|
||||
upgrades: upgrades
|
||||
dependencies:
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/rangeanalysis: ${workspace}
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
|
||||
@@ -32,7 +32,7 @@ private module Input implements InputSig {
|
||||
private module Impl = Make<Input>;
|
||||
|
||||
/** A file or folder. */
|
||||
class Container extends Locatable, Impl::Container {
|
||||
class Container extends ElementBase, Impl::Container {
|
||||
override string toString() { result = Impl::Container.super.toString() }
|
||||
}
|
||||
|
||||
@@ -47,11 +47,6 @@ class Container extends Locatable, Impl::Container {
|
||||
* To get the full path, use `getAbsolutePath`.
|
||||
*/
|
||||
class Folder extends Container, Impl::Folder {
|
||||
override Location getLocation() {
|
||||
result.getContainer() = this and
|
||||
result.hasLocationInfo(_, 0, 0, 0, 0)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Folder" }
|
||||
}
|
||||
|
||||
@@ -67,7 +62,7 @@ class Folder extends Container, Impl::Folder {
|
||||
* The base name further decomposes into the _stem_ and _extension_ -- see
|
||||
* `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`.
|
||||
*/
|
||||
class File extends Container, Impl::File {
|
||||
class File extends Container, Locatable, Impl::File {
|
||||
override string getAPrimaryQlClass() { result = "File" }
|
||||
|
||||
override Location getLocation() {
|
||||
|
||||
@@ -819,6 +819,30 @@ private predicate floatingPointTypeMapping(
|
||||
or
|
||||
// _Complex _Float16
|
||||
kind = 53 and base = 2 and domain = TComplexDomain() and realKind = 52 and extended = false
|
||||
or
|
||||
// __fp16
|
||||
kind = 54 and base = 2 and domain = TRealDomain() and realKind = 54 and extended = false
|
||||
or
|
||||
// __bf16
|
||||
kind = 55 and base = 2 and domain = TRealDomain() and realKind = 55 and extended = false
|
||||
or
|
||||
// std::float16_t
|
||||
kind = 56 and base = 2 and domain = TRealDomain() and realKind = 56 and extended = false
|
||||
or
|
||||
// _Complex _Float32
|
||||
kind = 57 and base = 2 and domain = TComplexDomain() and realKind = 45 and extended = false
|
||||
or
|
||||
// _Complex _Float32x
|
||||
kind = 58 and base = 2 and domain = TComplexDomain() and realKind = 46 and extended = true
|
||||
or
|
||||
// _Complex _Float64
|
||||
kind = 59 and base = 2 and domain = TComplexDomain() and realKind = 47 and extended = false
|
||||
or
|
||||
// _Complex _Float64x
|
||||
kind = 60 and base = 2 and domain = TComplexDomain() and realKind = 48 and extended = true
|
||||
or
|
||||
// _Complex _Float128
|
||||
kind = 61 and base = 2 and domain = TComplexDomain() and realKind = 49 and extended = false
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -306,15 +306,13 @@ private predicate exprHasReferenceConversion(Expr e) { referenceConversion(e.get
|
||||
* }
|
||||
* };
|
||||
* ```
|
||||
* Note: the C++ front-end often automatically desugars `field` to
|
||||
* `this->field`, so most accesses of `this->field` are instances
|
||||
* of `PointerFieldAccess` (with `ThisExpr` as the qualifier), not
|
||||
* `ImplicitThisFieldAccess`.
|
||||
*/
|
||||
class ImplicitThisFieldAccess extends FieldAccess {
|
||||
override string getAPrimaryQlClass() { result = "ImplicitThisFieldAccess" }
|
||||
|
||||
ImplicitThisFieldAccess() { not exists(this.getQualifier()) }
|
||||
ImplicitThisFieldAccess() {
|
||||
this.getQualifier().(ThisExpr).isCompilerGenerated() or not exists(this.getQualifier())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,7 +330,7 @@ class PointerToFieldLiteral extends ImplicitThisFieldAccess {
|
||||
// access without a qualifier. The only other unqualified field accesses it
|
||||
// emits are for compiler-generated constructors and destructors. When we
|
||||
// filter those out, there are only pointer-to-field literals left.
|
||||
not this.isCompilerGenerated()
|
||||
not this.isCompilerGenerated() and not exists(this.getQualifier())
|
||||
}
|
||||
|
||||
override predicate isConstant() { any() }
|
||||
|
||||
15
cpp/ql/lib/semmle/code/cpp/internal/ExtractorVersion.qll
Normal file
15
cpp/ql/lib/semmle/code/cpp/internal/ExtractorVersion.qll
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* INTERNAL: Do not use. Provides predicates for getting the CodeQL and frontend
|
||||
* version used during database extraction.
|
||||
*/
|
||||
|
||||
/** Get the extractor CodeQL version */
|
||||
string getExtractorCodeQLVersion() { extractor_version(result, _) }
|
||||
|
||||
/** Get the extractor frontend version */
|
||||
string getExtractorFrontendVersion() { extractor_version(_, result) }
|
||||
|
||||
predicate isExtractorFrontendVersion65OrHigher() {
|
||||
// Version numbers we not included in the database before 6.5.
|
||||
exists(getExtractorCodeQLVersion())
|
||||
}
|
||||
@@ -7,9 +7,12 @@ private import DataFlowImplCommon as DataFlowImplCommon
|
||||
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
*
|
||||
* This predicate does not take additional call targets
|
||||
* from `AdditionalCallTarget` into account.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
DataFlowCallable defaultViableCallable(DataFlowCall call) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
result = call.getStaticCallTarget()
|
||||
or
|
||||
@@ -29,6 +32,17 @@ DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
result = call.(VirtualDispatch::DataSensitiveCall).resolve()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a function that might be called by `call`.
|
||||
*/
|
||||
cached
|
||||
DataFlowCallable viableCallable(DataFlowCall call) {
|
||||
result = defaultViableCallable(call)
|
||||
or
|
||||
// Additional call targets
|
||||
result = any(AdditionalCallTarget additional).viableTarget(call.getUnconvertedResultExpression())
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides virtual dispatch support compatible with the original
|
||||
* implementation of `semmle.code.cpp.security.TaintTracking`.
|
||||
|
||||
@@ -14,6 +14,7 @@ private import DataFlowPrivate
|
||||
private import ModelUtil
|
||||
private import SsaInternals as Ssa
|
||||
private import DataFlowImplCommon as DataFlowImplCommon
|
||||
private import codeql.util.Unit
|
||||
|
||||
/**
|
||||
* The IR dataflow graph consists of the following nodes:
|
||||
@@ -43,11 +44,12 @@ private newtype TIRDataFlowNode =
|
||||
TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) {
|
||||
Ssa::isModifiableByCall(operand, indirectionIndex)
|
||||
} or
|
||||
TRawIndirectOperand(Operand op, int indirectionIndex) {
|
||||
Ssa::hasRawIndirectOperand(op, indirectionIndex)
|
||||
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
|
||||
Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
|
||||
} or
|
||||
TRawIndirectInstruction(Instruction instr, int indirectionIndex) {
|
||||
Ssa::hasRawIndirectInstruction(instr, indirectionIndex)
|
||||
TRawIndirectInstruction0(Node0Impl node, int indirectionIndex) {
|
||||
not exists(node.asOperand()) and
|
||||
Ssa::hasRawIndirectInstruction(node.asInstruction(), indirectionIndex)
|
||||
} or
|
||||
TFinalParameterNode(Parameter p, int indirectionIndex) {
|
||||
exists(Ssa::FinalParameterUse use |
|
||||
@@ -917,48 +919,146 @@ Type getTypeImpl(Type t, int indirectionIndex) {
|
||||
result instanceof UnknownType
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an operand in the IR
|
||||
* after `index` number of loads.
|
||||
*/
|
||||
class RawIndirectOperand extends Node, TRawIndirectOperand {
|
||||
Operand operand;
|
||||
int indirectionIndex;
|
||||
private module RawIndirectNodes {
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an operand in the IR
|
||||
* after `index` number of loads.
|
||||
*/
|
||||
private class RawIndirectOperand0 extends Node, TRawIndirectOperand0 {
|
||||
Node0Impl node;
|
||||
int indirectionIndex;
|
||||
|
||||
RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) }
|
||||
RawIndirectOperand0() { this = TRawIndirectOperand0(node, indirectionIndex) }
|
||||
|
||||
/** Gets the underlying instruction. */
|
||||
Operand getOperand() { result = operand }
|
||||
/** Gets the underlying instruction. */
|
||||
Operand getOperand() { result = node.asOperand() }
|
||||
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Declaration getFunction() { result = this.getOperand().getDef().getEnclosingFunction() }
|
||||
override Declaration getFunction() {
|
||||
result = this.getOperand().getDef().getEnclosingFunction()
|
||||
}
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getOperandType(operand, isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
)
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getOperandType(this.getOperand(), isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
)
|
||||
}
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
if exists(this.getOperand().getLocation())
|
||||
then result = this.getOperand().getLocation()
|
||||
else result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
override string toStringImpl() {
|
||||
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
|
||||
}
|
||||
}
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
if exists(this.getOperand().getLocation())
|
||||
then result = this.getOperand().getLocation()
|
||||
else result instanceof UnknownDefaultLocation
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an instruction in the IR
|
||||
* after `index` number of loads.
|
||||
*/
|
||||
private class RawIndirectInstruction0 extends Node, TRawIndirectInstruction0 {
|
||||
Node0Impl node;
|
||||
int indirectionIndex;
|
||||
|
||||
RawIndirectInstruction0() { this = TRawIndirectInstruction0(node, indirectionIndex) }
|
||||
|
||||
/** Gets the underlying instruction. */
|
||||
Instruction getInstruction() { result = node.asInstruction() }
|
||||
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getInstructionType(this.getInstruction(), isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
)
|
||||
}
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
if exists(this.getInstruction().getLocation())
|
||||
then result = this.getInstruction().getLocation()
|
||||
else result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
override string toStringImpl() {
|
||||
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
|
||||
}
|
||||
}
|
||||
|
||||
override string toStringImpl() {
|
||||
result = operandNode(this.getOperand()).toStringImpl() + " indirection"
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an operand in the IR
|
||||
* after a number of loads.
|
||||
*/
|
||||
class RawIndirectOperand extends Node {
|
||||
int indirectionIndex;
|
||||
Operand operand;
|
||||
|
||||
RawIndirectOperand() {
|
||||
exists(Node0Impl node | operand = node.asOperand() |
|
||||
this = TRawIndirectOperand0(node, indirectionIndex)
|
||||
or
|
||||
this = TRawIndirectInstruction0(node, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the operand associated with this node. */
|
||||
Operand getOperand() { result = operand }
|
||||
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an instruction in the IR
|
||||
* after a number of loads.
|
||||
*/
|
||||
class RawIndirectInstruction extends Node {
|
||||
int indirectionIndex;
|
||||
Instruction instr;
|
||||
|
||||
RawIndirectInstruction() {
|
||||
exists(Node0Impl node | instr = node.asInstruction() |
|
||||
this = TRawIndirectOperand0(node, indirectionIndex)
|
||||
or
|
||||
this = TRawIndirectInstruction0(node, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the instruction associated with this node. */
|
||||
Instruction getInstruction() { result = instr }
|
||||
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
}
|
||||
}
|
||||
|
||||
import RawIndirectNodes
|
||||
|
||||
/**
|
||||
* INTERNAL: do not use.
|
||||
*
|
||||
@@ -1020,48 +1120,6 @@ class UninitializedNode extends Node {
|
||||
LocalVariable getLocalVariable() { result = v }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* A node that represents the indirect value of an instruction in the IR
|
||||
* after `index` number of loads.
|
||||
*/
|
||||
class RawIndirectInstruction extends Node, TRawIndirectInstruction {
|
||||
Instruction instr;
|
||||
int indirectionIndex;
|
||||
|
||||
RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) }
|
||||
|
||||
/** Gets the underlying instruction. */
|
||||
Instruction getInstruction() { result = instr }
|
||||
|
||||
/** Gets the underlying indirection index. */
|
||||
int getIndirectionIndex() { result = indirectionIndex }
|
||||
|
||||
override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
|
||||
override DataFlowType getType() {
|
||||
exists(int sub, DataFlowType type, boolean isGLValue |
|
||||
type = getInstructionType(instr, isGLValue) and
|
||||
if isGLValue = true then sub = 1 else sub = 0
|
||||
|
|
||||
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
|
||||
)
|
||||
}
|
||||
|
||||
final override Location getLocationImpl() {
|
||||
if exists(this.getInstruction().getLocation())
|
||||
then result = this.getInstruction().getLocation()
|
||||
else result instanceof UnknownDefaultLocation
|
||||
}
|
||||
|
||||
override string toStringImpl() {
|
||||
result = instructionNode(this.getInstruction()).toStringImpl() + " indirection"
|
||||
}
|
||||
}
|
||||
|
||||
private module GetConvertedResultExpression {
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedExpr
|
||||
private import semmle.code.cpp.ir.implementation.raw.internal.InstructionTag
|
||||
@@ -1599,26 +1657,29 @@ private module Cached {
|
||||
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
|
||||
|
||||
private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) {
|
||||
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
|
||||
exists(int ind, LoadInstruction load |
|
||||
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
|
||||
nodeHasInstruction(nodeTo, load, ind - 1)
|
||||
)
|
||||
or
|
||||
// If an operand flows to an instruction, then the indirection of
|
||||
// the operand also flows to the indirection of the instruction.
|
||||
exists(Operand operand, Instruction instr, int indirectionIndex |
|
||||
simpleInstructionLocalFlowStep(operand, instr) and
|
||||
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
|
||||
)
|
||||
or
|
||||
// If there's indirect flow to an operand, then there's also indirect
|
||||
// flow to the operand after applying some pointer arithmetic.
|
||||
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
|
||||
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
|
||||
pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
|
||||
nodeFrom != nodeTo and
|
||||
(
|
||||
// Reduce the indirection count by 1 if we're passing through a `LoadInstruction`.
|
||||
exists(int ind, LoadInstruction load |
|
||||
hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and
|
||||
nodeHasInstruction(nodeTo, load, ind - 1)
|
||||
)
|
||||
or
|
||||
// If an operand flows to an instruction, then the indirection of
|
||||
// the operand also flows to the indirection of the instruction.
|
||||
exists(Operand operand, Instruction instr, int indirectionIndex |
|
||||
simpleInstructionLocalFlowStep(operand, instr) and
|
||||
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
|
||||
)
|
||||
or
|
||||
// If there's indirect flow to an operand, then there's also indirect
|
||||
// flow to the operand after applying some pointer arithmetic.
|
||||
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
|
||||
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
|
||||
pragma[only_bind_into](indirectionIndex)) and
|
||||
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1644,6 +1705,7 @@ private module Cached {
|
||||
private predicate indirectionInstructionFlow(
|
||||
RawIndirectInstruction nodeFrom, IndirectOperand nodeTo
|
||||
) {
|
||||
nodeFrom != nodeTo and
|
||||
// If there's flow from an instruction to an operand, then there's also flow from the
|
||||
// indirect instruction to the indirect operand.
|
||||
exists(Operand operand, Instruction instr, int indirectionIndex |
|
||||
@@ -2237,3 +2299,43 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A unit class for adding additional call steps.
|
||||
*
|
||||
* Extend this class to add additional call steps to the data flow graph.
|
||||
*
|
||||
* For example, if the following subclass is added:
|
||||
* ```ql
|
||||
* class MyAdditionalCallTarget extends DataFlow::AdditionalCallTarget {
|
||||
* override Function viableTarget(Call call) {
|
||||
* call.getTarget().hasName("f") and
|
||||
* result.hasName("g")
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
* then flow from `source()` to `x` in `sink(x)` is reported in the following example:
|
||||
* ```cpp
|
||||
* void sink(int);
|
||||
* int source();
|
||||
* void f(int);
|
||||
*
|
||||
* void g(int x) {
|
||||
* sink(x);
|
||||
* }
|
||||
*
|
||||
* void test() {
|
||||
* int x = source();
|
||||
* f(x);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Note: To prevent reevaluation of cached dataflow-related predicates any
|
||||
* subclass of `AdditionalCallTarget` must be imported in all dataflow queries.
|
||||
*/
|
||||
class AdditionalCallTarget extends Unit {
|
||||
/**
|
||||
* Gets a viable target for `call`.
|
||||
*/
|
||||
abstract DataFlowCallable viableTarget(Call call);
|
||||
}
|
||||
|
||||
@@ -31,26 +31,35 @@ DataFlow::Node callInput(CallInstruction call, FunctionInput input) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the node that represents the output of `call` with kind `output` at
|
||||
* indirection index `indirectionIndex`.
|
||||
*/
|
||||
private Node callOutputWithIndirectionIndex(
|
||||
CallInstruction call, FunctionOutput output, int indirectionIndex
|
||||
) {
|
||||
// The return value
|
||||
simpleOutNode(result, call) and
|
||||
output.isReturnValue() and
|
||||
indirectionIndex = 0
|
||||
or
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
exists(int index |
|
||||
result.(IndirectArgumentOutNode).getArgumentIndex() = index and
|
||||
result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex - 1 and
|
||||
result.(IndirectArgumentOutNode).getCallInstruction() = call and
|
||||
output.isParameterDerefOrQualifierObject(index, indirectionIndex - 1)
|
||||
)
|
||||
or
|
||||
result = getIndirectReturnOutNode(call, indirectionIndex) and
|
||||
output.isReturnValueDeref(indirectionIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction that holds the `output` for `call`.
|
||||
*/
|
||||
Node callOutput(CallInstruction call, FunctionOutput output) {
|
||||
// The return value
|
||||
simpleOutNode(result, call) and
|
||||
output.isReturnValue()
|
||||
or
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
exists(int index, int indirectionIndex |
|
||||
result.(IndirectArgumentOutNode).getArgumentIndex() = index and
|
||||
result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and
|
||||
result.(IndirectArgumentOutNode).getCallInstruction() = call and
|
||||
output.isParameterDerefOrQualifierObject(index, indirectionIndex)
|
||||
)
|
||||
or
|
||||
exists(int ind |
|
||||
result = getIndirectReturnOutNode(call, ind) and
|
||||
output.isReturnValueDeref(ind)
|
||||
)
|
||||
result = callOutputWithIndirectionIndex(call, output, _)
|
||||
}
|
||||
|
||||
DataFlow::Node callInput(CallInstruction call, FunctionInput input, int d) {
|
||||
@@ -76,19 +85,15 @@ private IndirectReturnOutNode getIndirectReturnOutNode(CallInstruction call, int
|
||||
*/
|
||||
bindingset[d]
|
||||
Node callOutput(CallInstruction call, FunctionOutput output, int d) {
|
||||
exists(DataFlow::Node n | n = callOutput(call, output) and d > 0 |
|
||||
exists(DataFlow::Node n, int indirectionIndex |
|
||||
n = callOutputWithIndirectionIndex(call, output, indirectionIndex) and d > 0
|
||||
|
|
||||
// The return value
|
||||
result = getIndirectReturnOutNode(n.asInstruction(), d)
|
||||
result = callOutputWithIndirectionIndex(call, output, indirectionIndex + d)
|
||||
or
|
||||
// If there isn't an indirect out node for the call with indirection `d` then
|
||||
// we conflate this with the underlying `CallInstruction`.
|
||||
not exists(getIndirectReturnOutNode(call, d)) and
|
||||
not exists(getIndirectReturnOutNode(call, indirectionIndex + d)) and
|
||||
n = result
|
||||
or
|
||||
// The side effect of a call on the value pointed to by an argument or qualifier
|
||||
exists(Operand operand, int indirectionIndex |
|
||||
Ssa::outNodeHasAddressAndIndex(n, operand, indirectionIndex) and
|
||||
Ssa::outNodeHasAddressAndIndex(result, operand, indirectionIndex + d)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ private class PointerWrapperTypeIndirection extends Indirection instanceof Point
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
this = call.getStaticCallTarget().getClassAndName("operator*") and
|
||||
this = call.getStaticCallTarget().getClassAndName(["operator*", "operator->", "get"]) and
|
||||
address = call.getThisArgumentOperand()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
private import cpp
|
||||
import semmle.code.cpp.ir.implementation.raw.IR
|
||||
private import semmle.code.cpp.internal.ExtractorVersion
|
||||
private import semmle.code.cpp.ir.IRConfiguration
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
@@ -361,6 +362,12 @@ predicate ignoreLoad(Expr expr) {
|
||||
or
|
||||
expr instanceof FunctionAccess
|
||||
or
|
||||
// The load is duplicated from the operand.
|
||||
isExtractorFrontendVersion65OrHigher() and expr instanceof ParenthesisExpr
|
||||
or
|
||||
// The load is duplicated from the right operand.
|
||||
isExtractorFrontendVersion65OrHigher() and expr instanceof CommaExpr
|
||||
or
|
||||
expr.(PointerDereferenceExpr).getOperand().getFullyConverted().getType().getUnspecifiedType()
|
||||
instanceof FunctionPointerType
|
||||
or
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.internal.ExtractorVersion
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
@@ -649,7 +650,9 @@ class TranslatedPrefixCrementOperation extends TranslatedCrementOperation {
|
||||
override PrefixCrementOperation expr;
|
||||
|
||||
override Instruction getResult() {
|
||||
if expr.isPRValueCategory()
|
||||
// The following distinction is needed to work around extractor limitations
|
||||
// in old versions of the extractor.
|
||||
if expr.isPRValueCategory() and not isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
// If this is C, then the result of a prefix crement is a prvalue for the
|
||||
// new value assigned to the operand. If this is C++, then the result is
|
||||
@@ -1504,7 +1507,9 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
|
||||
}
|
||||
|
||||
final override Instruction getResult() {
|
||||
if expr.isPRValueCategory()
|
||||
// The following distinction is needed to work around extractor limitations
|
||||
// in old versions of the extractor.
|
||||
if expr.isPRValueCategory() and not isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
// If this is C, then the result of an assignment is a prvalue for the new
|
||||
// value assigned to the left operand. If this is C++, then the result is
|
||||
@@ -1642,7 +1647,9 @@ class TranslatedAssignOperation extends TranslatedNonConstantExpr {
|
||||
}
|
||||
|
||||
final override Instruction getResult() {
|
||||
if expr.isPRValueCategory()
|
||||
// The following distinction is needed to work around extractor limitations
|
||||
// in old versions of the extractor.
|
||||
if expr.isPRValueCategory() and not isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
// If this is C, then the result of an assignment is a prvalue for the new
|
||||
// value assigned to the left operand. If this is C++, then the result is
|
||||
@@ -2191,8 +2198,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
not this.elseIsVoid() and tag = ConditionValueFalseStoreTag()
|
||||
) and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = this.getResultType()
|
||||
if isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
not expr.hasLValueToRValueConversion() and
|
||||
resultType = this.getResultType()
|
||||
or
|
||||
expr.hasLValueToRValueConversion() and
|
||||
resultType = getTypeForPRValue(expr.getType())
|
||||
else resultType = this.getResultType()
|
||||
or
|
||||
(not expr.hasLValueToRValueConversion() or not isExtractorFrontendVersion65OrHigher()) and
|
||||
tag = ConditionValueResultLoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = this.getResultType()
|
||||
@@ -2222,8 +2237,16 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
)
|
||||
or
|
||||
tag = ConditionValueResultTempAddressTag() and
|
||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
if isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
not expr.hasLValueToRValueConversion() and
|
||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
or
|
||||
expr.hasLValueToRValueConversion() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
or
|
||||
(not expr.hasLValueToRValueConversion() or not isExtractorFrontendVersion65OrHigher()) and
|
||||
tag = ConditionValueResultLoadTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
@@ -2252,18 +2275,24 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
result = this.getElse().getResult()
|
||||
)
|
||||
or
|
||||
(not expr.hasLValueToRValueConversion() or not isExtractorFrontendVersion65OrHigher()) and
|
||||
tag = ConditionValueResultLoadTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
||||
)
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
||||
)
|
||||
}
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
not this.resultIsVoid() and
|
||||
tag = ConditionValueTempVar() and
|
||||
type = this.getResultType()
|
||||
if isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
not expr.hasLValueToRValueConversion() and
|
||||
type = this.getResultType()
|
||||
or
|
||||
expr.hasLValueToRValueConversion() and
|
||||
type = getTypeForPRValue(expr.getType())
|
||||
else type = this.getResultType()
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -2278,7 +2307,14 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
|
||||
final override Instruction getResult() {
|
||||
not this.resultIsVoid() and
|
||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
if isExtractorFrontendVersion65OrHigher()
|
||||
then
|
||||
expr.hasLValueToRValueConversion() and
|
||||
result = this.getInstruction(ConditionValueResultTempAddressTag())
|
||||
or
|
||||
not expr.hasLValueToRValueConversion() and
|
||||
result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
else result = this.getInstruction(ConditionValueResultLoadTag())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
@@ -3238,10 +3274,18 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) {
|
||||
expr instanceof AssignExpr
|
||||
or
|
||||
expr instanceof AssignOperation and
|
||||
not expr.isPRValueCategory() // is C++
|
||||
(
|
||||
not expr.isPRValueCategory() // is C++
|
||||
or
|
||||
isExtractorFrontendVersion65OrHigher()
|
||||
)
|
||||
or
|
||||
expr instanceof PrefixCrementOperation and
|
||||
not expr.isPRValueCategory() // is C++
|
||||
(
|
||||
not expr.isPRValueCategory() // is C++
|
||||
or
|
||||
isExtractorFrontendVersion65OrHigher()
|
||||
)
|
||||
or
|
||||
// Because the load is on the `e` in `e++`.
|
||||
expr instanceof PostfixCrementOperation
|
||||
|
||||
@@ -19,6 +19,7 @@ private import implementations.Strtok
|
||||
private import implementations.Strset
|
||||
private import implementations.Strcrement
|
||||
private import implementations.Strnextc
|
||||
private import implementations.Strtol
|
||||
private import implementations.StdContainer
|
||||
private import implementations.StdPair
|
||||
private import implementations.StdMap
|
||||
@@ -34,6 +35,7 @@ private import implementations.Accept
|
||||
private import implementations.Poll
|
||||
private import implementations.Select
|
||||
private import implementations.MySql
|
||||
private import implementations.ODBC
|
||||
private import implementations.SqLite3
|
||||
private import implementations.PostgreSql
|
||||
private import implementations.System
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.models.interfaces.Allocation
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
/**
|
||||
* An allocation function (such as `malloc`) that has an argument for the size
|
||||
@@ -121,7 +122,7 @@ private class CallocAllocationFunction extends AllocationFunction {
|
||||
* An allocation function (such as `realloc`) that has an argument for the size
|
||||
* in bytes, and an argument for an existing pointer that is to be reallocated.
|
||||
*/
|
||||
private class ReallocAllocationFunction extends AllocationFunction {
|
||||
private class ReallocAllocationFunction extends AllocationFunction, TaintFunction {
|
||||
int sizeArg;
|
||||
int reallocArg;
|
||||
|
||||
@@ -151,6 +152,10 @@ private class ReallocAllocationFunction extends AllocationFunction {
|
||||
override int getSizeArg() { result = sizeArg }
|
||||
|
||||
override int getReallocPtrArg() { result = reallocArg }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameterDeref(this.getReallocPtrArg()) and output.isReturnValueDeref()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -157,7 +157,7 @@ private class Getaddrinfo extends TaintFunction, ArrayFunction, RemoteFlowSource
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam in [0, 1] }
|
||||
|
||||
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
|
||||
output.isParameterDeref(3) and
|
||||
output.isParameterDeref(3, 2) and
|
||||
description = "address returned by " + this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,18 +9,17 @@ import semmle.code.cpp.models.interfaces.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
/**
|
||||
* The standard function `memset` and its assorted variants
|
||||
*/
|
||||
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
|
||||
private class MemsetFunctionModel extends ArrayFunction, DataFlowFunction, AliasFunction,
|
||||
SideEffectFunction
|
||||
{
|
||||
MemsetFunction() {
|
||||
MemsetFunctionModel() {
|
||||
this.hasGlobalOrStdOrBslName("memset")
|
||||
or
|
||||
this.hasGlobalOrStdName("wmemset")
|
||||
or
|
||||
this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"])
|
||||
this.hasGlobalName([
|
||||
bzero(), "__builtin_memset", "__builtin_memset_chk", "RtlZeroMemory", "RtlSecureZeroMemory"
|
||||
])
|
||||
}
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
@@ -60,3 +59,8 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
|
||||
}
|
||||
|
||||
private string bzero() { result = ["bzero", "explicit_bzero"] }
|
||||
|
||||
/**
|
||||
* The standard function `memset` and its assorted variants
|
||||
*/
|
||||
class MemsetFunction extends Function instanceof MemsetFunctionModel { }
|
||||
|
||||
28
cpp/ql/lib/semmle/code/cpp/models/implementations/ODBC.qll
Normal file
28
cpp/ql/lib/semmle/code/cpp/models/implementations/ODBC.qll
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Provides implementation classes modeling the ODBC C/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 `SQLExecDirect`, and `SQLPrepare` from the ODBC C/C++ API:
|
||||
* https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlexecdirect-function?view=sql-server-ver16
|
||||
* https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlprepare-function?view=sql-server-ver16
|
||||
*
|
||||
* Note, `SQLExecute` is not included because it operates on a SQLHSTMT type, not a string.
|
||||
* The SQLHSTMT parameter for `SQLExecute` is set through a `SQLPrepare`, which is modeled.
|
||||
* The other source of input to a `SQLExecute` is via a `SQLBindParameter`, which sanitizes user input,
|
||||
* and would be considered a barrier to SQL injection.
|
||||
*/
|
||||
private class ODBCExecutionFunction extends SqlExecutionFunction {
|
||||
ODBCExecutionFunction() { this.hasGlobalName(["SQLExecDirect", "SQLPrepare"]) }
|
||||
|
||||
override predicate hasSqlArgument(FunctionInput input) { input.isParameterDeref(1) }
|
||||
}
|
||||
// NOTE: no need to define a barrier explicitly.
|
||||
// `SQLBindParameter` is the typical means for sanitizing user input.
|
||||
// https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindparameter-function?view=sql-server-ver16
|
||||
// First a query is establisehed via `SQLPrepare`, then parameters are bound via `SQLBindParameter`, before
|
||||
// the query is executed via `SQLExecute`. We are not modeling SQLExecute, so we do not need to model SQLBindParameter.
|
||||
@@ -13,7 +13,7 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
|
||||
PureStrFunction() {
|
||||
this.hasGlobalOrStdOrBslName([
|
||||
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
|
||||
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr()
|
||||
"strspn", strrev(), strcmp(), strlwr(), strupr()
|
||||
])
|
||||
}
|
||||
|
||||
@@ -70,8 +70,6 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
|
||||
|
||||
private string atoi() { result = ["atof", "atoi", "atol", "atoll"] }
|
||||
|
||||
private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] }
|
||||
|
||||
private string strlwr() {
|
||||
result = ["_strlwr", "_wcslwr", "_mbslwr", "_strlwr_l", "_wcslwr_l", "_mbslwr_l"]
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ private class Send extends AliasFunction, ArrayFunction, SideEffectFunction, Rem
|
||||
override ParameterIndex getParameterSizeIndex(ParameterIndex i) { i = 1 and result = 2 }
|
||||
|
||||
override predicate hasRemoteFlowSink(FunctionInput input, string description) {
|
||||
input.isParameterDeref(1) and description = "buffer sent by " + this.getName()
|
||||
input.isParameterDeref(1, 1) and description = "buffer sent by " + this.getName()
|
||||
}
|
||||
|
||||
override predicate hasSocketInput(FunctionInput input) { input.isParameter(0) }
|
||||
|
||||
@@ -32,6 +32,8 @@ private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEf
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(0) and output.isReturnValue()
|
||||
or
|
||||
input.isParameterDeref(0) and output.isReturnValueDeref()
|
||||
}
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { none() }
|
||||
|
||||
54
cpp/ql/lib/semmle/code/cpp/models/implementations/Strtol.qll
Normal file
54
cpp/ql/lib/semmle/code/cpp/models/implementations/Strtol.qll
Normal file
@@ -0,0 +1,54 @@
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Taint
|
||||
import semmle.code.cpp.models.interfaces.Alias
|
||||
import semmle.code.cpp.models.interfaces.SideEffect
|
||||
|
||||
private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] }
|
||||
|
||||
/**
|
||||
* The standard function `strtol` and its assorted variants
|
||||
*/
|
||||
private class Strtol extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction {
|
||||
Strtol() { this.hasGlobalOrStdOrBslName(strtol()) }
|
||||
|
||||
override predicate hasArrayInput(int bufParam) {
|
||||
// All the functions given by `strtol()` takes a `const char*` input as the first parameter
|
||||
bufParam = 0
|
||||
}
|
||||
|
||||
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
(
|
||||
input.isParameter(0)
|
||||
or
|
||||
input.isParameterDeref(0)
|
||||
) and
|
||||
output.isReturnValue()
|
||||
or
|
||||
input.isParameter(0) and
|
||||
output.isParameterDeref(1)
|
||||
}
|
||||
|
||||
override predicate parameterNeverEscapes(int i) {
|
||||
// Parameter 0 does escape into parameter 1.
|
||||
i = 1
|
||||
}
|
||||
|
||||
override predicate parameterEscapesOnlyViaReturn(int i) { none() }
|
||||
|
||||
override predicate parameterIsAlwaysReturned(int i) { none() }
|
||||
|
||||
override predicate hasOnlySpecificReadSideEffects() { any() }
|
||||
|
||||
override predicate hasOnlySpecificWriteSideEffects() { any() }
|
||||
|
||||
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
|
||||
i = 0 and
|
||||
buffer = true
|
||||
}
|
||||
|
||||
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
|
||||
i = 1 and buffer = false and mustWrite = false
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import semmle.code.cpp.Parameter
|
||||
|
||||
private newtype TFunctionInput =
|
||||
TInParameter(ParameterIndex i) or
|
||||
TInParameterDeref(ParameterIndex i) or
|
||||
TInParameterDeref(ParameterIndex i, int indirectionIndex) { indirectionIndex = [1, 2] } or
|
||||
TInQualifierObject() or
|
||||
TInQualifierAddress() or
|
||||
TInReturnValueDeref()
|
||||
@@ -245,15 +245,18 @@ class InParameter extends FunctionInput, TInParameter {
|
||||
*/
|
||||
class InParameterDeref extends FunctionInput, TInParameterDeref {
|
||||
ParameterIndex index;
|
||||
int indirectionIndex;
|
||||
|
||||
InParameterDeref() { this = TInParameterDeref(index) }
|
||||
InParameterDeref() { this = TInParameterDeref(index, indirectionIndex) }
|
||||
|
||||
override string toString() { result = "InParameterDeref " + index.toString() }
|
||||
|
||||
/** Gets the zero-based index of the parameter. */
|
||||
ParameterIndex getIndex() { result = index }
|
||||
|
||||
override predicate isParameterDeref(ParameterIndex i) { i = index }
|
||||
override predicate isParameterDeref(ParameterIndex i, int indirection) {
|
||||
i = index and indirectionIndex = indirection
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,10 +324,10 @@ class InReturnValueDeref extends FunctionInput, TInReturnValueDeref {
|
||||
}
|
||||
|
||||
private newtype TFunctionOutput =
|
||||
TOutParameterDeref(ParameterIndex i) or
|
||||
TOutParameterDeref(ParameterIndex i, int indirectionIndex) { indirectionIndex = [1, 2] } or
|
||||
TOutQualifierObject() or
|
||||
TOutReturnValue() or
|
||||
TOutReturnValueDeref()
|
||||
TOutReturnValueDeref(int indirections) { indirections = [1, 2] }
|
||||
|
||||
/**
|
||||
* An output from a function. This can be:
|
||||
@@ -498,17 +501,16 @@ class FunctionOutput extends TFunctionOutput {
|
||||
*/
|
||||
class OutParameterDeref extends FunctionOutput, TOutParameterDeref {
|
||||
ParameterIndex index;
|
||||
int indirectionIndex;
|
||||
|
||||
OutParameterDeref() { this = TOutParameterDeref(index) }
|
||||
OutParameterDeref() { this = TOutParameterDeref(index, indirectionIndex) }
|
||||
|
||||
override string toString() { result = "OutParameterDeref " + index.toString() }
|
||||
|
||||
ParameterIndex getIndex() { result = index }
|
||||
|
||||
override predicate isParameterDeref(ParameterIndex i) { i = index }
|
||||
|
||||
override predicate isParameterDeref(ParameterIndex i, int ind) {
|
||||
this.isParameterDeref(i) and ind = 1
|
||||
i = index and ind = indirectionIndex
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,4 +574,8 @@ class OutReturnValueDeref extends FunctionOutput, TOutReturnValueDeref {
|
||||
override string toString() { result = "OutReturnValueDeref" }
|
||||
|
||||
override predicate isReturnValueDeref() { any() }
|
||||
|
||||
override predicate isReturnValueDeref(int indirectionIndex) {
|
||||
this = TOutReturnValueDeref(indirectionIndex)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,7 @@ private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
* `upper` is true, and can be traced back to a guard represented by `reason`.
|
||||
*/
|
||||
predicate bounded(Expr e, Bound b, float delta, boolean upper, Reason reason) {
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getUnconvertedResultExpression() = e
|
||||
|
|
||||
exists(SemanticExprConfig::Expr semExpr | semExpr.getUnconvertedResultExpression() = e |
|
||||
semBounded(semExpr, b, delta, upper, reason)
|
||||
)
|
||||
}
|
||||
@@ -30,9 +28,7 @@ predicate bounded(Expr e, Bound b, float delta, boolean upper, Reason reason) {
|
||||
* The `Expr` may be a conversion.
|
||||
*/
|
||||
predicate convertedBounded(Expr e, Bound b, float delta, boolean upper, Reason reason) {
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getConverted().getConvertedResultExpression() = e
|
||||
|
|
||||
exists(SemanticExprConfig::Expr semExpr | semExpr.getConvertedResultExpression() = e |
|
||||
semBounded(semExpr, b, delta, upper, reason)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ predicate exprMightOverflowNegatively(Expr expr) {
|
||||
lowerBound(expr) < exprMinVal(expr)
|
||||
or
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getAst() = expr and
|
||||
semExpr.getAst() = expr and
|
||||
ConstantStage::potentiallyOverflowingExpr(false, semExpr) and
|
||||
not ConstantStage::initialBounded(semExpr, _, _, false, _, _, _)
|
||||
)
|
||||
@@ -126,7 +126,7 @@ predicate exprMightOverflowPositively(Expr expr) {
|
||||
upperBound(expr) > exprMaxVal(expr)
|
||||
or
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getAst() = expr and
|
||||
semExpr.getAst() = expr and
|
||||
ConstantStage::potentiallyOverflowingExpr(true, semExpr) and
|
||||
not ConstantStage::initialBounded(semExpr, _, _, true, _, _, _)
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
private import Semantic
|
||||
private import SemanticExprSpecific::SemanticExprConfig as Specific
|
||||
private import SemanticType
|
||||
|
||||
/**
|
||||
* An language-neutral expression.
|
||||
@@ -241,8 +242,21 @@ class SemConvertExpr extends SemUnaryExpr {
|
||||
SemConvertExpr() { opcode instanceof Opcode::Convert }
|
||||
}
|
||||
|
||||
private import semmle.code.cpp.ir.IR as IR
|
||||
|
||||
/** A conversion instruction which is guaranteed to not overflow. */
|
||||
private class SafeConversion extends IR::ConvertInstruction {
|
||||
SafeConversion() {
|
||||
exists(SemType tFrom, SemType tTo |
|
||||
tFrom = getSemanticType(super.getUnary().getResultIRType()) and
|
||||
tTo = getSemanticType(super.getResultIRType()) and
|
||||
conversionCannotOverflow(tFrom, tTo)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SemCopyValueExpr extends SemUnaryExpr {
|
||||
SemCopyValueExpr() { opcode instanceof Opcode::CopyValue }
|
||||
SemCopyValueExpr() { opcode instanceof Opcode::CopyValue or this instanceof SafeConversion }
|
||||
}
|
||||
|
||||
class SemNegateExpr extends SemUnaryExpr {
|
||||
|
||||
@@ -12,87 +12,10 @@ private import semmle.code.cpp.ir.ValueNumbering
|
||||
module SemanticExprConfig {
|
||||
class Location = Cpp::Location;
|
||||
|
||||
/** A `ConvertInstruction` or a `CopyValueInstruction`. */
|
||||
private class Conversion extends IR::UnaryInstruction {
|
||||
Conversion() {
|
||||
this instanceof IR::CopyValueInstruction
|
||||
or
|
||||
this instanceof IR::ConvertInstruction
|
||||
}
|
||||
|
||||
/** Holds if this instruction converts a value of type `tFrom` to a value of type `tTo`. */
|
||||
predicate converts(SemType tFrom, SemType tTo) {
|
||||
tFrom = getSemanticType(this.getUnary().getResultIRType()) and
|
||||
tTo = getSemanticType(this.getResultIRType())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a conversion-like instruction that consumes `op`, and
|
||||
* which is guaranteed to not overflow.
|
||||
*/
|
||||
private IR::Instruction safeConversion(IR::Operand op) {
|
||||
exists(Conversion conv, SemType tFrom, SemType tTo |
|
||||
conv.converts(tFrom, tTo) and
|
||||
conversionCannotOverflow(tFrom, tTo) and
|
||||
conv.getUnaryOperand() = op and
|
||||
result = conv
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */
|
||||
private predicate idOrSafeConversion(IR::Instruction i1, IR::Instruction i2) {
|
||||
not i1.getResultIRType() instanceof IR::IRVoidType and
|
||||
(
|
||||
i1 = i2
|
||||
or
|
||||
i2 = safeConversion(i1.getAUse()) and
|
||||
i1.getBlock() = i2.getBlock()
|
||||
)
|
||||
}
|
||||
|
||||
module Equiv = QlBuiltins::EquivalenceRelation<IR::Instruction, idOrSafeConversion/2>;
|
||||
|
||||
/**
|
||||
* The expressions on which we perform range analysis.
|
||||
*/
|
||||
class Expr extends Equiv::EquivalenceClass {
|
||||
/** Gets the n'th instruction in this equivalence class. */
|
||||
private IR::Instruction getInstruction(int n) {
|
||||
result =
|
||||
rank[n + 1](IR::Instruction instr, int i, IR::IRBlock block |
|
||||
this = Equiv::getEquivalenceClass(instr) and block.getInstruction(i) = instr
|
||||
|
|
||||
instr order by i
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.getUnconverted().toString() }
|
||||
|
||||
/** Gets the basic block of this expression. */
|
||||
IR::IRBlock getBlock() { result = this.getUnconverted().getBlock() }
|
||||
|
||||
/** Gets the unconverted instruction associated with this expression. */
|
||||
IR::Instruction getUnconverted() { result = this.getInstruction(0) }
|
||||
|
||||
/**
|
||||
* Gets the final instruction associated with this expression. This
|
||||
* represents the result after applying all the safe conversions.
|
||||
*/
|
||||
IR::Instruction getConverted() {
|
||||
exists(int n |
|
||||
result = this.getInstruction(n) and
|
||||
not exists(this.getInstruction(n + 1))
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the type of the result produced by this instruction. */
|
||||
IR::IRType getResultIRType() { result = this.getConverted().getResultIRType() }
|
||||
|
||||
/** Gets the location of the source code for this expression. */
|
||||
Location getLocation() { result = this.getUnconverted().getLocation() }
|
||||
}
|
||||
class Expr = IR::Instruction;
|
||||
|
||||
SemBasicBlock getExprBasicBlock(Expr e) { result = getSemanticBasicBlock(e.getBlock()) }
|
||||
|
||||
@@ -139,12 +62,12 @@ module SemanticExprConfig {
|
||||
|
||||
predicate stringLiteral(Expr expr, SemType type, string value) {
|
||||
anyConstantExpr(expr, type, value) and
|
||||
expr.getUnconverted() instanceof IR::StringConstantInstruction
|
||||
expr instanceof IR::StringConstantInstruction
|
||||
}
|
||||
|
||||
predicate binaryExpr(Expr expr, Opcode opcode, SemType type, Expr leftOperand, Expr rightOperand) {
|
||||
exists(IR::BinaryInstruction instr |
|
||||
instr = expr.getUnconverted() and
|
||||
instr = expr and
|
||||
type = getSemanticType(instr.getResultIRType()) and
|
||||
leftOperand = getSemanticExpr(instr.getLeft()) and
|
||||
rightOperand = getSemanticExpr(instr.getRight()) and
|
||||
@@ -154,14 +77,14 @@ module SemanticExprConfig {
|
||||
}
|
||||
|
||||
predicate unaryExpr(Expr expr, Opcode opcode, SemType type, Expr operand) {
|
||||
exists(IR::UnaryInstruction instr | instr = expr.getUnconverted() |
|
||||
exists(IR::UnaryInstruction instr | instr = expr |
|
||||
type = getSemanticType(instr.getResultIRType()) and
|
||||
operand = getSemanticExpr(instr.getUnary()) and
|
||||
// REVIEW: Merge the two operand types.
|
||||
opcode.toString() = instr.getOpcode().toString()
|
||||
)
|
||||
or
|
||||
exists(IR::StoreInstruction instr | instr = expr.getUnconverted() |
|
||||
exists(IR::StoreInstruction instr | instr = expr |
|
||||
type = getSemanticType(instr.getResultIRType()) and
|
||||
operand = getSemanticExpr(instr.getSourceValue()) and
|
||||
opcode instanceof Opcode::Store
|
||||
@@ -170,13 +93,13 @@ module SemanticExprConfig {
|
||||
|
||||
predicate nullaryExpr(Expr expr, Opcode opcode, SemType type) {
|
||||
exists(IR::LoadInstruction load |
|
||||
load = expr.getUnconverted() and
|
||||
load = expr and
|
||||
type = getSemanticType(load.getResultIRType()) and
|
||||
opcode instanceof Opcode::Load
|
||||
)
|
||||
or
|
||||
exists(IR::InitializeParameterInstruction init |
|
||||
init = expr.getUnconverted() and
|
||||
init = expr and
|
||||
type = getSemanticType(init.getResultIRType()) and
|
||||
opcode instanceof Opcode::InitializeParameter
|
||||
)
|
||||
@@ -290,9 +213,9 @@ module SemanticExprConfig {
|
||||
}
|
||||
|
||||
Expr getAUse(SsaVariable v) {
|
||||
result.getUnconverted().(IR::LoadInstruction).getSourceValue() = v.asInstruction()
|
||||
result.(IR::LoadInstruction).getSourceValue() = v.asInstruction()
|
||||
or
|
||||
result.getUnconverted() = v.asPointerArithGuard().getAnInstruction()
|
||||
result = v.asPointerArithGuard().getAnInstruction()
|
||||
}
|
||||
|
||||
SemType getSsaVariableType(SsaVariable v) {
|
||||
@@ -433,7 +356,7 @@ module SemanticExprConfig {
|
||||
}
|
||||
|
||||
/** Gets the expression associated with `instr`. */
|
||||
SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) }
|
||||
SemExpr getSemanticExpr(IR::Instruction instr) { result = instr }
|
||||
}
|
||||
|
||||
predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1;
|
||||
|
||||
@@ -8,6 +8,18 @@ class SemLocation instanceof Location {
|
||||
*/
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/** Gets the 1-based line number (inclusive) where this location starts. */
|
||||
int getStartLine() { result = super.getStartLine() }
|
||||
|
||||
/** Gets the 1-based column number (inclusive) where this location starts. */
|
||||
int getStartColumn() { result = super.getStartColumn() }
|
||||
|
||||
/** Gets the 1-based line number (inclusive) where this location ends. */
|
||||
int getEndLine() { result = super.getEndLine() }
|
||||
|
||||
/** Gets the 1-based column number (inclusive) where this location ends. */
|
||||
int getEndColumn() { result = super.getEndColumn() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
|
||||
@@ -23,6 +23,8 @@ class SemSsaExplicitUpdate extends SemSsaVariable {
|
||||
SemSsaExplicitUpdate() { Specific::explicitUpdate(this, sourceExpr) }
|
||||
|
||||
final SemExpr getSourceExpr() { result = sourceExpr }
|
||||
|
||||
final SemExpr getDefiningExpr() { result = sourceExpr }
|
||||
}
|
||||
|
||||
class SemSsaPhiNode extends SemSsaVariable {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisImpl
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType
|
||||
|
||||
module FloatDelta implements DeltaSig {
|
||||
class Delta = float;
|
||||
@@ -20,7 +22,7 @@ module FloatDelta implements DeltaSig {
|
||||
Delta fromFloat(float f) { result = f }
|
||||
}
|
||||
|
||||
module FloatOverflow implements OverflowSig<FloatDelta> {
|
||||
module FloatOverflow implements OverflowSig<Sem, FloatDelta> {
|
||||
predicate semExprDoesNotOverflow(boolean positively, SemExpr expr) {
|
||||
exists(float lb, float ub, float delta |
|
||||
typeBounds(expr.getSemType(), lb, ub) and
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
private import RangeAnalysisStage
|
||||
|
||||
module IntDelta implements DeltaSig {
|
||||
class Delta = int;
|
||||
|
||||
bindingset[d]
|
||||
bindingset[result]
|
||||
float toFloat(Delta d) { result = d }
|
||||
|
||||
bindingset[d]
|
||||
bindingset[result]
|
||||
int toInt(Delta d) { result = d }
|
||||
|
||||
bindingset[n]
|
||||
bindingset[result]
|
||||
Delta fromInt(int n) { result = n }
|
||||
|
||||
bindingset[f]
|
||||
Delta fromFloat(float f) {
|
||||
result =
|
||||
min(float diff, float res |
|
||||
diff = (res - f) and res = f.ceil()
|
||||
or
|
||||
diff = (f - res) and res = f.floor()
|
||||
|
|
||||
res order by diff
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
/**
|
||||
* Provides inferences of the form: `e` equals `b + v` modulo `m` where `e` is
|
||||
* an expression, `b` is a `Bound` (typically zero or the value of an SSA
|
||||
* variable), and `v` is an integer in the range `[0 .. m-1]`.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The main recursion has base cases in both `ssaModulus` (for guarded reads) and `semExprModulus`
|
||||
* (for constant values). The most interesting recursive case is `phiModulusRankStep`, which
|
||||
* handles phi inputs.
|
||||
*/
|
||||
|
||||
private import ModulusAnalysisSpecific::Private
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import ConstantAnalysis
|
||||
private import RangeUtils
|
||||
private import RangeAnalysisStage
|
||||
|
||||
module ModulusAnalysis<DeltaSig D, BoundSig<D> Bounds, UtilSig<D> U> {
|
||||
pragma[nomagic]
|
||||
private predicate valueFlowStepSsaEqFlowCond(
|
||||
SemSsaReadPosition pos, SemSsaVariable v, SemExpr e, int delta
|
||||
) {
|
||||
exists(SemGuard guard, boolean testIsTrue |
|
||||
guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and
|
||||
semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e + delta` equals `v` at `pos`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) {
|
||||
U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v)
|
||||
or
|
||||
pos.hasReadOfVar(v) and
|
||||
valueFlowStepSsaEqFlowCond(pos, v, e, delta)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `add` is the addition of `larg` and `rarg`, neither of which are
|
||||
* `ConstantIntegerExpr`s.
|
||||
*/
|
||||
private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) {
|
||||
exists(SemAddExpr a | a = add |
|
||||
larg = a.getLeftOperand() and
|
||||
rarg = a.getRightOperand()
|
||||
) and
|
||||
not larg instanceof SemConstantIntegerExpr and
|
||||
not rarg instanceof SemConstantIntegerExpr
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not
|
||||
* a `ConstantIntegerExpr`.
|
||||
*/
|
||||
private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) {
|
||||
exists(SemSubExpr s | s = sub |
|
||||
larg = s.getLeftOperand() and
|
||||
rarg = s.getRightOperand()
|
||||
) and
|
||||
not rarg instanceof SemConstantIntegerExpr
|
||||
}
|
||||
|
||||
/** Gets an expression that is the remainder modulo `mod` of `arg`. */
|
||||
private SemExpr modExpr(SemExpr arg, int mod) {
|
||||
exists(SemRemExpr rem |
|
||||
result = rem and
|
||||
arg = rem.getLeftOperand() and
|
||||
rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and
|
||||
mod >= 2
|
||||
)
|
||||
or
|
||||
exists(SemConstantIntegerExpr c |
|
||||
mod = 2.pow([1 .. 30]) and
|
||||
c.getIntValue() = mod - 1 and
|
||||
result.(SemBitAndExpr).hasOperands(arg, c)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on
|
||||
* its `testIsTrue` branch.
|
||||
*/
|
||||
private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) {
|
||||
exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity |
|
||||
result.isEquality(rem, c, polarity) and
|
||||
c.getIntValue() = r and
|
||||
rem = modExpr(v.getAUse(), mod) and
|
||||
(
|
||||
testIsTrue = polarity and val = r
|
||||
or
|
||||
testIsTrue = polarity.booleanNot() and
|
||||
mod = 2 and
|
||||
val = 1 - r and
|
||||
(r = 0 or r = 1)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`.
|
||||
*/
|
||||
private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) {
|
||||
exists(SemGuard guard, boolean testIsTrue |
|
||||
pos.hasReadOfVar(v) and
|
||||
guard = moduloCheck(v, val, mod, testIsTrue) and
|
||||
semGuardControlsSsaRead(guard, pos, testIsTrue)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `factor` is a power of 2 that divides `mask`. */
|
||||
bindingset[mask]
|
||||
private predicate andmaskFactor(int mask, int factor) {
|
||||
mask % factor = 0 and
|
||||
factor = 2.pow([1 .. 30])
|
||||
}
|
||||
|
||||
/** Holds if `e` is evenly divisible by `factor`. */
|
||||
private predicate evenlyDivisibleExpr(SemExpr e, int factor) {
|
||||
exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() |
|
||||
e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2
|
||||
or
|
||||
e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0
|
||||
or
|
||||
e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f))
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the remainder of `val` modulo `mod`.
|
||||
*
|
||||
* For `mod = 0` the result equals `val` and for `mod > 1` the result is within
|
||||
* the range `[0 .. mod-1]`.
|
||||
*/
|
||||
bindingset[val, mod]
|
||||
private int remainder(int val, int mod) {
|
||||
mod = 0 and result = val
|
||||
or
|
||||
mod > 1 and result = ((val % mod) + mod) % mod
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`.
|
||||
*/
|
||||
private predicate phiSelfModulus(
|
||||
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod
|
||||
) {
|
||||
exists(Bounds::SemSsaBound phibound, int v, int m |
|
||||
edge.phiInput(phi, inp) and
|
||||
phibound.getAVariable() = phi and
|
||||
ssaModulus(inp, edge, phibound, v, m) and
|
||||
mod = m.gcd(v) and
|
||||
mod != 1
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`.
|
||||
*/
|
||||
private predicate phiModulusInit(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
|
||||
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge |
|
||||
edge.phiInput(phi, inp) and
|
||||
ssaModulus(inp, edge, b, val, mod)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate phiModulusRankStep(
|
||||
SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix
|
||||
) {
|
||||
/*
|
||||
* base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence
|
||||
* class for the phi node.
|
||||
*/
|
||||
|
||||
rix = 0 and
|
||||
phiModulusInit(phi, b, val, mod)
|
||||
or
|
||||
exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 |
|
||||
mod != 1 and
|
||||
val = remainder(v1, mod)
|
||||
|
|
||||
/*
|
||||
* Recursive case. If `inp` = `b + v2` mod `m2`, we combine that with the preceding potential
|
||||
* congruence class `b + v1` mod `m1`. The result will be the congruence class of `v1` modulo
|
||||
* the greatest common denominator of `m1`, `m2`, and `v1 - v2`.
|
||||
*/
|
||||
|
||||
exists(int v2, int m2 |
|
||||
rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and
|
||||
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
||||
ssaModulus(inp, edge, b, v2, m2) and
|
||||
mod = m1.gcd(m2).gcd(v1 - v2)
|
||||
)
|
||||
or
|
||||
/*
|
||||
* Recursive case. If `inp` = `phi` mod `m2`, we combine that with the preceding potential
|
||||
* congruence class `b + v1` mod `m1`. The result will be a congruence class modulo the greatest
|
||||
* common denominator of `m1` and `m2`.
|
||||
*/
|
||||
|
||||
exists(int m2 |
|
||||
rankedPhiInput(phi, inp, edge, rix) and
|
||||
phiModulusRankStep(phi, b, v1, m1, rix - 1) and
|
||||
phiSelfModulus(phi, inp, edge, m2) and
|
||||
mod = m1.gcd(m2)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `phi` is equal to `b + val` modulo `mod`.
|
||||
*/
|
||||
private predicate phiModulus(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) {
|
||||
exists(int r |
|
||||
maxPhiInputRank(phi, r) and
|
||||
phiModulusRankStep(phi, b, val, mod, r)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `v` at `pos` is equal to `b + val` modulo `mod`.
|
||||
*/
|
||||
private predicate ssaModulus(
|
||||
SemSsaVariable v, SemSsaReadPosition pos, Bounds::SemBound b, int val, int mod
|
||||
) {
|
||||
phiModulus(v, b, val, mod) and pos.hasReadOfVar(v)
|
||||
or
|
||||
b.(Bounds::SemSsaBound).getAVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0
|
||||
or
|
||||
exists(SemExpr e, int val0, int delta |
|
||||
semExprModulus(e, b, val0, mod) and
|
||||
valueFlowStepSsa(v, pos, e, delta) and
|
||||
val = remainder(val0 + delta, mod)
|
||||
)
|
||||
or
|
||||
moduloGuardedRead(v, pos, val, mod) and b instanceof Bounds::SemZeroBound
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is equal to `b + val` modulo `mod`.
|
||||
*
|
||||
* There are two cases for the modulus:
|
||||
* - `mod = 0`: The equality `e = b + val` is an ordinary equality.
|
||||
* - `mod > 1`: `val` lies within the range `[0 .. mod-1]`.
|
||||
*/
|
||||
cached
|
||||
predicate semExprModulus(SemExpr e, Bounds::SemBound b, int val, int mod) {
|
||||
not ignoreExprModulus(e) and
|
||||
(
|
||||
e = b.getExpr(D::fromInt(val)) and mod = 0
|
||||
or
|
||||
evenlyDivisibleExpr(e, mod) and
|
||||
val = 0 and
|
||||
b instanceof Bounds::SemZeroBound
|
||||
or
|
||||
exists(SemSsaVariable v, SemSsaReadPositionBlock bb |
|
||||
ssaModulus(v, bb, b, val, mod) and
|
||||
e = v.getAUse() and
|
||||
bb.getAnExpr() = e
|
||||
)
|
||||
or
|
||||
exists(SemExpr mid, int val0, int delta |
|
||||
semExprModulus(mid, b, val0, mod) and
|
||||
U::semValueFlowStep(e, mid, D::fromInt(delta)) and
|
||||
val = remainder(val0 + delta, mod)
|
||||
)
|
||||
or
|
||||
exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 |
|
||||
cond = e and
|
||||
condExprBranchModulus(cond, true, b, v1, m1) and
|
||||
condExprBranchModulus(cond, false, b, v2, m2) and
|
||||
mod = m1.gcd(m2).gcd(v1 - v2) and
|
||||
mod != 1 and
|
||||
val = remainder(v1, mod)
|
||||
)
|
||||
or
|
||||
exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 |
|
||||
addModulus(e, true, b1, v1, m1) and
|
||||
addModulus(e, false, b2, v2, m2) and
|
||||
mod = m1.gcd(m2) and
|
||||
mod != 1 and
|
||||
val = remainder(v1 + v2, mod)
|
||||
|
|
||||
b = b1 and b2 instanceof Bounds::SemZeroBound
|
||||
or
|
||||
b = b2 and b1 instanceof Bounds::SemZeroBound
|
||||
)
|
||||
or
|
||||
exists(int v1, int v2, int m1, int m2 |
|
||||
subModulus(e, true, b, v1, m1) and
|
||||
subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and
|
||||
mod = m1.gcd(m2) and
|
||||
mod != 1 and
|
||||
val = remainder(v1 - v2, mod)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate condExprBranchModulus(
|
||||
SemConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod
|
||||
) {
|
||||
semExprModulus(cond.getBranchExpr(branch), b, val, mod)
|
||||
}
|
||||
|
||||
private predicate addModulus(SemExpr add, boolean isLeft, Bounds::SemBound b, int val, int mod) {
|
||||
exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) |
|
||||
semExprModulus(larg, b, val, mod) and isLeft = true
|
||||
or
|
||||
semExprModulus(rarg, b, val, mod) and isLeft = false
|
||||
)
|
||||
}
|
||||
|
||||
private predicate subModulus(SemExpr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) {
|
||||
exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) |
|
||||
semExprModulus(larg, b, val, mod) and isLeft = true
|
||||
or
|
||||
semExprModulus(rarg, b, val, mod) and isLeft = false
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* C++-specific implementation of modulus analysis.
|
||||
*/
|
||||
module Private {
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
|
||||
predicate ignoreExprModulus(SemExpr e) { none() }
|
||||
}
|
||||
@@ -3,18 +3,11 @@
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import RangeAnalysisStage
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
private import RangeAnalysisImpl
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
|
||||
module CppLangImplConstant implements LangSig<FloatDelta> {
|
||||
/**
|
||||
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadCopy(SemExpr e) { none() }
|
||||
|
||||
module CppLangImplConstant implements LangSig<Sem, FloatDelta> {
|
||||
/**
|
||||
* Ignore the bound on this expression.
|
||||
*
|
||||
@@ -23,40 +16,6 @@ module CppLangImplConstant implements LangSig<FloatDelta> {
|
||||
*/
|
||||
predicate ignoreExprBound(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Ignore any inferred zero lower bound on this expression.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreZeroLowerBound(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the specified variable should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() }
|
||||
|
||||
/**
|
||||
* Adds additional results to `ssaRead()` that are specific to Java.
|
||||
*
|
||||
* This predicate handles propagation of offsets for post-increment and post-decrement expressions
|
||||
* in exactly the same way as the old Java implementation. Once the new implementation matches the
|
||||
* old one, we should remove this predicate and propagate deltas for all similar patterns, whether
|
||||
* or not they come from a post-increment/decrement expression.
|
||||
*/
|
||||
SemExpr specificSsaRead(SemSsaVariable v, float delta) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`).
|
||||
*/
|
||||
|
||||
@@ -1,13 +1,118 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisConstantSpecific
|
||||
private import RangeAnalysisRelativeSpecific
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
private import RangeUtils
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticCFG
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticGuard
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound as SemanticBound
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticSSA
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType as SemanticType
|
||||
private import SemanticType
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
private import ConstantAnalysis as ConstantAnalysis
|
||||
|
||||
module ConstantBounds implements BoundSig<FloatDelta> {
|
||||
module Sem implements Semantic {
|
||||
class Expr = SemExpr;
|
||||
|
||||
class ConstantIntegerExpr = ConstantAnalysis::SemConstantIntegerExpr;
|
||||
|
||||
class BinaryExpr = SemBinaryExpr;
|
||||
|
||||
class AddExpr = SemAddExpr;
|
||||
|
||||
class SubExpr = SemSubExpr;
|
||||
|
||||
class MulExpr = SemMulExpr;
|
||||
|
||||
class DivExpr = SemDivExpr;
|
||||
|
||||
class RemExpr = SemRemExpr;
|
||||
|
||||
class BitAndExpr = SemBitAndExpr;
|
||||
|
||||
class BitOrExpr = SemBitOrExpr;
|
||||
|
||||
class ShiftLeftExpr = SemShiftLeftExpr;
|
||||
|
||||
class ShiftRightExpr = SemShiftRightExpr;
|
||||
|
||||
class ShiftRightUnsignedExpr = SemShiftRightUnsignedExpr;
|
||||
|
||||
class RelationalExpr = SemRelationalExpr;
|
||||
|
||||
class UnaryExpr = SemUnaryExpr;
|
||||
|
||||
class ConvertExpr = SemConvertExpr;
|
||||
|
||||
class BoxExpr = SemBoxExpr;
|
||||
|
||||
class UnboxExpr = SemUnboxExpr;
|
||||
|
||||
class NegateExpr = SemNegateExpr;
|
||||
|
||||
class PreIncExpr = SemAddOneExpr;
|
||||
|
||||
class PreDecExpr = SemSubOneExpr;
|
||||
|
||||
class PostIncExpr extends SemUnaryExpr {
|
||||
PostIncExpr() { none() }
|
||||
}
|
||||
|
||||
class PostDecExpr extends SemUnaryExpr {
|
||||
PostDecExpr() { none() }
|
||||
}
|
||||
|
||||
class CopyValueExpr extends SemUnaryExpr {
|
||||
CopyValueExpr() { this instanceof SemCopyValueExpr or this instanceof SemStoreExpr }
|
||||
}
|
||||
|
||||
class ConditionalExpr = SemConditionalExpr;
|
||||
|
||||
class BasicBlock = SemBasicBlock;
|
||||
|
||||
class Guard = SemGuard;
|
||||
|
||||
predicate implies_v2 = semImplies_v2/4;
|
||||
|
||||
predicate guardDirectlyControlsSsaRead = semGuardDirectlyControlsSsaRead/3;
|
||||
|
||||
predicate guardControlsSsaRead = semGuardControlsSsaRead/3;
|
||||
|
||||
class Type = SemType;
|
||||
|
||||
class IntegerType = SemIntegerType;
|
||||
|
||||
class FloatingPointType = SemFloatingPointType;
|
||||
|
||||
class AddressType = SemAddressType;
|
||||
|
||||
class SsaVariable = SemSsaVariable;
|
||||
|
||||
class SsaPhiNode = SemSsaPhiNode;
|
||||
|
||||
class SsaExplicitUpdate = SemSsaExplicitUpdate;
|
||||
|
||||
class SsaReadPosition = SemSsaReadPosition;
|
||||
|
||||
class SsaReadPositionPhiInputEdge = SemSsaReadPositionPhiInputEdge;
|
||||
|
||||
class SsaReadPositionBlock = SemSsaReadPositionBlock;
|
||||
|
||||
predicate backEdge = semBackEdge/3;
|
||||
|
||||
predicate conversionCannotOverflow(Type fromType, Type toType) {
|
||||
SemanticType::conversionCannotOverflow(fromType, toType)
|
||||
}
|
||||
}
|
||||
|
||||
module SignAnalysis implements SignAnalysisSig<Sem> {
|
||||
private import SignAnalysisCommon as SA
|
||||
import SA::SignAnalysis<FloatDelta, Util>
|
||||
}
|
||||
|
||||
module ConstantBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
SemBound() {
|
||||
this instanceof SemanticBound::SemZeroBound
|
||||
@@ -25,11 +130,11 @@ module ConstantBounds implements BoundSig<FloatDelta> {
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
SemSsaVariable getVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
module RelativeBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
SemBound() { not this instanceof SemanticBound::SemZeroBound }
|
||||
|
||||
@@ -43,17 +148,42 @@ module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
SemSsaVariable getVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
module AllBounds implements BoundSig<SemLocation, Sem, FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
SemLocation getLocation() { result = super.getLocation() }
|
||||
|
||||
SemExpr getExpr(float delta) { result = super.getExpr(delta) }
|
||||
}
|
||||
|
||||
class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { }
|
||||
|
||||
class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound {
|
||||
SemSsaVariable getVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() }
|
||||
}
|
||||
}
|
||||
|
||||
private module ModulusAnalysisInstantiated implements ModulusAnalysisSig<Sem> {
|
||||
class ModBound = AllBounds::SemBound;
|
||||
|
||||
private import codeql.rangeanalysis.ModulusAnalysis as MA
|
||||
import MA::ModulusAnalysis<SemLocation, Sem, FloatDelta, AllBounds, Util>
|
||||
}
|
||||
|
||||
module Util = RangeUtil<FloatDelta, CppLangImplConstant>;
|
||||
|
||||
module ConstantStage =
|
||||
RangeStage<FloatDelta, ConstantBounds, FloatOverflow, CppLangImplConstant,
|
||||
RangeUtil<FloatDelta, CppLangImplConstant>>;
|
||||
RangeStage<SemLocation, Sem, FloatDelta, ConstantBounds, FloatOverflow, CppLangImplConstant,
|
||||
SignAnalysis, ModulusAnalysisInstantiated, Util>;
|
||||
|
||||
module RelativeStage =
|
||||
RangeStage<FloatDelta, RelativeBounds, FloatOverflow, CppLangImplRelative,
|
||||
RangeUtil<FloatDelta, CppLangImplRelative>>;
|
||||
RangeStage<SemLocation, Sem, FloatDelta, RelativeBounds, FloatOverflow, CppLangImplRelative,
|
||||
SignAnalysis, ModulusAnalysisInstantiated, Util>;
|
||||
|
||||
private newtype TSemReason =
|
||||
TSemNoReason() or
|
||||
|
||||
@@ -3,21 +3,12 @@
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import RangeAnalysisStage
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.IntDelta
|
||||
private import RangeAnalysisImpl
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
|
||||
module CppLangImplRelative implements LangSig<FloatDelta> {
|
||||
/**
|
||||
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadCopy(SemExpr e) { none() }
|
||||
|
||||
module CppLangImplRelative implements LangSig<Sem, FloatDelta> {
|
||||
/**
|
||||
* Ignore the bound on this expression.
|
||||
*
|
||||
@@ -57,40 +48,6 @@ module CppLangImplRelative implements LangSig<FloatDelta> {
|
||||
t instanceof SemFloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore any inferred zero lower bound on this expression.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreZeroLowerBound(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the specified variable should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
* This predicate is to keep the results identical to the original Java implementation. It should be
|
||||
* removed once we have the new implementation matching the old results exactly.
|
||||
*/
|
||||
predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() }
|
||||
|
||||
/**
|
||||
* Adds additional results to `ssaRead()` that are specific to Java.
|
||||
*
|
||||
* This predicate handles propagation of offsets for post-increment and post-decrement expressions
|
||||
* in exactly the same way as the old Java implementation. Once the new implementation matches the
|
||||
* old one, we should remove this predicate and propagate deltas for all similar patterns, whether
|
||||
* or not they come from a post-increment/decrement expression.
|
||||
*/
|
||||
SemExpr specificSsaRead(SemSsaVariable v, float delta) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`).
|
||||
*/
|
||||
|
||||
@@ -4,40 +4,35 @@
|
||||
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import RangeAnalysisRelativeSpecific
|
||||
private import RangeAnalysisStage as Range
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
private import RangeAnalysisImpl
|
||||
private import ConstantAnalysis
|
||||
|
||||
module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::UtilSig<D> {
|
||||
module RangeUtil<DeltaSig D, LangSig<Sem, D> Lang> implements UtilSig<Sem, D> {
|
||||
/**
|
||||
* Gets an expression that equals `v - d`.
|
||||
*/
|
||||
SemExpr semSsaRead(SemSsaVariable v, D::Delta delta) {
|
||||
private SemExpr semSsaRead(SemSsaVariable v, D::Delta delta) {
|
||||
// There are various language-specific extension points that can be removed once we no longer
|
||||
// expect to match the original Java implementation's results exactly.
|
||||
result = v.getAUse() and delta = D::fromInt(0)
|
||||
or
|
||||
exists(D::Delta d1, SemConstantIntegerExpr c |
|
||||
result.(SemAddExpr).hasOperands(semSsaRead(v, d1), c) and
|
||||
delta = D::fromFloat(D::toFloat(d1) - c.getIntValue()) and
|
||||
not Lang::ignoreSsaReadArithmeticExpr(result)
|
||||
delta = D::fromFloat(D::toFloat(d1) - c.getIntValue())
|
||||
)
|
||||
or
|
||||
exists(SemSubExpr sub, D::Delta d1, SemConstantIntegerExpr c |
|
||||
result = sub and
|
||||
sub.getLeftOperand() = semSsaRead(v, d1) and
|
||||
sub.getRightOperand() = c and
|
||||
delta = D::fromFloat(D::toFloat(d1) + c.getIntValue()) and
|
||||
not Lang::ignoreSsaReadArithmeticExpr(result)
|
||||
delta = D::fromFloat(D::toFloat(d1) + c.getIntValue())
|
||||
)
|
||||
or
|
||||
result = v.(SemSsaExplicitUpdate).getSourceExpr() and
|
||||
delta = D::fromFloat(0) and
|
||||
not Lang::ignoreSsaReadAssignment(v)
|
||||
delta = D::fromFloat(0)
|
||||
or
|
||||
result = Lang::specificSsaRead(v, delta)
|
||||
or
|
||||
result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta) and
|
||||
not Lang::ignoreSsaReadCopy(result)
|
||||
result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta)
|
||||
or
|
||||
result.(SemStoreExpr).getOperand() = semSsaRead(v, delta)
|
||||
}
|
||||
@@ -138,27 +133,33 @@ module RangeUtil<Range::DeltaSig D, Range::LangSig<D> Lang> implements Range::Ut
|
||||
or
|
||||
not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType()
|
||||
}
|
||||
|
||||
import Ranking
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
|
||||
rix = max(int r | rankedPhiInput(phi, _, _, r))
|
||||
}
|
||||
import Ranking
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
predicate rankedPhiInput(
|
||||
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
edge =
|
||||
rank[r](SemSsaReadPositionPhiInputEdge e |
|
||||
e.phiInput(phi, _)
|
||||
|
|
||||
e order by e.getOrigBlock().getUniqueId()
|
||||
)
|
||||
module Ranking {
|
||||
/**
|
||||
* Holds if `rix` is the number of input edges to `phi`.
|
||||
*/
|
||||
predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) {
|
||||
rix = max(int r | rankedPhiInput(phi, _, _, r))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `inp` is an input to `phi` along `edge` and this input has index `r`
|
||||
* in an arbitrary 1-based numbering of the input edges to `phi`.
|
||||
*/
|
||||
predicate rankedPhiInput(
|
||||
SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r
|
||||
) {
|
||||
edge.phiInput(phi, inp) and
|
||||
edge =
|
||||
rank[r](SemSsaReadPositionPhiInputEdge e |
|
||||
e.phiInput(phi, _)
|
||||
|
|
||||
e order by e.getOrigBlock().getUniqueId()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,17 @@
|
||||
* three-valued domain `{negative, zero, positive}`.
|
||||
*/
|
||||
|
||||
private import RangeAnalysisStage
|
||||
private import codeql.rangeanalysis.RangeAnalysis
|
||||
private import RangeAnalysisImpl
|
||||
private import SignAnalysisSpecific as Specific
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import ConstantAnalysis
|
||||
private import RangeUtils
|
||||
private import Sign
|
||||
|
||||
module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
|
||||
module SignAnalysis<DeltaSig D, UtilSig<Sem, D> Utils> {
|
||||
private import codeql.rangeanalysis.internal.RangeUtils::MakeUtils<Sem, D>
|
||||
|
||||
/**
|
||||
* An SSA definition for which the analysis can compute the sign.
|
||||
*
|
||||
@@ -296,12 +299,12 @@ module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
|
||||
|
|
||||
testIsTrue = true and
|
||||
comp.getLesserOperand() = lowerbound and
|
||||
comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
|
||||
comp.getGreaterOperand() = ssaRead(v, D::fromInt(0)) and
|
||||
(if comp.isStrict() then isStrict = true else isStrict = false)
|
||||
or
|
||||
testIsTrue = false and
|
||||
comp.getGreaterOperand() = lowerbound and
|
||||
comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
|
||||
comp.getLesserOperand() = ssaRead(v, D::fromInt(0)) and
|
||||
(if comp.isStrict() then isStrict = false else isStrict = true)
|
||||
)
|
||||
}
|
||||
@@ -320,12 +323,12 @@ module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
|
||||
|
|
||||
testIsTrue = true and
|
||||
comp.getGreaterOperand() = upperbound and
|
||||
comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
|
||||
comp.getLesserOperand() = ssaRead(v, D::fromInt(0)) and
|
||||
(if comp.isStrict() then isStrict = true else isStrict = false)
|
||||
or
|
||||
testIsTrue = false and
|
||||
comp.getLesserOperand() = upperbound and
|
||||
comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and
|
||||
comp.getGreaterOperand() = ssaRead(v, D::fromInt(0)) and
|
||||
(if comp.isStrict() then isStrict = false else isStrict = true)
|
||||
)
|
||||
}
|
||||
@@ -341,7 +344,7 @@ module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
|
||||
exists(SemGuard guard, boolean testIsTrue, boolean polarity, SemExpr e |
|
||||
pos.hasReadOfVar(pragma[only_bind_into](v)) and
|
||||
semGuardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and
|
||||
e = Utils::semSsaRead(pragma[only_bind_into](v), D::fromInt(0)) and
|
||||
e = ssaRead(pragma[only_bind_into](v), D::fromInt(0)) and
|
||||
guard.isEquality(eqbound, e, polarity) and
|
||||
isEq = polarity.booleanXor(testIsTrue).booleanNot() and
|
||||
not unknownSign(eqbound)
|
||||
@@ -507,4 +510,16 @@ module SignAnalysis<DeltaSig D, UtilSig<D> Utils> {
|
||||
not semExprSign(e) = TPos() and
|
||||
not semExprSign(e) = TZero()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` may have positive values. This does not rule out the
|
||||
* possibility for negative values.
|
||||
*/
|
||||
predicate semMayBePositive(SemExpr e) { semExprSign(e) = TPos() }
|
||||
|
||||
/**
|
||||
* Holds if `e` may have negative values. This does not rule out the
|
||||
* possibility for positive values.
|
||||
*/
|
||||
predicate semMayBeNegative(SemExpr e) { semExprSign(e) = TNeg() }
|
||||
}
|
||||
|
||||
@@ -23,9 +23,7 @@
|
||||
* configuration (see `InvalidPointerToDerefConfig`).
|
||||
*
|
||||
* The dataflow traversal defines the set of sources as any dataflow node `n` such that there exists a pointer-arithmetic
|
||||
* instruction `pai` found by `AllocationToInvalidPointer.qll` and a `n.asInstruction() >= pai + deltaDerefSourceAndPai`.
|
||||
* Here, `deltaDerefSourceAndPai` is the constant difference between the source we track for finding a dereference and the
|
||||
* pointer-arithmetic instruction.
|
||||
* instruction `pai` found by `AllocationToInvalidPointer.qll` and a `n.asInstruction() = pai`.
|
||||
*
|
||||
* The set of sinks is defined as any dataflow node `n` such that `addr <= n.asInstruction() + deltaDerefSinkAndDerefAddress`
|
||||
* for some address operand `addr` and constant difference `deltaDerefSinkAndDerefAddress`. Since an address operand is
|
||||
@@ -37,9 +35,8 @@
|
||||
* `deltaDerefSinkAndDerefAddress >= 0`. The load attached to `*p` is the "operation". To ensure that the path makes
|
||||
* intuitive sense, we only pick operations that are control-flow reachable from the dereference sink.
|
||||
*
|
||||
* To compute how many elements the dereference is beyond the end position of the allocation, we sum the two deltas
|
||||
* `deltaDerefSourceAndPai` and `deltaDerefSinkAndDerefAddress`. This is done in the `operationIsOffBy` predicate
|
||||
* (which is the only predicate exposed by this file).
|
||||
* We use the `deltaDerefSinkAndDerefAddress` to compute how many elements the dereference is beyond the end position of
|
||||
* the allocation. This is done in the `operationIsOffBy` predicate (which is the only predicate exposed by this file).
|
||||
*
|
||||
* Handling false positives:
|
||||
*
|
||||
@@ -96,7 +93,7 @@ int invalidPointerToDereferenceFieldFlowBranchLimit() { result = 0 }
|
||||
private module InvalidPointerToDerefBarrier {
|
||||
private module BarrierConfig implements DataFlow::ConfigSig {
|
||||
additional predicate isSource(DataFlow::Node source, PointerArithmeticInstruction pai) {
|
||||
invalidPointerToDerefSource(_, pai, _, _) and
|
||||
invalidPointerToDerefSource(_, pai, _) and
|
||||
// source <= pai
|
||||
bounded2(source.asInstruction(), pai, any(int d | d <= 0))
|
||||
}
|
||||
@@ -169,11 +166,11 @@ private module InvalidPointerToDerefBarrier {
|
||||
*/
|
||||
private module InvalidPointerToDerefConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState extends PointerArithmeticInstruction {
|
||||
FlowState() { invalidPointerToDerefSource(_, this, _, _) }
|
||||
FlowState() { invalidPointerToDerefSource(_, this, _) }
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState pai) {
|
||||
invalidPointerToDerefSource(_, pai, source, _)
|
||||
invalidPointerToDerefSource(_, pai, source)
|
||||
}
|
||||
|
||||
pragma[inline]
|
||||
@@ -198,24 +195,17 @@ private import DataFlow::GlobalWithState<InvalidPointerToDerefConfig>
|
||||
|
||||
/**
|
||||
* Holds if `allocSource` is dataflow node that represents an allocation that flows to the
|
||||
* left-hand side of the pointer-arithmetic `pai`, and `derefSource <= pai + derefSourcePaiDelta`.
|
||||
*
|
||||
* For example, if `pai` is a pointer-arithmetic operation `p + size` in an expression such
|
||||
* as `(p + size) + 1` and `derefSource` is the node representing `(p + size) + 1`. In this
|
||||
* case `derefSourcePaiDelta` is 1.
|
||||
* left-hand side of the pointer-arithmetic instruction represented by `derefSource`.
|
||||
*/
|
||||
private predicate invalidPointerToDerefSource(
|
||||
DataFlow::Node allocSource, PointerArithmeticInstruction pai, DataFlow::Node derefSource,
|
||||
int deltaDerefSourceAndPai
|
||||
DataFlow::Node allocSource, PointerArithmeticInstruction pai, DataFlow::Node derefSource
|
||||
) {
|
||||
// Note that `deltaDerefSourceAndPai` is not necessarily equal to `rhsSizeDelta`:
|
||||
// `rhsSizeDelta` is the constant offset added to the size of the allocation, and
|
||||
// `deltaDerefSourceAndPai` is the constant difference between the pointer-arithmetic instruction
|
||||
// and the instruction computing the address for which we will search for a dereference.
|
||||
AllocToInvalidPointer::pointerAddInstructionHasBounds(allocSource, pai, _, _) and
|
||||
// derefSource <= pai + deltaDerefSourceAndPai
|
||||
bounded2(derefSource.asInstruction(), pai, deltaDerefSourceAndPai) and
|
||||
deltaDerefSourceAndPai >= 0
|
||||
derefSource.asInstruction() = pai
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,11 +248,9 @@ private Instruction getASuccessor(Instruction instr) {
|
||||
instr.getBlock().getASuccessor+() = result.getBlock()
|
||||
}
|
||||
|
||||
private predicate paiForDereferenceSink(
|
||||
PointerArithmeticInstruction pai, DataFlow::Node derefSink, int deltaDerefSourceAndPai
|
||||
) {
|
||||
private predicate paiForDereferenceSink(PointerArithmeticInstruction pai, DataFlow::Node derefSink) {
|
||||
exists(DataFlow::Node derefSource |
|
||||
invalidPointerToDerefSource(_, pai, derefSource, deltaDerefSourceAndPai) and
|
||||
invalidPointerToDerefSource(_, pai, derefSource) and
|
||||
flow(derefSource, derefSink)
|
||||
)
|
||||
}
|
||||
@@ -274,10 +262,10 @@ private predicate paiForDereferenceSink(
|
||||
*/
|
||||
private predicate derefSinkToOperation(
|
||||
DataFlow::Node derefSink, PointerArithmeticInstruction pai, DataFlow::Node operation,
|
||||
string description, int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress
|
||||
string description, int deltaDerefSinkAndDerefAddress
|
||||
) {
|
||||
exists(Instruction operationInstr, AddressOperand addr |
|
||||
paiForDereferenceSink(pai, pragma[only_bind_into](derefSink), deltaDerefSourceAndPai) and
|
||||
paiForDereferenceSink(pai, pragma[only_bind_into](derefSink)) and
|
||||
isInvalidPointerDerefSink(derefSink, addr, operationInstr, description,
|
||||
deltaDerefSinkAndDerefAddress) and
|
||||
operationInstr = getASuccessor(derefSink.asInstruction()) and
|
||||
@@ -298,11 +286,7 @@ predicate operationIsOffBy(
|
||||
DataFlow::Node allocation, PointerArithmeticInstruction pai, DataFlow::Node derefSource,
|
||||
DataFlow::Node derefSink, string description, DataFlow::Node operation, int delta
|
||||
) {
|
||||
exists(int deltaDerefSourceAndPai, int deltaDerefSinkAndDerefAddress |
|
||||
invalidPointerToDerefSource(allocation, pai, derefSource, deltaDerefSourceAndPai) and
|
||||
flow(derefSource, derefSink) and
|
||||
derefSinkToOperation(derefSink, pai, operation, description, deltaDerefSourceAndPai,
|
||||
deltaDerefSinkAndDerefAddress) and
|
||||
delta = deltaDerefSourceAndPai + deltaDerefSinkAndDerefAddress
|
||||
)
|
||||
invalidPointerToDerefSource(allocation, pai, derefSource) and
|
||||
flow(derefSource, derefSink) and
|
||||
derefSinkToOperation(derefSink, pai, operation, description, delta)
|
||||
}
|
||||
|
||||
@@ -372,7 +372,8 @@ private predicate analyzablePointerFieldAccess(PointerFieldAccess access) {
|
||||
private predicate mk_PointerFieldAccess(HashCons qualifier, Field target, PointerFieldAccess access) {
|
||||
analyzablePointerFieldAccess(access) and
|
||||
target = access.getTarget() and
|
||||
qualifier = hashCons(access.getQualifier().getFullyConverted())
|
||||
qualifier = hashCons(access.getQualifier().getFullyConverted()) and
|
||||
not access instanceof ImplicitThisFieldAccess
|
||||
}
|
||||
|
||||
private predicate analyzableImplicitThisFieldAccess(ImplicitThisFieldAccess access) {
|
||||
|
||||
@@ -197,6 +197,11 @@ svnchurn(
|
||||
* C++ dbscheme
|
||||
*/
|
||||
|
||||
extractor_version(
|
||||
string codeql_version: string ref,
|
||||
string frontend_version: string ref
|
||||
)
|
||||
|
||||
@location = @location_stmt | @location_expr | @location_default ;
|
||||
|
||||
/**
|
||||
@@ -612,6 +617,14 @@ case @builtintype.kind of
|
||||
| 51 = @char8_t
|
||||
| 52 = @float16 // _Float16
|
||||
| 53 = @complex_float16 // _Complex _Float16
|
||||
| 54 = @fp16 // __fp16
|
||||
| 55 = @std_bfloat16 // __bf16
|
||||
| 56 = @std_float16 // std::float16_t
|
||||
| 57 = @complex_std_float32 // _Complex _Float32
|
||||
| 58 = @complex_float32x // _Complex _Float32x
|
||||
| 59 = @complex_std_float64 // _Complex _Float64
|
||||
| 60 = @complex_float64x // _Complex _Float64x
|
||||
| 61 = @complex_std_float128 // _Complex _Float128
|
||||
;
|
||||
|
||||
builtintypes(
|
||||
@@ -1321,11 +1334,16 @@ funbind(
|
||||
| @assignxorexpr
|
||||
| @assignlshiftexpr
|
||||
| @assignrshiftexpr
|
||||
| @assignpaddexpr
|
||||
;
|
||||
|
||||
@assign_pointer_expr = @assignpaddexpr
|
||||
| @assignpsubexpr
|
||||
;
|
||||
|
||||
@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr
|
||||
@assign_op_expr = @assign_arith_expr
|
||||
| @assign_bitwise_expr
|
||||
| @assign_pointer_expr
|
||||
;
|
||||
|
||||
@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Introduce extractor version numbers
|
||||
compatibility: full
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Introduce new floating-point types from C23 and C++23
|
||||
compatibility: full
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Removed @assignpaddexpr and @assignpsubexpr from @assign_bitwise_expr
|
||||
compatibility: full
|
||||
@@ -1,3 +1,15 @@
|
||||
## 0.8.2
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.8.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* The query `cpp/redundant-null-check-simple` has been promoted to Code Scanning. The query finds cases where a pointer is compared to null after it has already been dereferenced. Such comparisons likely indicate a bug at the place where the pointer is dereferenced, or where the pointer is compared to null.
|
||||
|
||||
Note: This query was incorrectly noted as being promoted to Code Scanning in CodeQL version 2.14.6.
|
||||
|
||||
## 0.8.0
|
||||
|
||||
### Query Metadata Changes
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
* @id cpp/invalid-pointer-deref
|
||||
* @tags reliability
|
||||
* security
|
||||
* experimental
|
||||
* external/cwe/cwe-119
|
||||
* external/cwe/cwe-125
|
||||
* external/cwe/cwe-193
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.models.implementations.Memset
|
||||
import ExposedSystemData::PathGraph
|
||||
import SystemData
|
||||
|
||||
@@ -28,6 +29,10 @@ module ExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||
fc.getArgument(arg).getAChild*() = sink.asIndirectExpr()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.asIndirectArgument() = any(MemsetFunction func).getACallToThisFunction().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
module ExposedSystemData = TaintTracking::Global<ExposedSystemDataConfig>;
|
||||
|
||||
@@ -28,6 +28,7 @@ import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.models.interfaces.FlowSource
|
||||
import semmle.code.cpp.security.OutputWrite
|
||||
import semmle.code.cpp.models.implementations.Memset
|
||||
import PotentiallyExposedSystemData::PathGraph
|
||||
import SystemData
|
||||
|
||||
@@ -49,6 +50,10 @@ module PotentiallyExposedSystemDataConfig implements DataFlow::ConfigSig {
|
||||
else child = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
node.asIndirectArgument() = any(MemsetFunction func).getACallToThisFunction().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
module PotentiallyExposedSystemData = TaintTracking::Global<PotentiallyExposedSystemDataConfig>;
|
||||
|
||||
4
cpp/ql/src/change-notes/2023-10-31-odbc-models.md
Normal file
4
cpp/ql/src/change-notes/2023-10-31-odbc-models.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added SQL API models for `ODBC`.
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
## 0.8.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* The query `cpp/redundant-null-check-simple` has been promoted to Code Scanning. The query finds cases where a pointer is compared to null after it has already been dereferenced. Such comparisons likely indicate a bug at the place where the pointer is dereferenced, or where the pointer is compared to null.
|
||||
|
||||
Note: This query was incorrectly noted as being promoted to Code Scanning in CodeQL version 2.14.6.
|
||||
3
cpp/ql/src/change-notes/released/0.8.2.md
Normal file
3
cpp/ql/src/change-notes/released/0.8.2.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.8.2
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.8.0
|
||||
lastReleaseVersion: 0.8.2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.8.1-dev
|
||||
version: 0.8.3-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -763,7 +763,7 @@ StaticMemberAccess.cpp:
|
||||
# 7| ValueCategory = lvalue
|
||||
# 7| getRValue(): [VariableAccess] i
|
||||
# 7| Type = [IntType] int
|
||||
# 7| ValueCategory = prvalue
|
||||
# 7| ValueCategory = prvalue(load)
|
||||
# 7| getQualifier(): [VariableAccess] xref
|
||||
# 7| Type = [LValueReferenceType] X &
|
||||
# 7| ValueCategory = prvalue(load)
|
||||
@@ -1298,7 +1298,7 @@ union_etc.cpp:
|
||||
# 6| getExpr(): [AssignExpr] ... = ...
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = lvalue
|
||||
# 6| getLValue(): [PointerFieldAccess] x
|
||||
# 6| getLValue(): [ImplicitThisFieldAccess,PointerFieldAccess] x
|
||||
# 6| Type = [IntType] int
|
||||
# 6| ValueCategory = lvalue
|
||||
# 6| getQualifier(): [ThisExpr] this
|
||||
@@ -1394,7 +1394,7 @@ union_etc.cpp:
|
||||
# 26| ValueCategory = lvalue
|
||||
# 26| getRValue(): [AssignExpr] ... = ...
|
||||
# 26| Type = [IntType] int
|
||||
# 26| ValueCategory = prvalue
|
||||
# 26| ValueCategory = prvalue(load)
|
||||
# 26| getLValue(): [ValueFieldAccess] e
|
||||
# 26| Type = [IntType] int
|
||||
# 26| ValueCategory = lvalue
|
||||
@@ -1406,7 +1406,7 @@ union_etc.cpp:
|
||||
# 26| ValueCategory = lvalue
|
||||
# 26| getRValue(): [AssignExpr] ... = ...
|
||||
# 26| Type = [IntType] int
|
||||
# 26| ValueCategory = prvalue
|
||||
# 26| ValueCategory = prvalue(load)
|
||||
# 26| getLValue(): [ValueFieldAccess] i
|
||||
# 26| Type = [IntType] int
|
||||
# 26| ValueCategory = lvalue
|
||||
@@ -1488,7 +1488,7 @@ union_etc.cpp:
|
||||
# 33| getExpr(): [AssignExpr] ... = ...
|
||||
# 33| Type = [IntType] int
|
||||
# 33| ValueCategory = lvalue
|
||||
# 33| getLValue(): [PointerFieldAccess] q
|
||||
# 33| getLValue(): [ImplicitThisFieldAccess,PointerFieldAccess] q
|
||||
# 33| Type = [IntType] int
|
||||
# 33| ValueCategory = lvalue
|
||||
# 33| getQualifier(): [ThisExpr] this
|
||||
|
||||
@@ -675,6 +675,7 @@
|
||||
| test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive |
|
||||
| test.c:398:14:398:14 | Load: y | positive strictlyPositive |
|
||||
| test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive |
|
||||
| test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive |
|
||||
| test.c:398:14:398:19 | Store: ... += ... | positive strictlyPositive |
|
||||
| test.c:398:19:398:19 | Constant: (unsigned int)... | positive strictlyPositive |
|
||||
| test.c:398:22:398:22 | Load: y | positive strictlyPositive |
|
||||
|
||||
@@ -29,7 +29,6 @@ edges
|
||||
| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:70:5:70:7 | arr indirection [p] |
|
||||
| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... |
|
||||
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] |
|
||||
| test.cpp:70:5:70:7 | arr indirection [p] | test.cpp:70:5:70:7 | arr indirection [p] |
|
||||
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:79:9:79:11 | arr indirection [p] |
|
||||
| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:83:9:83:11 | arr indirection [p] |
|
||||
| test.cpp:79:9:79:11 | arr indirection [p] | test.cpp:79:14:79:14 | p |
|
||||
|
||||
@@ -35,9 +35,7 @@ edges
|
||||
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr |
|
||||
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr |
|
||||
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf |
|
||||
| test.cpp:146:26:146:26 | p indirection | test.cpp:148:6:148:9 | * ... |
|
||||
| test.cpp:146:26:146:26 | p indirection | test.cpp:149:6:149:9 | * ... |
|
||||
| test.cpp:146:26:146:26 | p indirection | test.cpp:150:6:150:9 | * ... |
|
||||
| test.cpp:146:26:146:26 | p indirection | test.cpp:147:4:147:9 | -- ... |
|
||||
| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... |
|
||||
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | & ... indirection |
|
||||
| test.cpp:158:17:158:18 | & ... indirection | test.cpp:146:26:146:26 | p indirection |
|
||||
@@ -124,9 +122,7 @@ nodes
|
||||
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
|
||||
| test.cpp:143:18:143:21 | asdf | semmle.label | asdf |
|
||||
| test.cpp:146:26:146:26 | p indirection | semmle.label | p indirection |
|
||||
| test.cpp:148:6:148:9 | * ... | semmle.label | * ... |
|
||||
| test.cpp:149:6:149:9 | * ... | semmle.label | * ... |
|
||||
| test.cpp:150:6:150:9 | * ... | semmle.label | * ... |
|
||||
| test.cpp:147:4:147:9 | -- ... | semmle.label | -- ... |
|
||||
| test.cpp:156:12:156:14 | buf | semmle.label | buf |
|
||||
| test.cpp:156:12:156:18 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:158:17:158:18 | & ... indirection | semmle.label | & ... indirection |
|
||||
@@ -179,9 +175,7 @@ subpaths
|
||||
| test.cpp:88:5:88:27 | PointerAdd: access to array | test.cpp:85:34:85:36 | buf | test.cpp:88:5:88:27 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:88:5:88:31 | Store: ... = ... | write |
|
||||
| test.cpp:128:9:128:14 | PointerAdd: access to array | test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:125:11:125:13 | arr | arr | test.cpp:128:9:128:18 | Store: ... = ... | write |
|
||||
| test.cpp:136:9:136:16 | PointerAdd: ... += ... | test.cpp:143:18:143:21 | asdf | test.cpp:138:13:138:15 | arr | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:142:10:142:13 | asdf | asdf | test.cpp:138:12:138:15 | Load: * ... | read |
|
||||
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:148:6:148:9 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
|
||||
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:149:6:149:9 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:148:3:148:13 | Store: ... = ... | write |
|
||||
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:150:6:150:9 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:149:3:149:13 | Store: ... = ... | write |
|
||||
| test.cpp:156:12:156:18 | PointerAdd: ... + ... | test.cpp:156:12:156:14 | buf | test.cpp:147:4:147:9 | -- ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:154:7:154:9 | buf | buf | test.cpp:147:3:147:13 | Store: ... = ... | write |
|
||||
| test.cpp:221:5:221:11 | PointerAdd: access to array | test.cpp:218:23:218:28 | buffer | test.cpp:221:5:221:11 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:217:19:217:24 | buffer | buffer | test.cpp:221:5:221:15 | Store: ... = ... | write |
|
||||
| test.cpp:232:5:232:10 | PointerAdd: access to array | test.cpp:229:25:229:29 | array | test.cpp:232:5:232:10 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:228:10:228:14 | array | array | test.cpp:232:5:232:19 | Store: ... = ... | write |
|
||||
| test.cpp:261:27:261:30 | PointerAdd: access to array | test.cpp:286:19:286:25 | buffer2 | test.cpp:261:27:261:30 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:285:19:285:25 | buffer2 | buffer2 | test.cpp:261:27:261:30 | Load: access to array | read |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| FieldAccess.cpp:11:12:11:13 | p1 | ptr |
|
||||
| FieldAccess.cpp:12:12:12:13 | p2 | ptr |
|
||||
| FieldAccess.cpp:25:12:25:13 | x1 | ptr |
|
||||
| FieldAccess.cpp:11:12:11:13 | p1 | ptr, this |
|
||||
| FieldAccess.cpp:12:12:12:13 | p2 | ptr, this |
|
||||
| FieldAccess.cpp:25:12:25:13 | x1 | ptr, this |
|
||||
| FieldAccess.cpp:29:18:29:19 | x2 | ptr |
|
||||
| FieldAccess.cpp:34:3:34:3 | d | this |
|
||||
| FieldAccess.cpp:45:13:45:14 | x1 | ptr |
|
||||
@@ -19,10 +19,10 @@
|
||||
| FieldAccess.cpp:91:7:91:7 | x | val |
|
||||
| FieldAccess.cpp:91:13:91:13 | y | ref |
|
||||
| FieldAccess.cpp:92:8:92:8 | x | ptr |
|
||||
| FieldAccess.cpp:92:12:92:12 | y | ptr |
|
||||
| FieldAccess.cpp:92:12:92:12 | y | ptr, this |
|
||||
| FieldAccess.cpp:93:8:93:8 | x | ptr |
|
||||
| FieldAccess.cpp:93:18:93:18 | y | ptr |
|
||||
| FieldAccess.cpp:94:11:94:11 | y | ptr |
|
||||
| FieldAccess.cpp:94:20:94:20 | y | val |
|
||||
| FieldAccess.cpp:113:5:113:5 | x | ptr |
|
||||
| FieldAccess.cpp:113:5:113:5 | x | ptr, this |
|
||||
| FieldAccess.cpp:116:3:116:3 | v | this |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
static int clang421 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40201 --edg --clang
|
||||
// semmle-extractor-options: --gnu_version 40201 --clang_version 30400
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
static int clang450 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40500 --edg --clang
|
||||
// semmle-extractor-options: --gnu_version 40500 --clang_version 30500
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
static int gcc421 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40201 --edg --clang
|
||||
// semmle-extractor-options: --gnu_version 40201
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
static int gcc450 = __has_feature(attribute_deprecated_with_message);
|
||||
// semmle-extractor-options: --gnu_version 40500 --edg --clang
|
||||
// semmle-extractor-options: --gnu_version 40500
|
||||
|
||||
@@ -41,6 +41,9 @@ postWithInFlow
|
||||
| example.c:26:9:26:9 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:26:19:26:24 | coords [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| example.c:28:23:28:25 | pos [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| flowOut.cpp:5:5:5:12 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| flowOut.cpp:5:6:5:12 | toTaint [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| flowOut.cpp:18:17:18:17 | x [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| globals.cpp:13:5:13:19 | flowTestGlobal1 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| globals.cpp:23:5:23:19 | flowTestGlobal2 [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -14,17 +14,14 @@ localCallNodes
|
||||
postIsNotPre
|
||||
postHasUniquePre
|
||||
uniquePostUpdate
|
||||
| example.c:24:13:24:18 | coords indirection | Node has multiple PostUpdateNodes. |
|
||||
postIsInSameCallable
|
||||
reverseRead
|
||||
argHasPostUpdate
|
||||
postWithInFlow
|
||||
| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
uniqueParameterNodeAtPosition
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
int source();
|
||||
void sink(int);
|
||||
|
||||
void source_ref(int *toTaint) { // $ ir-def=*toTaint ast-def=toTaint
|
||||
*toTaint = source();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void modify_copy(int* ptr) { // $ ast-def=ptr
|
||||
int deref = *ptr;
|
||||
int* other = &deref;
|
||||
source_ref(other);
|
||||
}
|
||||
|
||||
void test_output() {
|
||||
int x = 0;
|
||||
modify_copy(&x);
|
||||
sink(x); // $ SPURIOUS: ir
|
||||
}
|
||||
@@ -1,6 +1,19 @@
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import DataFlow
|
||||
|
||||
private class TestAdditionalCallTarget extends AdditionalCallTarget {
|
||||
override Function viableTarget(Call call) {
|
||||
// To test that call targets specified by `AdditionalCallTarget` are
|
||||
// resolved correctly this subclass resolves all calls to
|
||||
// `call_template_argument<f>(x)` as if the user had written `f(x)`.
|
||||
exists(FunctionTemplateInstantiation inst |
|
||||
inst.getTemplate().hasName("call_template_argument") and
|
||||
call.getTarget() = inst and
|
||||
result = inst.getTemplateArgument(0).(FunctionAccess).getTarget()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module IRConfig implements ConfigSig {
|
||||
predicate isSource(Node src) {
|
||||
src.asExpr() instanceof NewExpr
|
||||
|
||||
@@ -44,8 +44,6 @@ reverseRead
|
||||
argHasPostUpdate
|
||||
postWithInFlow
|
||||
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
uniqueParameterNodeAtPosition
|
||||
|
||||
@@ -83,7 +83,6 @@ edges
|
||||
| A.cpp:152:10:152:10 | d indirection [b] | A.cpp:152:10:152:13 | b |
|
||||
| A.cpp:153:10:153:10 | d indirection [b indirection, c] | A.cpp:153:13:153:13 | b indirection [c] |
|
||||
| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:10:153:16 | c |
|
||||
| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:13:153:13 | b indirection [c] |
|
||||
| A.cpp:154:10:154:10 | b indirection [c] | A.cpp:154:10:154:13 | c |
|
||||
| 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 indirection [head] |
|
||||
@@ -97,10 +96,8 @@ edges
|
||||
| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] |
|
||||
| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | A.cpp:181:32:181:35 | next indirection [next indirection, head] |
|
||||
| A.cpp:165:10:165:11 | l3 indirection [next indirection, next indirection, head] | A.cpp:165:14:165:17 | next indirection [next indirection, head] |
|
||||
| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:14:165:17 | next indirection [next indirection, head] |
|
||||
| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:20:165:23 | next indirection [head] |
|
||||
| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:10:165:29 | head |
|
||||
| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:20:165:23 | next indirection [head] |
|
||||
| A.cpp:167:44:167:44 | l indirection [next indirection, head] | A.cpp:167:47:167:50 | next indirection [head] |
|
||||
| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | A.cpp:167:47:167:50 | next indirection [next indirection, head] |
|
||||
| A.cpp:167:47:167:50 | next indirection [head] | A.cpp:169:12:169:12 | l indirection [head] |
|
||||
@@ -121,7 +118,6 @@ edges
|
||||
| B.cpp:8:25:8:26 | b1 indirection [elem1] | B.cpp:44:16:44:17 | b1 indirection [elem1] |
|
||||
| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] |
|
||||
| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:10:9:24 | elem1 |
|
||||
| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:14:9:17 | box1 indirection [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 indirection [elem2] |
|
||||
| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] |
|
||||
@@ -131,7 +127,6 @@ edges
|
||||
| B.cpp:17:25:17:26 | b1 indirection [elem2] | B.cpp:44:16:44:17 | b1 indirection [elem2] |
|
||||
| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] |
|
||||
| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:10:19:24 | elem2 |
|
||||
| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:14:19:17 | box1 indirection [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:13:35:17 | this indirection [post update] [elem1] |
|
||||
@@ -196,17 +191,12 @@ edges
|
||||
| D.cpp:58:20:58:23 | box indirection [post update] [elem] | D.cpp:58:15:58:17 | boxfield indirection [post update] [box indirection, elem] |
|
||||
| D.cpp:59:5:59:7 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:63:8:63:10 | this indirection [boxfield indirection, box indirection, elem] |
|
||||
| D.cpp:63:8:63:10 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] |
|
||||
| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] |
|
||||
| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | D.cpp:64:20:64:22 | box indirection [elem] |
|
||||
| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] |
|
||||
| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:10:64:28 | elem |
|
||||
| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:20:64:22 | box indirection [elem] |
|
||||
| E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | E.cpp:21:10:21:10 | p indirection [data, buffer indirection] |
|
||||
| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | E.cpp:21:13:21:16 | data indirection [buffer indirection] |
|
||||
| E.cpp:21:13:21:16 | data indirection [buffer indirection] | E.cpp:21:18:21:23 | buffer indirection |
|
||||
| E.cpp:21:13:21:16 | data indirection [buffer indirection] | E.cpp:21:18:21:23 | buffer indirection |
|
||||
| E.cpp:21:18:21:23 | buffer indirection | E.cpp:21:18:21:23 | buffer indirection |
|
||||
| E.cpp:21:18:21:23 | buffer indirection | E.cpp:21:18:21:23 | buffer indirection |
|
||||
| E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection |
|
||||
| E.cpp:29:21:29:29 | argument_source output argument | E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] |
|
||||
| E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] | E.cpp:32:10:32:10 | b indirection [buffer indirection] |
|
||||
@@ -214,9 +204,6 @@ edges
|
||||
| E.cpp:30:23:30:26 | p indirection [post update] [data, buffer indirection] | E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] |
|
||||
| E.cpp:30:28:30:33 | data indirection [post update] [buffer indirection] | E.cpp:30:23:30:26 | p indirection [post update] [data, buffer indirection] |
|
||||
| E.cpp:32:10:32:10 | b indirection [buffer indirection] | E.cpp:32:13:32:18 | buffer indirection |
|
||||
| E.cpp:32:10:32:10 | b indirection [buffer indirection] | E.cpp:32:13:32:18 | buffer indirection |
|
||||
| E.cpp:32:13:32:18 | buffer indirection | E.cpp:32:13:32:18 | buffer indirection |
|
||||
| E.cpp:32:13:32:18 | buffer indirection | E.cpp:32:13:32:18 | buffer indirection |
|
||||
| E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] | E.cpp:19:27:19:27 | p indirection [data, buffer indirection] |
|
||||
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] |
|
||||
| aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] |
|
||||
@@ -311,11 +298,9 @@ edges
|
||||
| arrays.cpp:43:8:43:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:43:10:43:17 | indirect indirection [arr, data] |
|
||||
| arrays.cpp:43:8:43:25 | access to array indirection [data] | arrays.cpp:43:27:43:30 | data |
|
||||
| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | arrays.cpp:43:8:43:25 | access to array indirection [data] |
|
||||
| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | arrays.cpp:43:10:43:17 | indirect indirection [arr, data] |
|
||||
| arrays.cpp:44:8:44:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:44:10:44:17 | indirect indirection [arr, data] |
|
||||
| arrays.cpp:44:8:44:25 | access to array indirection [data] | arrays.cpp:44:27:44:30 | data |
|
||||
| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | arrays.cpp:44:8:44:25 | access to array indirection [data] |
|
||||
| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | arrays.cpp:44:10:44:17 | indirect indirection [arr, data] |
|
||||
| arrays.cpp:48:3:48:40 | ... = ... | arrays.cpp:48:22:48:25 | access to array indirection [post update] [data] |
|
||||
| arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] |
|
||||
| arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] |
|
||||
@@ -325,13 +310,11 @@ edges
|
||||
| arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] |
|
||||
| arrays.cpp:49:8:49:25 | access to array indirection [data] | arrays.cpp:49:27:49:30 | data |
|
||||
| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:8:49:25 | access to array indirection [data] |
|
||||
| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] |
|
||||
| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:20:49:22 | ptr indirection [data] |
|
||||
| arrays.cpp:49:20:49:22 | ptr indirection [data] | arrays.cpp:49:8:49:25 | access to array indirection [data] |
|
||||
| arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] |
|
||||
| arrays.cpp:50:8:50:25 | access to array indirection [data] | arrays.cpp:50:27:50:30 | data |
|
||||
| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:8:50:25 | access to array indirection [data] |
|
||||
| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] |
|
||||
| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:20:50:22 | ptr indirection [data] |
|
||||
| arrays.cpp:50:20:50:22 | ptr indirection [data] | arrays.cpp:50:8:50:25 | access to array indirection [data] |
|
||||
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... |
|
||||
@@ -411,13 +394,11 @@ edges
|
||||
| by_reference.cpp:110:8:110:12 | outer indirection [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested indirection [a] |
|
||||
| by_reference.cpp:110:14:110:25 | inner_nested indirection [a] | by_reference.cpp:110:27:110:27 | a |
|
||||
| by_reference.cpp:111:8:111:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | by_reference.cpp:111:25:111:25 | a |
|
||||
| by_reference.cpp:112:8:112:12 | outer indirection [a] | by_reference.cpp:112:14:112:14 | a |
|
||||
| by_reference.cpp:114:8:114:13 | pouter indirection [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested indirection [a] |
|
||||
| by_reference.cpp:114:16:114:27 | inner_nested indirection [a] | by_reference.cpp:114:29:114:29 | a |
|
||||
| by_reference.cpp:115:8:115:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | by_reference.cpp:115:27:115:27 | a |
|
||||
| by_reference.cpp:116:8:116:13 | pouter indirection [a] | by_reference.cpp:116:16:116:16 | a |
|
||||
| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:27:122:38 | outer indirection [post update] [inner_nested, a] |
|
||||
@@ -435,13 +416,11 @@ edges
|
||||
| by_reference.cpp:130:8:130:12 | outer indirection [inner_nested, a] | by_reference.cpp:130:14:130:25 | inner_nested indirection [a] |
|
||||
| by_reference.cpp:130:14:130:25 | inner_nested indirection [a] | by_reference.cpp:130:27:130:27 | a |
|
||||
| by_reference.cpp:131:8:131:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | by_reference.cpp:131:25:131:25 | a |
|
||||
| by_reference.cpp:132:8:132:12 | outer indirection [a] | by_reference.cpp:132:14:132:14 | a |
|
||||
| by_reference.cpp:134:8:134:13 | pouter indirection [inner_nested, a] | by_reference.cpp:134:16:134:27 | inner_nested indirection [a] |
|
||||
| by_reference.cpp:134:16:134:27 | inner_nested indirection [a] | by_reference.cpp:134:29:134:29 | a |
|
||||
| by_reference.cpp:135:8:135:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] |
|
||||
| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | by_reference.cpp:135:27:135:27 | a |
|
||||
| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a |
|
||||
| clearning.cpp:32:3:32:25 | ... = ... | clearning.cpp:32:6:32:6 | s indirection [post update] [x indirection] |
|
||||
@@ -460,9 +439,6 @@ edges
|
||||
| clearning.cpp:54:5:54:5 | s indirection [post update] [x indirection] | clearning.cpp:55:8:55:8 | s indirection [x indirection] |
|
||||
| clearning.cpp:54:5:54:5 | x indirection | clearning.cpp:54:3:54:7 | ... ++ indirection |
|
||||
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
|
||||
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | clearning.cpp:55:10:55:10 | x indirection |
|
||||
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:55:10:55:10 | x indirection |
|
||||
| clearning.cpp:55:10:55:10 | x indirection | clearning.cpp:55:10:55:10 | x indirection |
|
||||
| clearning.cpp:60:3:60:22 | ... = ... | clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] |
|
||||
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | clearning.cpp:61:3:61:3 | s indirection [x indirection] |
|
||||
| clearning.cpp:60:11:60:20 | call to user_input | clearning.cpp:60:3:60:22 | ... = ... |
|
||||
@@ -474,9 +450,6 @@ edges
|
||||
| clearning.cpp:61:5:61:5 | s indirection [post update] [x indirection] | clearning.cpp:62:8:62:8 | s indirection [x indirection] |
|
||||
| clearning.cpp:61:5:61:5 | x indirection | clearning.cpp:61:3:61:7 | ... ++ indirection |
|
||||
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
|
||||
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | clearning.cpp:62:10:62:10 | x indirection |
|
||||
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:62:10:62:10 | x indirection |
|
||||
| clearning.cpp:62:10:62:10 | x indirection | clearning.cpp:62:10:62:10 | x indirection |
|
||||
| clearning.cpp:74:20:74:22 | argument_source output argument | clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] |
|
||||
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | clearning.cpp:76:8:76:8 | s indirection [val indirection] |
|
||||
| clearning.cpp:76:8:76:8 | s indirection [val indirection] | clearning.cpp:76:7:76:12 | * ... |
|
||||
@@ -620,14 +593,12 @@ edges
|
||||
| conflated.cpp:54:13:54:13 | next indirection [post update] [y] | conflated.cpp:54:7:54:10 | ll indirection [post update] [next indirection, y] |
|
||||
| conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:54:3:54:28 | ... = ... |
|
||||
| conflated.cpp:55:8:55:9 | ll indirection [next indirection, y] | conflated.cpp:55:12:55:15 | next indirection [y] |
|
||||
| conflated.cpp:55:12:55:15 | next indirection [y] | conflated.cpp:55:12:55:15 | next indirection [y] |
|
||||
| conflated.cpp:55:12:55:15 | next indirection [y] | conflated.cpp:55:18:55:18 | y |
|
||||
| conflated.cpp:60:3:60:28 | ... = ... | conflated.cpp:60:13:60:13 | next indirection [post update] [y] |
|
||||
| conflated.cpp:60:7:60:10 | ll indirection [post update] [next indirection, y] | conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] |
|
||||
| conflated.cpp:60:13:60:13 | next indirection [post update] [y] | conflated.cpp:60:7:60:10 | ll indirection [post update] [next indirection, y] |
|
||||
| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:3:60:28 | ... = ... |
|
||||
| conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] | conflated.cpp:61:12:61:15 | next indirection [y] |
|
||||
| conflated.cpp:61:12:61:15 | next indirection [y] | conflated.cpp:61:12:61:15 | next indirection [y] |
|
||||
| conflated.cpp:61:12:61:15 | next indirection [y] | conflated.cpp:61:18:61:18 | y |
|
||||
| constructors.cpp:18:9:18:9 | this indirection [a_] | constructors.cpp:18:22:18:23 | this indirection [a_] |
|
||||
| constructors.cpp:18:22:18:23 | a_ | constructors.cpp:18:9:18:9 | a indirection |
|
||||
@@ -672,42 +643,36 @@ edges
|
||||
| qualifiers.cpp:22:23:22:23 | call to getInner indirection [post update] [a] | qualifiers.cpp:22:5:22:9 | getInner output argument [inner indirection, a] |
|
||||
| qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:22:5:22:38 | ... = ... |
|
||||
| qualifiers.cpp:23:10:23:14 | outer indirection [inner indirection, a] | qualifiers.cpp:23:16:23:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:23:16:23:20 | inner indirection [a] | qualifiers.cpp:23:16:23:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:23:16:23:20 | inner indirection [a] | qualifiers.cpp:23:23:23:23 | a |
|
||||
| qualifiers.cpp:27:5:27:9 | getInner output argument [inner indirection, a] | qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] |
|
||||
| qualifiers.cpp:27:11:27:18 | setA output argument [a] | qualifiers.cpp:27:5:27:9 | getInner output argument [inner indirection, 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 | setA output argument [a] |
|
||||
| qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] | qualifiers.cpp:28:16:28:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:28:16:28:20 | inner indirection [a] | qualifiers.cpp:28:16:28:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:28:16:28:20 | inner indirection [a] | qualifiers.cpp:28:23:28:23 | a |
|
||||
| qualifiers.cpp:32:17:32:21 | getInner output argument [inner indirection, a] | qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] |
|
||||
| qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] | qualifiers.cpp:32:17:32:21 | getInner output argument [inner indirection, 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 | pointerSetA output argument [a] |
|
||||
| qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] | qualifiers.cpp:33:16:33:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:33:16:33:20 | inner indirection [a] | qualifiers.cpp:33:16:33:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:33:16:33:20 | inner indirection [a] | qualifiers.cpp:33:23:33:23 | a |
|
||||
| qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] | qualifiers.cpp:37:20:37:24 | getInner output argument [inner indirection, a] |
|
||||
| qualifiers.cpp:37:20:37:24 | getInner output argument [inner indirection, a] | qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, 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 | referenceSetA output argument [a] |
|
||||
| qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, a] | qualifiers.cpp:38:16:38:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:38:16:38:20 | inner indirection [a] | qualifiers.cpp:38:16:38:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:38:16:38:20 | inner indirection [a] | qualifiers.cpp:38:23:38:23 | a |
|
||||
| qualifiers.cpp:42:5:42:40 | ... = ... | qualifiers.cpp:42:25:42:25 | * ... indirection [post update] [a] |
|
||||
| qualifiers.cpp:42:7:42:11 | getInner output argument [inner indirection, a] | qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] |
|
||||
| qualifiers.cpp:42:25:42:25 | * ... indirection [post update] [a] | qualifiers.cpp:42:7:42:11 | getInner output argument [inner indirection, a] |
|
||||
| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:42:5:42:40 | ... = ... |
|
||||
| qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] | qualifiers.cpp:43:16:43:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:43:16:43:20 | inner indirection [a] | qualifiers.cpp:43:16:43:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:43:16:43:20 | inner indirection [a] | qualifiers.cpp:43:23:43:23 | a |
|
||||
| qualifiers.cpp:47:5:47:42 | ... = ... | qualifiers.cpp:47:27:47:27 | call to getInner indirection [post update] [a] |
|
||||
| qualifiers.cpp:47:6:47:11 | getInner output argument [inner indirection, a] | qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] |
|
||||
| qualifiers.cpp:47:27:47:27 | call to getInner indirection [post update] [a] | qualifiers.cpp:47:6:47:11 | getInner output argument [inner indirection, a] |
|
||||
| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:5:47:42 | ... = ... |
|
||||
| qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] | qualifiers.cpp:48:16:48:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:48:16:48:20 | inner indirection [a] | qualifiers.cpp:48:16:48:20 | inner indirection [a] |
|
||||
| qualifiers.cpp:48:16:48:20 | inner indirection [a] | qualifiers.cpp:48:23:48:23 | a |
|
||||
| realistic.cpp:53:9:53:66 | ... = ... | realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] |
|
||||
| realistic.cpp:53:13:53:15 | foo indirection [post update] [bar, baz indirection, userInput, bufferLen] | realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] |
|
||||
@@ -717,7 +682,6 @@ edges
|
||||
| realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... |
|
||||
| realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] |
|
||||
| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] |
|
||||
| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] |
|
||||
| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] |
|
||||
| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | realistic.cpp:61:14:61:55 | bufferLen |
|
||||
| simple.cpp:18:9:18:9 | this indirection [a_] | simple.cpp:18:22:18:23 | this indirection [a_] |
|
||||
@@ -770,6 +734,9 @@ edges
|
||||
| simple.cpp:92:7:92:7 | a indirection [post update] [i] | simple.cpp:94:10:94:11 | a2 indirection [i] |
|
||||
| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... |
|
||||
| simple.cpp:94:10:94:11 | a2 indirection [i] | simple.cpp:94:13:94:13 | i |
|
||||
| simple.cpp:103:24:103:24 | x | simple.cpp:104:14:104:14 | x |
|
||||
| simple.cpp:108:17:108:26 | call to user_input | simple.cpp:109:43:109:43 | x |
|
||||
| simple.cpp:109:43:109:43 | x | simple.cpp:103:24:103:24 | x |
|
||||
| struct_init.c:14:24:14:25 | ab indirection [a] | struct_init.c:15:8:15:9 | ab indirection [a] |
|
||||
| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a |
|
||||
| struct_init.c:20:13:20:14 | definition of ab indirection [a] | struct_init.c:22:8:22:9 | ab indirection [a] |
|
||||
@@ -793,7 +760,6 @@ edges
|
||||
| struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB indirection [a] |
|
||||
| struct_init.c:31:14:31:21 | nestedAB indirection [a] | struct_init.c:31:23:31:23 | a |
|
||||
| struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] | struct_init.c:33:14:33:22 | pointerAB indirection [a] |
|
||||
| struct_init.c:33:14:33:22 | pointerAB indirection [a] | struct_init.c:33:14:33:22 | pointerAB indirection [a] |
|
||||
| struct_init.c:33:14:33:22 | pointerAB indirection [a] | struct_init.c:33:25:33:25 | a |
|
||||
| struct_init.c:36:10:36:24 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
|
||||
| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | struct_init.c:36:10:36:24 | & ... indirection [a] |
|
||||
@@ -805,7 +771,6 @@ edges
|
||||
| struct_init.c:43:5:43:7 | & ... indirection [a] | struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] |
|
||||
| struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] | struct_init.c:46:16:46:24 | pointerAB indirection [a] |
|
||||
| struct_init.c:46:16:46:24 | pointerAB indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] |
|
||||
| struct_init.c:46:16:46:24 | pointerAB indirection [a] | struct_init.c:46:16:46:24 | pointerAB indirection [a] |
|
||||
nodes
|
||||
| A.cpp:23:10:23:10 | c | semmle.label | c |
|
||||
| A.cpp:25:7:25:17 | ... = ... | semmle.label | ... = ... |
|
||||
@@ -1016,7 +981,6 @@ nodes
|
||||
| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | semmle.label | p indirection [data, buffer indirection] |
|
||||
| E.cpp:21:13:21:16 | data indirection [buffer indirection] | semmle.label | data indirection [buffer indirection] |
|
||||
| E.cpp:21:18:21:23 | buffer indirection | semmle.label | buffer indirection |
|
||||
| E.cpp:21:18:21:23 | buffer indirection | semmle.label | buffer indirection |
|
||||
| E.cpp:28:21:28:23 | argument_source output argument | semmle.label | argument_source output argument |
|
||||
| E.cpp:29:21:29:29 | argument_source output argument | semmle.label | argument_source output argument |
|
||||
| E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] | semmle.label | b indirection [post update] [buffer indirection] |
|
||||
@@ -1026,7 +990,6 @@ nodes
|
||||
| E.cpp:31:10:31:12 | raw indirection | semmle.label | raw indirection |
|
||||
| E.cpp:32:10:32:10 | b indirection [buffer indirection] | semmle.label | b indirection [buffer indirection] |
|
||||
| E.cpp:32:13:32:18 | buffer indirection | semmle.label | buffer indirection |
|
||||
| E.cpp:32:13:32:18 | buffer indirection | semmle.label | buffer indirection |
|
||||
| E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] | semmle.label | & ... indirection [data, buffer indirection] |
|
||||
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
|
||||
| aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] |
|
||||
@@ -1274,7 +1237,6 @@ nodes
|
||||
| clearning.cpp:54:5:54:5 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:55:8:55:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
|
||||
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:55:10:55:10 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... |
|
||||
| clearning.cpp:60:7:60:7 | s indirection [post update] [x indirection] | semmle.label | s indirection [post update] [x indirection] |
|
||||
| clearning.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input |
|
||||
@@ -1285,7 +1247,6 @@ nodes
|
||||
| clearning.cpp:61:5:61:5 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:62:8:62:8 | s indirection [x indirection] | semmle.label | s indirection [x indirection] |
|
||||
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:62:10:62:10 | x indirection | semmle.label | x indirection |
|
||||
| clearning.cpp:74:20:74:22 | argument_source output argument | semmle.label | argument_source output argument |
|
||||
| clearning.cpp:74:20:74:22 | s indirection [post update] [val indirection] | semmle.label | s indirection [post update] [val indirection] |
|
||||
| clearning.cpp:76:7:76:12 | * ... | semmle.label | * ... |
|
||||
@@ -1576,6 +1537,10 @@ nodes
|
||||
| simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:94:10:94:11 | a2 indirection [i] | semmle.label | a2 indirection [i] |
|
||||
| simple.cpp:94:13:94:13 | i | semmle.label | i |
|
||||
| simple.cpp:103:24:103:24 | x | semmle.label | x |
|
||||
| simple.cpp:104:14:104:14 | x | semmle.label | x |
|
||||
| simple.cpp:108:17:108:26 | call to user_input | semmle.label | call to user_input |
|
||||
| simple.cpp:109:43:109:43 | x | semmle.label | x |
|
||||
| struct_init.c:14:24:14:25 | ab indirection [a] | semmle.label | ab indirection [a] |
|
||||
| struct_init.c:15:8:15:9 | ab indirection [a] | semmle.label | ab indirection [a] |
|
||||
| struct_init.c:15:12:15:12 | a | semmle.label | a |
|
||||
@@ -1782,6 +1747,7 @@ subpaths
|
||||
| simple.cpp:67:13:67:13 | i | simple.cpp:65:11:65:20 | call to user_input | simple.cpp:67:13:67:13 | i | i flows from $@ | simple.cpp:65:11:65:20 | call to user_input | call to user_input |
|
||||
| simple.cpp:84:14:84:20 | call to getf2f1 | simple.cpp:83:17:83:26 | call to user_input | simple.cpp:84:14:84:20 | call to getf2f1 | call to getf2f1 flows from $@ | simple.cpp:83:17:83:26 | call to user_input | call to user_input |
|
||||
| simple.cpp:94:13:94:13 | i | simple.cpp:92:11:92:20 | call to user_input | simple.cpp:94:13:94:13 | i | i flows from $@ | simple.cpp:92:11:92:20 | call to user_input | call to user_input |
|
||||
| simple.cpp:104:14:104:14 | x | simple.cpp:108:17:108:26 | call to user_input | simple.cpp:104:14:104:14 | x | x flows from $@ | simple.cpp:108:17:108:26 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:20:20:20:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:20:20:20:29 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:27:7:27:16 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:27:7:27:16 | call to user_input | call to user_input |
|
||||
| struct_init.c:15:12:15:12 | a | struct_init.c:40:20:40:29 | call to user_input | struct_init.c:15:12:15:12 | a | a flows from $@ | struct_init.c:40:20:40:29 | call to user_input | call to user_input |
|
||||
|
||||
@@ -94,4 +94,21 @@ void single_field_test_typedef(A_typedef a)
|
||||
sink(a2.i); //$ ast,ir
|
||||
}
|
||||
|
||||
namespace TestAdditionalCallTargets {
|
||||
|
||||
using TakesIntReturnsVoid = void(*)(int);
|
||||
template<TakesIntReturnsVoid F>
|
||||
void call_template_argument(int);
|
||||
|
||||
void call_sink(int x) {
|
||||
sink(x); // $ ir
|
||||
}
|
||||
|
||||
void test_additional_call_targets() {
|
||||
int x = user_input();
|
||||
call_template_argument<call_sink>(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace Simple
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
failures
|
||||
|
||||
@@ -2199,6 +2199,19 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
|
||||
| map.cpp:436:55:436:59 | def | map.cpp:436:19:436:60 | call to pair | TAINT |
|
||||
| map.cpp:436:63:436:67 | first | map.cpp:436:7:436:67 | call to iterator | |
|
||||
| map.cpp:437:7:437:9 | m35 | map.cpp:437:7:437:9 | call to unordered_map | |
|
||||
| map.cpp:446:23:446:23 | call to map | map.cpp:448:3:448:3 | m | |
|
||||
| map.cpp:446:23:446:23 | call to map | map.cpp:449:12:449:12 | m | |
|
||||
| map.cpp:446:23:446:23 | call to map | map.cpp:451:1:451:1 | m | |
|
||||
| map.cpp:447:12:447:26 | call to indirect_source | map.cpp:448:10:448:10 | p | |
|
||||
| map.cpp:448:3:448:3 | m | map.cpp:448:4:448:4 | call to operator[] | TAINT |
|
||||
| map.cpp:448:3:448:3 | ref arg m | map.cpp:449:12:449:12 | m | |
|
||||
| map.cpp:448:3:448:3 | ref arg m | map.cpp:451:1:451:1 | m | |
|
||||
| map.cpp:448:3:448:10 | ... = ... | map.cpp:448:4:448:4 | call to operator[] [post update] | |
|
||||
| map.cpp:448:4:448:4 | call to operator[] [post update] | map.cpp:448:3:448:3 | ref arg m | TAINT |
|
||||
| map.cpp:448:10:448:10 | p | map.cpp:448:3:448:10 | ... = ... | |
|
||||
| map.cpp:449:12:449:12 | m | map.cpp:449:13:449:13 | call to operator[] | TAINT |
|
||||
| map.cpp:449:12:449:12 | ref arg m | map.cpp:451:1:451:1 | m | |
|
||||
| map.cpp:449:13:449:13 | call to operator[] | map.cpp:450:8:450:8 | q | |
|
||||
| movableclass.cpp:8:2:8:15 | this | movableclass.cpp:8:27:8:31 | constructor init of field v [pre-this] | |
|
||||
| movableclass.cpp:8:21:8:22 | _v | movableclass.cpp:8:29:8:30 | _v | |
|
||||
| movableclass.cpp:8:29:8:30 | _v | movableclass.cpp:8:27:8:31 | constructor init of field v | TAINT |
|
||||
@@ -6609,6 +6622,41 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
|
||||
| taint.cpp:711:13:711:13 | s | taint.cpp:711:2:711:8 | call to strncpy | TAINT |
|
||||
| taint.cpp:711:13:711:13 | s | taint.cpp:711:10:711:10 | ref arg d | TAINT |
|
||||
| taint.cpp:712:7:712:7 | ref arg d | taint.cpp:709:25:709:25 | d | |
|
||||
| taint.cpp:718:17:718:31 | call to indirect_source | taint.cpp:720:27:720:32 | source | |
|
||||
| taint.cpp:719:22:719:29 | ,.-;:_ | taint.cpp:720:35:720:39 | delim | |
|
||||
| taint.cpp:719:22:719:29 | ,.-;:_ | taint.cpp:722:8:722:12 | delim | |
|
||||
| taint.cpp:720:20:720:25 | call to strtok | taint.cpp:721:8:721:16 | tokenized | |
|
||||
| taint.cpp:720:27:720:32 | source | taint.cpp:720:20:720:25 | call to strtok | TAINT |
|
||||
| taint.cpp:721:8:721:16 | tokenized | taint.cpp:721:7:721:16 | * ... | TAINT |
|
||||
| taint.cpp:722:8:722:12 | delim | taint.cpp:722:7:722:12 | * ... | TAINT |
|
||||
| taint.cpp:727:24:727:29 | source | taint.cpp:727:24:727:29 | source | |
|
||||
| taint.cpp:727:24:727:29 | source | taint.cpp:729:18:729:23 | source | |
|
||||
| taint.cpp:728:17:728:23 | 0 | taint.cpp:729:27:729:32 | endptr | |
|
||||
| taint.cpp:728:17:728:23 | 0 | taint.cpp:731:7:731:12 | endptr | |
|
||||
| taint.cpp:728:17:728:23 | 0 | taint.cpp:732:8:732:13 | endptr | |
|
||||
| taint.cpp:729:11:729:16 | call to strtol | taint.cpp:730:7:730:7 | l | |
|
||||
| taint.cpp:729:18:729:23 | source | taint.cpp:729:11:729:16 | call to strtol | TAINT |
|
||||
| taint.cpp:729:18:729:23 | source | taint.cpp:729:26:729:32 | ref arg & ... | TAINT |
|
||||
| taint.cpp:729:26:729:32 | ref arg & ... | taint.cpp:729:27:729:32 | endptr [inner post update] | |
|
||||
| taint.cpp:729:26:729:32 | ref arg & ... | taint.cpp:731:7:731:12 | endptr | |
|
||||
| taint.cpp:729:26:729:32 | ref arg & ... | taint.cpp:732:8:732:13 | endptr | |
|
||||
| taint.cpp:729:27:729:32 | endptr | taint.cpp:729:26:729:32 | & ... | |
|
||||
| taint.cpp:731:7:731:12 | ref arg endptr | taint.cpp:732:8:732:13 | endptr | |
|
||||
| taint.cpp:732:8:732:13 | endptr | taint.cpp:732:7:732:13 | * ... | TAINT |
|
||||
| taint.cpp:738:17:738:31 | call to indirect_source | taint.cpp:739:30:739:35 | source | |
|
||||
| taint.cpp:739:22:739:28 | call to realloc | taint.cpp:740:7:740:10 | dest | |
|
||||
| taint.cpp:739:30:739:35 | source | taint.cpp:739:22:739:28 | call to realloc | TAINT |
|
||||
| taint.cpp:743:40:743:45 | buffer | taint.cpp:744:5:744:10 | buffer | |
|
||||
| taint.cpp:743:40:743:45 | buffer | taint.cpp:745:27:745:32 | buffer | |
|
||||
| taint.cpp:744:4:744:10 | * ... | taint.cpp:744:3:744:10 | * ... | TAINT |
|
||||
| taint.cpp:744:5:744:10 | buffer | taint.cpp:744:4:744:10 | * ... | TAINT |
|
||||
| taint.cpp:744:14:744:19 | call to source | taint.cpp:744:3:744:21 | ... = ... | |
|
||||
| taint.cpp:745:19:745:25 | call to realloc | taint.cpp:743:40:743:45 | buffer | |
|
||||
| taint.cpp:745:19:745:25 | call to realloc | taint.cpp:745:3:745:37 | ... = ... | |
|
||||
| taint.cpp:745:19:745:25 | call to realloc | taint.cpp:746:10:746:15 | buffer | |
|
||||
| taint.cpp:745:27:745:32 | buffer | taint.cpp:745:19:745:25 | call to realloc | TAINT |
|
||||
| taint.cpp:746:9:746:15 | * ... | taint.cpp:746:8:746:15 | * ... | TAINT |
|
||||
| taint.cpp:746:10:746:15 | buffer | taint.cpp:746:9:746:15 | * ... | TAINT |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
|
||||
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
|
||||
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |
|
||||
|
||||
@@ -165,9 +165,9 @@ void test_map()
|
||||
// array-like access
|
||||
std::map<char *, char *> m10, m11, m12, m13;
|
||||
sink(m10["abc"] = "def");
|
||||
sink(m11["abc"] = source()); // $ ast ir=168:7 ir=168:20
|
||||
sink(m11["abc"] = source()); // $ ast,ir
|
||||
sink(m12.at("abc") = "def");
|
||||
sink(m13.at("abc") = source()); // $ ast ir=170:7 ir=170:23
|
||||
sink(m13.at("abc") = source()); // $ ast,ir
|
||||
sink(m10["abc"]);
|
||||
sink(m11["abc"]); // $ ast,ir
|
||||
sink(m12["abc"]);
|
||||
@@ -317,9 +317,9 @@ void test_unordered_map()
|
||||
// array-like access
|
||||
std::unordered_map<char *, char *> m10, m11, m12, m13;
|
||||
sink(m10["abc"] = "def");
|
||||
sink(m11["abc"] = source()); // $ ast ir=320:7 ir=320:20
|
||||
sink(m11["abc"] = source()); // $ ast,ir
|
||||
sink(m12.at("abc") = "def");
|
||||
sink(m13.at("abc") = source()); // $ ast ir=322:7 ir=322:23
|
||||
sink(m13.at("abc") = source()); // $ ast,ir
|
||||
sink(m10["abc"]);
|
||||
sink(m11["abc"]); // $ ast,ir
|
||||
sink(m12["abc"]);
|
||||
@@ -436,3 +436,16 @@ void test_unordered_map()
|
||||
sink(m35.emplace(std::pair<char *, char *>(source(), "def")).first); // $ MISSING: ast,ir
|
||||
sink(m35); // $ MISSING: ast,ir
|
||||
}
|
||||
|
||||
namespace {
|
||||
int* indirect_source();
|
||||
void indirect_sink(int*);
|
||||
}
|
||||
|
||||
void test_indirect_taint() {
|
||||
std::map<int, int*> m;
|
||||
int* p = indirect_source();
|
||||
m[1] = p;
|
||||
int* q = m[1];
|
||||
sink(q); // $ ir MISSING: ast
|
||||
}
|
||||
@@ -13,8 +13,8 @@ void arithAssignments(int source1, int clean1) {
|
||||
source1++;
|
||||
++source1;
|
||||
source1 += 1;
|
||||
sink(source1); // $ ast ir=12:13 ir=12:22
|
||||
sink(++source1); // $ ast ir=12:13 ir=12:22
|
||||
sink(source1); // $ ast,ir
|
||||
sink(++source1); // $ ast,ir
|
||||
}
|
||||
|
||||
// --- globals ---
|
||||
@@ -710,4 +710,38 @@ void test_strncpy(char* d, char* s) {
|
||||
argument_source(s);
|
||||
strncpy(d, s, 16);
|
||||
sink(d); // $ ast ir
|
||||
}
|
||||
|
||||
char* indirect_source();
|
||||
|
||||
void test_strtok_indirect() {
|
||||
char *source = indirect_source();
|
||||
const char* delim = ",.-;:_";
|
||||
char* tokenized = strtok(source, delim);
|
||||
sink(*tokenized); // $ ir MISSING: ast
|
||||
sink(*delim);
|
||||
}
|
||||
|
||||
long int strtol(const char*, char**, int);
|
||||
|
||||
void test_strtol(char *source) {
|
||||
char* endptr = nullptr;
|
||||
long l = strtol(source, &endptr, 10);
|
||||
sink(l); // $ ast,ir
|
||||
sink(endptr); // $ ast,ir
|
||||
sink(*endptr); // $ ast,ir
|
||||
}
|
||||
|
||||
void *realloc(void *, size_t);
|
||||
|
||||
void test_realloc() {
|
||||
char *source = indirect_source();
|
||||
char *dest = (char*)realloc(source, 16);
|
||||
sink(dest); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_realloc_2_indirections(int **buffer) {
|
||||
**buffer = source();
|
||||
buffer = (int**)realloc(buffer, 16);
|
||||
sink(**buffer); // $ ir MISSING: ast
|
||||
}
|
||||
@@ -84,6 +84,8 @@ module IRTest {
|
||||
or
|
||||
source.asIndirectExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asIndirectExpr().(FunctionCall).getTarget().getName() = "indirect_source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
exists(FunctionCall fc |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user