mirror of
https://github.com/github/codeql.git
synced 2026-07-05 11:35:30 +02:00
Compare commits
693 Commits
codeql-cli
...
oscarsj-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdb49fecf3 | ||
|
|
f8ef697978 | ||
|
|
a905917123 | ||
|
|
8ef961b776 | ||
|
|
4de4f35855 | ||
|
|
f29db40371 | ||
|
|
59e495aa31 | ||
|
|
1c80175a34 | ||
|
|
ea75996932 | ||
|
|
af18c98028 | ||
|
|
3f645e9401 | ||
|
|
1f018d69ab | ||
|
|
b56b843d13 | ||
|
|
205647331d | ||
|
|
841db151f6 | ||
|
|
0f134c6a3c | ||
|
|
aca2ace843 | ||
|
|
f86e540d2a | ||
|
|
d18be93e24 | ||
|
|
af2a9b21ab | ||
|
|
ca51200cd4 | ||
|
|
9e129ac38d | ||
|
|
a9d3cfccd4 | ||
|
|
532e1446f0 | ||
|
|
4b88279ccc | ||
|
|
e969018f99 | ||
|
|
68cf33e791 | ||
|
|
3eb5a95ee3 | ||
|
|
9590dde1e6 | ||
|
|
27fb42db76 | ||
|
|
dff6f17978 | ||
|
|
e9c25949fa | ||
|
|
be08b97418 | ||
|
|
a92a55f437 | ||
|
|
efdaffedee | ||
|
|
bfc48efdaa | ||
|
|
c9fba18c48 | ||
|
|
733a00039e | ||
|
|
0c6efb8c84 | ||
|
|
3bfcbbf7af | ||
|
|
0710ed97db | ||
|
|
2db304edee | ||
|
|
388b2abf68 | ||
|
|
82c025020d | ||
|
|
a571bc64ac | ||
|
|
2e5a04854e | ||
|
|
644d7f18c2 | ||
|
|
5e87111a8b | ||
|
|
1e2bdd88b1 | ||
|
|
635d290504 | ||
|
|
67afbee06d | ||
|
|
353d5f82a6 | ||
|
|
0ce27d13a7 | ||
|
|
ab67103e6e | ||
|
|
18d4af994d | ||
|
|
ca09649679 | ||
|
|
f59c149bae | ||
|
|
2001ce34d4 | ||
|
|
51c08f1314 | ||
|
|
fbc872cf1d | ||
|
|
5927bb2030 | ||
|
|
5d15ec99c8 | ||
|
|
383b2e183d | ||
|
|
a9cf6885d0 | ||
|
|
6c8cb0dc5e | ||
|
|
3a8a585335 | ||
|
|
4687ac16ff | ||
|
|
0bc6f10a71 | ||
|
|
2c89f9747b | ||
|
|
c81ea9d747 | ||
|
|
36ea61c25e | ||
|
|
e9f1e99526 | ||
|
|
1bba5258d6 | ||
|
|
a7d238f4c4 | ||
|
|
3d41cd583f | ||
|
|
d1c8e0abd7 | ||
|
|
1094018088 | ||
|
|
77ec181cac | ||
|
|
f87740ab18 | ||
|
|
1b75afb5b1 | ||
|
|
c1a52031cf | ||
|
|
3bd29171fb | ||
|
|
edfe2d7ab7 | ||
|
|
8ca80d3170 | ||
|
|
5a44fae515 | ||
|
|
2716c73f87 | ||
|
|
c35cb70c9f | ||
|
|
fd2f0257b6 | ||
|
|
24d1cac9d7 | ||
|
|
ee7b137c24 | ||
|
|
3eca60cc40 | ||
|
|
205bb76036 | ||
|
|
4ef58cd662 | ||
|
|
ce64408442 | ||
|
|
ee25f97ea5 | ||
|
|
5f4d0892ff | ||
|
|
933b55d37d | ||
|
|
8a9308c8b0 | ||
|
|
b3669b818b | ||
|
|
0c8f895e0f | ||
|
|
97a942de80 | ||
|
|
5c23474634 | ||
|
|
6c095d8143 | ||
|
|
72b082806b | ||
|
|
e46c53af1d | ||
|
|
1372ee7a44 | ||
|
|
0fb79bdf64 | ||
|
|
c674afb674 | ||
|
|
682ff23e04 | ||
|
|
36889f6d72 | ||
|
|
70331c0ea4 | ||
|
|
96e415aba6 | ||
|
|
abb98be996 | ||
|
|
fc65160a78 | ||
|
|
432c0b508a | ||
|
|
9df2ee00d6 | ||
|
|
71ae0909d8 | ||
|
|
9140cbefc0 | ||
|
|
a761eea2dc | ||
|
|
9ad2da6196 | ||
|
|
4f2d2361a4 | ||
|
|
5373b4d466 | ||
|
|
b534e7b6d5 | ||
|
|
a2fa97ac22 | ||
|
|
123534a676 | ||
|
|
ff3e45e1ba | ||
|
|
748bcba0ae | ||
|
|
95b95e5c27 | ||
|
|
52f50b8d9d | ||
|
|
142479eeb7 | ||
|
|
69202d2dae | ||
|
|
933d2fbb9f | ||
|
|
2cf58fccf7 | ||
|
|
e5d36ff461 | ||
|
|
77b09f3660 | ||
|
|
11c05257d4 | ||
|
|
fd36304da2 | ||
|
|
5a027b95bd | ||
|
|
209d9143be | ||
|
|
c79daf0116 | ||
|
|
b84b1a46d6 | ||
|
|
cda26ba7c0 | ||
|
|
246d904712 | ||
|
|
5a8bed0285 | ||
|
|
8517f11477 | ||
|
|
1b366fc87a | ||
|
|
f888382d35 | ||
|
|
5a77dfb5d5 | ||
|
|
9ded5b87a5 | ||
|
|
aa216e6535 | ||
|
|
507bb61c3c | ||
|
|
f685ae1fa7 | ||
|
|
c823c58e00 | ||
|
|
d73289ac4e | ||
|
|
cc8d7bff0b | ||
|
|
410719fd9e | ||
|
|
5a4fe1b4da | ||
|
|
6025feebd9 | ||
|
|
21a00f9197 | ||
|
|
a541fdf5e5 | ||
|
|
1bf159e9a9 | ||
|
|
e6c4bd18d6 | ||
|
|
1aa1153ed6 | ||
|
|
fc66aacf92 | ||
|
|
0040025661 | ||
|
|
067f3259c9 | ||
|
|
1ae116c4cc | ||
|
|
6bfdbef697 | ||
|
|
b18e096f7f | ||
|
|
1dcac76992 | ||
|
|
d7474f91dc | ||
|
|
128d102bbc | ||
|
|
60aab206b0 | ||
|
|
20f555c715 | ||
|
|
5838c5d9c8 | ||
|
|
6f804ff1e7 | ||
|
|
35788162ec | ||
|
|
d114388470 | ||
|
|
12d181143f | ||
|
|
d274fa16a1 | ||
|
|
0c4bcec39e | ||
|
|
16fc42a53f | ||
|
|
3d381331e1 | ||
|
|
91a151ec2a | ||
|
|
3d67970357 | ||
|
|
4c0384b4f1 | ||
|
|
82eb0026e6 | ||
|
|
2d9295a5a4 | ||
|
|
90ad36ed6c | ||
|
|
ce1c4b88d8 | ||
|
|
cf1e87de9e | ||
|
|
1f228a049f | ||
|
|
8e6038577d | ||
|
|
3c1456bd02 | ||
|
|
d681671356 | ||
|
|
32a738b082 | ||
|
|
8fcfc6f4f1 | ||
|
|
0d74d88b7b | ||
|
|
4df05b4e74 | ||
|
|
cb04df49eb | ||
|
|
5d80f0818c | ||
|
|
b696936d10 | ||
|
|
abc1d658e0 | ||
|
|
74242638e2 | ||
|
|
8ca5484dcf | ||
|
|
5b6d3afd89 | ||
|
|
9fe5462b1b | ||
|
|
09d4fe21e8 | ||
|
|
b178c9cfe6 | ||
|
|
3f39648065 | ||
|
|
1a97e8f329 | ||
|
|
6b049cb37a | ||
|
|
3d01763092 | ||
|
|
90f84bb516 | ||
|
|
81ce6c7779 | ||
|
|
c9c281cb9a | ||
|
|
5f011a262c | ||
|
|
611a7060b4 | ||
|
|
c1c2bcf419 | ||
|
|
0094c25791 | ||
|
|
a446c5452d | ||
|
|
799d92b218 | ||
|
|
b94289fde1 | ||
|
|
f32b8ad5b1 | ||
|
|
96fba2dac3 | ||
|
|
4c102ab99c | ||
|
|
bc08d67f19 | ||
|
|
2c4246f29a | ||
|
|
389e8c4fe8 | ||
|
|
0650c016f6 | ||
|
|
d54c444606 | ||
|
|
311498841e | ||
|
|
9d80a43d6a | ||
|
|
6110b7aca5 | ||
|
|
738e3857e7 | ||
|
|
cb82bd62e7 | ||
|
|
e50f56cc56 | ||
|
|
e5f2b90aec | ||
|
|
3f03cc27cd | ||
|
|
648c08bcd9 | ||
|
|
9cc4bfec2a | ||
|
|
d14ee931e1 | ||
|
|
a2a82fcde9 | ||
|
|
95b8a22529 | ||
|
|
a95fc79874 | ||
|
|
d98723c35a | ||
|
|
cff7f63193 | ||
|
|
909f40b6ea | ||
|
|
84ddfe9c3f | ||
|
|
b1712d33fe | ||
|
|
b35637e1c5 | ||
|
|
89ee2b9ace | ||
|
|
c3c3faa4b5 | ||
|
|
3694ed5ed6 | ||
|
|
cab76507e7 | ||
|
|
ff67118097 | ||
|
|
125aab8107 | ||
|
|
a9d34458de | ||
|
|
0ebb06e185 | ||
|
|
2c28fae7e3 | ||
|
|
b0b2d6e05f | ||
|
|
fcbd211783 | ||
|
|
934a455908 | ||
|
|
65835cdb92 | ||
|
|
c88f9bf818 | ||
|
|
621761b289 | ||
|
|
3af72fa28e | ||
|
|
59e59125d6 | ||
|
|
36d34f199b | ||
|
|
3d1da8a45d | ||
|
|
927522c563 | ||
|
|
b47c8e8c4c | ||
|
|
0a7e525c16 | ||
|
|
14706b42fa | ||
|
|
0ebf529dc4 | ||
|
|
8756c031e0 | ||
|
|
1afe845ed3 | ||
|
|
e3d93c3581 | ||
|
|
e84bdf5bed | ||
|
|
feb31612f5 | ||
|
|
95ef7fb3f1 | ||
|
|
71cd973b42 | ||
|
|
361b15b2c7 | ||
|
|
bfe5db20a3 | ||
|
|
ba4d326768 | ||
|
|
8ade7247a1 | ||
|
|
7453533ba4 | ||
|
|
7fa84a3613 | ||
|
|
bfbbb5277d | ||
|
|
b0efff0110 | ||
|
|
b16444dd22 | ||
|
|
1f126b60ff | ||
|
|
5e274c9664 | ||
|
|
a5e919b6cb | ||
|
|
19e6a9a1d3 | ||
|
|
40aed29858 | ||
|
|
b919547e31 | ||
|
|
bc44b9e4fb | ||
|
|
c4a7353583 | ||
|
|
f61565cab1 | ||
|
|
9c25c150a3 | ||
|
|
b60cab254a | ||
|
|
a4d7570788 | ||
|
|
9881fdfe27 | ||
|
|
4094ec5fcc | ||
|
|
f80a0916ac | ||
|
|
e0e978bd3e | ||
|
|
b56869551d | ||
|
|
6e31f64aaa | ||
|
|
4bf03e7962 | ||
|
|
f3b14e13b2 | ||
|
|
239a763ef9 | ||
|
|
149753c052 | ||
|
|
64ea4833d9 | ||
|
|
85542638d7 | ||
|
|
94f11029ee | ||
|
|
2ae4b646a0 | ||
|
|
2ca8103a7e | ||
|
|
5dbd11a584 | ||
|
|
fa1a6da60d | ||
|
|
7c72ece4a0 | ||
|
|
9828ad0fc3 | ||
|
|
2e76e12316 | ||
|
|
1f861fda25 | ||
|
|
0fdeeba46f | ||
|
|
76f8d460e7 | ||
|
|
00436828a9 | ||
|
|
b707c8162e | ||
|
|
c7378a1e5b | ||
|
|
94e0828ab9 | ||
|
|
aa8291e13f | ||
|
|
51b6da4183 | ||
|
|
603a97faf9 | ||
|
|
9dc1ea1216 | ||
|
|
377aa68bb3 | ||
|
|
a47778c22e | ||
|
|
1d0a0dec6f | ||
|
|
1acc0d2ddf | ||
|
|
656d8d2451 | ||
|
|
c71278ceb7 | ||
|
|
60c723e7cc | ||
|
|
b6a7661c7e | ||
|
|
bda0ef3a75 | ||
|
|
4f7275f064 | ||
|
|
88411ce439 | ||
|
|
31b56bf966 | ||
|
|
533e1d818b | ||
|
|
7285704807 | ||
|
|
e895cac569 | ||
|
|
3779d8423f | ||
|
|
aa3e8d6b87 | ||
|
|
4484574301 | ||
|
|
10c222e7e2 | ||
|
|
a3c66b6032 | ||
|
|
49dccaa89d | ||
|
|
23934292f0 | ||
|
|
65c1f4a151 | ||
|
|
ba6bb79dd3 | ||
|
|
e9ffefaa96 | ||
|
|
1a876f7762 | ||
|
|
3ca04338ca | ||
|
|
c2f2a0578b | ||
|
|
219c1686fd | ||
|
|
d7325ba4e1 | ||
|
|
b410791f28 | ||
|
|
e94b492404 | ||
|
|
f976eeb909 | ||
|
|
1b128a21e6 | ||
|
|
1979a78f02 | ||
|
|
b7e36b7dec | ||
|
|
5580023ec3 | ||
|
|
1bb006f43e | ||
|
|
641f16b0df | ||
|
|
a611769b43 | ||
|
|
d61d595b21 | ||
|
|
b45c0ff848 | ||
|
|
b76e655735 | ||
|
|
ba48eaa8a6 | ||
|
|
702c22b630 | ||
|
|
f0186957ca | ||
|
|
0bfb242e63 | ||
|
|
b169f1bfdf | ||
|
|
f872a11b85 | ||
|
|
2d8d9773c4 | ||
|
|
d613bc8a28 | ||
|
|
c092851c28 | ||
|
|
2914480ff6 | ||
|
|
1cf626f712 | ||
|
|
4e60697042 | ||
|
|
83674751fc | ||
|
|
8d62d5916e | ||
|
|
672cb92fbd | ||
|
|
1c2fdc8df9 | ||
|
|
c44fbc1063 | ||
|
|
dcca0e0c6c | ||
|
|
1caca21552 | ||
|
|
30468dd059 | ||
|
|
ab4eba11ec | ||
|
|
62f5a5dcd5 | ||
|
|
4ae8377713 | ||
|
|
78229bb264 | ||
|
|
7abc029872 | ||
|
|
fc3c776bdc | ||
|
|
9aca2d8533 | ||
|
|
c7ea08aa73 | ||
|
|
fb1a871777 | ||
|
|
7f675d8c3b | ||
|
|
96f06f8eca | ||
|
|
83d5cde01d | ||
|
|
09502c60d5 | ||
|
|
924ce250dd | ||
|
|
6e5f09f7bb | ||
|
|
231b0fcab2 | ||
|
|
a168af349e | ||
|
|
a5a0861be0 | ||
|
|
2f268b309b | ||
|
|
ba49386e6c | ||
|
|
61aba4683f | ||
|
|
e5d89b969a | ||
|
|
f6d000eb20 | ||
|
|
0a6bb3f7ce | ||
|
|
d777fd950f | ||
|
|
99ad43b21e | ||
|
|
9d34d090ab | ||
|
|
b8c55612e5 | ||
|
|
bbb1ee9597 | ||
|
|
cb90f9af3c | ||
|
|
522a285d9e | ||
|
|
2e27447c65 | ||
|
|
e6a2528c38 | ||
|
|
49521f6de8 | ||
|
|
66f971e70d | ||
|
|
93bd2a9409 | ||
|
|
547f00c3d1 | ||
|
|
9631b6545f | ||
|
|
e0e5bb131b | ||
|
|
2579852e90 | ||
|
|
6cda285d56 | ||
|
|
8d0e3ac033 | ||
|
|
38e65ee36d | ||
|
|
f745642252 | ||
|
|
95c28967cc | ||
|
|
0c380cdd72 | ||
|
|
13ec7db1ea | ||
|
|
3c2a3abb13 | ||
|
|
03e76378ca | ||
|
|
a149c41baf | ||
|
|
d1de453c7a | ||
|
|
bb8c3de6b2 | ||
|
|
027f08a0df | ||
|
|
25786f61be | ||
|
|
e4ec1ae261 | ||
|
|
88d2f65c5f | ||
|
|
cbe45f7e55 | ||
|
|
36d7370998 | ||
|
|
e65daaae49 | ||
|
|
d833850850 | ||
|
|
648f0e19ec | ||
|
|
2b41aef6a7 | ||
|
|
ea7996f1bb | ||
|
|
048fb8b953 | ||
|
|
3526b74ce7 | ||
|
|
d975ceb648 | ||
|
|
901db73d55 | ||
|
|
5272810ad9 | ||
|
|
44c1b48f94 | ||
|
|
c77cdcf4c3 | ||
|
|
ad82433a88 | ||
|
|
34d3040ce2 | ||
|
|
e180b7e2ba | ||
|
|
8c0c335daf | ||
|
|
8363171f1f | ||
|
|
7332cec9a5 | ||
|
|
29a20550f6 | ||
|
|
13b1e97caa | ||
|
|
eafef91dbc | ||
|
|
024760610a | ||
|
|
2f4a181a7d | ||
|
|
04079752f7 | ||
|
|
f87f6c8556 | ||
|
|
b728f71b4b | ||
|
|
e8e25b8e55 | ||
|
|
c7b0ae8490 | ||
|
|
518aceba64 | ||
|
|
388cb704d0 | ||
|
|
eaddb627ef | ||
|
|
73ddc0530a | ||
|
|
3687770dab | ||
|
|
ec68e91ba9 | ||
|
|
49d335695a | ||
|
|
5964daa44d | ||
|
|
a4ee35302d | ||
|
|
b3de105665 | ||
|
|
ee7d15ac5d | ||
|
|
8d5ca53126 | ||
|
|
5b8544343b | ||
|
|
5ea6cea894 | ||
|
|
fdd975b992 | ||
|
|
2a14479bf3 | ||
|
|
a87e67d89d | ||
|
|
cbe247e123 | ||
|
|
3f139bd93b | ||
|
|
edb355b47f | ||
|
|
f5702f5c69 | ||
|
|
e167d3ce00 | ||
|
|
4e49df1615 | ||
|
|
7eee589304 | ||
|
|
fa5ed04286 | ||
|
|
dba46bd324 | ||
|
|
ccb57f2a84 | ||
|
|
62dca44ee5 | ||
|
|
c250ba7f27 | ||
|
|
9db63c3a6a | ||
|
|
b0d4b31103 | ||
|
|
c7f16cd224 | ||
|
|
0d598c437d | ||
|
|
b321151a28 | ||
|
|
efb582b661 | ||
|
|
869c6d27fe | ||
|
|
74dbc71535 | ||
|
|
06bf246afe | ||
|
|
d94ed1b4a3 | ||
|
|
706fdce527 | ||
|
|
2adc4c0feb | ||
|
|
7b8606d411 | ||
|
|
38826c98f1 | ||
|
|
ba982e2f85 | ||
|
|
4bca9511cd | ||
|
|
9ecba6a94d | ||
|
|
619d572d50 | ||
|
|
46da73cc11 | ||
|
|
feccd307da | ||
|
|
bfdaf6951d | ||
|
|
21414089ee | ||
|
|
8a4ca7fb84 | ||
|
|
cece307c60 | ||
|
|
f4e8656c17 | ||
|
|
352866b52d | ||
|
|
a42dbc5bab | ||
|
|
d407a689fa | ||
|
|
169bde8671 | ||
|
|
8bf4b55309 | ||
|
|
f106783c39 | ||
|
|
ec97cdc8a0 | ||
|
|
7b56383b52 | ||
|
|
0a26916245 | ||
|
|
77b67cbf2e | ||
|
|
0fc775027f | ||
|
|
3826b9be6c | ||
|
|
74b71ff7e3 | ||
|
|
ea54ea47b1 | ||
|
|
3e55c47e3e | ||
|
|
5ed1868324 | ||
|
|
88eb0231c1 | ||
|
|
cd661f1d9f | ||
|
|
735a7383c6 | ||
|
|
1b1838b5a8 | ||
|
|
64cf3adfd4 | ||
|
|
820db43945 | ||
|
|
fddbffee6f | ||
|
|
4f9c51a02b | ||
|
|
316cb95547 | ||
|
|
0e3d9e1fec | ||
|
|
8a756eced9 | ||
|
|
f0749f69c7 | ||
|
|
0db05fe4fa | ||
|
|
544997d42f | ||
|
|
523feabaa2 | ||
|
|
e648c643ca | ||
|
|
0ffe9ab8d5 | ||
|
|
f27eff4f73 | ||
|
|
8aabd28461 | ||
|
|
fde855b25f | ||
|
|
6271b6f1c3 | ||
|
|
7fb8819a08 | ||
|
|
0445509080 | ||
|
|
6890434d63 | ||
|
|
d85bcacf84 | ||
|
|
540b8391dc | ||
|
|
99320857af | ||
|
|
8a6ff95035 | ||
|
|
4daaf783e1 | ||
|
|
cd7b79f62b | ||
|
|
1afa5af3dd | ||
|
|
a9595647c4 | ||
|
|
33afcd75f1 | ||
|
|
2a23f8766e | ||
|
|
e89df255e3 | ||
|
|
4ab184fc7d | ||
|
|
4ed101fa26 | ||
|
|
a991f87728 | ||
|
|
68fe486c05 | ||
|
|
60dab3d779 | ||
|
|
68391acc98 | ||
|
|
de4cfc3239 | ||
|
|
a3976305ca | ||
|
|
bb75ed03da | ||
|
|
f4ee1a5119 | ||
|
|
9a62f51694 | ||
|
|
ca029f5718 | ||
|
|
5601ad64ef | ||
|
|
eb7e401aea | ||
|
|
e3cbebae30 | ||
|
|
96f9c40fdb | ||
|
|
a96ad600fc | ||
|
|
3e4e75cee8 | ||
|
|
e6be88b10e | ||
|
|
60544c6889 | ||
|
|
bdf1da340d | ||
|
|
f9d5e56d9c | ||
|
|
f32d77b36c | ||
|
|
68cdc3b48e | ||
|
|
33bc7eabbb | ||
|
|
859b3051b7 | ||
|
|
b2d4a82932 | ||
|
|
1ac5db3a98 | ||
|
|
31b71ea163 | ||
|
|
40dde93beb | ||
|
|
23a7cd943f | ||
|
|
416f8d5ac9 | ||
|
|
c76dbebd9b | ||
|
|
3cc9dec9c8 | ||
|
|
d304022685 | ||
|
|
ead8108aed | ||
|
|
e0aeea058e | ||
|
|
184cb74cd0 | ||
|
|
f46ea325e8 | ||
|
|
21b03927c5 | ||
|
|
ba4e3ae949 | ||
|
|
824ff8ad88 | ||
|
|
ffec22a5d2 | ||
|
|
d0529bba2b | ||
|
|
69cb138912 | ||
|
|
7e23bf3938 | ||
|
|
b1957623c1 | ||
|
|
ab70f5722e | ||
|
|
49cceb2901 | ||
|
|
cdcee5cc75 | ||
|
|
539f8f0f70 | ||
|
|
51a62b54ee | ||
|
|
d299d92025 | ||
|
|
4995f13234 | ||
|
|
83cd55cb29 | ||
|
|
18c3feb9d8 | ||
|
|
259d5b6452 | ||
|
|
c1960c6ff9 | ||
|
|
3c88590df2 | ||
|
|
725004a6fe | ||
|
|
17fe5f2317 | ||
|
|
a8151b4ee4 | ||
|
|
fb2ec15dad | ||
|
|
cc12e74c23 | ||
|
|
dfe00ffe4b | ||
|
|
3c4bd5b6a7 | ||
|
|
b5e90483f5 | ||
|
|
d65bb3b232 | ||
|
|
a0f4a5100f | ||
|
|
8691845d23 | ||
|
|
2ef6d5c7b9 | ||
|
|
d942b54a9d | ||
|
|
c13999100b | ||
|
|
eff4729577 | ||
|
|
e4b4d8a3cd | ||
|
|
79089b40b9 | ||
|
|
5a8a6f2971 | ||
|
|
4fca4b668c | ||
|
|
f0b5f9c928 | ||
|
|
acaa6a5ea7 | ||
|
|
a5162b0b7d | ||
|
|
915c969efe | ||
|
|
17cfd489ea | ||
|
|
8b08e6042c | ||
|
|
37f1770623 | ||
|
|
941df4f274 | ||
|
|
cb2b2bc334 | ||
|
|
92198e1af0 | ||
|
|
6ef9088076 | ||
|
|
e4ae957cdd | ||
|
|
5a01feca6c | ||
|
|
6c932bc807 | ||
|
|
56dc2a4d4e | ||
|
|
abc0c7cf24 | ||
|
|
a386c58371 | ||
|
|
3fc488167f | ||
|
|
ed48065c2d | ||
|
|
2606abfc64 | ||
|
|
868b2385d1 | ||
|
|
4b4fc97221 | ||
|
|
7ea74df4b3 | ||
|
|
204dbee14c | ||
|
|
0f4157c534 | ||
|
|
f535923e67 | ||
|
|
54582031d8 |
@@ -1 +1 @@
|
||||
5.0.0
|
||||
6.1.2
|
||||
|
||||
4
.github/workflows/go-tests-other-os.yml
vendored
4
.github/workflows/go-tests-other-os.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.0
|
||||
go-version: '1.20'
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.0
|
||||
go-version: '1.20'
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
2
.github/workflows/go-tests.yml
vendored
2
.github/workflows/go-tests.yml
vendored
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Set up Go 1.20
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.0
|
||||
go-version: '1.20'
|
||||
id: go
|
||||
|
||||
- name: Check out code
|
||||
|
||||
29
.github/workflows/ruby-build.yml
vendored
29
.github/workflows/ruby-build.yml
vendored
@@ -58,10 +58,8 @@ jobs:
|
||||
id: cache-extractor
|
||||
with:
|
||||
path: |
|
||||
ruby/extractor/target/release/autobuilder
|
||||
ruby/extractor/target/release/autobuilder.exe
|
||||
ruby/extractor/target/release/extractor
|
||||
ruby/extractor/target/release/extractor.exe
|
||||
ruby/extractor/target/release/codeql-extractor-ruby
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}--${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
- uses: actions/cache@v3
|
||||
@@ -88,15 +86,13 @@ jobs:
|
||||
run: |
|
||||
cd extractor
|
||||
cross build --release
|
||||
mv target/x86_64-unknown-linux-gnu/release/extractor target/release/
|
||||
mv target/x86_64-unknown-linux-gnu/release/autobuilder target/release/
|
||||
mv target/x86_64-unknown-linux-gnu/release/generator target/release/
|
||||
mv target/x86_64-unknown-linux-gnu/release/codeql-extractor-ruby target/release/
|
||||
- name: Release build (windows and macos)
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true' && runner.os != 'Linux'
|
||||
run: cd extractor && cargo build --release
|
||||
- name: Generate dbscheme
|
||||
if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}}
|
||||
run: extractor/target/release/generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
run: extractor/target/release/codeql-extractor-ruby generate --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: ${{ matrix.os == 'ubuntu-latest' }}
|
||||
with:
|
||||
@@ -111,10 +107,8 @@ jobs:
|
||||
with:
|
||||
name: extractor-${{ matrix.os }}
|
||||
path: |
|
||||
ruby/extractor/target/release/autobuilder
|
||||
ruby/extractor/target/release/autobuilder.exe
|
||||
ruby/extractor/target/release/extractor
|
||||
ruby/extractor/target/release/extractor.exe
|
||||
ruby/extractor/target/release/codeql-extractor-ruby
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
retention-days: 1
|
||||
compile-queries:
|
||||
runs-on: ubuntu-latest-xl
|
||||
@@ -172,13 +166,10 @@ jobs:
|
||||
mkdir -p ruby
|
||||
cp -r codeql-extractor.yml tools ql/lib/ruby.dbscheme.stats ruby/
|
||||
mkdir -p ruby/tools/{linux64,osx64,win64}
|
||||
cp linux64/autobuilder ruby/tools/linux64/autobuilder
|
||||
cp osx64/autobuilder ruby/tools/osx64/autobuilder
|
||||
cp win64/autobuilder.exe ruby/tools/win64/autobuilder.exe
|
||||
cp linux64/extractor ruby/tools/linux64/extractor
|
||||
cp osx64/extractor ruby/tools/osx64/extractor
|
||||
cp win64/extractor.exe ruby/tools/win64/extractor.exe
|
||||
chmod +x ruby/tools/{linux64,osx64}/{autobuilder,extractor}
|
||||
cp linux64/codeql-extractor-ruby ruby/tools/linux64/extractor
|
||||
cp osx64/codeql-extractor-ruby ruby/tools/osx64/extractor
|
||||
cp win64/codeql-extractor-ruby.exe ruby/tools/win64/extractor.exe
|
||||
chmod +x ruby/tools/{linux64,osx64}/extractor
|
||||
zip -rq codeql-ruby.zip ruby
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Please do not merge this PR!
|
||||
|
||||
# CodeQL
|
||||
|
||||
This open source repository contains the standard CodeQL libraries and queries that power [GitHub Advanced Security](https://github.com/features/security/code) and the other application security products that [GitHub](https://github.com/features/security/) makes available to its customers worldwide.
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<queries language="cpp"/>
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.
|
||||
3
cpp/ql/lib/change-notes/released/0.7.1.md
Normal file
3
cpp/ql/lib/change-notes/released/0.7.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.0
|
||||
lastReleaseVersion: 0.7.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.7.0
|
||||
version: 0.7.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -815,24 +815,20 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
* `c`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -932,36 +928,15 @@ private module Cached {
|
||||
TReturnCtxNoFlowThrough() or
|
||||
TReturnCtxMaybeFlowThrough(ReturnPosition pos)
|
||||
|
||||
cached
|
||||
newtype TTypedContentApprox =
|
||||
MkTypedContentApprox(ContentApprox c, DataFlowType t) {
|
||||
exists(Content cont |
|
||||
c = getContentApprox(cont) and
|
||||
store(_, cont, _, _, t)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
|
||||
|
||||
cached
|
||||
TypedContent getATypedContent(TypedContentApprox c) {
|
||||
exists(ContentApprox cls, DataFlowType t, Content cont |
|
||||
c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and
|
||||
result = MkTypedContent(cont, pragma[only_bind_into](t)) and
|
||||
cls = getContentApprox(cont)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(TypedContent tc)
|
||||
TFrontNil() or
|
||||
TFrontHead(Content c)
|
||||
|
||||
cached
|
||||
newtype TApproxAccessPathFront =
|
||||
TApproxFrontNil(DataFlowType t) or
|
||||
TApproxFrontHead(TypedContentApprox tc)
|
||||
TApproxFrontNil() or
|
||||
TApproxFrontHead(ContentApprox c)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
@@ -986,8 +961,16 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode extends Node {
|
||||
class CastingNode instanceof Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1135,9 +1118,17 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode extends Node {
|
||||
class ParamNode instanceof Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1146,9 +1137,17 @@ class ParamNode extends Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode extends Node {
|
||||
class ArgNode instanceof Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1159,9 +1158,17 @@ class ArgNode extends Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt extends Node {
|
||||
class ReturnNodeExt instanceof Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1170,8 +1177,16 @@ class ReturnNodeExt extends Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
class OutNodeExt instanceof Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1387,67 +1402,37 @@ class ReturnCtx extends TReturnCtx {
|
||||
}
|
||||
}
|
||||
|
||||
/** An approximated `Content` tagged with the type of a containing object. */
|
||||
class TypedContentApprox extends MkTypedContentApprox {
|
||||
private ContentApprox c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContentApprox() { this = MkTypedContentApprox(c, t) }
|
||||
|
||||
/** Gets a typed content approximated by this value. */
|
||||
TypedContent getATypedContent() { result = getATypedContent(this) }
|
||||
|
||||
/** Gets the content. */
|
||||
ContentApprox getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this approximated content. */
|
||||
string toString() { result = c.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an approximated access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
ContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
|
||||
pragma[nomagic]
|
||||
TypedContent getAHead() {
|
||||
exists(TypedContentApprox cont |
|
||||
Content getAHead() {
|
||||
exists(ContentApprox cont |
|
||||
this = TApproxFrontHead(cont) and
|
||||
result = cont.getATypedContent()
|
||||
cont = getContentApprox(result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
|
||||
private DataFlowType t;
|
||||
|
||||
ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
override string toString() { result = "nil" }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
|
||||
private TypedContentApprox tc;
|
||||
private ContentApprox c;
|
||||
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) }
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
|
||||
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
override string toString() { result = c.toString() }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
@@ -1461,65 +1446,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContent() { this = MkTypedContent(c, t) }
|
||||
|
||||
/** Gets the content. */
|
||||
Content getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { result = c.toString() }
|
||||
|
||||
/**
|
||||
* Holds if access paths with this `TypedContent` at their head always should
|
||||
* be tracked at high precision. This disables adaptive access path precision
|
||||
* for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision() { forceHighPrecision(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract ApproxAccessPathFront toApprox();
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
Content getHead() { this = TFrontHead(result) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
private DataFlowType t;
|
||||
override string toString() { result = "nil" }
|
||||
|
||||
AccessPathFrontNil() { this = TFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) }
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
private TypedContent tc;
|
||||
private Content c;
|
||||
|
||||
AccessPathFrontHead() { this = TFrontHead(tc) }
|
||||
AccessPathFrontHead() { this = TFrontHead(c) }
|
||||
|
||||
override string toString() { result = tc.toString() }
|
||||
override string toString() { result = c.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = tc }
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
|
||||
@@ -361,3 +361,52 @@ module MergePathGraph<
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `PathGraph` from three `PathGraph`s by disjoint union.
|
||||
*/
|
||||
module MergePathGraph3<
|
||||
PathNodeSig PathNode1, PathNodeSig PathNode2, PathNodeSig PathNode3,
|
||||
PathGraphSig<PathNode1> Graph1, PathGraphSig<PathNode2> Graph2, PathGraphSig<PathNode3> Graph3>
|
||||
{
|
||||
private module MergedInner = MergePathGraph<PathNode1, PathNode2, Graph1, Graph2>;
|
||||
|
||||
private module Merged =
|
||||
MergePathGraph<MergedInner::PathNode, PathNode3, MergedInner::PathGraph, Graph3>;
|
||||
|
||||
/** A node in a graph of path explanations that is formed by disjoint union of the three given graphs. */
|
||||
class PathNode instanceof Merged::PathNode {
|
||||
/** Gets this as a projection on the first given `PathGraph`. */
|
||||
PathNode1 asPathNode1() { result = super.asPathNode1().asPathNode1() }
|
||||
|
||||
/** Gets this as a projection on the second given `PathGraph`. */
|
||||
PathNode2 asPathNode2() { result = super.asPathNode1().asPathNode2() }
|
||||
|
||||
/** Gets this as a projection on the third given `PathGraph`. */
|
||||
PathNode3 asPathNode3() { result = super.asPathNode2() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
* column `endcolumn` of line `endline` in file `filepath`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the underlying `Node`. */
|
||||
Node getNode() { result = super.getNode() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph = Merged::PathGraph;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -815,24 +815,20 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
* `c`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -932,36 +928,15 @@ private module Cached {
|
||||
TReturnCtxNoFlowThrough() or
|
||||
TReturnCtxMaybeFlowThrough(ReturnPosition pos)
|
||||
|
||||
cached
|
||||
newtype TTypedContentApprox =
|
||||
MkTypedContentApprox(ContentApprox c, DataFlowType t) {
|
||||
exists(Content cont |
|
||||
c = getContentApprox(cont) and
|
||||
store(_, cont, _, _, t)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
|
||||
|
||||
cached
|
||||
TypedContent getATypedContent(TypedContentApprox c) {
|
||||
exists(ContentApprox cls, DataFlowType t, Content cont |
|
||||
c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and
|
||||
result = MkTypedContent(cont, pragma[only_bind_into](t)) and
|
||||
cls = getContentApprox(cont)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(TypedContent tc)
|
||||
TFrontNil() or
|
||||
TFrontHead(Content c)
|
||||
|
||||
cached
|
||||
newtype TApproxAccessPathFront =
|
||||
TApproxFrontNil(DataFlowType t) or
|
||||
TApproxFrontHead(TypedContentApprox tc)
|
||||
TApproxFrontNil() or
|
||||
TApproxFrontHead(ContentApprox c)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
@@ -986,8 +961,16 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode extends Node {
|
||||
class CastingNode instanceof Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1135,9 +1118,17 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode extends Node {
|
||||
class ParamNode instanceof Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1146,9 +1137,17 @@ class ParamNode extends Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode extends Node {
|
||||
class ArgNode instanceof Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1159,9 +1158,17 @@ class ArgNode extends Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt extends Node {
|
||||
class ReturnNodeExt instanceof Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1170,8 +1177,16 @@ class ReturnNodeExt extends Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt extends Node {
|
||||
class OutNodeExt instanceof Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1387,67 +1402,37 @@ class ReturnCtx extends TReturnCtx {
|
||||
}
|
||||
}
|
||||
|
||||
/** An approximated `Content` tagged with the type of a containing object. */
|
||||
class TypedContentApprox extends MkTypedContentApprox {
|
||||
private ContentApprox c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContentApprox() { this = MkTypedContentApprox(c, t) }
|
||||
|
||||
/** Gets a typed content approximated by this value. */
|
||||
TypedContent getATypedContent() { result = getATypedContent(this) }
|
||||
|
||||
/** Gets the content. */
|
||||
ContentApprox getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this approximated content. */
|
||||
string toString() { result = c.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an approximated access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
ContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
|
||||
pragma[nomagic]
|
||||
TypedContent getAHead() {
|
||||
exists(TypedContentApprox cont |
|
||||
Content getAHead() {
|
||||
exists(ContentApprox cont |
|
||||
this = TApproxFrontHead(cont) and
|
||||
result = cont.getATypedContent()
|
||||
cont = getContentApprox(result)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
|
||||
private DataFlowType t;
|
||||
|
||||
ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
override string toString() { result = "nil" }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
|
||||
private TypedContentApprox tc;
|
||||
private ContentApprox c;
|
||||
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) }
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
|
||||
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
override string toString() { result = c.toString() }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
@@ -1461,65 +1446,31 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContent() { this = MkTypedContent(c, t) }
|
||||
|
||||
/** Gets the content. */
|
||||
Content getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { result = c.toString() }
|
||||
|
||||
/**
|
||||
* Holds if access paths with this `TypedContent` at their head always should
|
||||
* be tracked at high precision. This disables adaptive access path precision
|
||||
* for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision() { forceHighPrecision(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract ApproxAccessPathFront toApprox();
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
Content getHead() { this = TFrontHead(result) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
private DataFlowType t;
|
||||
override string toString() { result = "nil" }
|
||||
|
||||
AccessPathFrontNil() { this = TFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) }
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
private TypedContent tc;
|
||||
private Content c;
|
||||
|
||||
AccessPathFrontHead() { this = TFrontHead(tc) }
|
||||
AccessPathFrontHead() { this = TFrontHead(c) }
|
||||
|
||||
override string toString() { result = tc.toString() }
|
||||
override string toString() { result = c.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = tc }
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
|
||||
@@ -607,13 +607,21 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
||||
result.getReturnKind() = kind
|
||||
}
|
||||
|
||||
/** A variable that behaves like a global variable. */
|
||||
class GlobalLikeVariable extends Variable {
|
||||
GlobalLikeVariable() {
|
||||
this instanceof Cpp::GlobalOrNamespaceVariable or
|
||||
this instanceof Cpp::StaticLocalVariable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that loses the
|
||||
* calling context. For example, this would happen with flow through a
|
||||
* global or static variable.
|
||||
*/
|
||||
predicate jumpStep(Node n1, Node n2) {
|
||||
exists(Cpp::GlobalOrNamespaceVariable v |
|
||||
exists(GlobalLikeVariable v |
|
||||
exists(Ssa::GlobalUse globalUse |
|
||||
v = globalUse.getVariable() and
|
||||
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
||||
@@ -897,23 +905,6 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the basic block of `node`.
|
||||
*/
|
||||
IRBlock getBasicBlock(Node node) {
|
||||
node.asInstruction().getBlock() = result
|
||||
or
|
||||
node.asOperand().getUse().getBlock() = result
|
||||
or
|
||||
node.(SsaPhiNode).getPhiNode().getBasicBlock() = result
|
||||
or
|
||||
node.(RawIndirectOperand).getOperand().getUse().getBlock() = result
|
||||
or
|
||||
node.(RawIndirectInstruction).getInstruction().getBlock() = result
|
||||
or
|
||||
result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode())
|
||||
}
|
||||
|
||||
/**
|
||||
* A local flow relation that includes both local steps, read steps and
|
||||
* argument-to-return flow through summarized functions.
|
||||
@@ -999,7 +990,8 @@ private int countNumberOfBranchesUsingParameter(SwitchInstruction switch, Parame
|
||||
// we pick the one with the highest edge count.
|
||||
result =
|
||||
max(SsaPhiNode phi |
|
||||
switch.getSuccessor(caseOrDefaultEdge()).getBlock().dominanceFrontier() = getBasicBlock(phi) and
|
||||
switch.getSuccessor(caseOrDefaultEdge()).getBlock().dominanceFrontier() =
|
||||
phi.getBasicBlock() and
|
||||
phi.getSourceVariable() = sv
|
||||
|
|
||||
strictcount(phi.getAnInput())
|
||||
|
||||
@@ -160,6 +160,28 @@ class Node extends TIRDataFlowNode {
|
||||
/** Gets the operands corresponding to this node, if any. */
|
||||
Operand asOperand() { result = this.(OperandNode).getOperand() }
|
||||
|
||||
/**
|
||||
* Holds if this node is at index `i` in basic block `block`.
|
||||
*
|
||||
* Note: Phi nodes are considered to be at index `-1`.
|
||||
*/
|
||||
final predicate hasIndexInBlock(IRBlock block, int i) {
|
||||
this.asInstruction() = block.getInstruction(i)
|
||||
or
|
||||
this.asOperand().getUse() = block.getInstruction(i)
|
||||
or
|
||||
this.(SsaPhiNode).getPhiNode().getBasicBlock() = block and i = -1
|
||||
or
|
||||
this.(RawIndirectOperand).getOperand().getUse() = block.getInstruction(i)
|
||||
or
|
||||
this.(RawIndirectInstruction).getInstruction() = block.getInstruction(i)
|
||||
or
|
||||
this.(PostUpdateNode).getPreUpdateNode().hasIndexInBlock(block, i)
|
||||
}
|
||||
|
||||
/** Gets the basic block of this node, if any. */
|
||||
final IRBlock getBasicBlock() { this.hasIndexInBlock(result, _) }
|
||||
|
||||
/**
|
||||
* Gets the non-conversion expression corresponding to this node, if any.
|
||||
* This predicate only has a result on nodes that represent the value of
|
||||
@@ -530,7 +552,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
*/
|
||||
final Node getAnInput(boolean fromBackEdge) {
|
||||
localFlowStep(result, this) and
|
||||
if phi.getBasicBlock().dominates(getBasicBlock(result))
|
||||
if phi.getBasicBlock().dominates(result.getBasicBlock())
|
||||
then fromBackEdge = true
|
||||
else fromBackEdge = false
|
||||
}
|
||||
@@ -1887,7 +1909,7 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
result.getConvertedExpr() = e and
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
g.controls(getBasicBlock(result), edge)
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,14 +145,14 @@ private newtype TDefOrUseImpl =
|
||||
or
|
||||
// Since the pruning stage doesn't know about global variables we can't use the above check to
|
||||
// rule out dead assignments to globals.
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof Cpp::GlobalOrNamespaceVariable
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
|
||||
)
|
||||
} or
|
||||
TUseImpl(Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, _, _, indirectionIndex) and
|
||||
not isDef(_, _, operand, _, _, _)
|
||||
} or
|
||||
TGlobalUse(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents a final "use" of a global variable to ensure that
|
||||
// the assignment to a global variable isn't ruled out as dead.
|
||||
exists(VariableAddressInstruction vai, int defIndex |
|
||||
@@ -162,7 +162,7 @@ private newtype TDefOrUseImpl =
|
||||
indirectionIndex = [0 .. defIndex] + 1
|
||||
)
|
||||
} or
|
||||
TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents the initial "definition" of a global variable when entering
|
||||
// a function body.
|
||||
exists(VariableAddressInstruction vai |
|
||||
@@ -458,7 +458,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
|
||||
}
|
||||
|
||||
class GlobalUse extends UseImpl, TGlobalUse {
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
GlobalLikeVariable global;
|
||||
IRFunction f;
|
||||
|
||||
GlobalUse() { this = TGlobalUse(global, f, ind) }
|
||||
@@ -468,7 +468,7 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
override int getIndirection() { result = ind + 1 }
|
||||
|
||||
/** Gets the global variable associated with this use. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is exited from after this use. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -496,14 +496,14 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
}
|
||||
|
||||
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
GlobalLikeVariable global;
|
||||
IRFunction f;
|
||||
int indirectionIndex;
|
||||
|
||||
GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is evaluated after this definition. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -760,13 +760,14 @@ private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
|
||||
}
|
||||
|
||||
private predicate sourceVariableIsGlobal(
|
||||
SourceVariable sv, Cpp::GlobalOrNamespaceVariable global, IRFunction func, int indirectionIndex
|
||||
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
|
||||
) {
|
||||
exists(IRVariable irVar, BaseIRVariable base |
|
||||
sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and
|
||||
irVar = base.getIRVariable() and
|
||||
irVar.getEnclosingIRFunction() = func and
|
||||
global = irVar.getAst()
|
||||
global = irVar.getAst() and
|
||||
not irVar instanceof IRDynamicInitializationFlag
|
||||
)
|
||||
}
|
||||
|
||||
@@ -919,7 +920,7 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
|
||||
IRFunction getIRFunction() { result = global.getIRFunction() }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() }
|
||||
GlobalLikeVariable getVariable() { result = global.getVariable() }
|
||||
}
|
||||
|
||||
class Phi extends TPhi, SsaDefOrUse {
|
||||
|
||||
@@ -26,12 +26,17 @@ predicate ignoreOperand(Operand operand) {
|
||||
predicate ignoreInstruction(Instruction instr) {
|
||||
DataFlowImplCommon::forceCachingInSameStage() and
|
||||
(
|
||||
instr instanceof CallSideEffectInstruction or
|
||||
instr instanceof CallReadSideEffectInstruction or
|
||||
instr instanceof ExitFunctionInstruction or
|
||||
instr instanceof EnterFunctionInstruction or
|
||||
instr instanceof WriteSideEffectInstruction or
|
||||
instr instanceof PhiInstruction or
|
||||
instr instanceof ReadSideEffectInstruction or
|
||||
instr instanceof ChiInstruction or
|
||||
instr instanceof InitializeIndirectionInstruction or
|
||||
instr instanceof AliasedDefinitionInstruction or
|
||||
instr instanceof AliasedUseInstruction or
|
||||
instr instanceof InitializeNonLocalInstruction or
|
||||
instr instanceof ReturnIndirectionInstruction
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ private import IRFunctionBaseInternal
|
||||
|
||||
private newtype TIRFunction =
|
||||
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
|
||||
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) }
|
||||
TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) }
|
||||
|
||||
/**
|
||||
* The IR for a function. This base class contains only the predicates that are the same between all
|
||||
|
||||
@@ -37,7 +37,13 @@ module Raw {
|
||||
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
|
||||
|
||||
cached
|
||||
predicate varHasIRFunc(GlobalOrNamespaceVariable var) {
|
||||
predicate varHasIRFunc(Variable var) {
|
||||
(
|
||||
var instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
not var.isFromUninstantiatedTemplate(_) and
|
||||
var instanceof StaticInitializedStaticLocalVariable
|
||||
) and
|
||||
var.hasInitializer() and
|
||||
(
|
||||
not var.getType().isDeeplyConst()
|
||||
@@ -75,9 +81,10 @@ module Raw {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasDynamicInitializationFlag(Function func, StaticLocalVariable var, CppType type) {
|
||||
predicate hasDynamicInitializationFlag(
|
||||
Function func, RuntimeInitializedStaticLocalVariable var, CppType type
|
||||
) {
|
||||
var.getFunction() = func and
|
||||
var.hasDynamicInitialization() and
|
||||
type = getBoolType()
|
||||
}
|
||||
|
||||
|
||||
@@ -180,7 +180,7 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Declaration getFunction() { result = getExpr().getEnclosingDeclaration() }
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(getExpr()) }
|
||||
|
||||
final override TranslatedElement getChild(int i) {
|
||||
result =
|
||||
|
||||
@@ -28,7 +28,11 @@ abstract class TranslatedCondition extends TranslatedElement {
|
||||
|
||||
final Expr getExpr() { result = expr }
|
||||
|
||||
final override Function getFunction() { result = expr.getEnclosingFunction() }
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final Type getResultType() { result = expr.getUnspecifiedType() }
|
||||
}
|
||||
|
||||
@@ -28,9 +28,14 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
|
||||
TranslatedDeclarationEntry() { this = TTranslatedDeclarationEntry(entry) }
|
||||
|
||||
final override Function getFunction() {
|
||||
exists(DeclStmt stmt |
|
||||
stmt = entry.getStmt() and
|
||||
final override Declaration getFunction() {
|
||||
exists(DeclStmt stmt | stmt = entry.getStmt() |
|
||||
result = entry.getDeclaration().(StaticInitializedStaticLocalVariable)
|
||||
or
|
||||
result = entry.getDeclaration().(GlobalOrNamespaceVariable)
|
||||
or
|
||||
not entry.getDeclaration() instanceof StaticInitializedStaticLocalVariable and
|
||||
not entry.getDeclaration() instanceof GlobalOrNamespaceVariable and
|
||||
result = stmt.getEnclosingFunction()
|
||||
)
|
||||
}
|
||||
@@ -237,7 +242,7 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
|
||||
|
||||
final override LocalVariable getVariable() { result = var }
|
||||
|
||||
final override Function getFunction() { result = var.getFunction() }
|
||||
final override Declaration getFunction() { result = var.getFunction() }
|
||||
}
|
||||
|
||||
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
|
||||
@@ -264,7 +269,7 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() }
|
||||
override Declaration getFunction() { result = getEnclosingFunction(conditionDeclExpr) }
|
||||
|
||||
override LocalVariable getVariable() { result = conditionDeclExpr.getVariable() }
|
||||
}
|
||||
|
||||
@@ -62,15 +62,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
// constant value.
|
||||
isIRConstant(getRealParent(expr))
|
||||
or
|
||||
// Only translate the initializer of a static local if it uses run-time data.
|
||||
// Otherwise the initializer does not run in function scope.
|
||||
exists(Initializer init, StaticStorageDurationVariable var |
|
||||
init = var.getInitializer() and
|
||||
not var.hasDynamicInitialization() and
|
||||
expr = init.getExpr().getFullyConverted() and
|
||||
not var instanceof GlobalOrNamespaceVariable
|
||||
)
|
||||
or
|
||||
// Ignore descendants of `__assume` expressions, since we translated these to `NoOp`.
|
||||
getRealParent(expr) instanceof AssumeExpr
|
||||
or
|
||||
@@ -118,8 +109,8 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
// should not be translated.
|
||||
exists(NewOrNewArrayExpr new | expr = new.getAllocatorCall().getArgument(0))
|
||||
or
|
||||
not translateFunction(expr.getEnclosingFunction()) and
|
||||
not Raw::varHasIRFunc(expr.getEnclosingVariable())
|
||||
not translateFunction(getEnclosingFunction(expr)) and
|
||||
not Raw::varHasIRFunc(getEnclosingVariable(expr))
|
||||
or
|
||||
// We do not yet translate destructors properly, so for now we ignore the
|
||||
// destructor call. We do, however, translate the expression being
|
||||
@@ -438,6 +429,17 @@ predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
|
||||
not expr.hasLValueToRValueConversion()
|
||||
}
|
||||
|
||||
class StaticInitializedStaticLocalVariable extends StaticLocalVariable {
|
||||
StaticInitializedStaticLocalVariable() {
|
||||
this.hasInitializer() and
|
||||
not this.hasDynamicInitialization()
|
||||
}
|
||||
}
|
||||
|
||||
class RuntimeInitializedStaticLocalVariable extends StaticLocalVariable {
|
||||
RuntimeInitializedStaticLocalVariable() { this.hasDynamicInitialization() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only
|
||||
* necessary for automatic local variables, or for static local variables with dynamic
|
||||
@@ -453,7 +455,7 @@ private predicate translateDeclarationEntry(IRDeclarationEntry entry) {
|
||||
not var.isStatic()
|
||||
or
|
||||
// Ignore static variables unless they have a dynamic initializer.
|
||||
var.(StaticLocalVariable).hasDynamicInitialization()
|
||||
var instanceof RuntimeInitializedStaticLocalVariable
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -755,7 +757,7 @@ newtype TTranslatedElement =
|
||||
} or
|
||||
// The side effect that initializes newly-allocated memory.
|
||||
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
|
||||
TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) }
|
||||
TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) }
|
||||
|
||||
/**
|
||||
* Gets the index of the first explicitly initialized element in `initList`
|
||||
@@ -819,7 +821,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
abstract Locatable getAst();
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
deprecated Locatable getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Get the first instruction to be executed in the evaluation of this element.
|
||||
@@ -829,7 +831,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Get the immediate child elements of this element.
|
||||
*/
|
||||
final TranslatedElement getAChild() { result = getChild(_) }
|
||||
final TranslatedElement getAChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the immediate child element of this element. The `id` is unique
|
||||
@@ -842,25 +844,29 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* Gets the an identifier string for the element. This id is unique within
|
||||
* the scope of the element's function.
|
||||
*/
|
||||
final int getId() { result = getUniqueId() }
|
||||
final int getId() { result = this.getUniqueId() }
|
||||
|
||||
private TranslatedElement getChildByRank(int rankIndex) {
|
||||
result =
|
||||
rank[rankIndex + 1](TranslatedElement child, int id | child = getChild(id) | child order by id)
|
||||
rank[rankIndex + 1](TranslatedElement child, int id |
|
||||
child = this.getChild(id)
|
||||
|
|
||||
child order by id
|
||||
)
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
private int getDescendantCount() {
|
||||
result =
|
||||
1 + sum(TranslatedElement child | child = getChildByRank(_) | child.getDescendantCount())
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(getParent())
|
||||
if not exists(this.getParent())
|
||||
then result = 0
|
||||
else
|
||||
exists(TranslatedElement parent |
|
||||
parent = getParent() and
|
||||
parent = this.getParent() and
|
||||
if this = parent.getChildByRank(0)
|
||||
then result = 1 + parent.getUniqueId()
|
||||
else
|
||||
@@ -906,7 +912,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* there is no enclosing `try`.
|
||||
*/
|
||||
Instruction getExceptionSuccessorInstruction() {
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1020,14 +1026,14 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
exists(Locatable ast |
|
||||
result.getAst() = ast and
|
||||
result.getTag() = tag and
|
||||
hasTempVariableAndAst(tag, ast)
|
||||
this.hasTempVariableAndAst(tag, ast)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) {
|
||||
hasTempVariable(tag, _) and
|
||||
ast = getAst()
|
||||
this.hasTempVariable(tag, _) and
|
||||
ast = this.getAst()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1043,6 +1049,6 @@ abstract class TranslatedRootElement extends TranslatedElement {
|
||||
TranslatedRootElement() {
|
||||
this instanceof TTranslatedFunction
|
||||
or
|
||||
this instanceof TTranslatedGlobalOrNamespaceVarInit
|
||||
this instanceof TTranslatedStaticStorageDurationVarInit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() { result = expr.getEnclosingDeclaration() }
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(expr) }
|
||||
|
||||
/**
|
||||
* Gets the expression from which this `TranslatedExpr` is generated.
|
||||
@@ -90,12 +90,57 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
* Gets the `TranslatedFunction` containing this expression.
|
||||
*/
|
||||
final TranslatedRootElement getEnclosingFunction() {
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction())
|
||||
result = getTranslatedFunction(getEnclosingFunction(expr))
|
||||
or
|
||||
result = getTranslatedVarInit(expr.getEnclosingVariable())
|
||||
result = getTranslatedVarInit(getEnclosingVariable(expr))
|
||||
}
|
||||
}
|
||||
|
||||
Function getEnclosingFunction(Expr e) {
|
||||
not exists(getEnclosingVariable(e)) and
|
||||
result = e.getEnclosingFunction()
|
||||
}
|
||||
|
||||
Declaration getEnclosingDeclaration0(Expr e) {
|
||||
result = getEnclosingDeclaration0(e.getParentWithConversions())
|
||||
or
|
||||
exists(Initializer i, Variable v |
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
then result = v
|
||||
else result = e.getEnclosingDeclaration()
|
||||
)
|
||||
}
|
||||
|
||||
Declaration getEnclosingDeclaration(Expr e) {
|
||||
result = getEnclosingDeclaration0(e)
|
||||
or
|
||||
not exists(getEnclosingDeclaration0(e)) and
|
||||
result = e.getEnclosingDeclaration()
|
||||
}
|
||||
|
||||
Variable getEnclosingVariable0(Expr e) {
|
||||
result = getEnclosingVariable0(e.getParentWithConversions())
|
||||
or
|
||||
exists(Initializer i, Variable v |
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
then result = v
|
||||
else result = e.getEnclosingVariable()
|
||||
)
|
||||
}
|
||||
|
||||
Variable getEnclosingVariable(Expr e) {
|
||||
result = getEnclosingVariable0(e)
|
||||
or
|
||||
not exists(getEnclosingVariable0(e)) and
|
||||
result = e.getEnclosingVariable()
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of the "core" part of an expression. This is the part of
|
||||
* the expression that produces the result value of the expression, before any
|
||||
@@ -843,10 +888,21 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getIRUserVariable(expr.getEnclosingDeclaration(), expr.getTarget())
|
||||
exists(Declaration d, Variable v |
|
||||
accessHasEnclosingDeclarationAndVariable(d, v, expr) and
|
||||
result = getIRUserVariable(d, v)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate accessHasEnclosingDeclarationAndVariable(
|
||||
Declaration d, Variable v, VariableAccess va
|
||||
) {
|
||||
d = getEnclosingDeclaration(va) and
|
||||
v = va.getTarget()
|
||||
}
|
||||
|
||||
class TranslatedFieldAccess extends TranslatedVariableAccess {
|
||||
override FieldAccess expr;
|
||||
|
||||
@@ -2000,7 +2056,7 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(getEnclosingFunction(expr)).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override Field getInstructionField(InstructionTag tag) {
|
||||
|
||||
@@ -322,11 +322,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
(
|
||||
var instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
var instanceof StaticLocalVariable
|
||||
or
|
||||
var instanceof MemberVariable and not var instanceof Field
|
||||
) and
|
||||
exists(VariableAccess access |
|
||||
access.getTarget() = var and
|
||||
access.getEnclosingFunction() = func
|
||||
getEnclosingFunction(access) = func
|
||||
)
|
||||
or
|
||||
var.(LocalScopeVariable).getFunction() = func
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
@@ -8,16 +9,16 @@ private import TranslatedInitialization
|
||||
private import InstructionTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
|
||||
class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
|
||||
TTranslatedGlobalOrNamespaceVarInit, InitializationContext
|
||||
class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
TTranslatedStaticStorageDurationVarInit, InitializationContext
|
||||
{
|
||||
GlobalOrNamespaceVariable var;
|
||||
Variable var;
|
||||
|
||||
TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) }
|
||||
TranslatedStaticStorageDurationVarInit() { this = TTranslatedStaticStorageDurationVarInit(var) }
|
||||
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
final override GlobalOrNamespaceVariable getAst() { result = var }
|
||||
final override Variable getAst() { result = var }
|
||||
|
||||
final override Declaration getFunction() { result = var }
|
||||
|
||||
@@ -111,11 +112,13 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
|
||||
(
|
||||
varUsed instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
varUsed instanceof StaticLocalVariable
|
||||
or
|
||||
varUsed instanceof MemberVariable and not varUsed instanceof Field
|
||||
) and
|
||||
exists(VariableAccess access |
|
||||
access.getTarget() = varUsed and
|
||||
access.getEnclosingVariable() = var
|
||||
getEnclosingVariable(access) = var
|
||||
)
|
||||
or
|
||||
var = varUsed
|
||||
@@ -128,6 +131,4 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
|
||||
}
|
||||
}
|
||||
|
||||
TranslatedGlobalOrNamespaceVarInit getTranslatedVarInit(GlobalOrNamespaceVariable var) {
|
||||
result.getAst() = var
|
||||
}
|
||||
TranslatedStaticStorageDurationVarInit getTranslatedVarInit(Variable var) { result.getAst() = var }
|
||||
|
||||
@@ -35,64 +35,64 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(getTargetType())
|
||||
resultType = getTypeForGLValue(this.getTargetType())
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getTypeForPRValue(getTargetType())
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
if hasUninitializedInstruction()
|
||||
then result = getInstruction(InitializerStoreTag())
|
||||
else result = getInitialization().getFirstInstruction()
|
||||
if this.hasUninitializedInstruction()
|
||||
then result = this.getInstruction(InitializerStoreTag())
|
||||
else result = this.getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
result = getInitialization().getFirstInstruction()
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
or
|
||||
not exists(getInitialization()) and result = getInitializationSuccessor()
|
||||
not exists(this.getInitialization()) and result = this.getInitializationSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getInitializationSuccessor()
|
||||
child = this.getInitialization() and result = this.getInitializationSuccessor()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
hasUninitializedInstruction() and
|
||||
this.hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag()
|
||||
or
|
||||
hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
this.hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
) and
|
||||
result = getIRVariable()
|
||||
result = this.getIRVariable()
|
||||
}
|
||||
|
||||
final override Instruction getTargetAddress() {
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,13 +116,13 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
*/
|
||||
final predicate hasUninitializedInstruction() {
|
||||
(
|
||||
not exists(getInitialization()) or
|
||||
getInitialization() instanceof TranslatedListInitialization or
|
||||
getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
not exists(this.getInitialization()) or
|
||||
this.getInitialization() instanceof TranslatedListInitialization or
|
||||
this.getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
this.getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
) and
|
||||
// Variables with static or thread-local storage duration are zero-initialized at program startup.
|
||||
getIRVariable() instanceof IRAutomaticVariable
|
||||
this.getIRVariable() instanceof IRAutomaticVariable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,14 +138,15 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
final override string toString() { result = "init: " + expr.toString() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = expr.getEnclosingFunction() or
|
||||
result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is doing the initialization.
|
||||
@@ -156,10 +157,10 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
* Gets the initialization context that describes the location being
|
||||
* initialized.
|
||||
*/
|
||||
final InitializationContext getContext() { result = getParent() }
|
||||
final InitializationContext getContext() { result = this.getParent() }
|
||||
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction())
|
||||
result = getTranslatedFunction(this.getFunction())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,17 +169,17 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
*/
|
||||
abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext {
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getChild(0).getFirstInstruction()
|
||||
result = this.getChild(0).getFirstInstruction()
|
||||
or
|
||||
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
|
||||
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -188,9 +189,9 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getTargetAddress() { result = getContext().getTargetAddress() }
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
|
||||
override Type getTargetType() { result = getContext().getTargetType() }
|
||||
override Type getTargetType() { result = this.getContext().getTargetType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,9 +237,11 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization {
|
||||
abstract class TranslatedDirectInitialization extends TranslatedInitialization {
|
||||
TranslatedDirectInitialization() { not expr instanceof AggregateLiteral }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitializer() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInitializer().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getInitializer().getFirstInstruction()
|
||||
}
|
||||
|
||||
final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
|
||||
}
|
||||
@@ -257,27 +260,27 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(getContext().getTargetType())
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getInstruction(InitializerStoreTag())
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInitializer().getResult()
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -304,13 +307,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// If the initializer string isn't large enough to fill the target, then
|
||||
// we have to generate another instruction sequence to store a constant
|
||||
// zero into the remainder of the array.
|
||||
zeroInitRange(_, elementCount) and
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
(
|
||||
// Create a constant zero whose size is the size of the remaining
|
||||
// space in the target array.
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
or
|
||||
// The index of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
@@ -320,12 +323,12 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// Compute the address of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
or
|
||||
// Store the constant zero into the remainder of the string.
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -334,78 +337,78 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
or
|
||||
if zeroInitRange(_, _)
|
||||
if this.zeroInitRange(_, _)
|
||||
then (
|
||||
tag = InitializerStoreTag() and
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
or
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
or
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = getInstruction(ZeroPadStringStoreTag())
|
||||
result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
) else (
|
||||
tag = InitializerStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getInstruction(InitializerLoadStringTag())
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerLoadStringTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerLoadStringTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInitializer().getResult()
|
||||
result = this.getInitializer().getResult()
|
||||
)
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(InitializerLoadStringTag())
|
||||
result = this.getInstruction(InitializerLoadStringTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = getContext().getTargetAddress()
|
||||
result = this.getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = max(getElementType().getSize())
|
||||
result = max(this.getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
exists(int startIndex |
|
||||
zeroInitRange(startIndex, _) and
|
||||
this.zeroInitRange(startIndex, _) and
|
||||
(
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = "0"
|
||||
@@ -418,13 +421,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
exists(int elementCount |
|
||||
zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * getElementType().getSize()
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * this.getElementType().getSize()
|
||||
)
|
||||
}
|
||||
|
||||
private Type getElementType() {
|
||||
result = getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
result = this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,7 +437,8 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
predicate zeroInitRange(int startIndex, int elementCount) {
|
||||
exists(int targetCount |
|
||||
startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount =
|
||||
this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
elementCount = targetCount - startIndex and
|
||||
elementCount > 0
|
||||
)
|
||||
@@ -453,14 +457,14 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitializer() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getReceiver() { result = getContext().getTargetAddress() }
|
||||
override Instruction getReceiver() { result = this.getContext().getTargetAddress() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,14 +494,17 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final override Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = ast.getEnclosingFunction() or
|
||||
result = ast.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
result = getEnclosingFunction(ast) or
|
||||
result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the zero-based index describing the order in which this field is to be
|
||||
@@ -506,19 +513,19 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final int getOrder() { result = field.getInitializationOrder() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getFieldAddressTag() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = getTypeForGLValue(field.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = getFieldAddressTag() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
}
|
||||
|
||||
override Field getInstructionField(InstructionTag tag) {
|
||||
tag = getFieldAddressTag() and result = field
|
||||
tag = this.getFieldAddressTag() and result = field
|
||||
}
|
||||
|
||||
final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() }
|
||||
@@ -543,21 +550,23 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = getInstruction(getFieldAddressTag()) }
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
@@ -582,11 +591,11 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getFieldDefaultValueTag() and
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(field.getType())
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
@@ -594,32 +603,32 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
or
|
||||
tag = getFieldDefaultValueTag() and
|
||||
result = getInstruction(getFieldDefaultValueStoreTag())
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = getFieldDefaultValueTag() and
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
result = getZeroValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(getFieldAddressTag())
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -642,57 +651,61 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
ArrayOrVectorAggregateLiteral initList;
|
||||
|
||||
final override string toString() {
|
||||
result = initList.toString() + "[" + getElementIndex().toString() + "]"
|
||||
result = initList.toString() + "[" + this.getElementIndex().toString() + "]"
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = initList }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = initList.getEnclosingFunction()
|
||||
result = getEnclosingFunction(initList)
|
||||
or
|
||||
result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
result = getEnclosingVariable(initList).(GlobalOrNamespaceVariable)
|
||||
or
|
||||
result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = getElementIndexTag() and
|
||||
tag = this.getElementIndexTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getIntType()
|
||||
or
|
||||
tag = getElementAddressTag() and
|
||||
tag = this.getElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = getElementIndexTag() and
|
||||
result = getInstruction(getElementAddressTag()) and
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = getElementAddressTag() and
|
||||
tag = this.getElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = getInstruction(getElementIndexTag())
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = getElementAddressTag() and
|
||||
result = max(getElementType().getSize())
|
||||
tag = this.getElementAddressTag() and
|
||||
result = max(this.getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = getElementIndexTag() and
|
||||
result = getElementIndex().toString()
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getElementIndex().toString()
|
||||
}
|
||||
|
||||
abstract int getElementIndex();
|
||||
@@ -722,23 +735,25 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() { result = getInstruction(getElementAddressTag()) }
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
|
||||
override Type getTargetType() { result = getElementType() }
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = getElementAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
@@ -769,13 +784,13 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getDefaultValueType()
|
||||
resultType = this.getDefaultValueType()
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getDefaultValueType()
|
||||
resultType = this.getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -783,34 +798,34 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = getElementAddressTag() and
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getInstruction(getElementDefaultValueStoreTag())
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionConstantValue(tag)
|
||||
or
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getZeroValue(getElementType())
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = getZeroValue(this.getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = getInstruction(getElementAddressTag())
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -821,7 +836,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
elementCount != 0 and byteSize = elementCount * getElementType().getSize()
|
||||
elementCount != 0 and byteSize = elementCount * this.getElementType().getSize()
|
||||
}
|
||||
|
||||
private InstructionTag getElementDefaultValueTag() {
|
||||
@@ -834,8 +849,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
|
||||
private CppType getDefaultValueType() {
|
||||
if elementCount = 1
|
||||
then result = getTypeForPRValue(getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
then result = getTypeForPRValue(this.getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -845,18 +860,18 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = getStructorCall()
|
||||
result = this.getStructorCall()
|
||||
}
|
||||
|
||||
final override Function getFunction() { result = call.getEnclosingFunction() }
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getStructorCall() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
@@ -867,7 +882,9 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
* destructor from within a derived class constructor or destructor.
|
||||
*/
|
||||
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -878,15 +895,15 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override predicate getInstructionInheritance(
|
||||
@@ -894,7 +911,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
) {
|
||||
tag = OnlyInstructionTag() and
|
||||
baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and
|
||||
derivedClass = getFunction().getDeclaringType().getUnspecifiedType()
|
||||
derivedClass = this.getFunction().getDeclaringType().getUnspecifiedType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -920,7 +937,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override string toString() { result = "delegation construct: " + call.toString() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -930,7 +947,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -977,11 +994,11 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
override Locatable getAst() { result = init }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override string toString() { result = "construct base (no constructor)" }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
|
||||
override Instruction getFirstInstruction() { result = this.getParent().getChildSuccessor(this) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -989,7 +1006,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Function getFunction() { result = getParent().getFunction() }
|
||||
override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
final override Locatable getAst() { result = stmt }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() { result = stmt.getEnclosingFunction() }
|
||||
}
|
||||
@@ -254,7 +254,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -264,7 +264,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -279,19 +279,19 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getDeclarationEntry(0).getFirstInstruction()
|
||||
result = this.getDeclarationEntry(0).getFirstInstruction()
|
||||
or
|
||||
not exists(getDeclarationEntry(0)) and result = getParent().getChildSuccessor(this)
|
||||
not exists(this.getDeclarationEntry(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private int getChildCount() { result = count(getDeclarationEntry(_)) }
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
result.hasIndex(index) and
|
||||
@@ -319,10 +319,10 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getDeclarationEntry(index) and
|
||||
if index = (getChildCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -332,19 +332,19 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getExpr() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,16 +363,18 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor() {
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = getEnclosingFunction().getReturnType() }
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() }
|
||||
final override IRVariable getIRVariable() {
|
||||
result = this.getEnclosingFunction().getReturnVariable()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,10 +387,10 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = getExpr()
|
||||
result = this.getExpr()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -398,13 +400,13 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getExpr() and
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -421,7 +423,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -431,7 +433,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -452,7 +454,7 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -511,9 +513,9 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getBody()
|
||||
id = 0 and result = this.getBody()
|
||||
or
|
||||
result = getHandler(id - 1)
|
||||
result = this.getHandler(id - 1)
|
||||
or
|
||||
id = stmt.getNumberOfCatchClauses() + 1 and
|
||||
result = this.getFinally()
|
||||
@@ -525,7 +527,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
@@ -546,19 +548,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
final Instruction getNextHandler(TranslatedHandler handler) {
|
||||
exists(int index |
|
||||
handler = getHandler(index) and
|
||||
result = getHandler(index + 1).getFirstInstruction()
|
||||
handler = this.getHandler(index) and
|
||||
result = this.getHandler(index + 1).getFirstInstruction()
|
||||
)
|
||||
or
|
||||
// The last catch clause flows to the exception successor of the parent
|
||||
// of the `try`, because the exception successor of the `try` itself is
|
||||
// the first catch clause.
|
||||
handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
handler = this.getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getExceptionSuccessorInstruction() {
|
||||
result = getHandler(0).getFirstInstruction()
|
||||
result = this.getHandler(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
|
||||
@@ -571,19 +573,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = getStmt(id) }
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
isEmpty() and
|
||||
this.isEmpty() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if isEmpty()
|
||||
then result = getInstruction(OnlyInstructionTag())
|
||||
else result = getStmt(0).getFirstInstruction()
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
@@ -594,16 +596,16 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getStmt(index) and
|
||||
if index = (getStmtCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getStmt(index + 1).getFirstInstruction()
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getStmt(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -614,18 +616,18 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = getBlock() }
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(CatchTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(CatchTag()) }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBlock() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getExceptionSuccessorInstruction() {
|
||||
// A throw from within a `catch` block flows to the handler for the parent of
|
||||
// the `try`.
|
||||
result = getParent().getParent().getExceptionSuccessorInstruction()
|
||||
result = this.getParent().getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
|
||||
@@ -647,23 +649,23 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
or
|
||||
id = 0 and result = getParameter()
|
||||
id = 0 and result = this.getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
result = super.getChildSuccessor(child)
|
||||
or
|
||||
child = getParameter() and result = getBlock().getFirstInstruction()
|
||||
child = this.getParameter() and result = this.getBlock().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
result = getParameter().getFirstInstruction()
|
||||
result = this.getParameter().getFirstInstruction()
|
||||
or
|
||||
kind instanceof ExceptionEdge and
|
||||
result = getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
result = this.getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -692,7 +694,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = getBlock().getFirstInstruction()
|
||||
result = this.getBlock().getFirstInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -700,19 +702,19 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override IfStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getCondition()
|
||||
id = 1 and result = this.getCondition()
|
||||
or
|
||||
id = 2 and result = getThen()
|
||||
id = 2 and result = this.getThen()
|
||||
or
|
||||
id = 3 and result = getElse()
|
||||
id = 3 and result = this.getElse()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -726,7 +728,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
}
|
||||
|
||||
private Instruction getFirstConditionInstruction() {
|
||||
result = getCondition().getFirstInstruction()
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
|
||||
@@ -738,23 +740,23 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and
|
||||
result = getThen().getFirstInstruction()
|
||||
child = this.getCondition() and
|
||||
result = this.getThen().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and
|
||||
if hasElse()
|
||||
then result = getElse().getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and
|
||||
if this.hasElse()
|
||||
then result = this.getElse().getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
or
|
||||
(child = getThen() or child = getElse()) and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
(child = this.getThen() or child = this.getElse()) and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -772,17 +774,17 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
final Instruction getFirstConditionInstruction() {
|
||||
if hasCondition()
|
||||
then result = getCondition().getFirstInstruction()
|
||||
else result = getBody().getFirstInstruction()
|
||||
if this.hasCondition()
|
||||
then result = this.getCondition().getFirstInstruction()
|
||||
else result = this.getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getCondition()
|
||||
id = 0 and result = this.getCondition()
|
||||
or
|
||||
id = 1 and result = getBody()
|
||||
id = 1 and result = this.getBody()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -792,31 +794,31 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getBody().getFirstInstruction()
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getFirstConditionInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getFirstConditionInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedDoStmt extends TranslatedLoop {
|
||||
TranslatedDoStmt() { stmt instanceof DoStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -824,13 +826,13 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getCondition()
|
||||
id = 1 and result = this.getCondition()
|
||||
or
|
||||
id = 2 and result = getUpdate()
|
||||
id = 2 and result = this.getUpdate()
|
||||
or
|
||||
id = 3 and result = getBody()
|
||||
id = 3 and result = this.getBody()
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -844,23 +846,23 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
private predicate hasUpdate() { exists(stmt.getUpdate()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
or
|
||||
(
|
||||
child = getBody() and
|
||||
if hasUpdate()
|
||||
then result = getUpdate().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
child = this.getBody() and
|
||||
if this.hasUpdate()
|
||||
then result = this.getUpdate().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
)
|
||||
or
|
||||
child = getUpdate() and result = getFirstConditionInstruction()
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -875,39 +877,39 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getRangeVariableDeclStmt()
|
||||
id = 0 and result = this.getRangeVariableDeclStmt()
|
||||
or
|
||||
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
|
||||
id = 1 and result = getBeginEndVariableDeclStmt()
|
||||
id = 1 and result = this.getBeginEndVariableDeclStmt()
|
||||
or
|
||||
id = 2 and result = getCondition()
|
||||
id = 2 and result = this.getCondition()
|
||||
or
|
||||
id = 3 and result = getUpdate()
|
||||
id = 3 and result = this.getUpdate()
|
||||
or
|
||||
id = 4 and result = getVariableDeclStmt()
|
||||
id = 4 and result = this.getVariableDeclStmt()
|
||||
or
|
||||
id = 5 and result = getBody()
|
||||
id = 5 and result = this.getBody()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = getRangeVariableDeclStmt().getFirstInstruction()
|
||||
result = this.getRangeVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getRangeVariableDeclStmt() and
|
||||
result = getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
child = this.getRangeVariableDeclStmt() and
|
||||
result = this.getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
or
|
||||
child = getBeginEndVariableDeclStmt() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
child = this.getBeginEndVariableDeclStmt() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
or
|
||||
child = getVariableDeclStmt() and
|
||||
result = getBody().getFirstInstruction()
|
||||
child = this.getVariableDeclStmt() and
|
||||
result = this.getBody().getFirstInstruction()
|
||||
or
|
||||
child = getBody() and
|
||||
result = getUpdate().getFirstInstruction()
|
||||
child = this.getBody() and
|
||||
result = this.getUpdate().getFirstInstruction()
|
||||
or
|
||||
child = getUpdate() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
child = this.getUpdate() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -917,11 +919,11 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getVariableDeclStmt().getFirstInstruction()
|
||||
child = this.getCondition() and result = this.getVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private TranslatedDeclStmt getRangeVariableDeclStmt() {
|
||||
@@ -961,7 +963,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedJumpStmt extends TranslatedStmt {
|
||||
override JumpStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -996,22 +998,22 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = getTranslatedExpr(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
private Instruction getFirstExprInstruction() { result = getExpr().getFirstInstruction() }
|
||||
private Instruction getFirstExprInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
|
||||
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstExprInstruction()
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstExprInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = getInitialization()
|
||||
id = 0 and result = this.getInitialization()
|
||||
or
|
||||
id = 1 and result = getExpr()
|
||||
id = 1 and result = this.getExpr()
|
||||
or
|
||||
id = 2 and result = getBody()
|
||||
id = 2 and result = this.getBody()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -1029,7 +1031,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = SwitchBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = getExpr().getResult()
|
||||
result = this.getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1043,15 +1045,15 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
not stmt.hasDefaultCase() and
|
||||
tag = SwitchBranchTag() and
|
||||
kind instanceof DefaultEdge and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = getInitialization() and result = getFirstExprInstruction()
|
||||
child = this.getInitialization() and result = this.getFirstExprInstruction()
|
||||
or
|
||||
child = getExpr() and result = getInstruction(SwitchBranchTag())
|
||||
child = this.getExpr() and result = this.getInstruction(SwitchBranchTag())
|
||||
or
|
||||
child = getBody() and result = getParent().getChildSuccessor(this)
|
||||
child = this.getBody() and result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,9 +1065,9 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -1078,7 +1080,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = getChild(index).getResult()
|
||||
result = this.getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1092,16 +1094,16 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class Variable = Cpp::Variable;
|
||||
|
||||
class AutomaticVariable = Cpp::StackVariable;
|
||||
|
||||
class StaticVariable = Cpp::Variable;
|
||||
class StaticVariable = Cpp::StaticStorageDurationVariable;
|
||||
|
||||
class GlobalVariable = Cpp::GlobalOrNamespaceVariable;
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
private import cpp
|
||||
private import semmle.code.cpp.Print as Print
|
||||
|
||||
predicate getIdentityString = Print::getIdentityString/1;
|
||||
string getIdentityString(Declaration decl) {
|
||||
if decl instanceof StaticLocalVariable
|
||||
then
|
||||
exists(StaticLocalVariable v | v = decl | result = v.getType().toString() + " " + v.getName())
|
||||
else result = Print::getIdentityString(decl)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisImpl
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
|
||||
/**
|
||||
* Gets the lower bound of the expression.
|
||||
@@ -22,8 +24,10 @@ private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.Rang
|
||||
* `lowerBound(expr.getFullyConverted())`
|
||||
*/
|
||||
float lowerBound(Expr expr) {
|
||||
exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound |
|
||||
semBounded(getSemanticExpr(i), b, result, false, _)
|
||||
exists(Instruction i, ConstantBounds::SemBound b |
|
||||
i.getAst() = expr and b instanceof ConstantBounds::SemZeroBound
|
||||
|
|
||||
ConstantStage::semBounded(getSemanticExpr(i), b, result, false, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,8 +44,10 @@ float lowerBound(Expr expr) {
|
||||
* `upperBound(expr.getFullyConverted())`
|
||||
*/
|
||||
float upperBound(Expr expr) {
|
||||
exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound |
|
||||
semBounded(getSemanticExpr(i), b, result, true, _)
|
||||
exists(Instruction i, ConstantBounds::SemBound b |
|
||||
i.getAst() = expr and b instanceof ConstantBounds::SemZeroBound
|
||||
|
|
||||
ConstantStage::semBounded(getSemanticExpr(i), b, result, true, _)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -90,7 +96,15 @@ predicate defMightOverflow(RangeSsaDefinition def, StackVariable v) {
|
||||
* does not consider the possibility that the expression might overflow
|
||||
* due to a conversion.
|
||||
*/
|
||||
predicate exprMightOverflowNegatively(Expr expr) { none() }
|
||||
predicate exprMightOverflowNegatively(Expr expr) {
|
||||
lowerBound(expr) < exprMinVal(expr)
|
||||
or
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getAst() = expr and
|
||||
ConstantStage::potentiallyOverflowingExpr(false, semExpr) and
|
||||
not ConstantStage::initialBounded(semExpr, _, _, false, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the expression might overflow negatively. Conversions
|
||||
@@ -108,7 +122,15 @@ predicate convertedExprMightOverflowNegatively(Expr expr) {
|
||||
* does not consider the possibility that the expression might overflow
|
||||
* due to a conversion.
|
||||
*/
|
||||
predicate exprMightOverflowPositively(Expr expr) { none() }
|
||||
predicate exprMightOverflowPositively(Expr expr) {
|
||||
upperBound(expr) > exprMaxVal(expr)
|
||||
or
|
||||
exists(SemanticExprConfig::Expr semExpr |
|
||||
semExpr.getUnconverted().getAst() = expr and
|
||||
ConstantStage::potentiallyOverflowingExpr(true, semExpr) and
|
||||
not ConstantStage::initialBounded(semExpr, _, _, true, _, _, _)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the expression might overflow positively. Conversions
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisImpl
|
||||
|
||||
module FloatDelta implements DeltaSig {
|
||||
class Delta = float;
|
||||
@@ -18,3 +19,36 @@ module FloatDelta implements DeltaSig {
|
||||
bindingset[f]
|
||||
Delta fromFloat(float f) { result = f }
|
||||
}
|
||||
|
||||
module FloatOverflow implements OverflowSig<FloatDelta> {
|
||||
predicate semExprDoesNotOverflow(boolean positively, SemExpr expr) {
|
||||
exists(float lb, float ub, float delta |
|
||||
typeBounds(expr.getSemType(), lb, ub) and
|
||||
ConstantStage::initialBounded(expr, any(ConstantBounds::SemZeroBound b), delta, positively, _,
|
||||
_, _)
|
||||
|
|
||||
positively = true and delta < ub
|
||||
or
|
||||
positively = false and delta > lb
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate typeBounds(SemType t, float lb, float ub) {
|
||||
exists(SemIntegerType integralType, float limit |
|
||||
integralType = t and limit = 2.pow(8 * integralType.getByteSize())
|
||||
|
|
||||
if integralType instanceof SemBooleanType
|
||||
then lb = 0 and ub = 1
|
||||
else
|
||||
if integralType.isSigned()
|
||||
then (
|
||||
lb = -(limit / 2) and ub = (limit / 2) - 1
|
||||
) else (
|
||||
lb = 0 and ub = limit - 1
|
||||
)
|
||||
)
|
||||
or
|
||||
// This covers all floating point types. The range is (-Inf, +Inf).
|
||||
t instanceof SemFloatingPointType and lb = -(1.0 / 0.0) and ub = 1.0 / 0.0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import RangeAnalysisImpl
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound
|
||||
private import RangeAnalysisImpl as Impl
|
||||
import Impl::Public
|
||||
|
||||
@@ -6,7 +6,7 @@ private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import RangeAnalysisStage
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
|
||||
module CppLangImpl implements LangSig<FloatDelta> {
|
||||
module CppLangImplConstant implements LangSig<FloatDelta> {
|
||||
/**
|
||||
* Holds if the specified expression should be excluded from the result of `ssaRead()`.
|
||||
*
|
||||
@@ -1,5 +1,6 @@
|
||||
private import RangeAnalysisStage
|
||||
private import RangeAnalysisSpecific
|
||||
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.SemanticBound as SemanticBound
|
||||
@@ -28,7 +29,7 @@ module ConstantBounds implements BoundSig<FloatDelta> {
|
||||
}
|
||||
}
|
||||
|
||||
private module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
class SemBound instanceof SemanticBound::SemBound {
|
||||
SemBound() { not this instanceof SemanticBound::SemZeroBound }
|
||||
|
||||
@@ -46,11 +47,13 @@ private module RelativeBounds implements BoundSig<FloatDelta> {
|
||||
}
|
||||
}
|
||||
|
||||
private module ConstantStage =
|
||||
RangeStage<FloatDelta, ConstantBounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
module ConstantStage =
|
||||
RangeStage<FloatDelta, ConstantBounds, FloatOverflow, CppLangImplConstant,
|
||||
RangeUtil<FloatDelta, CppLangImplConstant>>;
|
||||
|
||||
private module RelativeStage =
|
||||
RangeStage<FloatDelta, RelativeBounds, CppLangImpl, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
module RelativeStage =
|
||||
RangeStage<FloatDelta, RelativeBounds, FloatOverflow, CppLangImplRelative,
|
||||
RangeUtil<FloatDelta, CppLangImplRelative>>;
|
||||
|
||||
private newtype TSemReason =
|
||||
TSemNoReason() or
|
||||
@@ -60,48 +63,52 @@ private newtype TSemReason =
|
||||
guard = any(RelativeStage::SemCondReason reason).getCond()
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound. This can either be `CondReason` if the bound
|
||||
* is due to a specific condition, or `NoReason` if the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
abstract class SemReason extends TSemReason {
|
||||
/** Gets a textual representation of this reason. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound that indicates that the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class SemNoReason extends SemReason, TSemNoReason {
|
||||
override string toString() { result = "NoReason" }
|
||||
}
|
||||
|
||||
/** A reason for an inferred bound pointing to a condition. */
|
||||
class SemCondReason extends SemReason, TSemCondReason {
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
SemGuard getCond() { this = TSemCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
}
|
||||
|
||||
private ConstantStage::SemReason constantReason(SemReason reason) {
|
||||
ConstantStage::SemReason constantReason(SemReason reason) {
|
||||
result instanceof ConstantStage::SemNoReason and reason instanceof SemNoReason
|
||||
or
|
||||
result.(ConstantStage::SemCondReason).getCond() = reason.(SemCondReason).getCond()
|
||||
}
|
||||
|
||||
private RelativeStage::SemReason relativeReason(SemReason reason) {
|
||||
RelativeStage::SemReason relativeReason(SemReason reason) {
|
||||
result instanceof RelativeStage::SemNoReason and reason instanceof SemNoReason
|
||||
or
|
||||
result.(RelativeStage::SemCondReason).getCond() = reason.(SemCondReason).getCond()
|
||||
}
|
||||
|
||||
predicate semBounded(
|
||||
SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason
|
||||
) {
|
||||
ConstantStage::semBounded(e, b, delta, upper, constantReason(reason))
|
||||
or
|
||||
RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason))
|
||||
import Public
|
||||
|
||||
module Public {
|
||||
predicate semBounded(
|
||||
SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason
|
||||
) {
|
||||
ConstantStage::semBounded(e, b, delta, upper, constantReason(reason))
|
||||
or
|
||||
RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason))
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound. This can either be `CondReason` if the bound
|
||||
* is due to a specific condition, or `NoReason` if the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
abstract class SemReason extends TSemReason {
|
||||
/** Gets a textual representation of this reason. */
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for an inferred bound that indicates that the bound is inferred
|
||||
* without going through a bounding condition.
|
||||
*/
|
||||
class SemNoReason extends SemReason, TSemNoReason {
|
||||
override string toString() { result = "NoReason" }
|
||||
}
|
||||
|
||||
/** A reason for an inferred bound pointing to a condition. */
|
||||
class SemCondReason extends SemReason, TSemCondReason {
|
||||
/** Gets the condition that is the reason for the bound. */
|
||||
SemGuard getCond() { this = TSemCondReason(result) }
|
||||
|
||||
override string toString() { result = getCond().toString() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* C++-specific implementation of range analysis.
|
||||
*/
|
||||
|
||||
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
|
||||
|
||||
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() }
|
||||
|
||||
/**
|
||||
* Ignore the 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 ignoreExprBound(SemExpr e) {
|
||||
exists(boolean upper, float delta, ConstantBounds::SemZeroBound b, float lb, float ub |
|
||||
ConstantStage::semBounded(e, b, delta, upper, _) and
|
||||
typeBounds(e.getSemType(), lb, ub) and
|
||||
(
|
||||
upper = false and
|
||||
delta < lb
|
||||
or
|
||||
upper = true and
|
||||
delta > ub
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate typeBounds(SemType t, float lb, float ub) {
|
||||
exists(SemIntegerType integralType, float limit |
|
||||
integralType = t and limit = 2.pow(8 * integralType.getByteSize())
|
||||
|
|
||||
if integralType instanceof SemBooleanType
|
||||
then lb = 0 and ub = 1
|
||||
else
|
||||
if integralType.isSigned()
|
||||
then (
|
||||
lb = -(limit / 2) and ub = (limit / 2) - 1
|
||||
) else (
|
||||
lb = 0 and ub = limit - 1
|
||||
)
|
||||
)
|
||||
or
|
||||
// This covers all floating point types. The range is (-Inf, +Inf).
|
||||
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`).
|
||||
*/
|
||||
predicate hasConstantBound(SemExpr e, float bound, boolean upper) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`).
|
||||
*/
|
||||
predicate hasBound(SemExpr e, SemExpr bound, float delta, boolean upper) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the value of `dest` is known to be `src + delta`.
|
||||
*/
|
||||
predicate additionalValueFlowStep(SemExpr dest, SemExpr src, float delta) { none() }
|
||||
|
||||
/**
|
||||
* Gets the type that range analysis should use to track the result of the specified expression,
|
||||
* if a type other than the original type of the expression is to be used.
|
||||
*
|
||||
* This predicate is commonly used in languages that support immutable "boxed" types that are
|
||||
* actually references but whose values can be tracked as the type contained in the box.
|
||||
*/
|
||||
SemType getAlternateType(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Gets the type that range analysis should use to track the result of the specified source
|
||||
* variable, if a type other than the original type of the expression is to be used.
|
||||
*
|
||||
* This predicate is commonly used in languages that support immutable "boxed" types that are
|
||||
* actually references but whose values can be tracked as the type contained in the box.
|
||||
*/
|
||||
SemType getAlternateTypeForSsaVariable(SemSsaVariable var) { none() }
|
||||
}
|
||||
@@ -73,6 +73,7 @@ import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticCFG
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticOpcode
|
||||
private import ConstantAnalysis
|
||||
private import Sign
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation
|
||||
|
||||
/**
|
||||
@@ -240,11 +241,19 @@ signature module BoundSig<DeltaSig D> {
|
||||
}
|
||||
}
|
||||
|
||||
module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<D> UtilParam> {
|
||||
signature module OverflowSig<DeltaSig D> {
|
||||
predicate semExprDoesNotOverflow(boolean positively, SemExpr expr);
|
||||
}
|
||||
|
||||
module RangeStage<
|
||||
DeltaSig D, BoundSig<D> Bounds, OverflowSig<D> OverflowParam, LangSig<D> LangParam,
|
||||
UtilSig<D> UtilParam>
|
||||
{
|
||||
private import Bounds
|
||||
private import LangParam
|
||||
private import UtilParam
|
||||
private import D
|
||||
private import OverflowParam
|
||||
|
||||
/**
|
||||
* An expression that does conversion, boxing, or unboxing
|
||||
@@ -920,6 +929,81 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
|
||||
bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason)
|
||||
}
|
||||
|
||||
predicate bounded(
|
||||
SemExpr e, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta,
|
||||
SemReason reason
|
||||
) {
|
||||
initialBounded(e, b, delta, upper, fromBackEdge, origdelta, reason) and
|
||||
(
|
||||
semExprDoesNotOverflow(upper.booleanNot(), e)
|
||||
or
|
||||
not potentiallyOverflowingExpr(upper.booleanNot(), e)
|
||||
or
|
||||
exists(D::Delta otherDelta |
|
||||
initialBounded(e, _, otherDelta, upper.booleanNot(), _, _, _) and
|
||||
(
|
||||
upper = true and D::toFloat(otherDelta) >= 0
|
||||
or
|
||||
upper = false and D::toFloat(otherDelta) <= 0
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate potentiallyOverflowingExpr(boolean positively, SemExpr expr) {
|
||||
(
|
||||
expr.getOpcode() instanceof Opcode::Add or
|
||||
expr.getOpcode() instanceof Opcode::PointerAdd
|
||||
) and
|
||||
(
|
||||
positively = true and
|
||||
(
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getLeftOperand())) = TPos() and
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getRightOperand())) = TPos()
|
||||
)
|
||||
or
|
||||
positively = false and
|
||||
(
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getLeftOperand())) = TNeg() and
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getRightOperand())) = TNeg()
|
||||
)
|
||||
)
|
||||
or
|
||||
(
|
||||
expr.getOpcode() instanceof Opcode::Sub or
|
||||
expr.getOpcode() instanceof Opcode::PointerSub
|
||||
) and
|
||||
(
|
||||
positively = true and
|
||||
(
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getLeftOperand())) = TPos() and
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getRightOperand())) = TNeg()
|
||||
)
|
||||
or
|
||||
positively = false and
|
||||
(
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getLeftOperand())) = TNeg() and
|
||||
pragma[only_bind_out](semExprSign(expr.(SemBinaryExpr).getRightOperand())) = TPos()
|
||||
)
|
||||
)
|
||||
or
|
||||
positively in [true, false] and
|
||||
(
|
||||
expr.getOpcode() instanceof Opcode::Mul or
|
||||
expr.getOpcode() instanceof Opcode::ShiftLeft
|
||||
)
|
||||
or
|
||||
positively = false and
|
||||
(
|
||||
expr.getOpcode() instanceof Opcode::Negate or
|
||||
expr.getOpcode() instanceof Opcode::SubOne or
|
||||
expr.(SemDivExpr).getSemType() instanceof SemFloatingPointType
|
||||
)
|
||||
or
|
||||
positively = true and
|
||||
expr.getOpcode() instanceof Opcode::AddOne
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a normal form of `x` where -0.0 has changed to +0.0. This can be
|
||||
* needed on the lesser side of a floating-point comparison or on both sides of
|
||||
@@ -934,7 +1018,7 @@ module RangeStage<DeltaSig D, BoundSig<D> Bounds, LangSig<D> LangParam, UtilSig<
|
||||
* - `upper = true` : `e <= b + delta`
|
||||
* - `upper = false` : `e >= b + delta`
|
||||
*/
|
||||
private predicate bounded(
|
||||
predicate initialBounded(
|
||||
SemExpr e, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta,
|
||||
SemReason reason
|
||||
) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
private import RangeAnalysisSpecific
|
||||
private import RangeAnalysisRelativeSpecific
|
||||
private import RangeAnalysisStage as Range
|
||||
private import ConstantAnalysis
|
||||
|
||||
|
||||
@@ -314,9 +314,8 @@ class FreadBA extends BufferAccess {
|
||||
* but not:
|
||||
* &buffer[ix]
|
||||
*/
|
||||
class ArrayExprBA extends BufferAccess {
|
||||
class ArrayExprBA extends BufferAccess, ArrayExpr {
|
||||
ArrayExprBA() {
|
||||
exists(this.(ArrayExpr).getArrayOffset().getValue().toInt()) and
|
||||
not exists(AddressOfExpr aoe | aoe.getAChild() = this) and
|
||||
// exclude accesses in macro implementation of `strcmp`,
|
||||
// which are carefully controlled but can look dangerous.
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
## 0.6.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/double-free` has been added. The query finds possible cases of deallocating the same pointer twice. The precision of the query has been set to "medium".
|
||||
* The query `cpp/use-after-free` has been modernized and assigned the precision "medium". The query finds cases of where a pointer is dereferenced after its memory has been deallocated.
|
||||
|
||||
## 0.6.0
|
||||
|
||||
### New Queries
|
||||
|
||||
10
cpp/ql/src/Critical/DoubleFree.cpp
Normal file
10
cpp/ql/src/Critical/DoubleFree.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
int* f() {
|
||||
int *buff = malloc(SIZE*sizeof(int));
|
||||
do_stuff(buff);
|
||||
free(buff);
|
||||
int *new_buffer = malloc(SIZE*sizeof(int));
|
||||
free(buff); // BAD: If new_buffer is assigned the same address as buff,
|
||||
// the memory allocator will free the new buffer memory region,
|
||||
// leading to use-after-free problems and memory corruption.
|
||||
return new_buffer;
|
||||
}
|
||||
33
cpp/ql/src/Critical/DoubleFree.qhelp
Normal file
33
cpp/ql/src/Critical/DoubleFree.qhelp
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Deallocating memory more than once can lead to a double-free vulnerability. This can be exploited to
|
||||
corrupt the allocator's internal data structures, which can lead to denial-of-service attacks by crashing
|
||||
the program, or security vulnerabilities, by allowing an attacker to overwrite arbitrary memory locations.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>
|
||||
Ensure that all execution paths deallocate the allocated memory at most once. If possible, reassign
|
||||
the pointer to a null value after deallocating it. This will prevent double-free vulnerabilities since
|
||||
most deallocation functions will perform a null-pointer check before attempting to deallocate the memory.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
<example><sample src="DoubleFree.cpp" />
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://owasp.org/www-community/vulnerabilities/Doubly_freeing_memory">Doubly freeing memory</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
49
cpp/ql/src/Critical/DoubleFree.ql
Normal file
49
cpp/ql/src/Critical/DoubleFree.ql
Normal file
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @name Potential double free
|
||||
* @description Freeing a resource more than once can lead to undefined behavior and cause memory corruption.
|
||||
* @kind path-problem
|
||||
* @precision medium
|
||||
* @id cpp/double-free
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-415
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import FlowAfterFree
|
||||
import DoubleFree::PathGraph
|
||||
|
||||
predicate isFree(DataFlow::Node n, Expr e) { isFree(n, e, _) }
|
||||
|
||||
/**
|
||||
* `dealloc1` is a deallocation expression and `e` is an expression such
|
||||
* that is deallocated by a deallocation expression, and the `(dealloc1, e)` pair
|
||||
* should be excluded by the `FlowFromFree` library.
|
||||
*
|
||||
* Note that `e` is not necessarily the expression deallocated by `dealloc1`. It will
|
||||
* be bound to the second deallocation as identified by the `FlowFromFree` library.
|
||||
*/
|
||||
bindingset[dealloc1, e]
|
||||
predicate isExcludeFreePair(DeallocationExpr dealloc1, Expr e) {
|
||||
exists(DeallocationExpr dealloc2 | isFree(_, e, dealloc2) |
|
||||
dealloc1.(FunctionCall).getTarget().hasGlobalName("MmFreePagesFromMdl") and
|
||||
// From https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-mmfreepagesfrommdl:
|
||||
// "After calling MmFreePagesFromMdl, the caller must also call ExFreePool
|
||||
// to release the memory that was allocated for the MDL structure."
|
||||
isExFreePoolCall(dealloc2, _)
|
||||
)
|
||||
}
|
||||
|
||||
module DoubleFree = FlowFromFree<isFree/2, isExcludeFreePair/2>;
|
||||
|
||||
from DoubleFree::PathNode source, DoubleFree::PathNode sink, DeallocationExpr dealloc, Expr e2
|
||||
where
|
||||
DoubleFree::flowPath(source, sink) and
|
||||
isFree(source.getNode(), _, dealloc) and
|
||||
isFree(sink.getNode(), e2)
|
||||
select sink.getNode(), source, sink,
|
||||
"Memory pointed to by '" + e2.toString() + "' may already have been freed by $@.", dealloc,
|
||||
dealloc.toString()
|
||||
129
cpp/ql/src/Critical/FlowAfterFree.qll
Normal file
129
cpp/ql/src/Critical/FlowAfterFree.qll
Normal file
@@ -0,0 +1,129 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
/**
|
||||
* Signature for a predicate that holds if `n.asExpr() = e` and `n` is a sink in
|
||||
* the `FlowFromFreeConfig` module.
|
||||
*/
|
||||
private signature predicate isSinkSig(DataFlow::Node n, Expr e);
|
||||
|
||||
/**
|
||||
* Holds if `dealloc` is a deallocation expression and `e` is an expression such
|
||||
* that `isFree(_, e)` holds for some `isFree` predicate satisfying `isSinkSig`,
|
||||
* and this source-sink pair should be excluded from the analysis.
|
||||
*/
|
||||
bindingset[dealloc, e]
|
||||
private signature predicate isExcludedSig(DeallocationExpr dealloc, Expr e);
|
||||
|
||||
/**
|
||||
* Holds if `(b1, i1)` strictly post-dominates `(b2, i2)`
|
||||
*/
|
||||
bindingset[i1, i2]
|
||||
predicate strictlyPostDominates(IRBlock b1, int i1, IRBlock b2, int i2) {
|
||||
b1 = b2 and
|
||||
i1 > i2
|
||||
or
|
||||
b1.strictlyPostDominates(b2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `(b1, i1)` strictly dominates `(b2, i2)`
|
||||
*/
|
||||
bindingset[i1, i2]
|
||||
predicate strictlyDominates(IRBlock b1, int i1, IRBlock b2, int i2) {
|
||||
b1 = b2 and
|
||||
i1 < i2
|
||||
or
|
||||
b1.strictlyDominates(b2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a `FlowFromFreeConfig` module that can be used to find flow between
|
||||
* a pointer being freed by some deallocation function, and a user-specified sink.
|
||||
*
|
||||
* In order to reduce false positives, the set of sinks is restricted to only those
|
||||
* that satisfy at least one of the following two criteria:
|
||||
* 1. The source dominates the sink, or
|
||||
* 2. The sink post-dominates the source.
|
||||
*/
|
||||
module FlowFromFree<isSinkSig/2 isASink, isExcludedSig/2 isExcluded> {
|
||||
module FlowFromFreeConfig implements DataFlow::StateConfigSig {
|
||||
class FlowState instanceof Expr {
|
||||
FlowState() { isFree(_, this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
}
|
||||
|
||||
predicate isSource(DataFlow::Node node, FlowState state) { isFree(node, state, _) }
|
||||
|
||||
pragma[inline]
|
||||
predicate isSink(DataFlow::Node sink, FlowState state) {
|
||||
exists(
|
||||
Expr e, DataFlow::Node source, IRBlock b1, int i1, IRBlock b2, int i2,
|
||||
DeallocationExpr dealloc
|
||||
|
|
||||
isASink(sink, e) and
|
||||
isFree(source, state, dealloc) and
|
||||
e != state and
|
||||
source.hasIndexInBlock(b1, i1) and
|
||||
sink.hasIndexInBlock(b2, i2) and
|
||||
not isExcluded(dealloc, e)
|
||||
|
|
||||
strictlyDominates(b1, i1, b2, i2)
|
||||
or
|
||||
strictlyPostDominates(b2, i2, b1, i1)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node n) {
|
||||
n.asIndirectExpr() = any(AddressOfExpr aoe)
|
||||
or
|
||||
n.asIndirectExpr() = any(Call call).getAnArgument()
|
||||
or
|
||||
exists(Expr e |
|
||||
n.asIndirectExpr() = e.(PointerDereferenceExpr).getOperand() or
|
||||
n.asIndirectExpr() = e.(ArrayExpr).getArrayBase()
|
||||
|
|
||||
e = any(StoreInstruction store).getDestinationAddress().getUnconvertedResultExpression()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node n, FlowState state) { none() }
|
||||
|
||||
predicate isAdditionalFlowStep(
|
||||
DataFlow::Node n1, FlowState state1, DataFlow::Node n2, FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
import DataFlow::GlobalWithState<FlowFromFreeConfig>
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is a dataflow node such that `n.asExpr() = e` and `e`
|
||||
* is being freed by a deallocation expression `dealloc`.
|
||||
*/
|
||||
predicate isFree(DataFlow::Node n, Expr e, DeallocationExpr dealloc) {
|
||||
e = dealloc.getFreedExpr() and
|
||||
e = n.asExpr() and
|
||||
// Ignore realloc functions
|
||||
not exists(dealloc.(FunctionCall).getTarget().(AllocationFunction).getReallocPtrArg())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` is a function call that is the result of expanding
|
||||
* the `ExFreePool` macro.
|
||||
*/
|
||||
predicate isExFreePoolCall(FunctionCall fc, Expr e) {
|
||||
e = fc.getArgument(0) and
|
||||
(
|
||||
exists(MacroInvocation mi |
|
||||
mi.getMacroName() = "ExFreePool" and
|
||||
mi.getExpr() = fc
|
||||
)
|
||||
or
|
||||
fc.getTarget().hasGlobalName("ExFreePool")
|
||||
)
|
||||
}
|
||||
@@ -16,160 +16,133 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.Scanf
|
||||
import semmle.code.cpp.controlflow.Guards
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import semmle.code.cpp.dataflow.new.DataFlow::DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
/**
|
||||
* Holds if `call` is a `scanf`-like function that may write to `output` at index `index`.
|
||||
*
|
||||
* Furthermore, `instr` is the instruction that defines the address of the `index`'th argument
|
||||
* of `call`, and `vn` is the value number of `instr.`
|
||||
*/
|
||||
predicate isSource(ScanfFunctionCall call, int index, Instruction instr, ValueNumber vn, Expr output) {
|
||||
output = call.getOutputArgument(index).getFullyConverted() and
|
||||
instr.getConvertedResultExpression() = output and
|
||||
vn.getAnInstruction() = instr
|
||||
/** Holds if `n` reaches an argument to a call to a `scanf`-like function. */
|
||||
pragma[nomagic]
|
||||
predicate revFlow0(Node n) {
|
||||
isSink(_, _, n, _)
|
||||
or
|
||||
exists(Node succ | revFlow0(succ) | localFlowStep(n, succ))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is control-flow reachable in 0 or more steps from
|
||||
* a call to a `scanf`-like function.
|
||||
* Holds if `n` represents an uninitialized stack-allocated variable, or a
|
||||
* newly (and presumed uninitialized) heap allocation.
|
||||
*/
|
||||
predicate isUninitialized(Node n) {
|
||||
exists(n.asUninitialized()) or
|
||||
n.asIndirectExpr(1) instanceof AllocationExpr
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow0(Instruction instr) {
|
||||
isSource(_, _, instr, _, _)
|
||||
or
|
||||
exists(Instruction prev |
|
||||
fwdFlow0(prev) and
|
||||
prev.getASuccessor() = instr
|
||||
predicate fwdFlow0(Node n) {
|
||||
revFlow0(n) and
|
||||
(
|
||||
isUninitialized(n)
|
||||
or
|
||||
exists(Node prev |
|
||||
fwdFlow0(prev) and
|
||||
localFlowStep(prev, n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of the IR translation of `access` that
|
||||
* is not an expression being deallocated, and `instr` has value
|
||||
* number `vn`.
|
||||
*/
|
||||
predicate isSink(Instruction instr, Access access, ValueNumber vn) {
|
||||
instr.getAst() = access and
|
||||
not any(DeallocationExpr dealloc).getFreedExpr() = access and
|
||||
vn.getAnInstruction() = instr
|
||||
predicate isSink(ScanfFunctionCall call, int index, Node n, Expr input) {
|
||||
input = call.getOutputArgument(index) and
|
||||
n.asIndirectExpr() = input
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of a path from a call to a `scanf`-like function
|
||||
* Holds if `call` is a `scanf`-like call and `output` is the `index`'th
|
||||
* argument that has not been previously initialized.
|
||||
*/
|
||||
predicate isRelevantScanfCall(ScanfFunctionCall call, int index, Expr output) {
|
||||
exists(Node n | fwdFlow0(n) and isSink(call, index, n, output))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `call` is a `scanf`-like function that may write to `output` at
|
||||
* index `index` and `n` is the dataflow node that represents the data after
|
||||
* it has been written to by `call`.
|
||||
*/
|
||||
predicate isSource(ScanfFunctionCall call, int index, Node n, Expr output) {
|
||||
isRelevantScanfCall(call, index, output) and
|
||||
output = call.getOutputArgument(index) and
|
||||
n.asDefiningArgument() = output
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is reachable from an output argument of a relevant call to
|
||||
* a `scanf`-like function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate fwdFlow(Node n) {
|
||||
isSource(_, _, n, _)
|
||||
or
|
||||
exists(Node prev |
|
||||
fwdFlow(prev) and
|
||||
localFlowStep(prev, n) and
|
||||
not isSanitizerOut(prev)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` should not have outgoing flow. */
|
||||
predicate isSanitizerOut(Node n) {
|
||||
// We disable flow out of sinks to reduce result duplication
|
||||
isSink(n, _)
|
||||
or
|
||||
// If the node is being passed to a function it may be
|
||||
// modified, and thus it's safe to later read the value.
|
||||
exists(n.asIndirectArgument())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is a node such that `n.asExpr() = e` and `e` is not an
|
||||
* argument of a deallocation expression.
|
||||
*/
|
||||
predicate isSink(Node n, Expr e) {
|
||||
n.asExpr() = e and
|
||||
not any(DeallocationExpr dealloc).getFreedExpr() = e
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n` is part of a path from a call to a `scanf`-like function
|
||||
* to a use of the written variable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow0(Instruction instr) {
|
||||
fwdFlow0(instr) and
|
||||
predicate revFlow(Node n) {
|
||||
fwdFlow(n) and
|
||||
(
|
||||
isSink(instr, _, _)
|
||||
isSink(n, _)
|
||||
or
|
||||
exists(Instruction succ | revFlow0(succ) | instr.getASuccessor() = succ)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of a path from a call to a `scanf`-like function
|
||||
* that writes to a variable with value number `vn`, without passing through
|
||||
* redefinitions of the variable.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
private predicate fwdFlow(Instruction instr, ValueNumber vn) {
|
||||
revFlow0(instr) and
|
||||
(
|
||||
isSource(_, _, instr, vn, _)
|
||||
or
|
||||
exists(Instruction prev |
|
||||
fwdFlow(prev, vn) and
|
||||
prev.getASuccessor() = instr and
|
||||
not isBarrier(instr, vn)
|
||||
exists(Node succ |
|
||||
revFlow(succ) and
|
||||
localFlowStep(n, succ) and
|
||||
not isSanitizerOut(n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is part of a path from a call to a `scanf`-like function
|
||||
* that writes to a variable with value number `vn`, without passing through
|
||||
* redefinitions of the variable.
|
||||
*
|
||||
* Note: This predicate only holds for the `(intr, vn)` pairs that are also
|
||||
* control-flow reachable from an argument to a `scanf`-like function call.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate revFlow(Instruction instr, ValueNumber vn) {
|
||||
fwdFlow(instr, pragma[only_bind_out](vn)) and
|
||||
(
|
||||
isSink(instr, _, vn)
|
||||
or
|
||||
exists(Instruction succ | revFlow(succ, vn) |
|
||||
instr.getASuccessor() = succ and
|
||||
not isBarrier(succ, vn)
|
||||
)
|
||||
)
|
||||
/** A local flow step, restricted to relevant dataflow nodes. */
|
||||
private predicate step(Node n1, Node n2) {
|
||||
revFlow(n1) and
|
||||
revFlow(n2) and
|
||||
localFlowStep(n1, n2)
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that bundles together a reachable instruction with the appropriate
|
||||
* value number (i.e., the value number that's transferred from the source
|
||||
* to the sink).
|
||||
*/
|
||||
newtype TNode = MkNode(Instruction instr, ValueNumber vn) { revFlow(instr, vn) }
|
||||
|
||||
class Node extends MkNode {
|
||||
ValueNumber vn;
|
||||
Instruction instr;
|
||||
|
||||
Node() { this = MkNode(instr, vn) }
|
||||
|
||||
final string toString() { result = instr.toString() }
|
||||
|
||||
final Node getASuccessor() { result = MkNode(pragma[only_bind_out](instr.getASuccessor()), vn) }
|
||||
|
||||
final Location getLocation() { result = instr.getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an instruction with value number `vn` that is
|
||||
* used in a store operation, or is overwritten by another call to
|
||||
* a `scanf`-like function.
|
||||
*/
|
||||
private predicate isBarrier(Instruction instr, ValueNumber vn) {
|
||||
// We only need to compute barriers for instructions that we
|
||||
// managed to hit during the initial flow stage.
|
||||
revFlow0(pragma[only_bind_into](instr)) and
|
||||
valueNumber(instr) = vn and
|
||||
exists(Expr e | instr.getAst() = e |
|
||||
instr = any(StoreInstruction s).getDestinationAddress()
|
||||
or
|
||||
isSource(_, _, _, _, [e, e.getParent().(AddressOfExpr)])
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n1` steps to `n2` in a single step. */
|
||||
predicate isSuccessor(Node n1, Node n2) { n1.getASuccessor() = n2 }
|
||||
|
||||
predicate hasFlow(Node n1, Node n2) = fastTC(isSuccessor/2)(n1, n2)
|
||||
|
||||
Node getNode(Instruction instr, ValueNumber vn) { result = MkNode(instr, vn) }
|
||||
predicate hasFlow(Node n1, Node n2) = fastTC(step/2)(n1, n2)
|
||||
|
||||
/**
|
||||
* Holds if `source` is the `index`'th argument to the `scanf`-like call `call`, and `sink` is
|
||||
* an instruction that is part of the translation of `access` which is a transitive
|
||||
* control-flow successor of `call`.
|
||||
*
|
||||
* Furthermore, `source` and `sink` have identical global value numbers.
|
||||
* a dataflow node that represents the expression `e`.
|
||||
*/
|
||||
predicate hasFlow(
|
||||
Instruction source, ScanfFunctionCall call, int index, Instruction sink, Access access
|
||||
) {
|
||||
exists(ValueNumber vn |
|
||||
isSource(call, index, source, vn, _) and
|
||||
hasFlow(getNode(source, pragma[only_bind_into](vn)), getNode(sink, pragma[only_bind_into](vn))) and
|
||||
isSink(sink, access, vn)
|
||||
)
|
||||
predicate hasFlow(Node source, ScanfFunctionCall call, int index, Node sink, Expr e) {
|
||||
isSource(call, index, source, _) and
|
||||
hasFlow(source, sink) and
|
||||
isSink(sink, e)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,7 +150,7 @@ predicate hasFlow(
|
||||
* success in writing the output argument at index `index`.
|
||||
*/
|
||||
int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
|
||||
isSource(call, index, _, _, _) and
|
||||
isSource(call, index, _, _) and
|
||||
result =
|
||||
index + 1 -
|
||||
count(ScanfFormatLiteral f, int n |
|
||||
@@ -191,7 +164,7 @@ int getMinimumGuardConstant(ScanfFunctionCall call, int index) {
|
||||
* Holds the access to `e` isn't guarded by a check that ensures that `call` returned
|
||||
* at least `minGuard`.
|
||||
*/
|
||||
predicate hasNonGuardedAccess(ScanfFunctionCall call, Access e, int minGuard) {
|
||||
predicate hasNonGuardedAccess(ScanfFunctionCall call, Expr e, int minGuard) {
|
||||
exists(int index |
|
||||
hasFlow(_, call, index, _, e) and
|
||||
minGuard = getMinimumGuardConstant(call, index)
|
||||
@@ -211,7 +184,7 @@ BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
|
||||
exists(GuardCondition g, Expr left, Expr right |
|
||||
right = g.getAChild() and
|
||||
value = left.getValue().toInt() and
|
||||
DataFlow::localExprFlow(call, right)
|
||||
localExprFlow(call, right)
|
||||
|
|
||||
g.ensuresEq(left, right, 0, result, true) and op = "=="
|
||||
or
|
||||
@@ -221,9 +194,9 @@ BasicBlock blockGuardedBy(int value, string op, ScanfFunctionCall call) {
|
||||
)
|
||||
}
|
||||
|
||||
from ScanfFunctionCall call, Access access, int minGuard
|
||||
where hasNonGuardedAccess(call, access, minGuard)
|
||||
select access,
|
||||
from ScanfFunctionCall call, Expr e, int minGuard
|
||||
where hasNonGuardedAccess(call, e, minGuard)
|
||||
select e,
|
||||
"This variable is read, but may not have been written. " +
|
||||
"It should be guarded by a check that the $@ returns at least " + minGuard + ".", call,
|
||||
call.toString()
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* @name Potential use after free
|
||||
* @description An allocated memory block is used after it has been freed. Behavior in such cases is undefined and can cause memory corruption.
|
||||
* @kind problem
|
||||
* @kind path-problem
|
||||
* @precision medium
|
||||
* @id cpp/use-after-free
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
@@ -11,56 +12,159 @@
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.controlflow.StackVariableReachability
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import FlowAfterFree
|
||||
import UseAfterFree::PathGraph
|
||||
|
||||
/** `e` is an expression that frees the memory pointed to by `v`. */
|
||||
predicate isFreeExpr(Expr e, StackVariable v) {
|
||||
exists(VariableAccess va | va.getTarget() = v |
|
||||
exists(FunctionCall fc | fc = e |
|
||||
fc.getTarget().hasGlobalOrStdName("free") and
|
||||
va = fc.getArgument(0)
|
||||
)
|
||||
or
|
||||
e.(DeleteExpr).getExpr() = va
|
||||
or
|
||||
e.(DeleteArrayExpr).getExpr() = va
|
||||
/**
|
||||
* Holds if `call` is a call to a function that obviously
|
||||
* doesn't dereference its `i`'th argument.
|
||||
*/
|
||||
private predicate externalCallNeverDereferences(FormattingFunctionCall call, int arg) {
|
||||
exists(int formatArg |
|
||||
pragma[only_bind_out](call.getFormatArgument(formatArg)) =
|
||||
pragma[only_bind_out](call.getArgument(arg)) and
|
||||
call.getFormat().(FormatLiteral).getConvSpec(formatArg) != "%s"
|
||||
)
|
||||
}
|
||||
|
||||
/** `e` is an expression that (may) dereference `v`. */
|
||||
predicate isDerefExpr(Expr e, StackVariable v) {
|
||||
v.getAnAccess() = e and dereferenced(e)
|
||||
or
|
||||
isDerefByCallExpr(_, _, e, v)
|
||||
predicate isUse0(DataFlow::Node n, Expr e) {
|
||||
e = n.asExpr() and
|
||||
not isFree(_, e, _) and
|
||||
(
|
||||
e = any(PointerDereferenceExpr pde).getOperand()
|
||||
or
|
||||
e = any(PointerFieldAccess pfa).getQualifier()
|
||||
or
|
||||
e = any(ArrayExpr ae).getArrayBase()
|
||||
or
|
||||
e = any(Call call).getQualifier()
|
||||
or
|
||||
// Assume any function without a body will dereference the pointer
|
||||
exists(int i, Call call, Function f |
|
||||
n.asExpr() = call.getArgument(i) and
|
||||
f = call.getTarget() and
|
||||
not f.hasEntryPoint() and
|
||||
// Exclude known functions we know won't dereference the pointer.
|
||||
// For example, a call such as `printf("%p", myPointer)`.
|
||||
not externalCallNeverDereferences(call, i)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* `va` is passed by value as (part of) the `i`th argument in
|
||||
* call `c`. The target function is either a library function
|
||||
* or a source code function that dereferences the relevant
|
||||
* parameter.
|
||||
*/
|
||||
predicate isDerefByCallExpr(Call c, int i, VariableAccess va, StackVariable v) {
|
||||
v.getAnAccess() = va and
|
||||
va = c.getAnArgumentSubExpr(i) and
|
||||
not c.passesByReference(i, va) and
|
||||
(c.getTarget().hasEntryPoint() implies isDerefExpr(_, c.getTarget().getParameter(i)))
|
||||
}
|
||||
module ParameterSinks {
|
||||
import semmle.code.cpp.ir.ValueNumbering
|
||||
|
||||
class UseAfterFreeReachability extends StackVariableReachability {
|
||||
UseAfterFreeReachability() { this = "UseAfterFree" }
|
||||
predicate flowsToUse(DataFlow::Node n) {
|
||||
isUse0(n, _)
|
||||
or
|
||||
exists(DataFlow::Node succ |
|
||||
flowsToUse(succ) and
|
||||
DataFlow::localFlowStep(n, succ)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSource(ControlFlowNode node, StackVariable v) { isFreeExpr(node, v) }
|
||||
private predicate flowsFromParam(DataFlow::Node n) {
|
||||
flowsToUse(n) and
|
||||
(
|
||||
n.asParameter().getUnspecifiedType() instanceof PointerType
|
||||
or
|
||||
exists(DataFlow::Node prev |
|
||||
flowsFromParam(prev) and
|
||||
DataFlow::localFlowStep(prev, n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(ControlFlowNode node, StackVariable v) { isDerefExpr(node, v) }
|
||||
private predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
flowsFromParam(n1) and
|
||||
flowsFromParam(n2) and
|
||||
DataFlow::localFlowStep(n1, n2)
|
||||
}
|
||||
|
||||
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
|
||||
definitionBarrier(v, node) or
|
||||
isFreeExpr(node, v)
|
||||
private predicate paramToUse(DataFlow::Node n1, DataFlow::Node n2) = fastTC(step/2)(n1, n2)
|
||||
|
||||
private predicate hasFlow(
|
||||
DataFlow::Node source, InitializeParameterInstruction init, DataFlow::Node sink
|
||||
) {
|
||||
pragma[only_bind_out](source.asParameter()) = pragma[only_bind_out](init.getParameter()) and
|
||||
paramToUse(source, sink) and
|
||||
isUse0(sink, _)
|
||||
}
|
||||
|
||||
private InitializeParameterInstruction getAnAlwaysDereferencedParameter0() {
|
||||
exists(DataFlow::Node source, DataFlow::Node sink, IRBlock b1, int i1, IRBlock b2, int i2 |
|
||||
hasFlow(pragma[only_bind_into](source), result, pragma[only_bind_into](sink)) and
|
||||
source.hasIndexInBlock(b1, pragma[only_bind_into](i1)) and
|
||||
sink.hasIndexInBlock(b2, pragma[only_bind_into](i2)) and
|
||||
strictlyPostDominates(b2, i2, b1, i1)
|
||||
)
|
||||
}
|
||||
|
||||
private CallInstruction getAnAlwaysReachedCallInstruction(IRFunction f) {
|
||||
result.getBlock().postDominates(f.getEntryBlock())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate callHasTargetAndArgument(Function f, int i, CallInstruction call, Instruction argument) {
|
||||
call.getStaticCallTarget() = f and
|
||||
call.getArgument(i) = argument
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
predicate initializeParameterInFunction(Function f, int i, InitializeParameterInstruction init) {
|
||||
pragma[only_bind_out](init.getEnclosingFunction()) = f and
|
||||
init.hasIndex(i)
|
||||
}
|
||||
|
||||
InitializeParameterInstruction getAnAlwaysDereferencedParameter() {
|
||||
result = getAnAlwaysDereferencedParameter0()
|
||||
or
|
||||
exists(
|
||||
CallInstruction call, int i, InitializeParameterInstruction p, Instruction argument,
|
||||
Function f
|
||||
|
|
||||
callHasTargetAndArgument(f, i, call, argument) and
|
||||
initializeParameterInFunction(f, i, p) and
|
||||
p = getAnAlwaysDereferencedParameter() and
|
||||
result =
|
||||
pragma[only_bind_out](pragma[only_bind_into](valueNumber(argument)).getAnInstruction()) and
|
||||
call = getAnAlwaysReachedCallInstruction(_)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from UseAfterFreeReachability r, StackVariable v, Expr free, Expr e
|
||||
where r.reaches(free, v, e)
|
||||
select e, "Memory pointed to by '" + v.getName().toString() + "' may have $@.", free,
|
||||
"been previously freed"
|
||||
predicate isUse(DataFlow::Node n, Expr e) {
|
||||
isUse0(n, e)
|
||||
or
|
||||
exists(CallInstruction call, int i, InitializeParameterInstruction init |
|
||||
n.asOperand().getDef().getUnconvertedResultExpression() = e and
|
||||
init = ParameterSinks::getAnAlwaysDereferencedParameter() and
|
||||
call.getArgumentOperand(i) = n.asOperand() and
|
||||
init.hasIndex(i) and
|
||||
init.getEnclosingFunction() = call.getStaticCallTarget()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* `dealloc1` is a deallocation expression, `e` is an expression that dereferences a
|
||||
* pointer, and the `(dealloc1, e)` pair should be excluded by the `FlowFromFree` library.
|
||||
*/
|
||||
bindingset[dealloc1, e]
|
||||
predicate isExcludeFreeUsePair(DeallocationExpr dealloc1, Expr e) {
|
||||
// From https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-mmfreepagesfrommdl:
|
||||
// "After calling MmFreePagesFromMdl, the caller must also call ExFreePool
|
||||
// to release the memory that was allocated for the MDL structure."
|
||||
dealloc1.(FunctionCall).getTarget().hasGlobalName("MmFreePagesFromMdl") and
|
||||
isExFreePoolCall(_, e)
|
||||
}
|
||||
|
||||
module UseAfterFree = FlowFromFree<isUse/2, isExcludeFreeUsePair/2>;
|
||||
|
||||
from UseAfterFree::PathNode source, UseAfterFree::PathNode sink, DeallocationExpr dealloc
|
||||
where
|
||||
UseAfterFree::flowPath(source, sink) and
|
||||
isFree(source.getNode(), _, dealloc)
|
||||
select sink.getNode(), source, sink, "Memory may have been previously freed by $@.", dealloc,
|
||||
dealloc.toString()
|
||||
|
||||
6
cpp/ql/src/change-notes/released/0.6.1.md
Normal file
6
cpp/ql/src/change-notes/released/0.6.1.md
Normal file
@@ -0,0 +1,6 @@
|
||||
## 0.6.1
|
||||
|
||||
### New Queries
|
||||
|
||||
* A new query `cpp/double-free` has been added. The query finds possible cases of deallocating the same pointer twice. The precision of the query has been set to "medium".
|
||||
* The query `cpp/use-after-free` has been modernized and assigned the precision "medium". The query finds cases of where a pointer is dereferenced after its memory has been deallocated.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.0
|
||||
lastReleaseVersion: 0.6.1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Errors When Double Free
|
||||
* @description Freeing a previously allocated resource twice can lead to various vulnerabilities in the program.
|
||||
* @kind problem
|
||||
* @id cpp/double-free
|
||||
* @id cpp/experimental-double-free
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags security
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.6.0
|
||||
version: 0.6.2-dev
|
||||
groups:
|
||||
- cpp
|
||||
- queries
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<queries language="cpp"/>
|
||||
@@ -209,6 +209,9 @@ edges
|
||||
| test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string |
|
||||
| test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string indirection |
|
||||
| test.cpp:207:22:207:27 | string indirection | test.cpp:207:22:207:27 | string |
|
||||
| test.cpp:214:24:214:24 | p | test.cpp:216:10:216:10 | p |
|
||||
| test.cpp:220:43:220:48 | call to malloc | test.cpp:222:15:222:20 | buffer |
|
||||
| test.cpp:222:15:222:20 | buffer | test.cpp:214:24:214:24 | p |
|
||||
nodes
|
||||
| test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] |
|
||||
| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... |
|
||||
@@ -374,6 +377,10 @@ nodes
|
||||
| test.cpp:207:17:207:19 | str indirection [string] | semmle.label | str indirection [string] |
|
||||
| test.cpp:207:22:207:27 | string | semmle.label | string |
|
||||
| test.cpp:207:22:207:27 | string indirection | semmle.label | string indirection |
|
||||
| test.cpp:214:24:214:24 | p | semmle.label | p |
|
||||
| test.cpp:216:10:216:10 | p | semmle.label | p |
|
||||
| test.cpp:220:43:220:48 | call to malloc | semmle.label | call to malloc |
|
||||
| test.cpp:222:15:222:20 | buffer | semmle.label | buffer |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | string | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string |
|
||||
@@ -391,3 +398,4 @@ subpaths
|
||||
| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string |
|
||||
| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string |
|
||||
| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string |
|
||||
| test.cpp:216:3:216:8 | call to memset | test.cpp:220:43:220:48 | call to malloc | test.cpp:216:10:216:10 | p | This write may overflow $@ by 5 elements. | test.cpp:216:10:216:10 | p | p |
|
||||
|
||||
@@ -208,3 +208,16 @@ void test5(unsigned size, char *buf, unsigned anotherSize) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *memset(void *, int, unsigned);
|
||||
|
||||
void call_memset(void *p, unsigned size)
|
||||
{
|
||||
memset(p, 0, size); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test_missing_call_context(unsigned char *unrelated_buffer, unsigned size) {
|
||||
unsigned char* buffer = (unsigned char*)malloc(size);
|
||||
call_memset(unrelated_buffer, size + 5);
|
||||
call_memset(buffer, size);
|
||||
}
|
||||
@@ -575,6 +575,129 @@ edges
|
||||
| test.cpp:213:6:213:6 | q | test.cpp:213:5:213:13 | Store: ... = ... |
|
||||
| test.cpp:213:6:213:6 | q | test.cpp:213:5:213:13 | Store: ... = ... |
|
||||
| test.cpp:221:17:221:22 | call to malloc | test.cpp:222:5:222:5 | p |
|
||||
| test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:9 | newname |
|
||||
| test.cpp:232:3:232:9 | newname | test.cpp:232:3:232:16 | access to array |
|
||||
| test.cpp:232:3:232:16 | access to array | test.cpp:232:3:232:20 | Store: ... = ... |
|
||||
| test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:11 | newname |
|
||||
| test.cpp:239:5:239:11 | newname | test.cpp:239:5:239:18 | access to array |
|
||||
| test.cpp:239:5:239:18 | access to array | test.cpp:239:5:239:22 | Store: ... = ... |
|
||||
| test.cpp:248:24:248:30 | call to realloc | test.cpp:249:9:249:9 | p |
|
||||
| test.cpp:248:24:248:30 | call to realloc | test.cpp:250:22:250:22 | p |
|
||||
| test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:9 | p |
|
||||
| test.cpp:254:9:254:9 | p | test.cpp:254:9:254:12 | access to array |
|
||||
| test.cpp:254:9:254:12 | access to array | test.cpp:254:9:254:16 | Store: ... = ... |
|
||||
| test.cpp:260:13:260:24 | new[] | test.cpp:261:14:261:15 | xs |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:262:31:262:31 | x |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:262:31:262:33 | ... ++ |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:262:31:262:33 | ... ++ |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:261:14:261:15 | xs | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:261:14:261:21 | ... + ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:261:14:261:21 | ... + ... | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:262:21:262:21 | x | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:262:26:262:28 | end | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:262:26:262:28 | end | test.cpp:262:26:262:28 | end |
|
||||
| test.cpp:262:26:262:28 | end | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:262:26:262:28 | end | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:262:31:262:31 | x | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:262:21:262:21 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:262:21:262:21 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:262:31:262:31 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:262:31:262:31 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:262:31:262:33 | ... ++ | test.cpp:264:14:264:14 | x |
|
||||
| test.cpp:264:14:264:14 | x | test.cpp:262:31:262:31 | x |
|
||||
| test.cpp:264:14:264:14 | x | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:264:14:264:14 | x | test.cpp:264:13:264:14 | Load: * ... |
|
||||
| test.cpp:270:13:270:24 | new[] | test.cpp:271:14:271:15 | xs |
|
||||
| test.cpp:270:13:270:24 | new[] | test.cpp:272:31:272:31 | x |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:272:31:272:31 | x |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:272:31:272:33 | ... ++ |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:272:31:272:33 | ... ++ |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:274:5:274:6 | * ... |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:271:14:271:15 | xs | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:271:14:271:21 | ... + ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:271:14:271:21 | ... + ... | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:272:21:272:21 | x | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:272:26:272:28 | end | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:272:26:272:28 | end | test.cpp:272:26:272:28 | end |
|
||||
| test.cpp:272:26:272:28 | end | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:272:26:272:28 | end | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:272:31:272:31 | x | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:272:21:272:21 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:272:21:272:21 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:272:31:272:31 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:272:31:272:31 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:5:274:6 | * ... |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:5:274:6 | * ... |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:272:31:272:33 | ... ++ | test.cpp:274:6:274:6 | x |
|
||||
| test.cpp:274:5:274:6 | * ... | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:274:6:274:6 | x | test.cpp:272:31:272:31 | x |
|
||||
| test.cpp:274:6:274:6 | x | test.cpp:274:5:274:6 | * ... |
|
||||
| test.cpp:274:6:274:6 | x | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:274:6:274:6 | x | test.cpp:274:5:274:10 | Store: ... = ... |
|
||||
| test.cpp:280:13:280:24 | new[] | test.cpp:281:14:281:15 | xs |
|
||||
| test.cpp:281:14:281:15 | xs | test.cpp:282:30:282:32 | ... ++ |
|
||||
| test.cpp:281:14:281:15 | xs | test.cpp:282:30:282:32 | ... ++ |
|
||||
| test.cpp:282:21:282:21 | x | test.cpp:284:13:284:14 | Load: * ... |
|
||||
| test.cpp:282:30:282:30 | x | test.cpp:284:13:284:14 | Load: * ... |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:282:21:282:21 | x |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:282:21:282:21 | x |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:282:30:282:30 | x |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:282:30:282:30 | x |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:284:14:284:14 | x |
|
||||
| test.cpp:282:30:282:32 | ... ++ | test.cpp:284:14:284:14 | x |
|
||||
| test.cpp:284:14:284:14 | x | test.cpp:284:13:284:14 | Load: * ... |
|
||||
| test.cpp:290:13:290:24 | new[] | test.cpp:291:14:291:15 | xs |
|
||||
| test.cpp:290:13:290:24 | new[] | test.cpp:292:30:292:30 | x |
|
||||
| test.cpp:291:14:291:15 | xs | test.cpp:292:30:292:32 | ... ++ |
|
||||
| test.cpp:291:14:291:15 | xs | test.cpp:292:30:292:32 | ... ++ |
|
||||
| test.cpp:292:21:292:21 | x | test.cpp:294:5:294:10 | Store: ... = ... |
|
||||
| test.cpp:292:30:292:30 | x | test.cpp:294:5:294:10 | Store: ... = ... |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:292:21:292:21 | x |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:292:21:292:21 | x |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:292:30:292:30 | x |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:292:30:292:30 | x |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:294:5:294:6 | * ... |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:294:5:294:6 | * ... |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:294:6:294:6 | x |
|
||||
| test.cpp:292:30:292:32 | ... ++ | test.cpp:294:6:294:6 | x |
|
||||
| test.cpp:294:5:294:6 | * ... | test.cpp:294:5:294:10 | Store: ... = ... |
|
||||
| test.cpp:294:6:294:6 | x | test.cpp:294:5:294:10 | Store: ... = ... |
|
||||
#select
|
||||
| test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
|
||||
| test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size |
|
||||
@@ -593,3 +716,12 @@ edges
|
||||
| test.cpp:171:9:171:14 | Store: ... = ... | test.cpp:143:18:143:23 | call to malloc | test.cpp:171:9:171:14 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:143:18:143:23 | call to malloc | call to malloc | test.cpp:144:29:144:32 | size | size |
|
||||
| test.cpp:201:5:201:19 | Store: ... = ... | test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:19 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:194:23:194:28 | call to malloc | call to malloc | test.cpp:195:21:195:23 | len | len |
|
||||
| test.cpp:213:5:213:13 | Store: ... = ... | test.cpp:205:23:205:28 | call to malloc | test.cpp:213:5:213:13 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:205:23:205:28 | call to malloc | call to malloc | test.cpp:206:21:206:23 | len | len |
|
||||
| test.cpp:232:3:232:20 | Store: ... = ... | test.cpp:231:18:231:30 | new[] | test.cpp:232:3:232:20 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:231:18:231:30 | new[] | new[] | test.cpp:232:11:232:15 | index | index |
|
||||
| test.cpp:239:5:239:22 | Store: ... = ... | test.cpp:238:20:238:32 | new[] | test.cpp:239:5:239:22 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:238:20:238:32 | new[] | new[] | test.cpp:239:13:239:17 | index | index |
|
||||
| test.cpp:254:9:254:16 | Store: ... = ... | test.cpp:248:24:248:30 | call to realloc | test.cpp:254:9:254:16 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:248:24:248:30 | call to realloc | call to realloc | test.cpp:254:11:254:11 | i | i |
|
||||
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
|
||||
| test.cpp:264:13:264:14 | Load: * ... | test.cpp:260:13:260:24 | new[] | test.cpp:264:13:264:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:260:13:260:24 | new[] | new[] | test.cpp:261:19:261:21 | len | len |
|
||||
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
|
||||
| test.cpp:274:5:274:10 | Store: ... = ... | test.cpp:270:13:270:24 | new[] | test.cpp:274:5:274:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:270:13:270:24 | new[] | new[] | test.cpp:271:19:271:21 | len | len |
|
||||
| test.cpp:284:13:284:14 | Load: * ... | test.cpp:280:13:280:24 | new[] | test.cpp:284:13:284:14 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:280:13:280:24 | new[] | new[] | test.cpp:281:19:281:21 | len | len |
|
||||
| test.cpp:294:5:294:10 | Store: ... = ... | test.cpp:290:13:290:24 | new[] | test.cpp:294:5:294:10 | Store: ... = ... | This write might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:290:13:290:24 | new[] | new[] | test.cpp:291:19:291:21 | len | len |
|
||||
|
||||
@@ -222,3 +222,75 @@ void test14(unsigned long n, char *p) {
|
||||
p[n - 1] = 'a'; // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void test15(unsigned index) {
|
||||
unsigned size = index + 13;
|
||||
if(size < index) {
|
||||
return;
|
||||
}
|
||||
int* newname = new int[size];
|
||||
newname[index] = 0; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test16(unsigned index) {
|
||||
unsigned size = index + 13;
|
||||
if(size >= index) {
|
||||
int* newname = new int[size];
|
||||
newname[index] = 0; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void *realloc(void *, unsigned);
|
||||
|
||||
void test17(unsigned *p, unsigned x, unsigned k) {
|
||||
if(k > 0 && p[1] <= p[0]){
|
||||
unsigned n = 3*p[0] + k;
|
||||
p = (unsigned*)realloc(p, n);
|
||||
p[0] = n;
|
||||
unsigned i = p[1];
|
||||
// The following access is okay because:
|
||||
// n = 3*p[0] + k >= p[0] + k >= p[1] + k > p[1] = i
|
||||
// (where p[0] denotes the original value for p[0])
|
||||
p[i] = x; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void test17(unsigned len)
|
||||
{
|
||||
int *xs = new int[len];
|
||||
int *end = xs + len;
|
||||
for (int *x = xs; x <= end; x++)
|
||||
{
|
||||
int i = *x; // BAD
|
||||
}
|
||||
}
|
||||
|
||||
void test18(unsigned len)
|
||||
{
|
||||
int *xs = new int[len];
|
||||
int *end = xs + len;
|
||||
for (int *x = xs; x <= end; x++)
|
||||
{
|
||||
*x = 0; // BAD
|
||||
}
|
||||
}
|
||||
|
||||
void test19(unsigned len)
|
||||
{
|
||||
int *xs = new int[len];
|
||||
int *end = xs + len;
|
||||
for (int *x = xs; x < end; x++)
|
||||
{
|
||||
int i = *x; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
void test20(unsigned len)
|
||||
{
|
||||
int *xs = new int[len];
|
||||
int *end = xs + len;
|
||||
for (int *x = xs; x < end; x++)
|
||||
{
|
||||
*x = 0; // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
| file://:0:0:0:0 | short __attribute((__may_alias__)) | type_attributes.c:25:30:25:42 | may_alias |
|
||||
| type_attributes.c:5:36:5:51 | my_packed_struct | type_attributes.c:5:23:5:32 | packed |
|
||||
| type_attributes.c:10:54:10:54 | union <unnamed> | type_attributes.c:10:30:10:50 | transparent_union |
|
||||
| type_attributes.c:16:54:16:54 | union <unnamed> | type_attributes.c:16:30:16:50 | transparent_union |
|
||||
| type_attributes.c:10:54:10:54 | (unnamed class/struct/union) | type_attributes.c:10:30:10:50 | transparent_union |
|
||||
| type_attributes.c:16:54:16:54 | (unnamed class/struct/union) | type_attributes.c:16:30:16:50 | transparent_union |
|
||||
| type_attributes.c:21:37:21:45 | unusedInt | type_attributes.c:21:24:21:29 | unused |
|
||||
| type_attributes.c:23:13:23:18 | depInt | type_attributes.c:23:36:23:45 | deprecated |
|
||||
| type_attributes_ms.cpp:1:29:1:29 | X | type_attributes_ms.cpp:1:19:1:26 | novtable |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
| (unnamed class/struct/union) |
|
||||
| float[3] |
|
||||
| float[3][3] |
|
||||
| foo[1] |
|
||||
| struct <unnamed> |
|
||||
|
||||
@@ -115,6 +115,16 @@ postWithInFlow
|
||||
| test.cpp:602:3:602:7 | access to array [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:608:3:608:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:608:4:608:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:639:3:639:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:646:3:646:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:652:3:652:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:653:3:653:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:659:3:659:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:660:3:660:3 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:671:3:671:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:681:3:681:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:689:3:689:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:690:3:690:3 | s [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
viableImplInCallContextTooLarge
|
||||
uniqueParameterNodeAtPosition
|
||||
uniqueParameterNodePosition
|
||||
|
||||
@@ -627,4 +627,66 @@ void test_def_via_phi_read(bool b)
|
||||
}
|
||||
intPointerSource(buffer);
|
||||
sink(buffer); // $ ast,ir
|
||||
}
|
||||
}
|
||||
|
||||
void test_static_local_1() {
|
||||
static int x = source();
|
||||
sink(x); // $ ast,ir
|
||||
}
|
||||
|
||||
void test_static_local_2() {
|
||||
static int x = source();
|
||||
x = 0;
|
||||
sink(x); // clean
|
||||
}
|
||||
|
||||
void test_static_local_3() {
|
||||
static int x = 0;
|
||||
sink(x); // $ ir MISSING: ast
|
||||
x = source();
|
||||
}
|
||||
|
||||
void test_static_local_4() {
|
||||
static int x = 0;
|
||||
sink(x); // clean
|
||||
x = source();
|
||||
x = 0;
|
||||
}
|
||||
|
||||
void test_static_local_5() {
|
||||
static int x = 0;
|
||||
sink(x); // $ ir MISSING: ast
|
||||
x = 0;
|
||||
x = source();
|
||||
}
|
||||
|
||||
void test_static_local_6() {
|
||||
static int s = source();
|
||||
static int* ptr_to_s = &s;
|
||||
sink(*ptr_to_s); // $ ir MISSING: ast
|
||||
}
|
||||
|
||||
void test_static_local_7() {
|
||||
static int s = source();
|
||||
s = 0;
|
||||
static int* ptr_to_s = &s;
|
||||
sink(*ptr_to_s); // clean
|
||||
}
|
||||
|
||||
void test_static_local_8() {
|
||||
static int s;
|
||||
static int* ptr_to_s = &s;
|
||||
sink(*ptr_to_s); // $ ir MISSING: ast
|
||||
|
||||
s = source();
|
||||
}
|
||||
|
||||
void test_static_local_9() {
|
||||
static int s;
|
||||
static int* ptr_to_s = &s;
|
||||
sink(*ptr_to_s); // clean
|
||||
|
||||
s = source();
|
||||
s = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -14377,6 +14377,37 @@ ir.cpp:
|
||||
# 1885| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
|
||||
# 1885| ValueCategory = lvalue
|
||||
# 1886| getStmt(2): [ReturnStmt] return ...
|
||||
# 1891| [TopLevelFunction] int test_global_template_int()
|
||||
# 1891| <params>:
|
||||
# 1891| getEntryPoint(): [BlockStmt] { ... }
|
||||
# 1892| getStmt(0): [DeclStmt] declaration
|
||||
# 1892| getDeclarationEntry(0): [VariableDeclarationEntry] definition of local_int
|
||||
# 1892| Type = [IntType] int
|
||||
# 1892| getVariable().getInitializer(): [Initializer] initializer for local_int
|
||||
# 1892| getExpr(): [VariableAccess] global_template
|
||||
# 1892| Type = [IntType] int
|
||||
# 1892| ValueCategory = prvalue(load)
|
||||
# 1893| getStmt(1): [DeclStmt] declaration
|
||||
# 1893| getDeclarationEntry(0): [VariableDeclarationEntry] definition of local_char
|
||||
# 1893| Type = [PlainCharType] char
|
||||
# 1893| getVariable().getInitializer(): [Initializer] initializer for local_char
|
||||
# 1893| getExpr(): [VariableAccess] global_template
|
||||
# 1893| Type = [PlainCharType] char
|
||||
# 1893| ValueCategory = prvalue(load)
|
||||
# 1894| getStmt(2): [ReturnStmt] return ...
|
||||
# 1894| getExpr(): [AddExpr] ... + ...
|
||||
# 1894| Type = [IntType] int
|
||||
# 1894| ValueCategory = prvalue
|
||||
# 1894| getLeftOperand(): [VariableAccess] local_int
|
||||
# 1894| Type = [IntType] int
|
||||
# 1894| ValueCategory = prvalue(load)
|
||||
# 1894| getRightOperand(): [VariableAccess] local_char
|
||||
# 1894| Type = [PlainCharType] char
|
||||
# 1894| ValueCategory = prvalue(load)
|
||||
# 1894| getRightOperand().getFullyConverted(): [CStyleCast] (int)...
|
||||
# 1894| Conversion = [IntegralConversion] integral conversion
|
||||
# 1894| Type = [IntType] int
|
||||
# 1894| ValueCategory = prvalue
|
||||
perf-regression.cpp:
|
||||
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
|
||||
# 4| <params>:
|
||||
|
||||
@@ -18,5 +18,7 @@ predicate shouldDumpFunction(Declaration decl) {
|
||||
decl instanceof Function
|
||||
or
|
||||
decl.(GlobalOrNamespaceVariable).hasInitializer()
|
||||
or
|
||||
decl.(StaticLocalVariable).hasInitializer()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1886,4 +1886,12 @@ namespace missing_declaration_entries {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T global_template = 42;
|
||||
|
||||
int test_global_template_int() {
|
||||
int local_int = global_template<int>;
|
||||
char local_char = global_template<char>;
|
||||
return local_int + (int)local_char;
|
||||
}
|
||||
|
||||
// semmle-extractor-options: -std=c++17 --clang
|
||||
|
||||
@@ -5754,6 +5754,16 @@
|
||||
| ir.cpp:1231:5:1231:19 | Load | m1237_15 |
|
||||
| ir.cpp:1231:5:1231:19 | SideEffect | ~m1237_2 |
|
||||
| ir.cpp:1231:25:1231:25 | Address | &:r1231_5 |
|
||||
| ir.cpp:1232:16:1232:16 | Address | &:r1232_3 |
|
||||
| ir.cpp:1232:16:1232:16 | SideEffect | ~m1232_6 |
|
||||
| ir.cpp:1232:20:1232:20 | ChiPartial | partial:m1232_5 |
|
||||
| ir.cpp:1232:20:1232:20 | ChiTotal | total:m1232_2 |
|
||||
| ir.cpp:1232:20:1232:20 | StoreValue | r1232_4 |
|
||||
| ir.cpp:1233:16:1233:16 | Address | &:r1233_3 |
|
||||
| ir.cpp:1233:16:1233:16 | SideEffect | ~m1233_6 |
|
||||
| ir.cpp:1233:20:1233:28 | ChiPartial | partial:m1233_5 |
|
||||
| ir.cpp:1233:20:1233:28 | ChiTotal | total:m1233_2 |
|
||||
| ir.cpp:1233:20:1233:28 | StoreValue | r1233_4 |
|
||||
| ir.cpp:1234:16:1234:16 | Address | &:r1234_1 |
|
||||
| ir.cpp:1234:16:1234:16 | Address | &:r1234_1 |
|
||||
| ir.cpp:1234:16:1234:16 | Address | &:r1234_4 |
|
||||
@@ -8741,6 +8751,38 @@
|
||||
| ir.cpp:1885:11:1885:50 | ChiPartial | partial:m1885_4 |
|
||||
| ir.cpp:1885:11:1885:50 | ChiTotal | total:m1883_4 |
|
||||
| ir.cpp:1885:11:1885:50 | SideEffect | ~m1883_4 |
|
||||
| ir.cpp:1889:24:1889:24 | Address | &:r1889_3 |
|
||||
| ir.cpp:1889:24:1889:24 | Address | &:r1889_3 |
|
||||
| ir.cpp:1889:24:1889:24 | SideEffect | ~m1889_6 |
|
||||
| ir.cpp:1889:24:1889:24 | SideEffect | ~m1889_6 |
|
||||
| ir.cpp:1889:42:1889:43 | ChiPartial | partial:m1889_5 |
|
||||
| ir.cpp:1889:42:1889:43 | ChiPartial | partial:m1889_5 |
|
||||
| ir.cpp:1889:42:1889:43 | ChiTotal | total:m1889_2 |
|
||||
| ir.cpp:1889:42:1889:43 | ChiTotal | total:m1889_2 |
|
||||
| ir.cpp:1889:42:1889:43 | StoreValue | r1889_4 |
|
||||
| ir.cpp:1889:42:1889:43 | StoreValue | r1889_4 |
|
||||
| ir.cpp:1891:5:1891:28 | Address | &:r1891_5 |
|
||||
| ir.cpp:1891:5:1891:28 | ChiPartial | partial:m1891_3 |
|
||||
| ir.cpp:1891:5:1891:28 | ChiTotal | total:m1891_2 |
|
||||
| ir.cpp:1891:5:1891:28 | Load | m1894_8 |
|
||||
| ir.cpp:1891:5:1891:28 | SideEffect | m1891_3 |
|
||||
| ir.cpp:1892:9:1892:17 | Address | &:r1892_1 |
|
||||
| ir.cpp:1892:21:1892:40 | Address | &:r1892_2 |
|
||||
| ir.cpp:1892:21:1892:40 | Load | ~m1891_3 |
|
||||
| ir.cpp:1892:21:1892:40 | StoreValue | r1892_3 |
|
||||
| ir.cpp:1893:10:1893:19 | Address | &:r1893_1 |
|
||||
| ir.cpp:1893:23:1893:43 | Address | &:r1893_2 |
|
||||
| ir.cpp:1893:23:1893:43 | Load | ~m1891_3 |
|
||||
| ir.cpp:1893:23:1893:43 | StoreValue | r1893_3 |
|
||||
| ir.cpp:1894:5:1894:39 | Address | &:r1894_1 |
|
||||
| ir.cpp:1894:12:1894:20 | Address | &:r1894_2 |
|
||||
| ir.cpp:1894:12:1894:20 | Left | r1894_3 |
|
||||
| ir.cpp:1894:12:1894:20 | Load | m1892_4 |
|
||||
| ir.cpp:1894:12:1894:38 | StoreValue | r1894_7 |
|
||||
| ir.cpp:1894:24:1894:38 | Right | r1894_6 |
|
||||
| ir.cpp:1894:29:1894:38 | Address | &:r1894_4 |
|
||||
| ir.cpp:1894:29:1894:38 | Load | m1893_4 |
|
||||
| ir.cpp:1894:29:1894:38 | Unary | r1894_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
|
||||
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |
|
||||
@@ -9030,6 +9072,34 @@
|
||||
| struct_init.cpp:20:6:20:25 | ChiPartial | partial:m20_3 |
|
||||
| struct_init.cpp:20:6:20:25 | ChiTotal | total:m20_2 |
|
||||
| struct_init.cpp:20:6:20:25 | SideEffect | ~m25_9 |
|
||||
| struct_init.cpp:21:17:21:28 | Left | r21_3 |
|
||||
| struct_init.cpp:21:17:21:28 | Left | r21_3 |
|
||||
| struct_init.cpp:21:17:21:28 | SideEffect | ~m23_10 |
|
||||
| struct_init.cpp:21:34:24:5 | Right | r21_4 |
|
||||
| struct_init.cpp:21:34:24:5 | Right | r21_6 |
|
||||
| struct_init.cpp:21:34:24:5 | Unary | r21_5 |
|
||||
| struct_init.cpp:21:34:24:5 | Unary | r21_5 |
|
||||
| struct_init.cpp:21:34:24:5 | Unary | r21_7 |
|
||||
| struct_init.cpp:21:34:24:5 | Unary | r21_7 |
|
||||
| struct_init.cpp:22:9:22:25 | Address | &:r22_1 |
|
||||
| struct_init.cpp:22:9:22:25 | Address | &:r22_6 |
|
||||
| struct_init.cpp:22:11:22:13 | ChiPartial | partial:m22_4 |
|
||||
| struct_init.cpp:22:11:22:13 | ChiTotal | total:m21_2 |
|
||||
| struct_init.cpp:22:11:22:13 | StoreValue | r22_3 |
|
||||
| struct_init.cpp:22:11:22:13 | Unary | r22_2 |
|
||||
| struct_init.cpp:22:16:22:23 | ChiPartial | partial:m22_8 |
|
||||
| struct_init.cpp:22:16:22:23 | ChiTotal | total:m22_5 |
|
||||
| struct_init.cpp:22:16:22:23 | StoreValue | r22_7 |
|
||||
| struct_init.cpp:23:9:23:26 | Address | &:r23_1 |
|
||||
| struct_init.cpp:23:9:23:26 | Address | &:r23_6 |
|
||||
| struct_init.cpp:23:11:23:13 | ChiPartial | partial:m23_4 |
|
||||
| struct_init.cpp:23:11:23:13 | ChiTotal | total:m22_9 |
|
||||
| struct_init.cpp:23:11:23:13 | StoreValue | r23_3 |
|
||||
| struct_init.cpp:23:11:23:13 | Unary | r23_2 |
|
||||
| struct_init.cpp:23:16:23:24 | ChiPartial | partial:m23_9 |
|
||||
| struct_init.cpp:23:16:23:24 | ChiTotal | total:m23_5 |
|
||||
| struct_init.cpp:23:16:23:24 | StoreValue | r23_8 |
|
||||
| struct_init.cpp:23:17:23:24 | Unary | r23_7 |
|
||||
| struct_init.cpp:25:5:25:19 | CallTarget | func:r25_1 |
|
||||
| struct_init.cpp:25:5:25:19 | ChiPartial | partial:m25_5 |
|
||||
| struct_init.cpp:25:5:25:19 | ChiTotal | total:m20_4 |
|
||||
|
||||
@@ -6841,6 +6841,28 @@ ir.cpp:
|
||||
# 1231| v1231_8(void) = AliasedUse : ~m?
|
||||
# 1231| v1231_9(void) = ExitFunction :
|
||||
|
||||
# 1232| int a
|
||||
# 1232| Block 0
|
||||
# 1232| v1232_1(void) = EnterFunction :
|
||||
# 1232| mu1232_2(unknown) = AliasedDefinition :
|
||||
# 1232| r1232_3(glval<int>) = VariableAddress[a] :
|
||||
# 1232| r1232_4(int) = Constant[0] :
|
||||
# 1232| mu1232_5(int) = Store[a] : &:r1232_3, r1232_4
|
||||
# 1232| v1232_6(void) = ReturnVoid :
|
||||
# 1232| v1232_7(void) = AliasedUse : ~m?
|
||||
# 1232| v1232_8(void) = ExitFunction :
|
||||
|
||||
# 1233| int b
|
||||
# 1233| Block 0
|
||||
# 1233| v1233_1(void) = EnterFunction :
|
||||
# 1233| mu1233_2(unknown) = AliasedDefinition :
|
||||
# 1233| r1233_3(glval<int>) = VariableAddress[b] :
|
||||
# 1233| r1233_4(int) = Constant[4] :
|
||||
# 1233| mu1233_5(int) = Store[b] : &:r1233_3, r1233_4
|
||||
# 1233| v1233_6(void) = ReturnVoid :
|
||||
# 1233| v1233_7(void) = AliasedUse : ~m?
|
||||
# 1233| v1233_8(void) = ExitFunction :
|
||||
|
||||
# 1240| void staticLocalWithConstructor(char const*)
|
||||
# 1240| Block 0
|
||||
# 1240| v1240_1(void) = EnterFunction :
|
||||
@@ -10035,6 +10057,54 @@ ir.cpp:
|
||||
# 1883| v1883_5(void) = AliasedUse : ~m?
|
||||
# 1883| v1883_6(void) = ExitFunction :
|
||||
|
||||
# 1889| char global_template<char>
|
||||
# 1889| Block 0
|
||||
# 1889| v1889_1(void) = EnterFunction :
|
||||
# 1889| mu1889_2(unknown) = AliasedDefinition :
|
||||
# 1889| r1889_3(glval<char>) = VariableAddress[global_template] :
|
||||
# 1889| r1889_4(char) = Constant[42] :
|
||||
# 1889| mu1889_5(char) = Store[global_template] : &:r1889_3, r1889_4
|
||||
# 1889| v1889_6(void) = ReturnVoid :
|
||||
# 1889| v1889_7(void) = AliasedUse : ~m?
|
||||
# 1889| v1889_8(void) = ExitFunction :
|
||||
|
||||
# 1889| int global_template<int>
|
||||
# 1889| Block 0
|
||||
# 1889| v1889_1(void) = EnterFunction :
|
||||
# 1889| mu1889_2(unknown) = AliasedDefinition :
|
||||
# 1889| r1889_3(glval<int>) = VariableAddress[global_template] :
|
||||
# 1889| r1889_4(int) = Constant[42] :
|
||||
# 1889| mu1889_5(int) = Store[global_template] : &:r1889_3, r1889_4
|
||||
# 1889| v1889_6(void) = ReturnVoid :
|
||||
# 1889| v1889_7(void) = AliasedUse : ~m?
|
||||
# 1889| v1889_8(void) = ExitFunction :
|
||||
|
||||
# 1891| int test_global_template_int()
|
||||
# 1891| Block 0
|
||||
# 1891| v1891_1(void) = EnterFunction :
|
||||
# 1891| mu1891_2(unknown) = AliasedDefinition :
|
||||
# 1891| mu1891_3(unknown) = InitializeNonLocal :
|
||||
# 1892| r1892_1(glval<int>) = VariableAddress[local_int] :
|
||||
# 1892| r1892_2(glval<int>) = VariableAddress[global_template] :
|
||||
# 1892| r1892_3(int) = Load[global_template] : &:r1892_2, ~m?
|
||||
# 1892| mu1892_4(int) = Store[local_int] : &:r1892_1, r1892_3
|
||||
# 1893| r1893_1(glval<char>) = VariableAddress[local_char] :
|
||||
# 1893| r1893_2(glval<char>) = VariableAddress[global_template] :
|
||||
# 1893| r1893_3(char) = Load[global_template] : &:r1893_2, ~m?
|
||||
# 1893| mu1893_4(char) = Store[local_char] : &:r1893_1, r1893_3
|
||||
# 1894| r1894_1(glval<int>) = VariableAddress[#return] :
|
||||
# 1894| r1894_2(glval<int>) = VariableAddress[local_int] :
|
||||
# 1894| r1894_3(int) = Load[local_int] : &:r1894_2, ~m?
|
||||
# 1894| r1894_4(glval<char>) = VariableAddress[local_char] :
|
||||
# 1894| r1894_5(char) = Load[local_char] : &:r1894_4, ~m?
|
||||
# 1894| r1894_6(int) = Convert : r1894_5
|
||||
# 1894| r1894_7(int) = Add : r1894_3, r1894_6
|
||||
# 1894| mu1894_8(int) = Store[#return] : &:r1894_1, r1894_7
|
||||
# 1891| r1891_4(glval<int>) = VariableAddress[#return] :
|
||||
# 1891| v1891_5(void) = ReturnValue : &:r1891_4, ~m?
|
||||
# 1891| v1891_6(void) = AliasedUse : ~m?
|
||||
# 1891| v1891_7(void) = ExitFunction :
|
||||
|
||||
perf-regression.cpp:
|
||||
# 6| void Big::Big()
|
||||
# 6| Block 0
|
||||
@@ -10320,6 +10390,34 @@ struct_init.cpp:
|
||||
# 20| v20_5(void) = AliasedUse : ~m?
|
||||
# 20| v20_6(void) = ExitFunction :
|
||||
|
||||
# 21| Info[] static_infos
|
||||
# 21| Block 0
|
||||
# 21| v21_1(void) = EnterFunction :
|
||||
# 21| mu21_2(unknown) = AliasedDefinition :
|
||||
# 21| r21_3(glval<Info[]>) = VariableAddress[static_infos] :
|
||||
# 21| r21_4(int) = Constant[0] :
|
||||
# 21| r21_5(glval<Info>) = PointerAdd[16] : r21_3, r21_4
|
||||
# 22| r22_1(glval<char *>) = FieldAddress[name] : r21_5
|
||||
# 22| r22_2(glval<char[2]>) = StringConstant["1"] :
|
||||
# 22| r22_3(char *) = Convert : r22_2
|
||||
# 22| mu22_4(char *) = Store[?] : &:r22_1, r22_3
|
||||
# 22| r22_5(glval<..(*)(..)>) = FieldAddress[handler] : r21_5
|
||||
# 22| r22_6(..(*)(..)) = FunctionAddress[handler1] :
|
||||
# 22| mu22_7(..(*)(..)) = Store[?] : &:r22_5, r22_6
|
||||
# 21| r21_6(int) = Constant[1] :
|
||||
# 21| r21_7(glval<Info>) = PointerAdd[16] : r21_3, r21_6
|
||||
# 23| r23_1(glval<char *>) = FieldAddress[name] : r21_7
|
||||
# 23| r23_2(glval<char[2]>) = StringConstant["2"] :
|
||||
# 23| r23_3(char *) = Convert : r23_2
|
||||
# 23| mu23_4(char *) = Store[?] : &:r23_1, r23_3
|
||||
# 23| r23_5(glval<..(*)(..)>) = FieldAddress[handler] : r21_7
|
||||
# 23| r23_6(glval<..()(..)>) = FunctionAddress[handler2] :
|
||||
# 23| r23_7(..(*)(..)) = CopyValue : r23_6
|
||||
# 23| mu23_8(..(*)(..)) = Store[?] : &:r23_5, r23_7
|
||||
# 21| v21_8(void) = ReturnVoid :
|
||||
# 21| v21_9(void) = AliasedUse : ~m?
|
||||
# 21| v21_10(void) = ExitFunction :
|
||||
|
||||
# 28| void declare_local_infos()
|
||||
# 28| Block 0
|
||||
# 28| v28_1(void) = EnterFunction :
|
||||
|
||||
@@ -3,14 +3,14 @@ import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.ModulusAnaly
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeUtils
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisSpecific
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisRelativeSpecific
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisImpl
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
|
||||
import semmle.code.cpp.ir.IR as IR
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
module ModulusAnalysisInstantiated =
|
||||
ModulusAnalysis<FloatDelta, ConstantBounds, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
ModulusAnalysis<FloatDelta, ConstantBounds, RangeUtil<FloatDelta, CppLangImplRelative>>;
|
||||
|
||||
class ModulusAnalysisTest extends InlineExpectationsTest {
|
||||
ModulusAnalysisTest() { this = "ModulusAnalysisTest" }
|
||||
|
||||
23
cpp/ql/test/library-tests/ir/range-analysis/Overflow.ql
Normal file
23
cpp/ql/test/library-tests/ir/range-analysis/Overflow.ql
Normal file
@@ -0,0 +1,23 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.rangeanalysis.new.SimpleRangeAnalysis
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class RangeAnalysisTest extends InlineExpectationsTest {
|
||||
RangeAnalysisTest() { this = "RangeAnalysisTest" }
|
||||
|
||||
override string getARelevantTag() { result = "overflow" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(Expr e |
|
||||
tag = "overflow" and
|
||||
element = e.toString() and
|
||||
location = e.getLocation() and
|
||||
value =
|
||||
strictconcat(string s |
|
||||
s = "+" and exprMightOverflowPositively(e)
|
||||
or
|
||||
s = "-" and exprMightOverflowNegatively(e)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ int test1(struct List* p) {
|
||||
int count = 0;
|
||||
for (; p; p = p->next) {
|
||||
count = count+1;
|
||||
range(count); // $ range===count:p+1 range=>=1
|
||||
range(count); // $ range===count:p+1
|
||||
}
|
||||
range(count); // $ range=>=0
|
||||
range(count);
|
||||
return count;
|
||||
}
|
||||
|
||||
@@ -40,13 +40,13 @@ int test4() {
|
||||
int total = 0;
|
||||
for (i = 0; i < 2; i = i+1) {
|
||||
range(i); // $ range=<=1 range=>=0
|
||||
range(total); // $ range=>=0
|
||||
range(total);
|
||||
total += i;
|
||||
range(total); // $ range=<=i+1 range=<=i+1 range=>=0 range=>=i+0
|
||||
range(total); // $ range=<=i+1 range=<=i+1 MISSING: range=>=0 range=>=i+0
|
||||
}
|
||||
range(total); // $ range=>=0
|
||||
range(total); // $ MISSING: range=>=0
|
||||
range(i); // $ range===2
|
||||
range(total + i); // $ range===i+2 range=>=2 range=>=i+0
|
||||
range(total + i); // $ range=<=i+2 MISSING: range===i+2 range=>=2 range=>=i+0
|
||||
return total + i;
|
||||
}
|
||||
|
||||
@@ -55,13 +55,13 @@ int test5() {
|
||||
int total = 0;
|
||||
for (i = 0; i < 2; i++) {
|
||||
range(i); // $ range=<=1 range=>=0
|
||||
range(total); // $ range=>=0
|
||||
range(total); // $ MISSING: range=>=0
|
||||
total += i;
|
||||
range(total); // $ range=<=i+1 range=>=0 range=>=i+0
|
||||
range(total); // $ range=<=i+1 MISSING: range=>=0 range=>=i+0
|
||||
}
|
||||
range(total); // $ range=>=0
|
||||
range(total); // $ MISSING: range=>=0
|
||||
range(i); // $ range===2
|
||||
range(total + i); // $ range===i+2 range=>=2 range=>=i+0
|
||||
range(total + i); // $ range=<=i+2 MISSING: range===i+2 range=>=2 range=>=i+0
|
||||
return total + i;
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ int test6() {
|
||||
int total = 0;
|
||||
for (i = 0; i+2 < 4; i = i+1) {
|
||||
range(i); // $ range=<=1 range=>=0
|
||||
range(total); // $ range=>=0
|
||||
range(total); // $ MISSING: range=>=0
|
||||
total += i;
|
||||
range(total); // $ range=<=i+1 range=>=0 range=>=i+0
|
||||
range(total); // $ range=<=i+1 MISSING: range=>=0 range=>=i+0
|
||||
}
|
||||
return total + i;
|
||||
}
|
||||
@@ -168,19 +168,19 @@ typedef unsigned long long size_type;
|
||||
|
||||
size_type test12_helper() {
|
||||
static size_type n = 0;
|
||||
return n++;
|
||||
return n++; // $ overflow=+
|
||||
}
|
||||
|
||||
int test12() {
|
||||
size_type Start = 0;
|
||||
while (Start <= test12_helper()-1)
|
||||
{
|
||||
range(Start);
|
||||
range(Start); // $ MISSING:range=>=0
|
||||
const size_type Length = test12_helper();
|
||||
Start += Length + 1;
|
||||
range(Start);
|
||||
Start += Length + 1; // $ overflow=+
|
||||
range(Start); // $ MISSING:range=>=1 MISSING:range=>=Start+1 MISSING:range=">=call to test12_helper+1"
|
||||
}
|
||||
range(Start);
|
||||
range(Start); // $ MISSING:range=>=0
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -190,13 +190,13 @@ int test13(char c, int i) {
|
||||
unsigned char uc = c;
|
||||
range(uc);
|
||||
unsigned int x = 0;
|
||||
unsigned int y = x-1;
|
||||
range(y); // $ range===-1
|
||||
int z = i+1;
|
||||
unsigned int y = x-1; // $ overflow=-
|
||||
range(y); // $ range===-1 overflow=-
|
||||
int z = i+1; // $ overflow=+
|
||||
range(z); // $ range===i+1
|
||||
range(c + i + uc + x + y + z);
|
||||
range((double)(c + i + uc + x + y + z));
|
||||
return (double)(c + i + uc + x + y + z);
|
||||
range(c + i + uc + x + y + z); // $ overflow=+- overflow=+ overflow=- MISSING: range=>=1
|
||||
range((double)(c + i + uc + x + y + z)); // $ overflow=+ overflow=+- overflow=- MISSING: range=>=1
|
||||
return (double)(c + i + uc + x + y + z); // $ overflow=+- overflow=+ overflow=-
|
||||
}
|
||||
|
||||
// Regression test for ODASA-6013.
|
||||
@@ -213,8 +213,8 @@ int test14(int x) {
|
||||
range(c0);
|
||||
unsigned short s0 = x;
|
||||
range(s0);
|
||||
range(x0 + x1 + x2 + x3 + c0 + s0);
|
||||
return x0 + x1 + x2 + x3 + c0 + s0;
|
||||
range(x0 + x1 + x2 + x3 + c0 + s0); // $ overflow=+ overflow=+-
|
||||
return x0 + x1 + x2 + x3 + c0 + s0; // $ overflow=+ overflow=+-
|
||||
}
|
||||
|
||||
long long test15(long long x) {
|
||||
@@ -243,7 +243,7 @@ int test_unary(int a) {
|
||||
range(b); // $ range=<=11 range=>=0
|
||||
int c = -a;
|
||||
range(c); // $ range=<=0 range=>=-11
|
||||
range(b+c); // $ range=<=11 range=>=-11
|
||||
range(b+c); // $ range=<=11 range=>=-11 MISSING:range=">=- ...+0"
|
||||
total += b+c;
|
||||
range(total); // $ range=<=0+11 range=<=19 range=>=0-11 range=>=-19
|
||||
}
|
||||
@@ -273,7 +273,7 @@ int test_unary(int a) {
|
||||
range(b); // $ range=<=0 range=>=-7
|
||||
int c = -a;
|
||||
range(c); // $ range=<=7 range=>=0
|
||||
range(b+c); // $ range=>=-7 range=<=7
|
||||
range(b+c); // $ range=>=-7 range=<=7 MISSING:range="<=- ...+0"
|
||||
total += b+c;
|
||||
range(total); // $ range="<=- ...+7" range="<=- ...+15" range="<=- ...+33" range=">=- ...-7" range=">=- ...-15" range=">=- ...-33" range=<=0+44 range=<=52 range=>=0-44 range=>=-52
|
||||
}
|
||||
@@ -315,9 +315,9 @@ int test_mult01(int a, int b) {
|
||||
if (3 <= a && a <= 11 && -13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=3
|
||||
range(b); // $ range=<=23 range=>=-13
|
||||
int r = a*b; // -143 .. 253
|
||||
int r = a*b; // $ overflow=+- -143 .. 253
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+
|
||||
range(total); // $ MISSING: range=">=... * ...+0"
|
||||
}
|
||||
if (3 <= a && a <= 11 && -13 <= b && b <= 0) {
|
||||
@@ -326,7 +326,7 @@ int test_mult01(int a, int b) {
|
||||
int r = a*b; // -143 .. 0
|
||||
range(r); // $ range=<=0 range=>=-143
|
||||
total += r;
|
||||
range(total); // $ range=<=3+0 range=>=3-143
|
||||
range(total); // $ range=>=3-143
|
||||
}
|
||||
if (3 <= a && a <= 11 && -13 <= b && b <= -7) {
|
||||
range(a); // $ range=<=11 range=>=3
|
||||
@@ -334,9 +334,9 @@ int test_mult01(int a, int b) {
|
||||
int r = a*b; // -143 .. -21
|
||||
range(r); // $ range=<=-21 range=>=-143
|
||||
total += r;
|
||||
range(total); // $ range=<=3-21 range=>=3-143 range=>=3-286
|
||||
range(total); // $ range=>=3-143 range=>=3-286
|
||||
}
|
||||
range(total); // $ range=<=3+0 range=>=3-143 range=>=3-286
|
||||
range(total); // $ range=>=3-143 range=>=3-286
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -363,9 +363,9 @@ int test_mult02(int a, int b) {
|
||||
if (0 <= a && a <= 11 && -13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=0
|
||||
range(b); // $ range=<=23 range=>=-13
|
||||
int r = a*b; // -143 .. 253
|
||||
int r = a*b; // $ overflow=+- -143 .. 253
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+
|
||||
range(total); // $ MISSING: range=">=... * ...+0"
|
||||
}
|
||||
if (0 <= a && a <= 11 && -13 <= b && b <= 0) {
|
||||
@@ -374,7 +374,7 @@ int test_mult02(int a, int b) {
|
||||
int r = a*b; // -143 .. 0
|
||||
range(r); // $ range=<=0 range=>=-143
|
||||
total += r;
|
||||
range(total); // $ range=<=0+0 range=>=0-143
|
||||
range(total); // $ range=>=0-143
|
||||
}
|
||||
if (0 <= a && a <= 11 && -13 <= b && b <= -7) {
|
||||
range(a); // $ range=<=11 range=>=0
|
||||
@@ -382,9 +382,9 @@ int test_mult02(int a, int b) {
|
||||
int r = a*b; // -143 .. 0
|
||||
range(r); // $ range=<=0 range=>=-143
|
||||
total += r;
|
||||
range(total); // $ range=<=0+0 range=>=0-143 range=>=0-286
|
||||
range(total); // $ range=>=0-143 range=>=0-286
|
||||
}
|
||||
range(total); // $ range=<=0+0 range=>=0-143 range=>=0-286
|
||||
range(total); // $range=>=0-143 range=>=0-286
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ int test_mult03(int a, int b) {
|
||||
if (-17 <= a && a <= 11 && 5 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=-17
|
||||
range(b); // $ range=<=23 range=>=5
|
||||
int r = a*b; // -391 .. 253
|
||||
int r = a*b; // $ overflow=+- -391 .. 253
|
||||
range(r);
|
||||
total += r;
|
||||
range(total);
|
||||
@@ -403,33 +403,33 @@ int test_mult03(int a, int b) {
|
||||
if (-17 <= a && a <= 11 && 0 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=-17
|
||||
range(b); // $ range=<=23 range=>=0
|
||||
int r = a*b; // -391 .. 253
|
||||
int r = a*b; // $ overflow=+- -391 .. 253
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+-
|
||||
range(total);
|
||||
}
|
||||
if (-17 <= a && a <= 11 && -13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=-17
|
||||
range(b); // $ range=<=23 range=>=-13
|
||||
int r = a*b; // -391 .. 253
|
||||
int r = a*b; // $ overflow=+- -391 .. 25
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+-
|
||||
range(total);
|
||||
}
|
||||
if (-17 <= a && a <= 11 && -13 <= b && b <= 0) {
|
||||
range(a); // $ range=<=11 range=>=-17
|
||||
range(b); // $ range=<=0 range=>=-13
|
||||
int r = a*b; // -143 .. 221
|
||||
int r = a*b; // $ overflow=+- -143 .. 221
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+-
|
||||
range(total);
|
||||
}
|
||||
if (-17 <= a && a <= 11 && -13 <= b && b <= -7) {
|
||||
range(a); // $ range=<=11 range=>=-17
|
||||
range(b); // $ range=<=-7 range=>=-13
|
||||
int r = a*b; // -143 .. 221
|
||||
int r = a*b; // $ overflow=+- -143 .. 221
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=+-
|
||||
range(total);
|
||||
}
|
||||
range(total);
|
||||
@@ -458,9 +458,9 @@ int test_mult04(int a, int b) {
|
||||
if (-17 <= a && a <= 0 && -13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=0 range=>=-17
|
||||
range(b); // $ range=<=23 range=>=-13
|
||||
int r = a*b; // -391 .. 221
|
||||
int r = a*b; // $ overflow=+- -391 .. 221
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=-
|
||||
range(total); // $ MISSING: range="<=... * ...+0"
|
||||
}
|
||||
if (-17 <= a && a <= 0 && -13 <= b && b <= 0) {
|
||||
@@ -469,7 +469,7 @@ int test_mult04(int a, int b) {
|
||||
int r = a*b; // 0 .. 221
|
||||
range(r); // $ range=<=221 range=>=0
|
||||
total += r;
|
||||
range(total); // $ range="<=- ...+221" range=">=- ...+0"
|
||||
range(total); // $ range="<=- ...+221"
|
||||
}
|
||||
if (-17 <= a && a <= 0 && -13 <= b && b <= -7) {
|
||||
range(a); // $ range=<=0 range=>=-17
|
||||
@@ -477,9 +477,9 @@ int test_mult04(int a, int b) {
|
||||
int r = a*b; // 0 .. 221
|
||||
range(r); // $ range=<=221 range=>=0
|
||||
total += r;
|
||||
range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442"
|
||||
range(total); // $ range="<=- ...+221" range="<=- ...+442"
|
||||
}
|
||||
range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442"
|
||||
range(total); // $ range="<=- ...+221" range="<=- ...+442"
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -506,9 +506,9 @@ int test_mult05(int a, int b) {
|
||||
if (-17 <= a && a <= -2 && -13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=-2 range=>=-17
|
||||
range(b); // $ range=<=23 range=>=-13
|
||||
int r = a*b; // -391 .. 221
|
||||
int r = a*b; // $ overflow=+- -391 .. 221
|
||||
range(r);
|
||||
total += r;
|
||||
total += r; // $ overflow=-
|
||||
range(total); // $ MISSING: range="<=... * ...+0"
|
||||
}
|
||||
if (-17 <= a && a <= -2 && -13 <= b && b <= 0) {
|
||||
@@ -517,7 +517,7 @@ int test_mult05(int a, int b) {
|
||||
int r = a*b; // 0 .. 221
|
||||
range(r); // $ range=<=221 range=>=0
|
||||
total += r;
|
||||
range(total); // $ range="<=- ...+221" range=">=- ...+0"
|
||||
range(total); // $ range="<=- ...+221"
|
||||
}
|
||||
if (-17 <= a && a <= -2 && -13 <= b && b <= -7) {
|
||||
range(a); // $ range=<=-2 range=>=-17
|
||||
@@ -525,9 +525,9 @@ int test_mult05(int a, int b) {
|
||||
int r = a*b; // 14 .. 221
|
||||
range(r); // $ range=<=221 range=>=14
|
||||
total += r;
|
||||
range(total); // $ range="<=- ...+221" range="<=- ...+442" range=">=- ...+14"
|
||||
range(total); // $ range="<=- ...+221" range="<=- ...+442"
|
||||
}
|
||||
range(total); // $ range=">=- ...+0" range="<=- ...+221" range="<=- ...+442"
|
||||
range(total); // $ range="<=- ...+221" range="<=- ...+442"
|
||||
return total;
|
||||
}
|
||||
|
||||
@@ -541,7 +541,7 @@ int test16(int x) {
|
||||
while (i < 3) {
|
||||
range(i); // $ range=<=2 range=>=0
|
||||
i++;
|
||||
range(i); // $ range="==... = ...:i+1" range=<=3 range=>=1
|
||||
range(i); // $ range=<=3 range=>=1 range="==... = ...:i+1" SPURIOUS:range="==... = ...:i+1"
|
||||
}
|
||||
range(d);
|
||||
d = i;
|
||||
@@ -586,7 +586,7 @@ unsigned int test_ternary01(unsigned int x) {
|
||||
(range(x), 500);
|
||||
range(y4); // $ range=<=500
|
||||
y5 = (x+1) ?:
|
||||
(range(x), 500); // $ range===-1
|
||||
(range(x), 500); // $ overflow=- range===-1
|
||||
range(y5); // $ range=<=500
|
||||
y6 = ((unsigned char)(x+1)) ?:
|
||||
(range(x), 5); // $ range=<=299
|
||||
@@ -598,8 +598,8 @@ unsigned int test_ternary01(unsigned int x) {
|
||||
(range(x), 500); // $ range=<=299
|
||||
range(y8); // y8 <= 300
|
||||
}
|
||||
range(y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8); // $ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0"
|
||||
return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8;
|
||||
range(y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8); // $ overflow=+ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0"
|
||||
return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8; // $ overflow=+
|
||||
}
|
||||
|
||||
// Test ternary expression lower bounds.
|
||||
@@ -628,8 +628,8 @@ unsigned int test_ternary02(unsigned int x) {
|
||||
(range(x), 5); // $ range=>=300
|
||||
range(y5); // y6 >= 0
|
||||
}
|
||||
range(y1 + y2 + y3 + y4 + y5); // $ range=">=call to range+207" MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0"
|
||||
return y1 + y2 + y3 + y4 + y5;
|
||||
range(y1 + y2 + y3 + y4 + y5); // $ overflow=+ MISSING: range=">=call to range+207" range=">=... = ...:... ? ... : ...+0" range=">=call to range+0"
|
||||
return y1 + y2 + y3 + y4 + y5; // $ overflow=+
|
||||
}
|
||||
|
||||
// Test the comma expression.
|
||||
@@ -691,9 +691,9 @@ int test_unsigned_mult01(unsigned int a, unsigned b) {
|
||||
range(a); // $ range=<=11 range=>=3
|
||||
range(b); // $ range=<=23 range=>=0
|
||||
int r = a*b; // 0 .. 253
|
||||
range(r); // $ range=>=0 range=<=253
|
||||
range(r);// $ range=>=0 range=<=253
|
||||
total += r;
|
||||
range(total); // $ range=>=0 range=<=506 range=">=(unsigned int)...+0" range="<=(unsigned int)...+253"
|
||||
range(total); // $ range=">=(unsigned int)...+0" range=>=0 range=<=506 range="<=(unsigned int)...+253"
|
||||
}
|
||||
if (3 <= a && a <= 11 && 13 <= b && b <= 23) {
|
||||
range(a); // $ range=<=11 range=>=3
|
||||
@@ -701,7 +701,7 @@ int test_unsigned_mult01(unsigned int a, unsigned b) {
|
||||
int r = a*b; // 39 .. 253
|
||||
range(r); // $ range=>=39 range=<=253
|
||||
total += r;
|
||||
range(total); // $ range=>=39 range=<=759 range=">=(unsigned int)...+39" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253"
|
||||
range(total); // $ range=>=39 range=<=759 range="<=(unsigned int)...+253" range="<=(unsigned int)...+506" range=">=(unsigned int)...+39"
|
||||
}
|
||||
range(total); // $ range=>=0 range=<=759 range=">=(unsigned int)...+0" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253"
|
||||
return total;
|
||||
@@ -722,14 +722,14 @@ int test_unsigned_mult02(unsigned b) {
|
||||
int r = 11*b; // 0 .. 253
|
||||
range(r); // $ range=>=0 range=<=253
|
||||
total += r;
|
||||
range(total); // $ range=>=0 range=<=506 range=">=(unsigned int)...+0" range="<=(unsigned int)...+253"
|
||||
range(total); // $ range=">=(unsigned int)...+0" range=>=0 range="<=(unsigned int)...+253" range=<=506
|
||||
}
|
||||
if (13 <= b && b <= 23) {
|
||||
range(b); // $ range=<=23 range=>=13
|
||||
int r = 11*b; // 143 .. 253
|
||||
range(r); // $ range=>=143 range=<=253
|
||||
total += r;
|
||||
range(total); // $ range=>=143 range=<=759 range=">=(unsigned int)...+143" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253"
|
||||
range(total); // $ range="<=(unsigned int)...+253" range="<=(unsigned int)...+506" range=">=(unsigned int)...+143" range=>=143 range=<=759
|
||||
}
|
||||
range(total); // $ range=>=0 range=<=759 range=">=(unsigned int)...+0" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253"
|
||||
return total;
|
||||
@@ -751,7 +751,7 @@ unsigned long mult_overflow() {
|
||||
range(x); // $ range===274177
|
||||
y = 67280421310721UL;
|
||||
range(y);
|
||||
xy = x * y;
|
||||
xy = x * y; // $ overflow=+-
|
||||
range(xy);
|
||||
return xy; // BUG: upper bound should be >= 18446744073709551617UL
|
||||
}
|
||||
@@ -760,14 +760,14 @@ unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
|
||||
if (ui >= 10) {
|
||||
range(ui); // $ range=>=10
|
||||
range((unsigned long)ui); // $ range=>=10
|
||||
unsigned long result = (unsigned long)ui * ui;
|
||||
range(result); // $ range=>=100 range=>=100
|
||||
unsigned long result = (unsigned long)ui * ui; // $ overflow=+
|
||||
range(result); // $ MISSING: range=>=100
|
||||
return result; // BUG: upper bound should be >= 18446744065119617025
|
||||
}
|
||||
if (ul >= 10) {
|
||||
range(ul); // $ range=>=10
|
||||
unsigned long result = ul * ul;
|
||||
range(result); // $ range=>=100
|
||||
unsigned long result = ul * ul; // $ overflow=+
|
||||
range(result); // $ MISSING: range=>=100
|
||||
return result; // BUG: lower bound should be 0 (overflow is possible)
|
||||
}
|
||||
return 0;
|
||||
@@ -800,13 +800,13 @@ int mul_by_constant(int i, int j) {
|
||||
i = 5 * i;
|
||||
range(i); // $ range=<=10 range=>=-5
|
||||
|
||||
i = i * -3;
|
||||
i = i * -3; // $ overflow=+-
|
||||
range(i); // -30 .. 15
|
||||
|
||||
i *= 7;
|
||||
i *= 7; // $ overflow=+-
|
||||
range(i); // -210 .. 105
|
||||
|
||||
i *= -11;
|
||||
i *= -11; // $ overflow=+-
|
||||
range(i); // -1155 .. 2310
|
||||
}
|
||||
if (i == -1) {
|
||||
@@ -815,7 +815,7 @@ int mul_by_constant(int i, int j) {
|
||||
i = i * (int)0xffFFffFF; // fully converted literal is -1
|
||||
range(i); // $ range===1
|
||||
}
|
||||
i = i * -1;
|
||||
i = i * -1; // $ overflow=+-
|
||||
range( i); // -2^31 .. 2^31-1
|
||||
|
||||
signed char sc = 1;
|
||||
@@ -873,11 +873,11 @@ void notequal_refinement(short n) {
|
||||
}
|
||||
|
||||
while (n != 0) {
|
||||
range(n); // $ range=<=n+0
|
||||
range(n); // $ MISSING:range=<=n+0
|
||||
n--; // 1 ..
|
||||
}
|
||||
|
||||
range(n); // $ range=<=n+0 // 0 .. 0
|
||||
range(n); // $ MISSING:range=<=n+0 // 0 .. 0
|
||||
}
|
||||
|
||||
void notequal_variations(short n, float f) {
|
||||
@@ -888,7 +888,7 @@ void notequal_variations(short n, float f) {
|
||||
}
|
||||
|
||||
if (n >= 5) {
|
||||
if (2 * n - 10 == 0) { // Same as `n == 10/2` (modulo overflow)
|
||||
if (2 * n - 10 == 0) { // $ overflow=+
|
||||
range(n); // $ range=>=5 MISSING: range===5
|
||||
return;
|
||||
}
|
||||
@@ -921,7 +921,7 @@ void two_bounds_from_one_test(short ss, unsigned short us) {
|
||||
}
|
||||
|
||||
if (ss < 0x8001) { // Lower bound removed in `getDefLowerBounds`
|
||||
range(ss); // $ range=<=32768 MISSING: range=>=-32768
|
||||
range(ss); // $ overflow=+ range=<=32768 MISSING: range=>=-32768
|
||||
}
|
||||
|
||||
if ((short)us >= 0) {
|
||||
@@ -936,7 +936,7 @@ void two_bounds_from_one_test(short ss, unsigned short us) {
|
||||
range(ss); // -32768 .. 32767
|
||||
}
|
||||
|
||||
if (ss + 1 < sizeof(int)) {
|
||||
if (ss + 1 < sizeof(int)) { // $ overflow=+
|
||||
range(ss); // -1 .. 2
|
||||
}
|
||||
}
|
||||
@@ -1020,7 +1020,7 @@ void test_overflow() {
|
||||
|
||||
void test_negate_unsigned(unsigned u) {
|
||||
if(10 < u && u < 20) {
|
||||
range<unsigned>(-u); // underflows
|
||||
range<unsigned>(-u); // $ overflow=-
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,17 +6,17 @@
|
||||
return x;
|
||||
}
|
||||
|
||||
if (y - 2 == x && y > 300) {
|
||||
if (y - 2 == x && y > 300) { // $ overflow=-
|
||||
range(x + y); // $ range=<=802 range=>=600
|
||||
return x + y;
|
||||
}
|
||||
|
||||
if (x != y + 1) {
|
||||
if (x != y + 1) { // $ overflow=+
|
||||
range(x); // $ range=<=400
|
||||
int sum = x + y;
|
||||
int sum = x + y; // $ overflow=+-
|
||||
} else {
|
||||
if (y > 300) {
|
||||
range(x); // $ range=>=302 range=<=400 range===y+1
|
||||
range(x); // $ range=>=302 range=<=400 range=<=y+1 MISSING: range===y+1
|
||||
range(y); // $ range=>=301 range=<=399 range===x-1
|
||||
int sum = x + y;
|
||||
}
|
||||
@@ -38,10 +38,10 @@
|
||||
return x;
|
||||
}
|
||||
|
||||
if (y == x - 1 && y > 300 && y + 2 == z && z == 350) {
|
||||
if (y == x - 1 && y > 300 && y + 2 == z && z == 350) { // $ overflow=+ overflow=-
|
||||
range(x); // $ range===349 range===y+1 range===z-1
|
||||
range(y); // $ range===348 range===x-1 range===z-2
|
||||
range(z); // $ range===350 range===x+1 range===y+2
|
||||
range(y); // $ range===348 range=>=x-1 range===z-2 MISSING: range===x-1
|
||||
range(z); // $ range===350 range=<=y+2 MISSING: range===x+1 range===y+2
|
||||
return x + y + z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.SignAnalysis
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeUtils
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisSpecific
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisRelativeSpecific
|
||||
import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific
|
||||
import semmle.code.cpp.ir.IR as IR
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
module SignAnalysisInstantiated = SignAnalysis<FloatDelta, RangeUtil<FloatDelta, CppLangImpl>>;
|
||||
module SignAnalysisInstantiated =
|
||||
SignAnalysis<FloatDelta, RangeUtil<FloatDelta, CppLangImplRelative>>;
|
||||
|
||||
class SignAnalysisTest extends InlineExpectationsTest {
|
||||
SignAnalysisTest() { this = "SignAnalysisTest" }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
| a1.c:6:16:6:16 | struct <unnamed> | 0 members | 2 locations | -1 | <none> |
|
||||
| a1.c:10:16:10:16 | struct <unnamed> | 1 members | 2 locations | 0 | x |
|
||||
| a1.c:17:16:17:16 | struct <unnamed> | 1 members | 2 locations | 0 | x |
|
||||
| a1.c:6:16:6:16 | (unnamed class/struct/union) | 0 members | 2 locations | -1 | <none> |
|
||||
| a1.c:10:16:10:16 | (unnamed class/struct/union) | 1 members | 2 locations | 0 | x |
|
||||
| a1.c:17:16:17:16 | (unnamed class/struct/union) | 1 members | 2 locations | 0 | x |
|
||||
| a1.c:24:8:24:10 | Foo | 3 members | 2 locations | 0 | empty |
|
||||
| a1.c:24:8:24:10 | Foo | 3 members | 2 locations | 1 | nonempty |
|
||||
| a1.c:24:8:24:10 | Foo | 3 members | 2 locations | 2 | i |
|
||||
@@ -9,9 +9,9 @@
|
||||
| a1.c:36:8:36:10 | Bar | 3 members | 2 locations | 0 | empty |
|
||||
| a1.c:36:8:36:10 | Bar | 3 members | 2 locations | 1 | nonempty |
|
||||
| a1.c:36:8:36:10 | Bar | 3 members | 2 locations | 2 | i |
|
||||
| a2.c:6:16:6:16 | struct <unnamed> | 0 members | 2 locations | -1 | <none> |
|
||||
| a2.c:10:16:10:16 | struct <unnamed> | 1 members | 2 locations | 0 | x |
|
||||
| a2.c:17:16:17:16 | struct <unnamed> | 1 members | 2 locations | 0 | x |
|
||||
| a2.c:6:16:6:16 | (unnamed class/struct/union) | 0 members | 2 locations | -1 | <none> |
|
||||
| a2.c:10:16:10:16 | (unnamed class/struct/union) | 1 members | 2 locations | 0 | x |
|
||||
| a2.c:17:16:17:16 | (unnamed class/struct/union) | 1 members | 2 locations | 0 | x |
|
||||
| a2.c:24:8:24:10 | Foo | 3 members | 2 locations | 0 | empty |
|
||||
| a2.c:24:8:24:10 | Foo | 3 members | 2 locations | 1 | nonempty |
|
||||
| a2.c:24:8:24:10 | Foo | 3 members | 2 locations | 2 | i |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
| a1.c:10:16:10:16 | struct <unnamed> | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a1.c:17:16:17:16 | struct <unnamed> | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a1.c:10:16:10:16 | (unnamed class/struct/union) | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a1.c:17:16:17:16 | (unnamed class/struct/union) | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a1.c:24:8:24:10 | Foo | 0 | file://:0:0:0:0 | anon_empty_t * | 1 types |
|
||||
| a1.c:24:8:24:10 | Foo | 1 | file://:0:0:0:0 | anon_nonempty_t * | 1 types |
|
||||
| a1.c:24:8:24:10 | Foo | 2 | file://:0:0:0:0 | int | 1 types |
|
||||
@@ -7,8 +7,8 @@
|
||||
| a1.c:36:8:36:10 | Bar | 0 | file://:0:0:0:0 | Empty * | 1 types |
|
||||
| a1.c:36:8:36:10 | Bar | 1 | file://:0:0:0:0 | NonEmpty * | 1 types |
|
||||
| a1.c:36:8:36:10 | Bar | 2 | file://:0:0:0:0 | int | 1 types |
|
||||
| a2.c:10:16:10:16 | struct <unnamed> | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a2.c:17:16:17:16 | struct <unnamed> | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a2.c:10:16:10:16 | (unnamed class/struct/union) | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a2.c:17:16:17:16 | (unnamed class/struct/union) | 0 | file://:0:0:0:0 | int | 1 types |
|
||||
| a2.c:24:8:24:10 | Foo | 0 | file://:0:0:0:0 | anon_empty_t * | 1 types |
|
||||
| a2.c:24:8:24:10 | Foo | 1 | file://:0:0:0:0 | anon_nonempty_t * | 1 types |
|
||||
| a2.c:24:8:24:10 | Foo | 2 | file://:0:0:0:0 | int | 1 types |
|
||||
|
||||
@@ -4,7 +4,9 @@ uniqueType
|
||||
uniqueNodeLocation
|
||||
missingLocation
|
||||
uniqueNodeToString
|
||||
| cpp11.cpp:50:15:50:16 | (no string representation) | Node should have one toString but has 0. |
|
||||
missingToString
|
||||
| Nodes without toString: 1 |
|
||||
parameterCallable
|
||||
localFlowIsLocal
|
||||
readStepIsLocal
|
||||
|
||||
@@ -233,3 +233,14 @@ void f_if_ternary_1(int b, int x, int y) {
|
||||
if (b ? x : y) {
|
||||
}
|
||||
}
|
||||
|
||||
struct _A
|
||||
{
|
||||
unsigned int x;
|
||||
const char *y;
|
||||
} as[];
|
||||
|
||||
void regression_test(void)
|
||||
{
|
||||
static const void *a[] = {0 ? 0 : as};
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<queries language="cpp"/>
|
||||
@@ -0,0 +1,96 @@
|
||||
edges
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a |
|
||||
| test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a |
|
||||
| test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a |
|
||||
| test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a |
|
||||
| test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a |
|
||||
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
|
||||
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
|
||||
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
|
||||
| test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a |
|
||||
nodes
|
||||
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
|
||||
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
|
||||
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
|
||||
| test_free.cpp:14:10:14:10 | a | semmle.label | a |
|
||||
| test_free.cpp:30:10:30:10 | a | semmle.label | a |
|
||||
| test_free.cpp:31:27:31:27 | a | semmle.label | a |
|
||||
| test_free.cpp:35:10:35:10 | a | semmle.label | a |
|
||||
| test_free.cpp:37:27:37:27 | a | semmle.label | a |
|
||||
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
|
||||
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
|
||||
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
|
||||
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
|
||||
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
|
||||
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
|
||||
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
|
||||
| test_free.cpp:46:10:46:10 | a | semmle.label | a |
|
||||
| test_free.cpp:50:27:50:27 | a | semmle.label | a |
|
||||
| test_free.cpp:51:10:51:10 | a | semmle.label | a |
|
||||
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
|
||||
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
|
||||
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
|
||||
| test_free.cpp:72:14:72:14 | a | semmle.label | a |
|
||||
| test_free.cpp:101:10:101:10 | a | semmle.label | a |
|
||||
| test_free.cpp:103:10:103:10 | a | semmle.label | a |
|
||||
| test_free.cpp:128:10:128:11 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:129:10:129:11 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
|
||||
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
|
||||
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
|
||||
| test_free.cpp:154:10:154:10 | a | semmle.label | a |
|
||||
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
|
||||
| test_free.cpp:207:10:207:10 | a | semmle.label | a |
|
||||
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
|
||||
| test_free.cpp:209:10:209:10 | a | semmle.label | a |
|
||||
subpaths
|
||||
#select
|
||||
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:14:10:14:10 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:14:10:14:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:31:27:31:27 | a | test_free.cpp:30:10:30:10 | a | test_free.cpp:31:27:31:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:30:5:30:8 | call to free | call to free |
|
||||
| test_free.cpp:37:27:37:27 | a | test_free.cpp:35:10:35:10 | a | test_free.cpp:37:27:37:27 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:35:5:35:8 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:46:10:46:10 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:46:10:46:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:51:10:51:10 | a | test_free.cpp:50:27:50:27 | a | test_free.cpp:51:10:51:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:50:22:50:25 | call to free | call to free |
|
||||
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:72:14:72:14 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:72:14:72:14 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:103:10:103:10 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:103:10:103:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
|
||||
| test_free.cpp:129:10:129:11 | * ... | test_free.cpp:128:10:128:11 | * ... | test_free.cpp:129:10:129:11 | * ... | Memory pointed to by '* ...' may already have been freed by $@. | test_free.cpp:128:5:128:8 | call to free | call to free |
|
||||
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:154:10:154:10 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:154:10:154:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
|
||||
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
|
||||
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
|
||||
| test_free.cpp:209:10:209:10 | a | test_free.cpp:207:10:207:10 | a | test_free.cpp:209:10:209:10 | a | Memory pointed to by 'a' may already have been freed by $@. | test_free.cpp:207:5:207:8 | call to free | call to free |
|
||||
@@ -0,0 +1 @@
|
||||
Critical/DoubleFree.ql
|
||||
@@ -26,6 +26,72 @@
|
||||
| test.cpp:128:15:128:16 | v4 |
|
||||
| test.cpp:185:10:185:12 | cpy |
|
||||
| test.cpp:199:10:199:12 | cpy |
|
||||
| test_free.cpp:11:10:11:10 | a |
|
||||
| test_free.cpp:14:10:14:10 | a |
|
||||
| test_free.cpp:16:10:16:10 | a |
|
||||
| test_free.cpp:18:18:18:18 | a |
|
||||
| test_free.cpp:23:10:23:10 | a |
|
||||
| test_free.cpp:25:10:25:10 | a |
|
||||
| test_free.cpp:26:10:26:10 | b |
|
||||
| test_free.cpp:30:10:30:10 | a |
|
||||
| test_free.cpp:31:27:31:27 | a |
|
||||
| test_free.cpp:35:10:35:10 | a |
|
||||
| test_free.cpp:37:27:37:27 | a |
|
||||
| test_free.cpp:42:27:42:27 | a |
|
||||
| test_free.cpp:44:27:44:27 | a |
|
||||
| test_free.cpp:46:10:46:10 | a |
|
||||
| test_free.cpp:50:27:50:27 | a |
|
||||
| test_free.cpp:51:10:51:10 | a |
|
||||
| test_free.cpp:55:27:55:27 | a |
|
||||
| test_free.cpp:57:10:57:10 | a |
|
||||
| test_free.cpp:61:10:61:10 | a |
|
||||
| test_free.cpp:63:10:63:10 | b |
|
||||
| test_free.cpp:69:10:69:10 | a |
|
||||
| test_free.cpp:72:14:72:14 | a |
|
||||
| test_free.cpp:83:12:83:12 | a |
|
||||
| test_free.cpp:85:12:85:12 | a |
|
||||
| test_free.cpp:90:10:90:10 | a |
|
||||
| test_free.cpp:95:10:95:10 | a |
|
||||
| test_free.cpp:101:10:101:10 | a |
|
||||
| test_free.cpp:102:23:102:23 | a |
|
||||
| test_free.cpp:103:10:103:10 | a |
|
||||
| test_free.cpp:104:10:104:10 | b |
|
||||
| test_free.cpp:107:23:107:23 | a |
|
||||
| test_free.cpp:112:14:112:14 | a |
|
||||
| test_free.cpp:114:10:114:10 | b |
|
||||
| test_free.cpp:118:23:118:23 | a |
|
||||
| test_free.cpp:119:17:119:17 | b |
|
||||
| test_free.cpp:121:14:121:14 | a |
|
||||
| test_free.cpp:126:10:126:11 | * ... |
|
||||
| test_free.cpp:128:10:128:11 | * ... |
|
||||
| test_free.cpp:129:10:129:11 | * ... |
|
||||
| test_free.cpp:131:10:131:13 | access to array |
|
||||
| test_free.cpp:132:10:132:13 | access to array |
|
||||
| test_free.cpp:143:27:143:30 | data |
|
||||
| test_free.cpp:145:14:145:22 | * ... |
|
||||
| test_free.cpp:148:10:148:17 | list_ptr |
|
||||
| test_free.cpp:152:27:152:27 | a |
|
||||
| test_free.cpp:154:10:154:10 | a |
|
||||
| test_free.cpp:159:14:159:15 | * ... |
|
||||
| test_free.cpp:162:10:162:10 | a |
|
||||
| test_free.cpp:167:23:167:23 | a |
|
||||
| test_free.cpp:173:10:173:10 | a |
|
||||
| test_free.cpp:181:10:181:10 | a |
|
||||
| test_free.cpp:183:10:183:10 | a |
|
||||
| test_free.cpp:185:10:185:10 | a |
|
||||
| test_free.cpp:188:10:188:10 | a |
|
||||
| test_free.cpp:193:20:193:20 | a |
|
||||
| test_free.cpp:199:20:199:20 | a |
|
||||
| test_free.cpp:205:10:205:10 | a |
|
||||
| test_free.cpp:207:10:207:10 | a |
|
||||
| test_free.cpp:209:10:209:10 | a |
|
||||
| test_free.cpp:213:10:213:10 | a |
|
||||
| test_free.cpp:216:10:216:10 | a |
|
||||
| test_free.cpp:220:10:220:10 | a |
|
||||
| test_free.cpp:227:24:227:45 | memory_descriptor_list |
|
||||
| test_free.cpp:233:14:233:15 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... |
|
||||
| test_free.cpp:245:10:245:11 | * ... |
|
||||
| virtual.cpp:18:10:18:10 | a |
|
||||
| virtual.cpp:19:10:19:10 | c |
|
||||
| virtual.cpp:38:10:38:10 | b |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| test_free.cpp:36:22:36:35 | ... = ... | This memory allocation may not be released at $@. | test_free.cpp:38:1:38:1 | return ... | this exit point |
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
| test.cpp:156:3:156:26 | new | This memory is never freed. |
|
||||
| test.cpp:157:3:157:26 | new[] | This memory is never freed. |
|
||||
| test.cpp:169:14:169:19 | call to strdup | This memory is never freed. |
|
||||
| test_free.cpp:167:15:167:21 | call to realloc | This memory is never freed. |
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
edges
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a |
|
||||
| test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a |
|
||||
| test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a |
|
||||
| test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
|
||||
| test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a |
|
||||
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
|
||||
| test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a |
|
||||
| test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a |
|
||||
| test_free.cpp:101:10:101:10 | a | test_free.cpp:102:23:102:23 | a |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a |
|
||||
| test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a |
|
||||
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
|
||||
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
|
||||
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
|
||||
| test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:10:241:10 | b |
|
||||
| test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:10:241:10 | b |
|
||||
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
|
||||
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
|
||||
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
|
||||
| test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... |
|
||||
nodes
|
||||
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
|
||||
| test_free.cpp:11:10:11:10 | a | semmle.label | a |
|
||||
| test_free.cpp:12:5:12:5 | a | semmle.label | a |
|
||||
| test_free.cpp:13:6:13:6 | a | semmle.label | a |
|
||||
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
|
||||
| test_free.cpp:42:27:42:27 | a | semmle.label | a |
|
||||
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
|
||||
| test_free.cpp:44:27:44:27 | a | semmle.label | a |
|
||||
| test_free.cpp:45:5:45:5 | a | semmle.label | a |
|
||||
| test_free.cpp:45:5:45:5 | a | semmle.label | a |
|
||||
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
|
||||
| test_free.cpp:69:10:69:10 | a | semmle.label | a |
|
||||
| test_free.cpp:71:9:71:9 | a | semmle.label | a |
|
||||
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
|
||||
| test_free.cpp:90:10:90:10 | a | semmle.label | a |
|
||||
| test_free.cpp:91:5:91:5 | a | semmle.label | a |
|
||||
| test_free.cpp:95:10:95:10 | a | semmle.label | a |
|
||||
| test_free.cpp:96:9:96:9 | a | semmle.label | a |
|
||||
| test_free.cpp:101:10:101:10 | a | semmle.label | a |
|
||||
| test_free.cpp:102:23:102:23 | a | semmle.label | a |
|
||||
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
|
||||
| test_free.cpp:152:27:152:27 | a | semmle.label | a |
|
||||
| test_free.cpp:153:5:153:5 | a | semmle.label | a |
|
||||
| test_free.cpp:233:14:233:15 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:233:14:233:15 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:236:9:236:10 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:236:9:236:10 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:239:14:239:15 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:241:9:241:10 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:241:9:241:10 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:241:10:241:10 | b | semmle.label | b |
|
||||
| test_free.cpp:245:10:245:11 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:245:10:245:11 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
|
||||
| test_free.cpp:246:9:246:10 | * ... | semmle.label | * ... |
|
||||
subpaths
|
||||
#select
|
||||
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:12:5:12:5 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:12:5:12:5 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:13:6:13:6 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:13:6:13:6 | a | test_free.cpp:11:10:11:10 | a | test_free.cpp:13:6:13:6 | a | Memory may have been previously freed by $@. | test_free.cpp:11:5:11:8 | call to free | call to free |
|
||||
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:45:5:45:5 | a | test_free.cpp:42:27:42:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:42:22:42:25 | call to free | call to free |
|
||||
| test_free.cpp:45:5:45:5 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:45:5:45:5 | a | test_free.cpp:44:27:44:27 | a | test_free.cpp:45:5:45:5 | a | Memory may have been previously freed by $@. | test_free.cpp:44:22:44:25 | call to free | call to free |
|
||||
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:71:9:71:9 | a | test_free.cpp:69:10:69:10 | a | test_free.cpp:71:9:71:9 | a | Memory may have been previously freed by $@. | test_free.cpp:69:5:69:8 | call to free | call to free |
|
||||
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
|
||||
| test_free.cpp:91:5:91:5 | a | test_free.cpp:90:10:90:10 | a | test_free.cpp:91:5:91:5 | a | Memory may have been previously freed by $@. | test_free.cpp:90:5:90:8 | call to free | call to free |
|
||||
| test_free.cpp:96:9:96:9 | a | test_free.cpp:95:10:95:10 | a | test_free.cpp:96:9:96:9 | a | Memory may have been previously freed by $@. | test_free.cpp:95:5:95:8 | call to free | call to free |
|
||||
| test_free.cpp:102:23:102:23 | a | test_free.cpp:101:10:101:10 | a | test_free.cpp:102:23:102:23 | a | Memory may have been previously freed by $@. | test_free.cpp:101:5:101:8 | call to free | call to free |
|
||||
| test_free.cpp:153:5:153:5 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a | Memory may have been previously freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:153:5:153:5 | a | test_free.cpp:152:27:152:27 | a | test_free.cpp:153:5:153:5 | a | Memory may have been previously freed by $@. | test_free.cpp:152:22:152:25 | call to free | call to free |
|
||||
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
|
||||
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
|
||||
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
|
||||
| test_free.cpp:236:9:236:10 | * ... | test_free.cpp:233:14:233:15 | * ... | test_free.cpp:236:9:236:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:233:9:233:12 | call to free | call to free |
|
||||
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:241:9:241:10 | * ... | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:9:241:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:241:10:241:10 | b | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:10:241:10 | b | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:241:10:241:10 | b | test_free.cpp:239:14:239:15 | * ... | test_free.cpp:241:10:241:10 | b | Memory may have been previously freed by $@. | test_free.cpp:239:9:239:12 | call to free | call to free |
|
||||
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
|
||||
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
|
||||
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
|
||||
| test_free.cpp:246:9:246:10 | * ... | test_free.cpp:245:10:245:11 | * ... | test_free.cpp:246:9:246:10 | * ... | Memory may have been previously freed by $@. | test_free.cpp:245:5:245:8 | call to free | call to free |
|
||||
@@ -0,0 +1 @@
|
||||
Critical/UseAfterFree.ql
|
||||
247
cpp/ql/test/query-tests/Critical/MemoryFreed/test_free.cpp
Normal file
247
cpp/ql/test/query-tests/Critical/MemoryFreed/test_free.cpp
Normal file
@@ -0,0 +1,247 @@
|
||||
void *malloc(int);
|
||||
void free(void *);
|
||||
bool condition();
|
||||
void use(void*);
|
||||
void *realloc(void*, unsigned long);
|
||||
int strlen(char*);
|
||||
int asprintf(char ** strp, const char * fmt, ...);
|
||||
|
||||
|
||||
void* test_double_free1(int *a) {
|
||||
free(a); // GOOD
|
||||
a[5] = 5; // BAD
|
||||
*a = 5; // BAD
|
||||
free(a); // BAD
|
||||
a = (int*) malloc(8);
|
||||
free(a); // GOOD
|
||||
a = (int*) malloc(8);
|
||||
if (!a) free(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void test_double_free_aliasing(void *a, void* b) {
|
||||
free(a); // GOOD
|
||||
a = b;
|
||||
free(a); // GOOD
|
||||
free(b); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_dominance1(void *a) {
|
||||
free(a);
|
||||
if (condition()) free(a); // BAD
|
||||
}
|
||||
|
||||
void test_dominance2(void *a) {
|
||||
free(a);
|
||||
if (condition()) a = malloc(10);
|
||||
if (condition()) free(a); // BAD
|
||||
}
|
||||
|
||||
void test_post_dominance1(int *a)
|
||||
{
|
||||
if (condition()) free(a);
|
||||
if (condition()) a[2] = 5; // BAD [NOT DETECTED]
|
||||
if (condition()) free(a); // BAD [NOT DETECTED]
|
||||
a[2] = 5; // BAD
|
||||
free(a); // BAD
|
||||
}
|
||||
|
||||
void test_post_dominance2(void *a) {
|
||||
if (condition()) free(a);
|
||||
free(a); // BAD
|
||||
}
|
||||
|
||||
void test_post_dominance3(void *a) {
|
||||
if (condition()) free(a);
|
||||
a = malloc(10);
|
||||
free(a); // GOOD
|
||||
}
|
||||
|
||||
void test_use_after_free6(int *a, int *b) {
|
||||
free(a);
|
||||
a=b;
|
||||
free(b);
|
||||
if (condition()) a[0] = 5; // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_use_after_free7(int *a) {
|
||||
a[0] = 42;
|
||||
free(a);
|
||||
|
||||
if (a[3]) { // BAD
|
||||
free(a); // BAD
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
public:
|
||||
void f();
|
||||
};
|
||||
|
||||
void test_new1() {
|
||||
A *a = new A();
|
||||
delete(a);
|
||||
a->f(); // BAD [NOT DETECTED]
|
||||
delete(a); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test_dereference1(A *a) {
|
||||
a->f(); // GOOD
|
||||
free(a);
|
||||
a->f(); // BAD
|
||||
}
|
||||
|
||||
void* use_after_free(void *a) {
|
||||
free(a);
|
||||
use(a); // BAD
|
||||
return a; // BAD
|
||||
}
|
||||
|
||||
void test_realloc1(void *a) {
|
||||
free(a);
|
||||
void *b = realloc(a, sizeof(a)*3); // BAD [NOT DETECTED by cpp/double-free]
|
||||
free(a); // BAD
|
||||
free(b); // GOOD
|
||||
}
|
||||
void* test_realloc2(char *a) {
|
||||
void *b = realloc(a, strlen(a)+3); // GOOD
|
||||
|
||||
// From the man page on return values from realloc and reallocarray:
|
||||
// "If these functions fail, the original block is left untouched; it is not freed or moved."
|
||||
if (!b) {
|
||||
free(a); // GOOD
|
||||
}
|
||||
free(b); // GOOD
|
||||
}
|
||||
|
||||
void test_realloc3(void *a) {
|
||||
void *b = realloc(a, 100);
|
||||
if (b) free(b); // GOOD
|
||||
if (!b) {
|
||||
free(a); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void test_ptr_deref(void ** a) {
|
||||
free(*a);
|
||||
*a = malloc(10);
|
||||
free(*a); // GOOD
|
||||
free(*a); // BAD [NOT DETECTED]
|
||||
*a = malloc(10);
|
||||
free(a[0]); // GOOD
|
||||
free(a[1]); // GOOD
|
||||
}
|
||||
|
||||
struct list {
|
||||
struct list *next;
|
||||
void* data;
|
||||
};
|
||||
|
||||
void test_loop1(struct list ** list_ptr) {
|
||||
struct list *next;
|
||||
while (*list_ptr) { // GOOD
|
||||
free((*list_ptr)->data); // GOOD
|
||||
next = (*list_ptr)->next; // GOOD
|
||||
free(*list_ptr); // GOOD
|
||||
*list_ptr = next; // GOOD
|
||||
}
|
||||
free(list_ptr); // GOOD
|
||||
}
|
||||
|
||||
void test_use_after_free8(struct list * a) {
|
||||
if (condition()) free(a);
|
||||
a->data = malloc(10); // BAD
|
||||
free(a); // BAD
|
||||
}
|
||||
|
||||
void test_loop2(char ** a) {
|
||||
while (*a) { // GOOD
|
||||
free(*a); // GOOD
|
||||
a++;
|
||||
}
|
||||
free(a); // GOOD
|
||||
}
|
||||
|
||||
void* test_realloc4() {
|
||||
void *a = 0;
|
||||
void *b = realloc(a, 10); // BAD for cpp/memory-never-freed
|
||||
if (!b) { return a; }
|
||||
return b;
|
||||
}
|
||||
|
||||
void test_sizeof(int *a) {
|
||||
free(a);
|
||||
int x = sizeof(a[0]); // GOOD
|
||||
}
|
||||
|
||||
void call_by_reference(char * &a);
|
||||
int custom_alloc_func(char ** a);
|
||||
|
||||
void test_reassign(char *a) {
|
||||
free(a); // GOOD
|
||||
asprintf(&a, "Hello world"); // GOOD
|
||||
free(a); //GOOD
|
||||
call_by_reference(a); // GOOD
|
||||
free(a); // GOOD
|
||||
int v;
|
||||
if (v = custom_alloc_func(&a)) return;
|
||||
free(a); // GOOD
|
||||
}
|
||||
|
||||
char* test_return1(char *a) {
|
||||
int ret = condition();
|
||||
if (!ret) free(a);
|
||||
return (ret ? a : 0);
|
||||
}
|
||||
|
||||
char* test_return2(char *a) {
|
||||
int ret = condition();
|
||||
if (!ret) free(a);
|
||||
if (ret) return a;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
void test_condition1(char *a) {
|
||||
free(a);
|
||||
if (asprintf(&a, "Hello world") || condition());
|
||||
free(a); //GOOD
|
||||
if (condition() || asprintf(&a, "Hello world"));
|
||||
free(a); // BAD
|
||||
}
|
||||
|
||||
void test_condition2(char *a) {
|
||||
free(a);
|
||||
if (condition()) a = (char*) malloc(10);
|
||||
else custom_alloc_func(&a);
|
||||
free(a); // GOOD
|
||||
}
|
||||
|
||||
void* test_return1(void *a) {
|
||||
free(a);
|
||||
return a;
|
||||
}
|
||||
|
||||
void MmFreePagesFromMdl(void*);
|
||||
void ExFreePool(void*);
|
||||
void test_ms_free(void * memory_descriptor_list) {
|
||||
MmFreePagesFromMdl(memory_descriptor_list); //GOOD
|
||||
ExFreePool(memory_descriptor_list); // GOOD
|
||||
}
|
||||
|
||||
void test_loop3(char ** a, char ** b) {
|
||||
if (*a) {
|
||||
free(*a);
|
||||
a++;
|
||||
}
|
||||
use(*a); // GOOD [FALSE POSITIVE]
|
||||
|
||||
for (;*b; b++) {
|
||||
free(*b);
|
||||
}
|
||||
use(*b); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test_deref(char **a) {
|
||||
free(*a);
|
||||
use(*a); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
| test.cpp:35:7:35:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:34:3:34:7 | call to scanf | call to scanf |
|
||||
| test.cpp:51:7:51:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:50:3:50:7 | call to scanf | call to scanf |
|
||||
| test.cpp:68:7:68:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:67:3:67:7 | call to scanf | call to scanf |
|
||||
| test.cpp:80:7:80:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:79:3:79:7 | call to scanf | call to scanf |
|
||||
| test.cpp:90:8:90:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:89:3:89:7 | call to scanf | call to scanf |
|
||||
| test.cpp:98:8:98:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:97:3:97:7 | call to scanf | call to scanf |
|
||||
| test.cpp:90:7:90:8 | * ... | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:89:3:89:7 | call to scanf | call to scanf |
|
||||
| test.cpp:98:7:98:8 | * ... | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:97:3:97:7 | call to scanf | call to scanf |
|
||||
| test.cpp:108:7:108:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:107:3:107:8 | call to fscanf | call to fscanf |
|
||||
| test.cpp:115:7:115:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:114:3:114:8 | call to sscanf | call to sscanf |
|
||||
| test.cpp:164:8:164:8 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:162:7:162:11 | call to scanf | call to scanf |
|
||||
@@ -12,13 +11,9 @@
|
||||
| test.cpp:224:8:224:8 | j | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:221:7:221:11 | call to scanf | call to scanf |
|
||||
| test.cpp:248:9:248:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:246:25:246:29 | call to scanf | call to scanf |
|
||||
| test.cpp:252:9:252:9 | d | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 2. | test.cpp:250:14:250:18 | call to scanf | call to scanf |
|
||||
| test.cpp:264:7:264:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:263:3:263:7 | call to scanf | call to scanf |
|
||||
| test.cpp:272:7:272:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:271:3:271:7 | call to scanf | call to scanf |
|
||||
| test.cpp:280:7:280:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:279:3:279:7 | call to scanf | call to scanf |
|
||||
| test.cpp:292:7:292:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:291:3:291:7 | call to scanf | call to scanf |
|
||||
| test.cpp:302:8:302:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:301:3:301:7 | call to scanf | call to scanf |
|
||||
| test.cpp:310:7:310:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:309:3:309:7 | call to scanf | call to scanf |
|
||||
| test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf |
|
||||
| test.cpp:416:7:416:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:413:7:413:11 | call to scanf | call to scanf |
|
||||
| test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf |
|
||||
| test.cpp:430:6:430:6 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:429:2:429:6 | call to scanf | call to scanf |
|
||||
|
||||
@@ -48,7 +48,7 @@ int main()
|
||||
int i = 0;
|
||||
|
||||
scanf("%d", &i);
|
||||
use(i); // BAD. Design choice: already initialized variables shouldn't make a difference.
|
||||
use(i); // GOOD. Design choice: already initialized variables are fine.
|
||||
}
|
||||
|
||||
{
|
||||
@@ -261,7 +261,7 @@ int main()
|
||||
i = 0;
|
||||
|
||||
scanf("%d", &i);
|
||||
use(i); // BAD
|
||||
use(i); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
@@ -269,7 +269,7 @@ int main()
|
||||
|
||||
set_by_ref(i);
|
||||
scanf("%d", &i);
|
||||
use(i); // BAD
|
||||
use(i); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
{
|
||||
@@ -277,7 +277,7 @@ int main()
|
||||
|
||||
set_by_ptr(&i);
|
||||
scanf("%d", &i);
|
||||
use(i); // BAD
|
||||
use(i); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
{
|
||||
@@ -299,7 +299,7 @@ int main()
|
||||
int *ptr_i = &i;
|
||||
|
||||
scanf("%d", &i);
|
||||
use(*ptr_i); // BAD: may not have written `i`
|
||||
use(*ptr_i); // BAD [NOT DETECTED]: may not have written `i`
|
||||
}
|
||||
|
||||
{
|
||||
@@ -307,7 +307,7 @@ int main()
|
||||
int *ptr_i = &i;
|
||||
|
||||
scanf("%d", ptr_i);
|
||||
use(i); // BAD: may not have written `*ptr_i`
|
||||
use(i); // BAD [NOT DETECTED]: may not have written `*ptr_i`
|
||||
}
|
||||
|
||||
{
|
||||
@@ -427,5 +427,5 @@ void scan_and_write() {
|
||||
void scan_and_static_variable() {
|
||||
static int i;
|
||||
scanf("%d", &i);
|
||||
use(i); // GOOD [FALSE POSITIVE]: static variables are always 0-initialized
|
||||
use(i); // GOOD: static variables are always 0-initialized
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
| nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. |
|
||||
| nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
|
||||
| nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:51:10:51:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:57:12:57:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:60:12:60:21 | call to const_wash | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
| test.cpp:61:12:61:26 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. |
|
||||
|
||||
@@ -48,7 +48,7 @@ int main(int argc, char **argv) {
|
||||
printf(choose_message(argc - 1), argc - 1); // GOOD
|
||||
printf(messages[1]); // GOOD
|
||||
printf(message); // GOOD
|
||||
printf(make_message(argc - 1)); // BAD [NOT DETECTED]
|
||||
printf(make_message(argc - 1)); // BAD
|
||||
printf("Hello, World\n"); // GOOD
|
||||
printf(_("Hello, World\n")); // GOOD
|
||||
{
|
||||
|
||||
@@ -1,9 +1,74 @@
|
||||
| test.cpp:36:6:36:9 | data | Memory pointed to by 'data' may have $@. | test.cpp:35:2:35:5 | call to free | been previously freed |
|
||||
| test.cpp:70:7:70:10 | data | Memory pointed to by 'data' may have $@. | test.cpp:67:2:67:5 | call to free | been previously freed |
|
||||
| test.cpp:107:6:107:9 | data | Memory pointed to by 'data' may have $@. | test.cpp:105:2:105:5 | call to free | been previously freed |
|
||||
| test.cpp:117:6:117:9 | data | Memory pointed to by 'data' may have $@. | test.cpp:115:2:115:5 | call to free | been previously freed |
|
||||
| test.cpp:150:2:150:2 | c | Memory pointed to by 'c' may have $@. | test.cpp:149:2:149:10 | delete | been previously freed |
|
||||
| test.cpp:151:4:151:4 | c | Memory pointed to by 'c' may have $@. | test.cpp:149:2:149:10 | delete | been previously freed |
|
||||
| test.cpp:170:6:170:9 | data | Memory pointed to by 'data' may have $@. | test.cpp:165:2:165:5 | call to free | been previously freed |
|
||||
| test.cpp:193:6:193:9 | data | Memory pointed to by 'data' may have $@. | test.cpp:191:3:191:6 | call to free | been previously freed |
|
||||
| test.cpp:201:6:201:6 | x | Memory pointed to by 'x' may have $@. | test.cpp:200:2:200:9 | delete | been previously freed |
|
||||
edges
|
||||
| test.cpp:39:7:39:10 | data | test.cpp:41:6:41:9 | data |
|
||||
| test.cpp:39:7:39:10 | data | test.cpp:41:6:41:9 | data |
|
||||
| test.cpp:75:7:75:10 | data | test.cpp:79:7:79:10 | data |
|
||||
| test.cpp:75:7:75:10 | data | test.cpp:79:7:79:10 | data |
|
||||
| test.cpp:106:7:106:10 | data | test.cpp:108:6:108:9 | data |
|
||||
| test.cpp:106:7:106:10 | data | test.cpp:108:6:108:9 | data |
|
||||
| test.cpp:116:7:116:10 | data | test.cpp:119:6:119:9 | data |
|
||||
| test.cpp:116:7:116:10 | data | test.cpp:119:6:119:9 | data |
|
||||
| test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data |
|
||||
| test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data |
|
||||
| test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data |
|
||||
| test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data |
|
||||
| test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data |
|
||||
| test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data |
|
||||
| test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data |
|
||||
| test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data |
|
||||
| test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data |
|
||||
| test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data |
|
||||
| test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data |
|
||||
| test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data |
|
||||
nodes
|
||||
| test.cpp:39:7:39:10 | data | semmle.label | data |
|
||||
| test.cpp:39:7:39:10 | data | semmle.label | data |
|
||||
| test.cpp:41:6:41:9 | data | semmle.label | data |
|
||||
| test.cpp:75:7:75:10 | data | semmle.label | data |
|
||||
| test.cpp:75:7:75:10 | data | semmle.label | data |
|
||||
| test.cpp:79:7:79:10 | data | semmle.label | data |
|
||||
| test.cpp:106:7:106:10 | data | semmle.label | data |
|
||||
| test.cpp:106:7:106:10 | data | semmle.label | data |
|
||||
| test.cpp:108:6:108:9 | data | semmle.label | data |
|
||||
| test.cpp:116:7:116:10 | data | semmle.label | data |
|
||||
| test.cpp:116:7:116:10 | data | semmle.label | data |
|
||||
| test.cpp:119:6:119:9 | data | semmle.label | data |
|
||||
| test.cpp:127:7:127:10 | data | semmle.label | data |
|
||||
| test.cpp:127:7:127:10 | data | semmle.label | data |
|
||||
| test.cpp:130:6:130:9 | data | semmle.label | data |
|
||||
| test.cpp:138:7:138:10 | data | semmle.label | data |
|
||||
| test.cpp:138:7:138:10 | data | semmle.label | data |
|
||||
| test.cpp:141:6:141:9 | data | semmle.label | data |
|
||||
| test.cpp:181:7:181:10 | data | semmle.label | data |
|
||||
| test.cpp:181:7:181:10 | data | semmle.label | data |
|
||||
| test.cpp:186:6:186:9 | data | semmle.label | data |
|
||||
| test.cpp:192:7:192:10 | data | semmle.label | data |
|
||||
| test.cpp:192:7:192:10 | data | semmle.label | data |
|
||||
| test.cpp:197:6:197:9 | data | semmle.label | data |
|
||||
| test.cpp:203:7:203:10 | data | semmle.label | data |
|
||||
| test.cpp:203:7:203:10 | data | semmle.label | data |
|
||||
| test.cpp:207:8:207:11 | data | semmle.label | data |
|
||||
| test.cpp:207:8:207:11 | data | semmle.label | data |
|
||||
| test.cpp:209:6:209:9 | data | semmle.label | data |
|
||||
| test.cpp:209:6:209:9 | data | semmle.label | data |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:41:6:41:9 | data | test.cpp:39:7:39:10 | data | test.cpp:41:6:41:9 | data | Memory may have been previously freed by $@. | test.cpp:39:2:39:5 | call to free | call to free |
|
||||
| test.cpp:41:6:41:9 | data | test.cpp:39:7:39:10 | data | test.cpp:41:6:41:9 | data | Memory may have been previously freed by $@. | test.cpp:39:2:39:5 | call to free | call to free |
|
||||
| test.cpp:79:7:79:10 | data | test.cpp:75:7:75:10 | data | test.cpp:79:7:79:10 | data | Memory may have been previously freed by $@. | test.cpp:75:2:75:5 | call to free | call to free |
|
||||
| test.cpp:79:7:79:10 | data | test.cpp:75:7:75:10 | data | test.cpp:79:7:79:10 | data | Memory may have been previously freed by $@. | test.cpp:75:2:75:5 | call to free | call to free |
|
||||
| test.cpp:108:6:108:9 | data | test.cpp:106:7:106:10 | data | test.cpp:108:6:108:9 | data | Memory may have been previously freed by $@. | test.cpp:106:2:106:5 | call to free | call to free |
|
||||
| test.cpp:108:6:108:9 | data | test.cpp:106:7:106:10 | data | test.cpp:108:6:108:9 | data | Memory may have been previously freed by $@. | test.cpp:106:2:106:5 | call to free | call to free |
|
||||
| test.cpp:119:6:119:9 | data | test.cpp:116:7:116:10 | data | test.cpp:119:6:119:9 | data | Memory may have been previously freed by $@. | test.cpp:116:2:116:5 | call to free | call to free |
|
||||
| test.cpp:119:6:119:9 | data | test.cpp:116:7:116:10 | data | test.cpp:119:6:119:9 | data | Memory may have been previously freed by $@. | test.cpp:116:2:116:5 | call to free | call to free |
|
||||
| test.cpp:130:6:130:9 | data | test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data | Memory may have been previously freed by $@. | test.cpp:127:2:127:5 | call to free | call to free |
|
||||
| test.cpp:130:6:130:9 | data | test.cpp:127:7:127:10 | data | test.cpp:130:6:130:9 | data | Memory may have been previously freed by $@. | test.cpp:127:2:127:5 | call to free | call to free |
|
||||
| test.cpp:141:6:141:9 | data | test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data | Memory may have been previously freed by $@. | test.cpp:138:2:138:5 | call to free | call to free |
|
||||
| test.cpp:141:6:141:9 | data | test.cpp:138:7:138:10 | data | test.cpp:141:6:141:9 | data | Memory may have been previously freed by $@. | test.cpp:138:2:138:5 | call to free | call to free |
|
||||
| test.cpp:186:6:186:9 | data | test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data | Memory may have been previously freed by $@. | test.cpp:181:2:181:5 | call to free | call to free |
|
||||
| test.cpp:186:6:186:9 | data | test.cpp:181:7:181:10 | data | test.cpp:186:6:186:9 | data | Memory may have been previously freed by $@. | test.cpp:181:2:181:5 | call to free | call to free |
|
||||
| test.cpp:197:6:197:9 | data | test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data | Memory may have been previously freed by $@. | test.cpp:192:2:192:5 | call to free | call to free |
|
||||
| test.cpp:197:6:197:9 | data | test.cpp:192:7:192:10 | data | test.cpp:197:6:197:9 | data | Memory may have been previously freed by $@. | test.cpp:192:2:192:5 | call to free | call to free |
|
||||
| test.cpp:209:6:209:9 | data | test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:203:2:203:5 | call to free | call to free |
|
||||
| test.cpp:209:6:209:9 | data | test.cpp:203:7:203:10 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:203:2:203:5 | call to free | call to free |
|
||||
| test.cpp:209:6:209:9 | data | test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:207:3:207:6 | call to free | call to free |
|
||||
| test.cpp:209:6:209:9 | data | test.cpp:207:8:207:11 | data | test.cpp:209:6:209:9 | data | Memory may have been previously freed by $@. | test.cpp:207:3:207:6 | call to free | call to free |
|
||||
|
||||
@@ -6,14 +6,18 @@ typedef unsigned long size_t;
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
|
||||
void useExternal(char* data);
|
||||
void useExternal(...);
|
||||
|
||||
void use(char* data)
|
||||
void use_if_nonzero(char* data)
|
||||
{
|
||||
if (data)
|
||||
useExternal(data);
|
||||
}
|
||||
|
||||
void use(char* data) {
|
||||
useExternal(*data);
|
||||
}
|
||||
|
||||
[[noreturn]]
|
||||
void noReturn();
|
||||
|
||||
@@ -31,8 +35,9 @@ void test1()
|
||||
{
|
||||
char* data;
|
||||
data = (char *)malloc(100*sizeof(char));
|
||||
use(data); // GOOD
|
||||
use_if_nonzero(data); // GOOD
|
||||
free(data);
|
||||
use_if_nonzero(data); // BAD [NOT DETECTED]
|
||||
use(data); // BAD
|
||||
}
|
||||
|
||||
@@ -42,9 +47,11 @@ void test2()
|
||||
data = (char *)malloc(100*sizeof(char));
|
||||
free(data);
|
||||
myMalloc(&data);
|
||||
use_if_nonzero(data); // GOOD
|
||||
use(data); // GOOD
|
||||
free(data);
|
||||
myMalloc2(data);
|
||||
use_if_nonzero(data); // GOOD
|
||||
use(data); // GOOD
|
||||
}
|
||||
|
||||
@@ -56,6 +63,7 @@ void test3()
|
||||
data = NULL;
|
||||
if (data)
|
||||
{
|
||||
use_if_nonzero(data); // GOOD
|
||||
use(data); // GOOD
|
||||
}
|
||||
}
|
||||
@@ -67,6 +75,7 @@ void test4()
|
||||
free(data);
|
||||
if (data)
|
||||
{
|
||||
use_if_nonzero(data); // BAD [NOT DETECTED]
|
||||
use(data); // BAD
|
||||
}
|
||||
}
|
||||
@@ -85,7 +94,8 @@ char* returnsFreedData(int i)
|
||||
void test5()
|
||||
{
|
||||
char* data = returnsFreedData(1);
|
||||
use(data); // BAD (NOT REPORTED)
|
||||
use_if_nonzero(data); // BAD [NOT DETECTED]
|
||||
use(data); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test6()
|
||||
@@ -94,7 +104,8 @@ void test6()
|
||||
data = (char *)malloc(100*sizeof(char));
|
||||
data2 = data;
|
||||
free(data);
|
||||
use(data2); // BAD (NOT REPORTED)
|
||||
use_if_nonzero(data2); // BAD [NOT DETECTED]
|
||||
use(data); // BAD
|
||||
}
|
||||
|
||||
void test7()
|
||||
@@ -104,6 +115,7 @@ void test7()
|
||||
data2 = data;
|
||||
free(data);
|
||||
data2 = NULL;
|
||||
use_if_nonzero(data); // BAD [NOT DETECTED]
|
||||
use(data); // BAD
|
||||
}
|
||||
|
||||
@@ -114,6 +126,7 @@ void test8()
|
||||
data = data2;
|
||||
free(data);
|
||||
data2 = NULL;
|
||||
use_if_nonzero(data); // BAD [NOT DETECTED]
|
||||
use(data); // BAD
|
||||
}
|
||||
|
||||
@@ -124,13 +137,15 @@ void test9()
|
||||
char *data, *data2;
|
||||
free(data);
|
||||
noReturnWrapper();
|
||||
use(data); // GOOD
|
||||
use_if_nonzero(data); // GOOD
|
||||
use(data); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test10()
|
||||
{
|
||||
for (char *data; true; data = NULL)
|
||||
{
|
||||
use_if_nonzero(data); // GOOD
|
||||
use(data); // GOOD
|
||||
free(data);
|
||||
}
|
||||
@@ -140,7 +155,7 @@ class myClass
|
||||
{
|
||||
public:
|
||||
myClass() { }
|
||||
|
||||
|
||||
void myMethod() { }
|
||||
};
|
||||
|
||||
@@ -156,7 +171,8 @@ template<class T> T test()
|
||||
T* x;
|
||||
use(x); // GOOD
|
||||
delete x;
|
||||
use(x); // BAD
|
||||
use_if_nonzero(x); // BAD [NOT DETECTED]
|
||||
use(x); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
void test12(int count)
|
||||
@@ -178,7 +194,7 @@ void test13()
|
||||
{
|
||||
data = NULL;
|
||||
}
|
||||
use(data); // GOOD
|
||||
use(data); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
|
||||
void test14()
|
||||
@@ -198,7 +214,7 @@ template<class T> T test15()
|
||||
T* x;
|
||||
use(x); // GOOD
|
||||
delete x;
|
||||
use(x); // BAD
|
||||
use(x); // BAD [NOT DETECTED]
|
||||
}
|
||||
void test15runner(void)
|
||||
{
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:local,source:remote,summary:taint,summary:value
|
||||
Dapper,55,,,,,,,,,,55,,,,,,
|
||||
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,7,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,
|
||||
Microsoft.CSharp,,,24,,,,,,,,,,,,,24,
|
||||
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,
|
||||
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,15,
|
||||
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,45,1
|
||||
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,80,3
|
||||
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,62,
|
||||
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,12,
|
||||
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,16,
|
||||
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,13,2
|
||||
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,16,1
|
||||
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,10,
|
||||
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,37,
|
||||
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,8,
|
||||
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,63,
|
||||
Microsoft.Interop,,,27,,,,,,,,,,,,,27,
|
||||
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,1,
|
||||
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,4,
|
||||
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,5,5
|
||||
Microsoft.Win32,,,8,,,,,,,,,,,,,8,
|
||||
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,
|
||||
Newtonsoft.Json,,,91,,,,,,,,,,,,,73,18
|
||||
ServiceStack,194,,7,27,,,,,,75,92,,,,,7,
|
||||
System,65,8,12154,,8,8,9,,4,,33,3,1,3,4,10163,1991
|
||||
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,
|
||||
package,sink,source,summary,sink:code,sink:encryption-decryptor,sink:encryption-encryptor,sink:encryption-keyprop,sink:encryption-symmetrickey,sink:html,sink:remote,sink:sql,sink:xss,source:file,source:file-write,source:local,source:remote,summary:taint,summary:value
|
||||
Dapper,55,,,,,,,,,,55,,,,,,,
|
||||
JsonToItemsTaskFactory,,,7,,,,,,,,,,,,,,7,
|
||||
Microsoft.ApplicationBlocks.Data,28,,,,,,,,,,28,,,,,,,
|
||||
Microsoft.CSharp,,,24,,,,,,,,,,,,,,24,
|
||||
Microsoft.EntityFrameworkCore,6,,,,,,,,,,6,,,,,,,
|
||||
Microsoft.Extensions.Caching.Distributed,,,15,,,,,,,,,,,,,,15,
|
||||
Microsoft.Extensions.Caching.Memory,,,46,,,,,,,,,,,,,,45,1
|
||||
Microsoft.Extensions.Configuration,,,83,,,,,,,,,,,,,,80,3
|
||||
Microsoft.Extensions.DependencyInjection,,,62,,,,,,,,,,,,,,62,
|
||||
Microsoft.Extensions.DependencyModel,,,12,,,,,,,,,,,,,,12,
|
||||
Microsoft.Extensions.FileProviders,,,16,,,,,,,,,,,,,,16,
|
||||
Microsoft.Extensions.FileSystemGlobbing,,,15,,,,,,,,,,,,,,13,2
|
||||
Microsoft.Extensions.Hosting,,,17,,,,,,,,,,,,,,16,1
|
||||
Microsoft.Extensions.Http,,,10,,,,,,,,,,,,,,10,
|
||||
Microsoft.Extensions.Logging,,,37,,,,,,,,,,,,,,37,
|
||||
Microsoft.Extensions.Options,,,8,,,,,,,,,,,,,,8,
|
||||
Microsoft.Extensions.Primitives,,,63,,,,,,,,,,,,,,63,
|
||||
Microsoft.Interop,,,27,,,,,,,,,,,,,,27,
|
||||
Microsoft.NET.Build.Tasks,,,1,,,,,,,,,,,,,,1,
|
||||
Microsoft.NETCore.Platforms.BuildTasks,,,4,,,,,,,,,,,,,,4,
|
||||
Microsoft.VisualBasic,,,10,,,,,,,,,,,,,,5,5
|
||||
Microsoft.Win32,,,8,,,,,,,,,,,,,,8,
|
||||
MySql.Data.MySqlClient,48,,,,,,,,,,48,,,,,,,
|
||||
Newtonsoft.Json,,,91,,,,,,,,,,,,,,73,18
|
||||
ServiceStack,194,,7,27,,,,,,75,92,,,,,,7,
|
||||
System,65,25,12154,,8,8,9,,4,,33,3,1,17,3,4,10163,1991
|
||||
Windows.Security.Cryptography.Core,1,,,,,,,1,,,,,,,,,,
|
||||
|
||||
|
@@ -8,7 +8,7 @@ C# framework & library support
|
||||
|
||||
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE-079` :sub:`Cross-site scripting`
|
||||
`ServiceStack <https://servicestack.net/>`_,"``ServiceStack.*``, ``ServiceStack``",,7,194,
|
||||
System,"``System.*``, ``System``",8,12154,65,7
|
||||
System,"``System.*``, ``System``",25,12154,65,7
|
||||
Others,"``Dapper``, ``JsonToItemsTaskFactory``, ``Microsoft.ApplicationBlocks.Data``, ``Microsoft.CSharp``, ``Microsoft.EntityFrameworkCore``, ``Microsoft.Extensions.Caching.Distributed``, ``Microsoft.Extensions.Caching.Memory``, ``Microsoft.Extensions.Configuration``, ``Microsoft.Extensions.DependencyInjection``, ``Microsoft.Extensions.DependencyModel``, ``Microsoft.Extensions.FileProviders``, ``Microsoft.Extensions.FileSystemGlobbing``, ``Microsoft.Extensions.Hosting``, ``Microsoft.Extensions.Http``, ``Microsoft.Extensions.Logging``, ``Microsoft.Extensions.Options``, ``Microsoft.Extensions.Primitives``, ``Microsoft.Interop``, ``Microsoft.NET.Build.Tasks``, ``Microsoft.NETCore.Platforms.BuildTasks``, ``Microsoft.VisualBasic``, ``Microsoft.Win32``, ``MySql.Data.MySqlClient``, ``Newtonsoft.Json``, ``Windows.Security.Cryptography.Core``",,556,138,
|
||||
Totals,,8,12717,397,7
|
||||
Totals,,25,12717,397,7
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 1.5.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 1.5.0
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
## 1.5.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 1.5.0
|
||||
lastReleaseVersion: 1.5.1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/csharp-solorigate-all
|
||||
version: 1.5.0
|
||||
version: 1.5.2-dev
|
||||
groups:
|
||||
- csharp
|
||||
- solorigate
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user