mirror of
https://github.com/github/codeql.git
synced 2026-05-24 08:07:07 +02:00
Compare commits
590 Commits
henrymerce
...
esbena/atm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f41b3afb6 | ||
|
|
477f83cf9e | ||
|
|
948ebe4b4c | ||
|
|
b7690e5e6b | ||
|
|
28e03a8aae | ||
|
|
2c27a07ead | ||
|
|
51205d6ce5 | ||
|
|
83fb822115 | ||
|
|
4c16320e28 | ||
|
|
941f230c94 | ||
|
|
15aa09fb7a | ||
|
|
662675ebf0 | ||
|
|
1c711e05be | ||
|
|
e722121be8 | ||
|
|
1b539eb4dc | ||
|
|
5d0f7efe84 | ||
|
|
70f7535988 | ||
|
|
afd6f58fe8 | ||
|
|
63ff17b3c1 | ||
|
|
082c712843 | ||
|
|
1cfd222770 | ||
|
|
d7a91fdbe6 | ||
|
|
4ee290acd3 | ||
|
|
20ea825e4a | ||
|
|
1462565810 | ||
|
|
cc527bdecd | ||
|
|
9e1e2ba442 | ||
|
|
49488fa0a0 | ||
|
|
caaee5e4e5 | ||
|
|
9f9dee5d18 | ||
|
|
67962cb93d | ||
|
|
26d9848fca | ||
|
|
d70b813949 | ||
|
|
9825136e58 | ||
|
|
0299b4603f | ||
|
|
962d0213b5 | ||
|
|
82ad79f55f | ||
|
|
72241886bf | ||
|
|
f6a8d50593 | ||
|
|
35cc5ff0e2 | ||
|
|
06776d19ee | ||
|
|
fdd787b89c | ||
|
|
6543b1a3a9 | ||
|
|
1c2f4e79ff | ||
|
|
8d1e22bc38 | ||
|
|
d4bac887cf | ||
|
|
364f07e3c5 | ||
|
|
6d3381cb89 | ||
|
|
66a24c5c49 | ||
|
|
af0fc37f39 | ||
|
|
f71217706a | ||
|
|
301318020f | ||
|
|
e3afcb1b06 | ||
|
|
65e1c0ebc1 | ||
|
|
e42d3e540a | ||
|
|
764f27f08e | ||
|
|
bbaac556e2 | ||
|
|
11929378c7 | ||
|
|
497c87851c | ||
|
|
75f389749a | ||
|
|
cc712c20cb | ||
|
|
bb786bc557 | ||
|
|
6efa595478 | ||
|
|
2a972dc045 | ||
|
|
b59fd4070f | ||
|
|
148b0c33a9 | ||
|
|
ab0d67a573 | ||
|
|
b2dc02b831 | ||
|
|
64f19637d4 | ||
|
|
823cadecd5 | ||
|
|
413c0a8f4f | ||
|
|
7db66055e5 | ||
|
|
08379df613 | ||
|
|
4c99d39acf | ||
|
|
78b4d7cbb5 | ||
|
|
0cef887683 | ||
|
|
683f909f7a | ||
|
|
ab1bc685bb | ||
|
|
02db472209 | ||
|
|
7af6dc7164 | ||
|
|
8be58fe01e | ||
|
|
5df1f7a0c3 | ||
|
|
7d7e9ba9e1 | ||
|
|
e9a01f9e8f | ||
|
|
634c8cd060 | ||
|
|
fcec8a8388 | ||
|
|
ab4935fe68 | ||
|
|
7630b277b8 | ||
|
|
26a0167d6d | ||
|
|
49c452239e | ||
|
|
77a3e4bd61 | ||
|
|
b277731312 | ||
|
|
908b7c43f2 | ||
|
|
9bd2ac96ea | ||
|
|
b4bf7a1561 | ||
|
|
020970ff4c | ||
|
|
aee9eb5203 | ||
|
|
67e3f5edbc | ||
|
|
85e1cda81b | ||
|
|
8e40899dfd | ||
|
|
2fa18801aa | ||
|
|
78d7e538a5 | ||
|
|
c41de33156 | ||
|
|
0b98397e9b | ||
|
|
97447d0b3a | ||
|
|
84907f91f1 | ||
|
|
48064c1c8f | ||
|
|
7c8c2090f7 | ||
|
|
117795c409 | ||
|
|
a77a6ec864 | ||
|
|
9d89cace95 | ||
|
|
5f7ee337cd | ||
|
|
41d294229d | ||
|
|
1eaa379bb7 | ||
|
|
c7e1df5689 | ||
|
|
a235f8f023 | ||
|
|
b75c316c27 | ||
|
|
f500bccbe4 | ||
|
|
ddfc3bc00f | ||
|
|
830c2dc90a | ||
|
|
5b9ae9cede | ||
|
|
0846d1f7b6 | ||
|
|
3f6e035016 | ||
|
|
4fd0ada9a8 | ||
|
|
f9d5cbf017 | ||
|
|
d22632ef78 | ||
|
|
f9b906d1e2 | ||
|
|
cba733136c | ||
|
|
f1a2b21e44 | ||
|
|
aa9cfebc65 | ||
|
|
b02f1c87a1 | ||
|
|
2287b6e549 | ||
|
|
ccc6291844 | ||
|
|
15c1ce722a | ||
|
|
8fc429caf4 | ||
|
|
bd1720f797 | ||
|
|
e689f6bad2 | ||
|
|
cbea5eaeaa | ||
|
|
6fe0b78978 | ||
|
|
534f8999b6 | ||
|
|
2bffe56580 | ||
|
|
3155114e36 | ||
|
|
fede7dd238 | ||
|
|
a77b2b0209 | ||
|
|
5780161b2c | ||
|
|
9613ff743b | ||
|
|
caab1c3332 | ||
|
|
29e87b3abd | ||
|
|
b230681bc8 | ||
|
|
f53dce3a83 | ||
|
|
43da5aabbe | ||
|
|
7167e856fe | ||
|
|
ab218421da | ||
|
|
62f847a82e | ||
|
|
3957ebe880 | ||
|
|
265f8a3b19 | ||
|
|
4e9849e19d | ||
|
|
62c21918b2 | ||
|
|
58a0bcd70f | ||
|
|
8767d2db23 | ||
|
|
596cfd399e | ||
|
|
ab560234e3 | ||
|
|
3405db31b8 | ||
|
|
6152c8a989 | ||
|
|
e1d30ebc09 | ||
|
|
ec8ffeed07 | ||
|
|
e804922a2c | ||
|
|
97d9985e0b | ||
|
|
c09b6691e1 | ||
|
|
e178626226 | ||
|
|
f154530141 | ||
|
|
8217873bae | ||
|
|
4aa2661dc1 | ||
|
|
4cac35adad | ||
|
|
857c2778a6 | ||
|
|
b20b3ab480 | ||
|
|
93f6fde63c | ||
|
|
d07997699f | ||
|
|
8bdbaf4b57 | ||
|
|
cfa670c123 | ||
|
|
a1cdf256ad | ||
|
|
4e8e3a7420 | ||
|
|
2748bbffa3 | ||
|
|
967308fbfd | ||
|
|
c105d71952 | ||
|
|
7a1a45f5f9 | ||
|
|
77c2b43560 | ||
|
|
76a0853f5b | ||
|
|
d58bb4753e | ||
|
|
ab4dc30f54 | ||
|
|
7cd05fb685 | ||
|
|
7d7ab58108 | ||
|
|
210bad6c29 | ||
|
|
fc7f642734 | ||
|
|
858aec3839 | ||
|
|
073d2f2c75 | ||
|
|
547f492be0 | ||
|
|
4ce8ccc52b | ||
|
|
6bae03a7cc | ||
|
|
13a0ece25c | ||
|
|
95355b5854 | ||
|
|
23548c50e1 | ||
|
|
70f4efb834 | ||
|
|
128682b59e | ||
|
|
dc71ecef83 | ||
|
|
b9ee2960e2 | ||
|
|
aa10ad6a8a | ||
|
|
e82ea7ad17 | ||
|
|
0990a1b404 | ||
|
|
695e77a219 | ||
|
|
40c8881575 | ||
|
|
58b1a6fd40 | ||
|
|
e442e50e6b | ||
|
|
101ad777e3 | ||
|
|
03020582af | ||
|
|
9ffc5ab183 | ||
|
|
c16181dd2f | ||
|
|
000a544729 | ||
|
|
1e2a956a30 | ||
|
|
d9e98ceacc | ||
|
|
4d207101e2 | ||
|
|
999acb0021 | ||
|
|
e9712f04a4 | ||
|
|
698fd64f7f | ||
|
|
68fe3dd9f4 | ||
|
|
c24520cb75 | ||
|
|
5997b874de | ||
|
|
9e93aecf75 | ||
|
|
19d1a780ca | ||
|
|
64518bf91a | ||
|
|
4508945f85 | ||
|
|
e842acf9e0 | ||
|
|
5d4cd70f8c | ||
|
|
e43fff2d30 | ||
|
|
02d0fa9188 | ||
|
|
4313baf622 | ||
|
|
e0f4c73aed | ||
|
|
6096080156 | ||
|
|
52406dc8df | ||
|
|
25d251c24f | ||
|
|
3c9fac0c6e | ||
|
|
6a4d2ee850 | ||
|
|
57ff13dd19 | ||
|
|
ea4ff80cc6 | ||
|
|
37916a8368 | ||
|
|
d9d9ad7d63 | ||
|
|
aef63f69b0 | ||
|
|
4b3029564c | ||
|
|
c675028537 | ||
|
|
9ae1f1cf85 | ||
|
|
211cb9370f | ||
|
|
520d8f5ec5 | ||
|
|
7e3f3c6e2a | ||
|
|
162b3822dd | ||
|
|
c134e6c9ef | ||
|
|
51e8b4c7ed | ||
|
|
e82e648ca1 | ||
|
|
c63fcb2c69 | ||
|
|
f3daff4e5a | ||
|
|
f0645a34b9 | ||
|
|
cb9e14f544 | ||
|
|
0aab670b17 | ||
|
|
cb098df4ea | ||
|
|
45ed5a806c | ||
|
|
b27d315ff4 | ||
|
|
dfbde23821 | ||
|
|
e4203a4109 | ||
|
|
dacb33d1dd | ||
|
|
0230494799 | ||
|
|
061b9badfe | ||
|
|
acfd593eb4 | ||
|
|
330b4c3704 | ||
|
|
9c2d961ae5 | ||
|
|
d7cd1cf0b9 | ||
|
|
4f90b45dd7 | ||
|
|
c8509cc382 | ||
|
|
d77ba020f9 | ||
|
|
974a8b1a9a | ||
|
|
d467725ccd | ||
|
|
3df30545d3 | ||
|
|
71ddd00a6c | ||
|
|
edafdc8fde | ||
|
|
194da454b1 | ||
|
|
2eea6ca5fd | ||
|
|
bdfde88e99 | ||
|
|
ef2eacebce | ||
|
|
55f787bcae | ||
|
|
994fcf54b5 | ||
|
|
08d48b9375 | ||
|
|
b2c7175ac5 | ||
|
|
f02aeafef1 | ||
|
|
f7240be136 | ||
|
|
a1b0315d90 | ||
|
|
01b5881de6 | ||
|
|
0cd6556964 | ||
|
|
7fcf567eda | ||
|
|
4f7f92490a | ||
|
|
3fa2516898 | ||
|
|
d1c89562b8 | ||
|
|
84097468cc | ||
|
|
63672ca394 | ||
|
|
1e32514600 | ||
|
|
9e91b805d6 | ||
|
|
e6800c877c | ||
|
|
736e68820c | ||
|
|
67b60dcf78 | ||
|
|
82bda6d573 | ||
|
|
8eb6743586 | ||
|
|
d744cf9053 | ||
|
|
748008ad51 | ||
|
|
a3d65a8ed0 | ||
|
|
982fb8f73a | ||
|
|
024bd27485 | ||
|
|
47697f59c1 | ||
|
|
1912c56f82 | ||
|
|
95e935e9c1 | ||
|
|
30d896bdbb | ||
|
|
92f5a5f893 | ||
|
|
14d2f5fe02 | ||
|
|
a1f4c85dea | ||
|
|
1ec868eeae | ||
|
|
95ae113994 | ||
|
|
ea7945bac1 | ||
|
|
be0c26f83d | ||
|
|
cb0cc8d859 | ||
|
|
b16b0270d2 | ||
|
|
548a62d1ab | ||
|
|
c3ed74d63c | ||
|
|
9819752bdd | ||
|
|
7e215a5193 | ||
|
|
1893b9f7a9 | ||
|
|
f103d45340 | ||
|
|
e1598aba5e | ||
|
|
3ff7710a18 | ||
|
|
fe2755c4a0 | ||
|
|
365a8d9bbd | ||
|
|
8e6a15640f | ||
|
|
fff3b5c5b4 | ||
|
|
9479301485 | ||
|
|
5cfa3c7927 | ||
|
|
7b98ca9b0a | ||
|
|
aa9912a699 | ||
|
|
71e39353ca | ||
|
|
b22c4e3c56 | ||
|
|
f7d3892320 | ||
|
|
dfa79f6119 | ||
|
|
46736a137c | ||
|
|
2c37885f6e | ||
|
|
7c9b44b4cb | ||
|
|
de3d62b3f4 | ||
|
|
bf21026771 | ||
|
|
8fd116fbd7 | ||
|
|
ac47c96f48 | ||
|
|
8b048ca17e | ||
|
|
93255dfe13 | ||
|
|
7e264668d8 | ||
|
|
af380f846e | ||
|
|
195d40c04e | ||
|
|
a197befb5f | ||
|
|
c9467d7e94 | ||
|
|
c41ec1f8ec | ||
|
|
b8959f7bdb | ||
|
|
c1a51d94a2 | ||
|
|
d63f4bfd94 | ||
|
|
e0110bd25e | ||
|
|
ffa4135cbe | ||
|
|
a4cfb80b81 | ||
|
|
e7dde79d50 | ||
|
|
85c273a413 | ||
|
|
e9128466d4 | ||
|
|
568d37e9b9 | ||
|
|
d475101286 | ||
|
|
065043b311 | ||
|
|
b927aad6ed | ||
|
|
6c1bb4a3a9 | ||
|
|
746fd603d8 | ||
|
|
9770f09839 | ||
|
|
55cb2aa160 | ||
|
|
dc76775d07 | ||
|
|
c17bd29640 | ||
|
|
e967b8a9be | ||
|
|
227929508f | ||
|
|
3c837c322b | ||
|
|
7beab7cb59 | ||
|
|
78642aaae2 | ||
|
|
16aa53a928 | ||
|
|
a23b8a4a43 | ||
|
|
ba3a4fb717 | ||
|
|
500deac12d | ||
|
|
d9e6e5aa04 | ||
|
|
22aad17d0e | ||
|
|
9bbba3c96f | ||
|
|
1e4840e071 | ||
|
|
79ddbd6fe4 | ||
|
|
c1ac09a063 | ||
|
|
6a53b7b233 | ||
|
|
d09f48ecb4 | ||
|
|
4797fce48a | ||
|
|
978ef1570a | ||
|
|
2ecf0d3264 | ||
|
|
5df6bcf952 | ||
|
|
bce2a810a3 | ||
|
|
9de63b2812 | ||
|
|
fbb5d7196f | ||
|
|
a2c98baf29 | ||
|
|
eb1806c0a9 | ||
|
|
bba8e45e74 | ||
|
|
ed28b7f174 | ||
|
|
e09009cd8e | ||
|
|
fdf77ad2b9 | ||
|
|
22dc24629f | ||
|
|
fb1287d577 | ||
|
|
25253c7b8d | ||
|
|
e8afec413a | ||
|
|
136fefbab5 | ||
|
|
877c52981f | ||
|
|
cde7a35c1f | ||
|
|
8c6c8b0adb | ||
|
|
6aac848015 | ||
|
|
9f616e7cbe | ||
|
|
b51c85597b | ||
|
|
b02fecf125 | ||
|
|
47e56365c4 | ||
|
|
d55e6d1ca7 | ||
|
|
a4429d01a3 | ||
|
|
37ca6a5e41 | ||
|
|
6d95d47467 | ||
|
|
6009d71e9a | ||
|
|
df95317a58 | ||
|
|
6f06be9419 | ||
|
|
bd4abf4fd0 | ||
|
|
a9757fbc83 | ||
|
|
a59a4024a5 | ||
|
|
66794665f3 | ||
|
|
a0a914466c | ||
|
|
9c12c5f8b8 | ||
|
|
f963887c58 | ||
|
|
48acff9262 | ||
|
|
9e3594fcf1 | ||
|
|
1e3e48132c | ||
|
|
47c851efaf | ||
|
|
12059a8a50 | ||
|
|
d49e52fb73 | ||
|
|
c73e4ebc48 | ||
|
|
7f85dae63b | ||
|
|
e58a8587db | ||
|
|
d43242d09e | ||
|
|
d0077b8c12 | ||
|
|
68385dfab5 | ||
|
|
6c20585fc7 | ||
|
|
411d2b2876 | ||
|
|
f025db0371 | ||
|
|
dcd6a6be40 | ||
|
|
a1eff1603a | ||
|
|
c118d9bf6f | ||
|
|
e305a8a6c5 | ||
|
|
6e72f6e2c4 | ||
|
|
f2818ebb5e | ||
|
|
8f73772955 | ||
|
|
0b24af901d | ||
|
|
685336fa23 | ||
|
|
e9bb9f5294 | ||
|
|
8e9d8c112d | ||
|
|
2aea3257cb | ||
|
|
4ffd8c62ac | ||
|
|
c6deccf863 | ||
|
|
71baf32596 | ||
|
|
d41c55c69c | ||
|
|
2de6340ff5 | ||
|
|
83a25698bb | ||
|
|
b6886b8e43 | ||
|
|
81feaaec02 | ||
|
|
c44cf29992 | ||
|
|
cd9a485c47 | ||
|
|
61490e74d8 | ||
|
|
6148af4621 | ||
|
|
f7cf327e71 | ||
|
|
a34c981209 | ||
|
|
69973dadb3 | ||
|
|
e6763c858d | ||
|
|
64d15d6226 | ||
|
|
7b4300e4cf | ||
|
|
9d49ad9f20 | ||
|
|
c117a1e21f | ||
|
|
630982cc31 | ||
|
|
9f811b2439 | ||
|
|
013216d5e6 | ||
|
|
aac029841a | ||
|
|
c8741f6475 | ||
|
|
1e4861a944 | ||
|
|
106400238a | ||
|
|
8ac34f3db5 | ||
|
|
4a85b9b0cc | ||
|
|
97f1a5bac0 | ||
|
|
10b62154a1 | ||
|
|
b979f02e5d | ||
|
|
db6214fdff | ||
|
|
a0059202db | ||
|
|
85fc127c0a | ||
|
|
7e42ccfbf1 | ||
|
|
7c11e2d7e9 | ||
|
|
6b937a939b | ||
|
|
40ad88ba53 | ||
|
|
8583a4ffea | ||
|
|
89bab6ae12 | ||
|
|
93507a2d71 | ||
|
|
aacb03a74b | ||
|
|
63aaf24063 | ||
|
|
da69886777 | ||
|
|
a6e4f29560 | ||
|
|
69f329ffec | ||
|
|
39b6678b7d | ||
|
|
625836a3be | ||
|
|
e435a3e9c3 | ||
|
|
1c3c9216f5 | ||
|
|
09a28c428c | ||
|
|
9abc3411a4 | ||
|
|
5031d6c4a3 | ||
|
|
8e8278764b | ||
|
|
c112980b81 | ||
|
|
9ec3d7787c | ||
|
|
8a2d92badc | ||
|
|
9e51908b02 | ||
|
|
263dbd33f6 | ||
|
|
e4eb2c2a59 | ||
|
|
b3a7090068 | ||
|
|
fdb4851521 | ||
|
|
132e0bf4b7 | ||
|
|
e2a9ced691 | ||
|
|
f36ee95128 | ||
|
|
fe355a0bc9 | ||
|
|
2a02ce137a | ||
|
|
f2d6bcd767 | ||
|
|
f590d2566e | ||
|
|
c8a6798c05 | ||
|
|
67fb48fcc1 | ||
|
|
fa9242befe | ||
|
|
cc5e9fea77 | ||
|
|
f7a63d5ea0 | ||
|
|
c8d29a9cf1 | ||
|
|
1a8b6d7414 | ||
|
|
acaf294bee | ||
|
|
bb94c42a35 | ||
|
|
9afd360731 | ||
|
|
759ec31508 | ||
|
|
05b0daa0b7 | ||
|
|
43ddc54f2b | ||
|
|
ac9cac78bc | ||
|
|
c3fd272f9b | ||
|
|
799ec23b0d | ||
|
|
322f8356dd | ||
|
|
301d0bbdf8 | ||
|
|
23f1352953 | ||
|
|
32c93e70e2 | ||
|
|
3df3fb092b | ||
|
|
b4b91e84a3 | ||
|
|
ef714f7328 | ||
|
|
6b6a9df0eb | ||
|
|
fd60c6e1ad | ||
|
|
1dfcf427aa | ||
|
|
081765cbe8 | ||
|
|
a616059761 | ||
|
|
fed1d88268 | ||
|
|
144ec8c629 | ||
|
|
d5ef1cf28d | ||
|
|
29ce0e9ef1 | ||
|
|
6dfe0ce7c5 | ||
|
|
f0e9b768f2 | ||
|
|
65b6c16254 | ||
|
|
6363ff3c08 | ||
|
|
7a1b854678 | ||
|
|
85526d71da | ||
|
|
701d12fb5b | ||
|
|
efb471687c | ||
|
|
8b0c79d16f | ||
|
|
744d139daf | ||
|
|
97193f72b3 | ||
|
|
1a2899168f | ||
|
|
e1c9bf2b30 | ||
|
|
a23fe04ccb | ||
|
|
464b9c3991 | ||
|
|
32cb8f362b | ||
|
|
219bf51ec2 | ||
|
|
8bcffc2886 | ||
|
|
6a2c7d54cd | ||
|
|
6bfe2f2ba6 | ||
|
|
f1788ed04e | ||
|
|
8ed2bc59ad | ||
|
|
46fd5bd92e | ||
|
|
07f45a51f8 |
@@ -27,4 +27,4 @@
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
|
||||
# QL for QL reviewers
|
||||
/ql/ @erik-krogh @tausbn
|
||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||
@@ -4,6 +4,9 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
|
||||
|
||||
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
|
||||
|
||||
## Change notes
|
||||
|
||||
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
|
||||
|
||||
## Submitting a new experimental query
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll",
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll",
|
||||
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll",
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
@name Badly bounded write (CWE-120)
|
||||
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWrite.ql: /CWE/CWE-120
|
||||
@name Potentially overrunning write (CWE-120)
|
||||
+ semmlecode-cpp-queries/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql: /CWE/CWE-120
|
||||
@name Likely overrunning write
|
||||
+ semmlecode-cpp-queries/Security/CWE/CWE-120/OverrunWriteFloat.ql: /CWE/CWE-120
|
||||
@name Potentially overrunning write with float to string conversion (CWE-120)
|
||||
+ semmlecode-cpp-queries/Best Practices/Likely Errors/OffsetUseBeforeRangeCheck.ql: /CWE/CWE-120
|
||||
@name Array offset used before range check (CWE-120)
|
||||
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/UnsafeUseOfStrcat.ql: /CWE/CWE-120
|
||||
@name Potentially unsafe use of strcat (CWE-120)
|
||||
@name Potentially unsafe use of strcat (CWE-120)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.0.7
|
||||
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
## 0.0.4
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* The `codeql/cpp-upgrades` CodeQL pack has been removed. All upgrades scripts have been merged into the `codeql/cpp-all` CodeQL pack.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `FormatLiteral::getMaxConvertedLength` now uses range analysis to provide a
|
||||
more accurate length for integers formatted with `%x`
|
||||
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
1
cpp/ql/lib/change-notes/released/0.0.7.md
Normal file
1
cpp/ql/lib/change-notes/released/0.0.7.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.7
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.8-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -206,9 +206,7 @@ class Class extends UserType {
|
||||
* it is callable by a particular caller. For C++11, there's also a question
|
||||
* of whether to include members that are defaulted or deleted.
|
||||
*/
|
||||
deprecated predicate hasCopyConstructor() {
|
||||
exists(CopyConstructor cc | cc = this.getAMemberFunction())
|
||||
}
|
||||
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor }
|
||||
|
||||
/**
|
||||
* Holds if this class has a copy assignment operator that is either
|
||||
@@ -224,7 +222,7 @@ class Class extends UserType {
|
||||
* or deleted.
|
||||
*/
|
||||
deprecated predicate hasCopyAssignmentOperator() {
|
||||
exists(CopyAssignmentOperator coa | coa = this.getAMemberFunction())
|
||||
this.getAMemberFunction() instanceof CopyAssignmentOperator
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -887,7 +885,7 @@ class NestedClass extends Class {
|
||||
* pure virtual function.
|
||||
*/
|
||||
class AbstractClass extends Class {
|
||||
AbstractClass() { exists(PureVirtualFunction f | this.getAMemberFunction() = f) }
|
||||
AbstractClass() { this.getAMemberFunction() instanceof PureVirtualFunction }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AbstractClass" }
|
||||
}
|
||||
|
||||
@@ -286,13 +286,13 @@ class AttributeArgument extends Element, @attribute_arg {
|
||||
override Location getLocation() { attribute_args(underlyingElement(this), _, _, _, result) }
|
||||
|
||||
override string toString() {
|
||||
if exists(@attribute_arg_empty self | self = underlyingElement(this))
|
||||
if underlyingElement(this) instanceof @attribute_arg_empty
|
||||
then result = "empty argument"
|
||||
else
|
||||
exists(string prefix, string tail |
|
||||
(if exists(this.getName()) then prefix = this.getName() + "=" else prefix = "") and
|
||||
(
|
||||
if exists(@attribute_arg_type self | self = underlyingElement(this))
|
||||
if underlyingElement(this) instanceof @attribute_arg_type
|
||||
then tail = this.getValueType().getName()
|
||||
else tail = this.getValueText()
|
||||
) and
|
||||
|
||||
@@ -233,7 +233,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
XMLAttribute getAttribute(string name) { result.getElement() = this and result.getName() = name }
|
||||
|
||||
/** Holds if this XML element has an attribute with the specified `name`. */
|
||||
predicate hasAttribute(string name) { exists(XMLAttribute a | a = this.getAttribute(name)) }
|
||||
predicate hasAttribute(string name) { exists(this.getAttribute(name)) }
|
||||
|
||||
/** Gets the value of the attribute with the specified `name`, if any. */
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
@@ -101,6 +101,21 @@ predicate functionArgumentMustBeNullTerminated(Function f, int i) {
|
||||
f instanceof StrcatFunction and i = 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `arg` is a string format argument to a formatting function call
|
||||
* `ffc`.
|
||||
*/
|
||||
predicate formatArgumentMustBeNullTerminated(FormattingFunctionCall ffc, Expr arg) {
|
||||
// String argument to a formatting function (such as `printf`)
|
||||
exists(int n, FormatLiteral fl |
|
||||
ffc.getConversionArgument(n) = arg and
|
||||
fl = ffc.getFormat() and
|
||||
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `va` is a variable access where the contents must be null terminated.
|
||||
*/
|
||||
@@ -113,13 +128,7 @@ predicate variableMustBeNullTerminated(VariableAccess va) {
|
||||
)
|
||||
or
|
||||
// String argument to a formatting function (such as `printf`)
|
||||
exists(int n, FormatLiteral fl |
|
||||
fc.(FormattingFunctionCall).getConversionArgument(n) = va and
|
||||
fl = fc.(FormattingFunctionCall).getFormat() and
|
||||
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||
)
|
||||
formatArgumentMustBeNullTerminated(fc, va)
|
||||
or
|
||||
// Call to a wrapper function that requires null termination
|
||||
// (not itself adding a null terminator)
|
||||
|
||||
@@ -10,10 +10,22 @@ private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
|
||||
private import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
|
||||
|
||||
private newtype TBufferWriteEstimationReason =
|
||||
TNoSpecifiedEstimateReason() or
|
||||
TUnspecifiedEstimateReason() or
|
||||
TTypeBoundsAnalysis() or
|
||||
TWidenedValueFlowAnalysis() or
|
||||
TValueFlowAnalysis()
|
||||
|
||||
private predicate gradeToReason(int grade, TBufferWriteEstimationReason reason) {
|
||||
// when combining reasons, lower grade takes precedence
|
||||
grade = 0 and reason = TUnspecifiedEstimateReason()
|
||||
or
|
||||
grade = 1 and reason = TTypeBoundsAnalysis()
|
||||
or
|
||||
grade = 2 and reason = TWidenedValueFlowAnalysis()
|
||||
or
|
||||
grade = 3 and reason = TValueFlowAnalysis()
|
||||
}
|
||||
|
||||
/**
|
||||
* A reason for a specific buffer write size estimate.
|
||||
*/
|
||||
@@ -32,7 +44,13 @@ abstract class BufferWriteEstimationReason extends TBufferWriteEstimationReason
|
||||
* Combine estimate reasons. Used to give a reason for the size of a format string
|
||||
* conversion given reasons coming from its individual specifiers.
|
||||
*/
|
||||
abstract BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other);
|
||||
BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
exists(int grade, int otherGrade |
|
||||
gradeToReason(grade, this) and gradeToReason(otherGrade, other)
|
||||
|
|
||||
if otherGrade < grade then result = other else result = this
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -40,16 +58,10 @@ abstract class BufferWriteEstimationReason extends TBufferWriteEstimationReason
|
||||
* classes derived from BufferWrite and overriding `getMaxData/0` still work with the
|
||||
* queries as intended.
|
||||
*/
|
||||
class NoSpecifiedEstimateReason extends BufferWriteEstimationReason, TNoSpecifiedEstimateReason {
|
||||
override string toString() { result = "NoSpecifiedEstimateReason" }
|
||||
class UnspecifiedEstimateReason extends BufferWriteEstimationReason, TUnspecifiedEstimateReason {
|
||||
override string toString() { result = "UnspecifiedEstimateReason" }
|
||||
|
||||
override string getDescription() { result = "no reason specified" }
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
// this reason should not be used in format specifiers, so it should not be combined
|
||||
// with other reasons
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,9 +72,24 @@ class TypeBoundsAnalysis extends BufferWriteEstimationReason, TTypeBoundsAnalysi
|
||||
override string toString() { result = "TypeBoundsAnalysis" }
|
||||
|
||||
override string getDescription() { result = "based on type bounds" }
|
||||
}
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
other != TNoSpecifiedEstimateReason() and result = TTypeBoundsAnalysis()
|
||||
/**
|
||||
* The estimation comes from non trivial bounds found via actual flow analysis,
|
||||
* but a widening aproximation might have been used for variables in loops.
|
||||
* For example
|
||||
* ```
|
||||
* for (int i = 0; i < 10; ++i) {
|
||||
* int j = i + i;
|
||||
* //... <- estimation done here based on j
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
class WidenedValueFlowAnalysis extends BufferWriteEstimationReason, TWidenedValueFlowAnalysis {
|
||||
override string toString() { result = "WidenedValueFlowAnalysis" }
|
||||
|
||||
override string getDescription() {
|
||||
result = "based on flow analysis of value bounds with a widening approximation"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +107,6 @@ class ValueFlowAnalysis extends BufferWriteEstimationReason, TValueFlowAnalysis
|
||||
override string toString() { result = "ValueFlowAnalysis" }
|
||||
|
||||
override string getDescription() { result = "based on flow analysis of value bounds" }
|
||||
|
||||
override BufferWriteEstimationReason combineWith(BufferWriteEstimationReason other) {
|
||||
other != TNoSpecifiedEstimateReason() and result = other
|
||||
}
|
||||
}
|
||||
|
||||
class PrintfFormatAttribute extends FormatAttribute {
|
||||
@@ -359,6 +382,38 @@ private int lengthInBase10(float f) {
|
||||
result = f.log10().floor() + 1
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate isPointerTypeWithBase(Type base, PointerType pt) { base = pt.getBaseType() }
|
||||
|
||||
bindingset[expr]
|
||||
private BufferWriteEstimationReason getEstimationReasonForIntegralExpression(Expr expr) {
|
||||
// we consider the range analysis non trivial if it
|
||||
// * constrained non-trivially both sides of a signed value, or
|
||||
// * constrained non-trivially the positive side of an unsigned value
|
||||
// expr should already be given as getFullyConverted
|
||||
if
|
||||
upperBound(expr) < exprMaxVal(expr) and
|
||||
(exprMinVal(expr) >= 0 or lowerBound(expr) > exprMinVal(expr))
|
||||
then
|
||||
// next we check whether the estimate may have been widened
|
||||
if upperBoundMayBeWidened(expr)
|
||||
then result = TWidenedValueFlowAnalysis()
|
||||
else result = TValueFlowAnalysis()
|
||||
else result = TTypeBoundsAnalysis()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of hex digits required to represent the integer represented by `f`.
|
||||
*
|
||||
* `f` is assumed to be nonnegative.
|
||||
*/
|
||||
bindingset[f]
|
||||
private int lengthInBase16(float f) {
|
||||
f = 0 and result = 1
|
||||
or
|
||||
result = (f.log2() / 4.0).floor() + 1
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent format strings that occur as arguments to invocations of formatting functions.
|
||||
*/
|
||||
@@ -910,19 +965,19 @@ class FormatLiteral extends Literal {
|
||||
(
|
||||
conv = ["s", "S"] and
|
||||
len = "h" and
|
||||
result.(PointerType).getBaseType() instanceof PlainCharType
|
||||
isPointerTypeWithBase(any(PlainCharType plainCharType), result)
|
||||
or
|
||||
conv = ["s", "S"] and
|
||||
len = ["l", "w"] and
|
||||
result.(PointerType).getBaseType() = this.getWideCharType()
|
||||
isPointerTypeWithBase(this.getWideCharType(), result)
|
||||
or
|
||||
conv = "s" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getDefaultCharType()
|
||||
isPointerTypeWithBase(this.getDefaultCharType(), result)
|
||||
or
|
||||
conv = "S" and
|
||||
(len != "l" and len != "w" and len != "h") and
|
||||
result.(PointerType).getBaseType() = this.getNonDefaultCharType()
|
||||
isPointerTypeWithBase(this.getNonDefaultCharType(), result)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -1067,7 +1122,7 @@ class FormatLiteral extends Literal {
|
||||
* conversion specifier of this format string; has no result if this cannot
|
||||
* be determined.
|
||||
*/
|
||||
int getMaxConvertedLength(int n) { result = max(getMaxConvertedLength(n, _)) }
|
||||
int getMaxConvertedLength(int n) { result = max(this.getMaxConvertedLength(n, _)) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by the nth
|
||||
@@ -1157,12 +1212,10 @@ class FormatLiteral extends Literal {
|
||||
1 + lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8 - 1)) and
|
||||
// The second case uses range analysis to deduce a length that's shorter than the length
|
||||
// of the number -2^31.
|
||||
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
|
||||
exists(Expr arg, float lower, float upper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted()) and
|
||||
typeLower = exprMinVal(arg.getFullyConverted()) and
|
||||
typeUpper = exprMaxVal(arg.getFullyConverted())
|
||||
upper = upperBound(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
max(int cand |
|
||||
@@ -1179,11 +1232,9 @@ class FormatLiteral extends Literal {
|
||||
else cand = lengthInBase10(upper)
|
||||
)
|
||||
) and
|
||||
(
|
||||
if lower > typeLower or upper < typeUpper
|
||||
then reason = TValueFlowAnalysis()
|
||||
else reason = TTypeBoundsAnalysis()
|
||||
)
|
||||
// we don't want to call this on `arg.getFullyConverted()` as we want
|
||||
// to detect non-trivial range analysis without taking into account up-casting
|
||||
reason = getEstimationReasonForIntegralExpression(arg)
|
||||
) and
|
||||
len = valueBasedBound.minimum(typeBasedBound)
|
||||
)
|
||||
@@ -1195,6 +1246,40 @@ class FormatLiteral extends Literal {
|
||||
typeBasedBound = lengthInBase10(2.pow(this.getIntegralDisplayType(n).getSize() * 8) - 1) and
|
||||
// The second case uses range analysis to deduce a length that's shorter than
|
||||
// the length of the number 2^31 - 1.
|
||||
exists(Expr arg, float lower, float upper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
upper = upperBound(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
lengthInBase10(max(float cand |
|
||||
// If lower can be negative we use `(unsigned)-1` as the candidate value.
|
||||
lower < 0 and
|
||||
cand = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
or
|
||||
cand = upper
|
||||
)) and
|
||||
// we don't want to call this on `arg.getFullyConverted()` as we want
|
||||
// to detect non-trivial range analysis without taking into account up-casting
|
||||
reason = getEstimationReasonForIntegralExpression(arg)
|
||||
) and
|
||||
len = valueBasedBound.minimum(typeBasedBound)
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "x" and
|
||||
// e.g. "12345678"
|
||||
exists(int baseLen, int typeBasedBound, int valueBasedBound |
|
||||
typeBasedBound =
|
||||
min(int digits |
|
||||
digits = 2 * this.getIntegralDisplayType(n).getSize()
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and
|
||||
digits = 2 * t.getSize()
|
||||
)
|
||||
) and
|
||||
exists(Expr arg, float lower, float upper, float typeLower, float typeUpper |
|
||||
arg = this.getUse().getConversionArgument(n) and
|
||||
lower = lowerBound(arg.getFullyConverted()) and
|
||||
@@ -1203,7 +1288,7 @@ class FormatLiteral extends Literal {
|
||||
typeUpper = exprMaxVal(arg.getFullyConverted())
|
||||
|
|
||||
valueBasedBound =
|
||||
lengthInBase10(max(float cand |
|
||||
lengthInBase16(max(float cand |
|
||||
// If lower can be negative we use `(unsigned)-1` as the candidate value.
|
||||
lower < 0 and
|
||||
cand = 2.pow(any(IntType t | t.isUnsigned()).getSize() * 8)
|
||||
@@ -1216,29 +1301,10 @@ class FormatLiteral extends Literal {
|
||||
else reason = TTypeBoundsAnalysis()
|
||||
)
|
||||
) and
|
||||
len = valueBasedBound.minimum(typeBasedBound)
|
||||
baseLen = valueBasedBound.minimum(typeBasedBound) and
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "x" and
|
||||
// e.g. "12345678"
|
||||
exists(int sizeBytes, int baseLen |
|
||||
sizeBytes =
|
||||
min(int bytes |
|
||||
bytes = this.getIntegralDisplayType(n).getSize()
|
||||
or
|
||||
exists(IntegralType t |
|
||||
t = this.getUse().getConversionArgument(n).getType().getUnderlyingType()
|
||||
|
|
||||
t.isUnsigned() and bytes = t.getSize()
|
||||
)
|
||||
) and
|
||||
baseLen = sizeBytes * 2 and
|
||||
(
|
||||
if this.hasAlternateFlag(n) then len = 2 + baseLen else len = baseLen // "0x"
|
||||
)
|
||||
) and
|
||||
reason = TTypeBoundsAnalysis()
|
||||
or
|
||||
this.getConversionChar(n).toLowerCase() = "p" and
|
||||
exists(PointerType ptrType, int baseLen |
|
||||
ptrType = this.getFullyConverted().getType() and
|
||||
@@ -1287,7 +1353,7 @@ class FormatLiteral extends Literal {
|
||||
* determining whether a buffer overflow is caused by long float to string
|
||||
* conversions.
|
||||
*/
|
||||
int getMaxConvertedLengthLimited(int n) { result = max(getMaxConvertedLengthLimited(n, _)) }
|
||||
int getMaxConvertedLengthLimited(int n) { result = max(this.getMaxConvertedLengthLimited(n, _)) }
|
||||
|
||||
/**
|
||||
* Gets the maximum length of the string that can be produced by the nth
|
||||
|
||||
@@ -29,7 +29,7 @@ class GuardCondition extends Expr {
|
||||
exists(IRGuardCondition ir | this = ir.getUnconvertedResultExpression())
|
||||
or
|
||||
// no binary operators in the IR
|
||||
exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc)
|
||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||
or
|
||||
// the IR short-circuits if(!x)
|
||||
// don't produce a guard condition for `y = !x` and other non-short-circuited cases
|
||||
@@ -98,7 +98,7 @@ class GuardCondition extends Expr {
|
||||
*/
|
||||
private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
GuardConditionFromBinaryLogicalOperator() {
|
||||
exists(GuardCondition gc | this.(BinaryLogicalOperation).getAnOperand() = gc)
|
||||
this.(BinaryLogicalOperation).getAnOperand() instanceof GuardCondition
|
||||
}
|
||||
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,17 @@ private import DataFlowImplSpecific::Public
|
||||
import Cached
|
||||
|
||||
module DataFlowImplCommonPublic {
|
||||
/** A state value to track during data flow. */
|
||||
class FlowState = string;
|
||||
|
||||
/**
|
||||
* The default state, which is used when the state is unspecified for a source
|
||||
* or a sink.
|
||||
*/
|
||||
class FlowStateEmpty extends FlowState {
|
||||
FlowStateEmpty() { this = "" }
|
||||
}
|
||||
|
||||
private newtype TFlowFeature =
|
||||
TFeatureHasSourceCallContext() or
|
||||
TFeatureHasSinkCallContext() or
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -48,7 +48,7 @@ private class Argument extends Expr {
|
||||
*/
|
||||
class ArgumentNode extends Node {
|
||||
ArgumentNode() {
|
||||
exists(Argument arg | this.asExpr() = arg) or
|
||||
this.asExpr() instanceof Argument or
|
||||
this = getInstanceArgument(_)
|
||||
}
|
||||
|
||||
|
||||
@@ -435,7 +435,7 @@ module FlowVar_internal {
|
||||
parameterIsNonConstReference(p) and
|
||||
p = v and
|
||||
// This definition reaches the exit node of the function CFG
|
||||
getAReachedBlockVarSBB(this).getANode() = p.getFunction()
|
||||
getAReachedBlockVarSBB(this).getEnd() = p.getFunction()
|
||||
}
|
||||
|
||||
override predicate definedByInitialValue(StackVariable lsv) {
|
||||
|
||||
@@ -47,6 +47,12 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding
|
||||
* local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent
|
||||
|
||||
@@ -61,7 +61,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
@@ -69,7 +69,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
@@ -93,7 +93,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
@@ -69,7 +69,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
@@ -93,7 +93,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -84,8 +84,8 @@ class VariableAccess extends Access, @varaccess {
|
||||
exists(Assignment a | a.getLValue() = this) or
|
||||
exists(CrementOperation c | c.getOperand() = this) or
|
||||
exists(AddressOfExpr addof | addof.getOperand() = this) or
|
||||
exists(ReferenceToExpr rte | this.getConversion() = rte) or
|
||||
exists(ArrayToPointerConversion atpc | this.getConversion() = atpc)
|
||||
this.getConversion() instanceof ReferenceToExpr or
|
||||
this.getConversion() instanceof ArrayToPointerConversion
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -104,8 +104,8 @@ class VariableAccess extends Access, @varaccess {
|
||||
predicate isRValue() {
|
||||
not exists(AssignExpr ae | ae.getLValue() = this) and
|
||||
not exists(AddressOfExpr addof | addof.getOperand() = this) and
|
||||
not exists(ReferenceToExpr rte | this.getConversion() = rte) and
|
||||
not exists(ArrayToPointerConversion atpc | this.getConversion() = atpc)
|
||||
not this.getConversion() instanceof ReferenceToExpr and
|
||||
not this.getConversion() instanceof ArrayToPointerConversion
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,9 +218,7 @@ class PointerFieldAccess extends FieldAccess {
|
||||
class DotFieldAccess extends FieldAccess {
|
||||
override string getAPrimaryQlClass() { result = "DotFieldAccess" }
|
||||
|
||||
DotFieldAccess() {
|
||||
exists(Class c | c = this.getQualifier().getFullyConverted().getUnspecifiedType())
|
||||
}
|
||||
DotFieldAccess() { this.getQualifier().getFullyConverted().getUnspecifiedType() instanceof Class }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ class Call extends Expr, NameQualifiableElement, TCall {
|
||||
*
|
||||
* For example, `ptr->f()` has a qualifier, whereas plain `f()` does not.
|
||||
*/
|
||||
predicate hasQualifier() { exists(Expr e | this.getChild(-1) = e) }
|
||||
predicate hasQualifier() { exists(this.getChild(-1)) }
|
||||
|
||||
/**
|
||||
* Gets the expression to the left of the function name or function pointer variable name.
|
||||
|
||||
@@ -724,7 +724,7 @@ class SizeofOperator extends Expr, @runtime_sizeof {
|
||||
* ```
|
||||
*/
|
||||
class SizeofExprOperator extends SizeofOperator {
|
||||
SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) }
|
||||
SizeofExprOperator() { exists(this.getChild(0)) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SizeofExprOperator" }
|
||||
|
||||
@@ -787,7 +787,7 @@ class AlignofOperator extends Expr, @runtime_alignof {
|
||||
* ```
|
||||
*/
|
||||
class AlignofExprOperator extends AlignofOperator {
|
||||
AlignofExprOperator() { exists(Expr e | this.getChild(0) = e) }
|
||||
AlignofExprOperator() { exists(this.getChild(0)) }
|
||||
|
||||
/**
|
||||
* Gets the contained expression.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,17 @@ private import DataFlowImplSpecific::Public
|
||||
import Cached
|
||||
|
||||
module DataFlowImplCommonPublic {
|
||||
/** A state value to track during data flow. */
|
||||
class FlowState = string;
|
||||
|
||||
/**
|
||||
* The default state, which is used when the state is unspecified for a source
|
||||
* or a sink.
|
||||
*/
|
||||
class FlowStateEmpty extends FlowState {
|
||||
FlowStateEmpty() { this = "" }
|
||||
}
|
||||
|
||||
private newtype TFlowFeature =
|
||||
TFeatureHasSourceCallContext() or
|
||||
TFeatureHasSinkCallContext() or
|
||||
|
||||
@@ -170,10 +170,16 @@ private class ReturnParameterIndirection extends Use, TReturnParamIndirection {
|
||||
}
|
||||
|
||||
private predicate isExplicitUse(Operand op) {
|
||||
op.getDef() instanceof VariableAddressInstruction and
|
||||
not exists(LoadInstruction load |
|
||||
load.getSourceAddressOperand() = op and
|
||||
load.getAUse().getUse() instanceof InitializeIndirectionInstruction
|
||||
exists(VariableAddressInstruction vai | vai = op.getDef() |
|
||||
// Don't include this operand as a use if it only exists to initialize the
|
||||
// indirection of a parameter.
|
||||
not exists(LoadInstruction load |
|
||||
load.getSourceAddressOperand() = op and
|
||||
load.getAUse().getUse() instanceof InitializeIndirectionInstruction
|
||||
) and
|
||||
// Don't include this operand as a use if the only use of the address is for a write
|
||||
// that definitely overrides a variable.
|
||||
not (explicitWrite(true, _, vai) and exists(unique( | | vai.getAUse())))
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +160,12 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n
|
||||
*/
|
||||
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `guard` should be a sanitizer guard in all global taint flow configurations
|
||||
* but not in local taint.
|
||||
*/
|
||||
predicate defaultTaintSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
/**
|
||||
* Holds if taint can flow from `instrIn` to `instrOut` through a call to a
|
||||
* modeled function.
|
||||
|
||||
@@ -61,7 +61,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
@@ -69,7 +69,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
@@ -93,7 +93,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
@@ -69,7 +69,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
@@ -93,7 +93,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,7 +61,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSource(DataFlow::Node source);
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
@@ -69,7 +69,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
abstract override predicate isSink(DataFlow::Node sink);
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
@@ -93,7 +93,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
this.isSanitizerGuard(guard) or defaultTaintSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -308,45 +308,45 @@ class MetricClass extends Class {
|
||||
}
|
||||
|
||||
private string getAUsedHalsteadN1Operator() {
|
||||
exists(CommaExpr e | e = this.getAnEnclosedExpression()) and result = "comma"
|
||||
this.getAnEnclosedExpression() instanceof CommaExpr and result = "comma"
|
||||
or
|
||||
exists(ReferenceToExpr e | e = this.getAnEnclosedExpression()) and result = "refTo"
|
||||
this.getAnEnclosedExpression() instanceof ReferenceToExpr and result = "refTo"
|
||||
or
|
||||
exists(PointerDereferenceExpr e | e = this.getAnEnclosedExpression()) and result = "dereference"
|
||||
this.getAnEnclosedExpression() instanceof PointerDereferenceExpr and result = "dereference"
|
||||
or
|
||||
exists(CStyleCast e | e = this.getAnEnclosedExpression()) and result = "cCast"
|
||||
this.getAnEnclosedExpression() instanceof CStyleCast and result = "cCast"
|
||||
or
|
||||
exists(StaticCast e | e = this.getAnEnclosedExpression()) and result = "staticCast"
|
||||
this.getAnEnclosedExpression() instanceof StaticCast and result = "staticCast"
|
||||
or
|
||||
exists(ConstCast e | e = this.getAnEnclosedExpression()) and result = "constCast"
|
||||
this.getAnEnclosedExpression() instanceof ConstCast and result = "constCast"
|
||||
or
|
||||
exists(ReinterpretCast e | e = this.getAnEnclosedExpression()) and result = "reinterpretCast"
|
||||
this.getAnEnclosedExpression() instanceof ReinterpretCast and result = "reinterpretCast"
|
||||
or
|
||||
exists(DynamicCast e | e = this.getAnEnclosedExpression()) and result = "dynamicCast"
|
||||
this.getAnEnclosedExpression() instanceof DynamicCast and result = "dynamicCast"
|
||||
or
|
||||
exists(SizeofExprOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofExpr"
|
||||
this.getAnEnclosedExpression() instanceof SizeofExprOperator and result = "sizeofExpr"
|
||||
or
|
||||
exists(SizeofTypeOperator e | e = this.getAnEnclosedExpression()) and result = "sizeofType"
|
||||
this.getAnEnclosedExpression() instanceof SizeofTypeOperator and result = "sizeofType"
|
||||
or
|
||||
exists(IfStmt e | e = this.getAnEnclosedStmt()) and result = "ifVal"
|
||||
this.getAnEnclosedStmt() instanceof IfStmt and result = "ifVal"
|
||||
or
|
||||
exists(SwitchStmt e | e = this.getAnEnclosedStmt()) and result = "switchVal"
|
||||
this.getAnEnclosedStmt() instanceof SwitchStmt and result = "switchVal"
|
||||
or
|
||||
exists(ForStmt e | e = this.getAnEnclosedStmt()) and result = "forVal"
|
||||
this.getAnEnclosedStmt() instanceof ForStmt and result = "forVal"
|
||||
or
|
||||
exists(DoStmt e | e = this.getAnEnclosedStmt()) and result = "doVal"
|
||||
this.getAnEnclosedStmt() instanceof DoStmt and result = "doVal"
|
||||
or
|
||||
exists(WhileStmt e | e = this.getAnEnclosedStmt()) and result = "whileVal"
|
||||
this.getAnEnclosedStmt() instanceof WhileStmt and result = "whileVal"
|
||||
or
|
||||
exists(GotoStmt e | e = this.getAnEnclosedStmt()) and result = "gotoVal"
|
||||
this.getAnEnclosedStmt() instanceof GotoStmt and result = "gotoVal"
|
||||
or
|
||||
exists(ContinueStmt e | e = this.getAnEnclosedStmt()) and result = "continueVal"
|
||||
this.getAnEnclosedStmt() instanceof ContinueStmt and result = "continueVal"
|
||||
or
|
||||
exists(BreakStmt e | e = this.getAnEnclosedStmt()) and result = "breakVal"
|
||||
this.getAnEnclosedStmt() instanceof BreakStmt and result = "breakVal"
|
||||
or
|
||||
exists(ReturnStmt e | e = this.getAnEnclosedStmt()) and result = "returnVal"
|
||||
this.getAnEnclosedStmt() instanceof ReturnStmt and result = "returnVal"
|
||||
or
|
||||
exists(SwitchCase e | e = this.getAnEnclosedStmt()) and result = "caseVal"
|
||||
this.getAnEnclosedStmt() instanceof SwitchCase and result = "caseVal"
|
||||
or
|
||||
exists(IfStmt s | s = this.getAnEnclosedStmt() and s.hasElse()) and
|
||||
result = "elseVal"
|
||||
|
||||
@@ -65,4 +65,6 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
|
||||
}
|
||||
|
||||
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
|
||||
|
||||
override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
|
||||
}
|
||||
|
||||
@@ -20,8 +20,9 @@ abstract class RemoteFlowSourceFunction extends Function {
|
||||
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
|
||||
|
||||
/**
|
||||
* Holds if remote data from this source comes from a socket described by
|
||||
* `input`. There is no result if a socket is not specified.
|
||||
* Holds if remote data from this source comes from a socket or stream
|
||||
* described by `input`. There is no result if none is specified by a
|
||||
* parameter.
|
||||
*/
|
||||
predicate hasSocketInput(FunctionInput input) { none() }
|
||||
}
|
||||
@@ -59,8 +60,9 @@ abstract class RemoteFlowSinkFunction extends Function {
|
||||
abstract predicate hasRemoteFlowSink(FunctionInput input, string description);
|
||||
|
||||
/**
|
||||
* Holds if data put into this sink is transmitted through a socket described
|
||||
* by `input`. There is no result if a socket is not specified.
|
||||
* Holds if data put into this sink is transmitted through a socket or stream
|
||||
* described by `input`. There is no result if none is specified by a
|
||||
* parameter.
|
||||
*/
|
||||
predicate hasSocketInput(FunctionInput input) { none() }
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ class PaddedType extends Class {
|
||||
// Support only single inheritance for now. If multiple inheritance is
|
||||
// supported, be sure to fix up the calls to getABaseClass*() to correctly
|
||||
// handle the presence of multiple base class subojects with the same type.
|
||||
not exists(ClassDerivation cd | cd = this.getDerivation(1))
|
||||
not exists(this.getDerivation(1))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -72,7 +72,7 @@ predicate lvalue(Element e) {
|
||||
or
|
||||
exists(Cast c | lvalue(c) and e.(Expr).getConversion() = c)
|
||||
or
|
||||
exists(ReferenceToExpr toref | e.(Expr).getConversion() = toref)
|
||||
e.(Expr).getConversion() instanceof ReferenceToExpr
|
||||
or
|
||||
// If f is a function-pointer, then the following two
|
||||
// calls are equivalent: f() and (*f)()
|
||||
|
||||
@@ -76,7 +76,7 @@ abstract class BufferWrite extends Expr {
|
||||
* can be found), specifying the reason for the estimation.
|
||||
*/
|
||||
int getMaxData(BufferWriteEstimationReason reason) {
|
||||
reason instanceof NoSpecifiedEstimateReason and result = getMaxData()
|
||||
reason instanceof UnspecifiedEstimateReason and result = this.getMaxData()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,7 +85,7 @@ abstract class BufferWrite extends Expr {
|
||||
* much smaller (8 bytes) than their true maximum length. This can be
|
||||
* helpful in determining the cause of a buffer overflow issue.
|
||||
*/
|
||||
int getMaxDataLimited() { result = getMaxData() }
|
||||
int getMaxDataLimited() { result = this.getMaxData() }
|
||||
|
||||
/**
|
||||
* Gets an upper bound to the amount of data that's being written (if one
|
||||
@@ -94,7 +94,7 @@ abstract class BufferWrite extends Expr {
|
||||
* than their true maximum length. This can be helpful in determining the
|
||||
* cause of a buffer overflow issue.
|
||||
*/
|
||||
int getMaxDataLimited(BufferWriteEstimationReason reason) { result = getMaxData(reason) }
|
||||
int getMaxDataLimited(BufferWriteEstimationReason reason) { result = this.getMaxData(reason) }
|
||||
|
||||
/**
|
||||
* Gets the size of a single character of the type this
|
||||
@@ -159,9 +159,11 @@ class StrCopyBW extends BufferWriteCall {
|
||||
this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -203,9 +205,11 @@ class StrCatBW extends BufferWriteCall {
|
||||
this.getArgument(this.getParamSrc()).(AnalysedString).getMaxLength() * this.getCharSize()
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,9 +273,11 @@ class SprintfBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
|
||||
private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
@@ -281,10 +287,10 @@ class SprintfBW extends BufferWriteCall {
|
||||
}
|
||||
|
||||
override int getMaxDataLimited(BufferWriteEstimationReason reason) {
|
||||
result = getMaxDataLimitedImpl(reason)
|
||||
result = this.getMaxDataLimitedImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) }
|
||||
override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,9 +388,11 @@ class SnprintfBW extends BufferWriteCall {
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
|
||||
private int getMaxDataLimitedImpl(BufferWriteEstimationReason reason) {
|
||||
exists(FormatLiteral fl |
|
||||
@@ -394,10 +402,10 @@ class SnprintfBW extends BufferWriteCall {
|
||||
}
|
||||
|
||||
override int getMaxDataLimited(BufferWriteEstimationReason reason) {
|
||||
result = getMaxDataLimitedImpl(reason)
|
||||
result = this.getMaxDataLimitedImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxDataLimited() { result = max(getMaxDataLimitedImpl(_)) }
|
||||
override int getMaxDataLimited() { result = max(this.getMaxDataLimitedImpl(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -495,9 +503,11 @@ class ScanfBW extends BufferWrite {
|
||||
)
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
|
||||
override string getBWDesc() {
|
||||
exists(FunctionCall fc |
|
||||
@@ -536,7 +546,9 @@ class RealpathBW extends BufferWriteCall {
|
||||
this = this // Suppress a compiler warning
|
||||
}
|
||||
|
||||
override int getMaxData(BufferWriteEstimationReason reason) { result = getMaxDataImpl(reason) }
|
||||
override int getMaxData(BufferWriteEstimationReason reason) {
|
||||
result = this.getMaxDataImpl(reason)
|
||||
}
|
||||
|
||||
override int getMaxData() { result = max(getMaxDataImpl(_)) }
|
||||
override int getMaxData() { result = max(this.getMaxDataImpl(_)) }
|
||||
}
|
||||
|
||||
@@ -258,7 +258,7 @@ private predicate insideFunctionValueMoveTo(Element src, Element dest) {
|
||||
format.getConversionChar(sourceArg - ffc.getTarget().getNumberOfParameters()) = ["s", "S"]
|
||||
)
|
||||
or
|
||||
not exists(FormatLiteral fl | fl = c.(FormattingFunctionCall).getFormat())
|
||||
not c.(FormattingFunctionCall).getFormat() instanceof FormatLiteral
|
||||
or
|
||||
not c instanceof FormattingFunctionCall
|
||||
) and
|
||||
|
||||
@@ -271,7 +271,7 @@ class IfStmt extends ConditionalStmt, @stmt_if {
|
||||
* if (b) { x = 1; }
|
||||
* ```
|
||||
*/
|
||||
predicate hasElse() { exists(Stmt s | this.getElse() = s) }
|
||||
predicate hasElse() { exists(this.getElse()) }
|
||||
|
||||
override string toString() { result = "if (...) ... " }
|
||||
|
||||
@@ -357,7 +357,7 @@ class ConstexprIfStmt extends ConditionalStmt, @stmt_constexpr_if {
|
||||
* if constexpr (b) { x = 1; }
|
||||
* ```
|
||||
*/
|
||||
predicate hasElse() { exists(Stmt s | this.getElse() = s) }
|
||||
predicate hasElse() { exists(this.getElse()) }
|
||||
|
||||
override string toString() { result = "if constexpr (...) ... " }
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.0.7
|
||||
|
||||
## 0.0.6
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### New Queries
|
||||
|
||||
@@ -30,8 +30,8 @@ where
|
||||
// the next statement isn't breaking out of a switch
|
||||
not s.(BreakStmt).getBreakable() instanceof SwitchStmt and
|
||||
// the next statement isn't a loop that can be jumped into
|
||||
not exists(LabelStmt ls | s.(Loop).getStmt().getAChild*() = ls) and
|
||||
not exists(SwitchCase sc | s.(Loop).getStmt().getAChild*() = sc) and
|
||||
not s.(Loop).getStmt().getAChild*() instanceof LabelStmt and
|
||||
not s.(Loop).getStmt().getAChild*() instanceof SwitchCase and
|
||||
// no preprocessor logic applies
|
||||
not functionContainsPreprocCode(js.getEnclosingFunction())
|
||||
select js, "This statement makes $@ unreachable.", s, s.toString()
|
||||
|
||||
@@ -55,7 +55,7 @@ abstract class LeapYearFieldAccess extends YearFieldAccess {
|
||||
op.getAnOperand() = this and
|
||||
(
|
||||
op instanceof AssignArithmeticOperation or
|
||||
exists(BinaryArithmeticOperation bao | bao = op.getAnOperand()) or
|
||||
op.getAnOperand() instanceof BinaryArithmeticOperation or
|
||||
op instanceof CrementOperation
|
||||
)
|
||||
)
|
||||
@@ -212,9 +212,7 @@ class ChecksForLeapYearFunctionCall extends FunctionCall {
|
||||
class LeapYearCheckConfiguration extends DataFlow::Configuration {
|
||||
LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(VariableAccess va | va = source.asExpr())
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument())
|
||||
|
||||
@@ -23,6 +23,10 @@ DeclStmt declWithNoInit(LocalVariable v) {
|
||||
not exists(v.getInitializer())
|
||||
}
|
||||
|
||||
/**
|
||||
* Control flow reachability from a buffer that is not not null terminated to a
|
||||
* sink that requires null termination.
|
||||
*/
|
||||
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
|
||||
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
|
||||
|
||||
@@ -52,12 +56,44 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR
|
||||
|
||||
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
|
||||
exprDefinition(v, node, _) or
|
||||
mayAddNullTerminator(node, v.getAnAccess()) or
|
||||
node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken
|
||||
isSinkActual(node, v) // only report first use
|
||||
}
|
||||
}
|
||||
|
||||
from ImproperNullTerminationReachability r, LocalVariable v, VariableAccess va
|
||||
where r.reaches(_, v, va)
|
||||
select va, "Variable $@ may not be null terminated.", v, v.getName()
|
||||
/**
|
||||
* Flow from a place where null termination is added, to a sink of
|
||||
* `ImproperNullTerminationReachability`. This was previously implemented as a
|
||||
* simple barrier in `ImproperNullTerminationReachability`, but there were
|
||||
* false positive results involving multiple paths from source to sink. We'd
|
||||
* prefer to report only the results we are sure of.
|
||||
*/
|
||||
class NullTerminationReachability extends StackVariableReachabilityWithReassignment {
|
||||
NullTerminationReachability() { this = "NullTerminationReachability" }
|
||||
|
||||
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
|
||||
mayAddNullTerminator(node, v.getAnAccess()) or // null termination
|
||||
node.(AddressOfExpr).getOperand() = v.getAnAccess() // address taken (possible null termination)
|
||||
}
|
||||
|
||||
override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
|
||||
// have the same sinks as `ImproperNullTerminationReachability`.
|
||||
exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
|
||||
}
|
||||
|
||||
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
|
||||
// don't look further back than the source, or further forward than the sink
|
||||
exists(ImproperNullTerminationReachability r | r.isSourceActual(node, v)) or
|
||||
exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
|
||||
}
|
||||
}
|
||||
|
||||
from
|
||||
ImproperNullTerminationReachability reaches, NullTerminationReachability nullTermReaches,
|
||||
ControlFlowNode source, LocalVariable v, VariableAccess sink
|
||||
where
|
||||
reaches.reaches(source, v, sink) and
|
||||
not exists(ControlFlowNode termination |
|
||||
nullTermReaches.reaches(termination, _, sink) and
|
||||
termination != source
|
||||
)
|
||||
select sink, "Variable $@ may not be null terminated.", v, v.getName()
|
||||
|
||||
@@ -4,4 +4,4 @@ Record* fixRecord(Record* r) {
|
||||
|
||||
myRecord.fix();
|
||||
return &myRecord; //returns reference to myRecord, which is a stack-allocated object
|
||||
}
|
||||
}
|
||||
@@ -3,68 +3,169 @@
|
||||
* @description A function returns a pointer to a stack-allocated region of
|
||||
* memory. This memory is deallocated at the end of the function,
|
||||
* which may lead the caller to dereference a dangling pointer.
|
||||
* @kind problem
|
||||
* @kind path-problem
|
||||
* @id cpp/return-stack-allocated-memory
|
||||
* @problem.severity warning
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-825
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.EscapesTree
|
||||
import semmle.code.cpp.models.interfaces.PointerWrapper
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.ir.IR
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow
|
||||
|
||||
/**
|
||||
* Holds if `n1` may flow to `n2`, ignoring flow through fields because these
|
||||
* are currently modeled as an overapproximation that assumes all objects may
|
||||
* alias.
|
||||
*/
|
||||
predicate conservativeDataFlowStep(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
DataFlow::localFlowStep(n1, n2) and
|
||||
not n2.asExpr() instanceof FieldAccess and
|
||||
not hasNontrivialConversion(n2.asExpr())
|
||||
/** Holds if `f` has a name that we intrepret as evidence of intentionally returning the value of the stack pointer. */
|
||||
predicate intentionallyReturnsStackPointer(Function f) {
|
||||
f.getName().toLowerCase().matches(["%stack%", "%sp%"])
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` has a conversion that changes it from lvalue to pointer or
|
||||
* back. As the data-flow library does not support conversions, we cannot track
|
||||
* data flow through such expressions.
|
||||
* Holds if `source` is a node that represents the use of a stack variable
|
||||
*/
|
||||
predicate hasNontrivialConversion(Expr e) {
|
||||
e instanceof Conversion and
|
||||
not (
|
||||
e instanceof Cast
|
||||
or
|
||||
e instanceof ParenthesisExpr
|
||||
predicate isSource(Node source) {
|
||||
exists(VariableAddressInstruction var, Function func |
|
||||
var = source.asInstruction() and
|
||||
func = var.getEnclosingFunction() and
|
||||
var.getASTVariable() instanceof StackVariable and
|
||||
// Pointer-to-member types aren't properly handled in the dbscheme.
|
||||
not var.getResultType() instanceof PointerToMemberType and
|
||||
// Rule out FPs caused by extraction errors.
|
||||
not any(ErrorExpr e).getEnclosingFunction() = func and
|
||||
not intentionallyReturnsStackPointer(func)
|
||||
)
|
||||
or
|
||||
// A smart pointer can be stack-allocated while the data it points to is heap-allocated.
|
||||
// So we exclude such "conversions" from this predicate.
|
||||
e = any(PointerWrapper wrapper).getAnUnwrapperFunction().getACallToThisFunction()
|
||||
or
|
||||
hasNontrivialConversion(e.getConversion())
|
||||
}
|
||||
|
||||
from StackVariable var, VariableAccess va, ReturnStmt r
|
||||
where
|
||||
not var.getUnspecifiedType() instanceof ReferenceType and
|
||||
not r.isFromUninstantiatedTemplate(_) and
|
||||
va = var.getAnAccess() and
|
||||
/**
|
||||
* Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in
|
||||
* a `ReturnValueInstruction`. We use the `StoreInstruction` instead of the instruction that defines the
|
||||
* `ReturnValueInstruction`'s source value oprand because the former has better location information.
|
||||
*/
|
||||
predicate isSink(Node sink) {
|
||||
exists(StoreInstruction store |
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getIRVariable() instanceof
|
||||
IRReturnVariable and
|
||||
sink.asOperand() = store.getSourceValueOperand()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node1` _must_ flow to `node2`. */
|
||||
predicate step(Node node1, Node node2) {
|
||||
instructionToOperandStep(node1.asInstruction(), node2.asOperand())
|
||||
or
|
||||
operandToInstructionStep(node1.asOperand(), node2.asInstruction())
|
||||
}
|
||||
|
||||
predicate instructionToOperandStep(Instruction instr, Operand operand) { operand.getDef() = instr }
|
||||
|
||||
/**
|
||||
* Holds if `operand` flows to the result of `instr`.
|
||||
*
|
||||
* This predicate ignores flow through `PhiInstruction`s to create a 'must flow' relation. It also
|
||||
* intentionally conflates addresses of fields and their object, and pointer offsets with their
|
||||
* base pointer as this allows us to detect cases where an object's address flows to a return statement
|
||||
* via a field. For example:
|
||||
*
|
||||
* ```cpp
|
||||
* struct S { int x, y };
|
||||
* int* test() {
|
||||
* S s;
|
||||
* return &s.x; // BAD: &s.x is an address of a variable on the stack.
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
predicate operandToInstructionStep(Operand operand, Instruction instr) {
|
||||
instr.(CopyInstruction).getSourceValueOperand() = operand
|
||||
or
|
||||
instr.(ConvertInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(CheckedConvertOrNullInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(InheritanceConversionInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(FieldAddressInstruction).getObjectAddressOperand() = operand
|
||||
or
|
||||
instr.(PointerOffsetInstruction).getLeftOperand() = operand
|
||||
}
|
||||
|
||||
/** Holds if a source node flows to `n`. */
|
||||
predicate branchlessLocalFlow0(Node n) {
|
||||
isSource(n)
|
||||
or
|
||||
exists(Node mid |
|
||||
branchlessLocalFlow0(mid) and
|
||||
step(mid, n)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `n` is reachable through some source node, and `n` also eventually reaches a sink. */
|
||||
predicate branchlessLocalFlow1(Node n) {
|
||||
branchlessLocalFlow0(n) and
|
||||
(
|
||||
// To check if the address escapes directly from `e` in `return e`, we need
|
||||
// to check the fully-converted `e` in case there are implicit
|
||||
// array-to-pointer conversions or reference conversions.
|
||||
variableAddressEscapesTree(va, r.getExpr().getFullyConverted())
|
||||
isSink(n)
|
||||
or
|
||||
// The data flow library doesn't support conversions, so here we check that
|
||||
// the address escapes into some expression `pointerToLocal`, which flows
|
||||
// in one or more steps to a returned expression.
|
||||
exists(Expr pointerToLocal |
|
||||
variableAddressEscapesTree(va, pointerToLocal.getFullyConverted()) and
|
||||
not hasNontrivialConversion(pointerToLocal) and
|
||||
conservativeDataFlowStep+(DataFlow::exprNode(pointerToLocal), DataFlow::exprNode(r.getExpr()))
|
||||
exists(Node mid |
|
||||
branchlessLocalFlow1(mid) and
|
||||
step(n, mid)
|
||||
)
|
||||
)
|
||||
select r, "May return stack-allocated memory from $@.", va, va.toString()
|
||||
}
|
||||
|
||||
newtype TLocalPathNode =
|
||||
TLocalPathNodeMid(Node n) {
|
||||
branchlessLocalFlow1(n) and
|
||||
(
|
||||
isSource(n) or
|
||||
exists(LocalPathNodeMid mid | step(mid.getNode(), n))
|
||||
)
|
||||
}
|
||||
|
||||
abstract class LocalPathNode extends TLocalPathNode {
|
||||
Node n;
|
||||
|
||||
/** Gets the underlying node. */
|
||||
Node getNode() { result = n }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
string toString() { result = n.toString() }
|
||||
|
||||
/** Gets the location of this element. */
|
||||
Location getLocation() { result = n.getLocation() }
|
||||
|
||||
/** Gets a successor `LocalPathNode`, if any. */
|
||||
LocalPathNode getASuccessor() { step(this.getNode(), result.getNode()) }
|
||||
}
|
||||
|
||||
class LocalPathNodeMid extends LocalPathNode, TLocalPathNodeMid {
|
||||
LocalPathNodeMid() { this = TLocalPathNodeMid(n) }
|
||||
}
|
||||
|
||||
class LocalPathNodeSink extends LocalPathNodeMid {
|
||||
LocalPathNodeSink() { isSink(this.getNode()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `source` is a source node, `sink` is a sink node, and there's flow
|
||||
* from `source` to `sink` using `step` relation.
|
||||
*/
|
||||
predicate hasFlow(LocalPathNode source, LocalPathNodeSink sink) {
|
||||
isSource(source.getNode()) and
|
||||
source.getASuccessor+() = sink
|
||||
}
|
||||
|
||||
predicate reach(LocalPathNode n) { n instanceof LocalPathNodeSink or reach(n.getASuccessor()) }
|
||||
|
||||
query predicate edges(LocalPathNode a, LocalPathNode b) { a.getASuccessor() = b and reach(b) }
|
||||
|
||||
query predicate nodes(LocalPathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
|
||||
from LocalPathNode source, LocalPathNodeSink sink, VariableAddressInstruction var
|
||||
where
|
||||
hasFlow(source, sink) and
|
||||
source.getNode().asInstruction() = var
|
||||
select sink.getNode(), source, sink, "May return stack-allocated memory from $@.", var.getAST(),
|
||||
var.getAST().toString()
|
||||
|
||||
@@ -18,8 +18,5 @@
|
||||
<p>To fix the problem, either the second argument to <code>snprintf</code> should be changed to 80, or the buffer extended to 256 characters. A further improvement is to use a preprocessor define so that the size is only specified in one place, potentially preventing future recurrence of this issue.</p>
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
|
||||
</references>
|
||||
<include src="OverrunWriteReferences.inc.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
void sayHello()
|
||||
void sayHello(uint32_t userId)
|
||||
{
|
||||
char buffer[10];
|
||||
char buffer[18];
|
||||
|
||||
// BAD: this message overflows the buffer
|
||||
strcpy(buffer, "Hello, world!");
|
||||
// BAD: this message overflows the buffer if userId >= 10000
|
||||
sprintf(buffer, "Hello, user %d!", userId);
|
||||
|
||||
MessageBox(hWnd, buffer, "New Message", MB_OK);
|
||||
}
|
||||
@@ -6,30 +6,20 @@
|
||||
<p>The program performs a buffer copy or write operation with no upper limit on the size of the copy, and it appears that certain inputs will cause a buffer overflow to occur in this case. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Always control the length of buffer copy and buffer write operations. <code>strncpy</code> should be used over <code>strcpy</code>, <code>snprintf</code> over <code>sprintf</code>, and in other cases 'n-variant' functions should be preferred.</p>
|
||||
|
||||
</recommendation>
|
||||
<include src="OverrunWriteRecommendation.inc.qhelp" />
|
||||
<example>
|
||||
<sample src="OverrunWrite.c" />
|
||||
|
||||
<p>In this example, the call to <code>strcpy</code> copies a message of 14 characters (including the terminating null) into a buffer with space for just 10 characters. As such, the last four characters overflow the buffer resulting in undefined behavior.</p>
|
||||
<p>In this example, the call to <code>sprintf</code> writes a message of 14 characters (including the terminating null) plus the length of the string conversion of `userId` into a buffer with space for just 18 characters. As such, if `userId` is greater or equal to `10000`, the last characters overflow the buffer resulting in undefined behavior.</p>
|
||||
|
||||
<p>To fix this issue three changes should be made:</p>
|
||||
<p>To fix this issue these changes should be made:</p>
|
||||
<ul>
|
||||
<li>Control the size of the buffer using a preprocessor define.</li>
|
||||
<li>Replace the call to <code>strcpy</code> with <code>strncpy</code>, specifying the define as the maximum length to copy. This will prevent the buffer overflow.</li>
|
||||
<li>Consider increasing the buffer size, say to 20 characters, so that the message is displayed correctly.</li>
|
||||
<li>Control the size of the buffer by declaring it with a compile time constant.</li>
|
||||
<li>Preferably, replace the call to <code>sprintf</code> with <code>snprintf</code>, using the defined constant size of the buffer or `sizeof(buffer)` as maximum length to write. This will prevent the buffer overflow.</li>
|
||||
<li>Optionally, if `userId` is expected to be less than `10000`, then return or throw an error if `userId` is out of bounds.</li>
|
||||
<li>Otherwise, consider increasing the buffer size to at least 25 characters, so that the message is displayed correctly regardless of the value of `userId`.</li>
|
||||
</ul>
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.</li>
|
||||
|
||||
|
||||
<!-- LocalWords: preprocessor CWE STR
|
||||
-->
|
||||
|
||||
</references>
|
||||
<include src="OverrunWriteReferences.inc.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
@@ -21,12 +21,14 @@ import semmle.code.cpp.commons.Alloc
|
||||
* See CWE-120/UnboundedWrite.ql for a summary of CWE-120 alert cases.
|
||||
*/
|
||||
|
||||
from BufferWrite bw, Expr dest, int destSize, int estimated
|
||||
from BufferWrite bw, Expr dest, int destSize, int estimated, BufferWriteEstimationReason reason
|
||||
where
|
||||
not bw.hasExplicitLimit() and // has no explicit size limit
|
||||
dest = bw.getDest() and
|
||||
destSize = getBufferSize(dest, _) and
|
||||
estimated = bw.getMaxDataLimited(_) and
|
||||
estimated = bw.getMaxDataLimited(reason) and
|
||||
// we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overruning-write
|
||||
not reason instanceof ValueFlowAnalysis and
|
||||
// we can deduce that too much data may be copied (even without
|
||||
// long '%f' conversions)
|
||||
estimated > destSize
|
||||
|
||||
@@ -6,30 +6,19 @@
|
||||
<p>The program performs a buffer copy or write operation that includes one or more float to string conversions (i.e. the %f format specifier), which may overflow the destination buffer if extreme inputs are given. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Always control the length of buffer copy and buffer write operations. <code>strncpy</code> should be used over <code>strcpy</code>, <code>snprintf</code> over <code>sprintf</code>, and in other cases 'n-variant' functions should be preferred.</p>
|
||||
|
||||
</recommendation>
|
||||
<include src="OverrunWriteRecommendation.inc.qhelp" />
|
||||
<example>
|
||||
<sample src="OverrunWriteFloat.c" />
|
||||
|
||||
<p>In this example, the call to <code>sprintf</code> contains a %f format specifier. Though a 256 character buffer has been allowed, it is not sufficient for the most extreme floating point inputs. For example the representation of double value 1e304 (that is 1 with 304 zeroes after it) will overflow a buffer of this length.</p>
|
||||
<p>In this example, the call to <code>sprintf</code> contains a <code>%f</code> format specifier. Though a 256 character buffer has been allowed, it is not sufficient for the most extreme floating point inputs. For example the representation of double value 1e304 (that is 1 with 304 zeroes after it) will overflow a buffer of this length.</p>
|
||||
|
||||
<p>To fix this issue three changes should be made:</p>
|
||||
<ul>
|
||||
<li>Control the size of the buffer using a preprocessor define.</li>
|
||||
<li>Replace the call to <code>sprintf</code> with <code>snprintf</code>, specifying the define as the maximum length to copy. This will prevent the buffer overflow.</li>
|
||||
<li>Consider using the %g format specifier instead of %f.</li>
|
||||
<li>Consider using the <code>%g</code> format specifier instead of <code>%f</code>.</li>
|
||||
</ul>
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding
|
||||
Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee
|
||||
that storage for strings has sufficient space for character data and
|
||||
the null terminator</a>.</li>
|
||||
|
||||
|
||||
</references>
|
||||
<include src="OverrunWriteReferences.inc.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<recommendation>
|
||||
<p>Always control the length of buffer copy and buffer write operations. <code>strncpy</code> should be used over <code>strcpy</code>, <code>snprintf</code> over <code>sprintf</code>, and in other cases 'n-variant' functions should be preferred.</p>
|
||||
</recommendation>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard: <a href="https://www.securecoding.cert.org/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.</li>
|
||||
<li>CERT C++ Coding Standard: <a href="https://www.securecoding.cert.org/confluence/display/cplusplus/STR50-CPP.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.</li>
|
||||
|
||||
<!-- LocalWords: preprocessor CWE STR
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -6,10 +6,7 @@
|
||||
<p>The program performs a buffer copy or write operation with no upper limit on the size of the copy. An unexpectedly long input that reaches this code will cause the buffer to overflow. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>Always control the length of buffer copy and buffer write operations. <code>strncpy</code> should be used over <code>strcpy</code>, <code>snprintf</code> over <code>sprintf</code> etc. In general 'n-variant' functions should be preferred.</p>
|
||||
|
||||
</recommendation>
|
||||
<include src="OverrunWriteRecommendation.inc.qhelp" />
|
||||
<example>
|
||||
<sample src="UnboundedWrite.c" />
|
||||
|
||||
@@ -18,13 +15,5 @@
|
||||
<p>To fix the problem the call to <code>sprintf</code> should be replaced with <code>snprintf</code>, specifying a maximum length of 80 characters.</p>
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C++ Coding Standard: <a href="https://www.securecoding.cert.org/confluence/display/cplusplus/STR50-CPP.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR50-CPP. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.</li>
|
||||
|
||||
|
||||
<!-- LocalWords: CWE STR
|
||||
-->
|
||||
|
||||
</references>
|
||||
<include src="OverrunWriteReferences.inc.qhelp" />
|
||||
</qhelp>
|
||||
|
||||
@@ -33,7 +33,7 @@ import TaintedWithPath
|
||||
* hasExplicitLimit() exists(getMaxData()) exists(getBufferSize(bw.getDest(), _))) handled by
|
||||
* NO NO either UnboundedWrite.ql isUnboundedWrite()
|
||||
* NO YES NO UnboundedWrite.ql isMaybeUnboundedWrite()
|
||||
* NO YES YES OverrunWrite.ql, OverrunWriteFloat.ql
|
||||
* NO YES YES VeryLikelyOverrunWrite.ql, OverrunWrite.ql, OverrunWriteFloat.ql
|
||||
* YES either YES BadlyBoundedWrite.ql
|
||||
* YES either NO (assumed OK)
|
||||
*/
|
||||
|
||||
14
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.c
Normal file
14
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.c
Normal file
@@ -0,0 +1,14 @@
|
||||
int sayHello(uint32_t userId)
|
||||
{
|
||||
char buffer[17];
|
||||
|
||||
if (userId > 9999) return USER_ID_OUT_OF_BOUNDS;
|
||||
|
||||
// BAD: this message overflows the buffer if userId >= 1000,
|
||||
// as no space for the null terminator was accounted for
|
||||
sprintf(buffer, "Hello, user %d!", userId);
|
||||
|
||||
MessageBox(hWnd, buffer, "New Message", MB_OK);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
24
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.qhelp
Normal file
24
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.qhelp
Normal file
@@ -0,0 +1,24 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The program performs a buffer copy or write operation with no upper limit on the size of the copy. By analyzing the bounds of the expressions involved, it appears that certain inputs will cause a buffer overflow to occur in this case. In addition to causing program instability, techniques exist which may allow an attacker to use this vulnerability to execute arbitrary code.</p>
|
||||
|
||||
</overview>
|
||||
<include src="OverrunWriteRecommendation.inc.qhelp" />
|
||||
<example>
|
||||
<sample src="VeryLikelyOverrunWrite.c" />
|
||||
|
||||
<p>In this example, the call to <code>sprintf</code> writes a message of 14 characters (including the terminating null) plus the length of the string conversion of `userId` into a buffer with space for just 17 characters. While `userId` is checked to occupy no more than 4 characters when converted, there is no space in the buffer for the terminating null character if `userId >= 1000`. In this case, the null character overflows the buffer resulting in undefined behavior.</p>
|
||||
|
||||
<p>To fix this issue these changes should be made:</p>
|
||||
<ul>
|
||||
<li>Control the size of the buffer by declaring it with a compile time constant.</li>
|
||||
<li>Preferably, replace the call to <code>sprintf</code> with <code>snprintf</code>, using the defined constant size of the buffer or `sizeof(buffer)` as maximum length to write. This will prevent the buffer overflow.</li>
|
||||
<li>Increasing the buffer size to account for the full range of `userId` and the terminating null character.</li>
|
||||
</ul>
|
||||
|
||||
</example>
|
||||
<include src="OverrunWriteReferences.inc.qhelp" />
|
||||
</qhelp>
|
||||
34
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql
Normal file
34
cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql
Normal file
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* @name Likely overrunning write
|
||||
* @description Buffer write operations that do not control the length
|
||||
* of data written may overflow
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id cpp/very-likely-overrunning-write
|
||||
* @tags reliability
|
||||
* security
|
||||
* external/cwe/cwe-120
|
||||
* external/cwe/cwe-787
|
||||
* external/cwe/cwe-805
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.security.BufferWrite
|
||||
import semmle.code.cpp.commons.Alloc
|
||||
|
||||
/*
|
||||
* See CWE-120/UnboundedWrite.ql for a summary of CWE-120 alert cases.
|
||||
*/
|
||||
|
||||
from BufferWrite bw, Expr dest, int destSize, int estimated, ValueFlowAnalysis reason
|
||||
where
|
||||
not bw.hasExplicitLimit() and // has no explicit size limit
|
||||
dest = bw.getDest() and
|
||||
destSize = getBufferSize(dest, _) and
|
||||
estimated = bw.getMaxDataLimited(reason) and
|
||||
// we can deduce from non-trivial range analysis that too much data may be copied
|
||||
estimated > destSize
|
||||
select bw,
|
||||
"This '" + bw.getBWDesc() + "' operation requires " + estimated +
|
||||
" bytes but the destination is only " + destSize + " bytes."
|
||||
@@ -19,6 +19,7 @@ import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
import semmle.code.cpp.models.interfaces.Allocation
|
||||
import semmle.code.cpp.commons.NullTermination
|
||||
|
||||
predicate terminationProblem(AllocationExpr malloc, string msg) {
|
||||
// malloc(strlen(...))
|
||||
@@ -35,13 +36,7 @@ predicate terminationProblem(AllocationExpr malloc, string msg) {
|
||||
af.hasArrayWithUnknownSize(arg)
|
||||
or
|
||||
// flows into string argument to a formatting function (such as `printf`)
|
||||
exists(int n, FormatLiteral fl |
|
||||
fc.getArgument(arg) = fc.(FormattingFunctionCall).getConversionArgument(n) and
|
||||
fl = fc.(FormattingFunctionCall).getFormat() and
|
||||
fl.getConversionType(n) instanceof PointerType and // `%s`, `%ws` etc
|
||||
not fl.getConversionType(n) instanceof VoidPointerType and // exclude: `%p`
|
||||
not fl.hasPrecision(n) // exclude: `%.*s`
|
||||
)
|
||||
formatArgumentMustBeNullTerminated(fc, fc.getArgument(arg))
|
||||
)
|
||||
) and
|
||||
msg = "This allocation does not include space to null-terminate the string."
|
||||
|
||||
@@ -22,11 +22,13 @@ import semmle.code.cpp.dataflow.DataFlow
|
||||
* Holds if `sub` is guarded by a condition which ensures that
|
||||
* `left >= right`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
pragma[nomagic]
|
||||
predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
exists(GuardCondition guard, int k |
|
||||
guard.controls(sub.getBasicBlock(), _) and
|
||||
guard.ensuresLt(left, right, k, sub.getBasicBlock(), false) and
|
||||
exprIsSubLeftOrLess(pragma[only_bind_into](sub), _) and // Manual magic
|
||||
exists(GuardCondition guard, int k, BasicBlock bb |
|
||||
pragma[only_bind_into](bb) = sub.getBasicBlock() and
|
||||
guard.controls(pragma[only_bind_into](bb), _) and
|
||||
guard.ensuresLt(left, right, k, bb, false) and
|
||||
k >= 0
|
||||
)
|
||||
}
|
||||
@@ -36,47 +38,56 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
|
||||
* `sub.getLeftOperand()`.
|
||||
*/
|
||||
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
interestingSubExpr(sub, _) and // Manual magic
|
||||
(
|
||||
n.asExpr() = sub.getLeftOperand()
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// dataflow
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
(
|
||||
DataFlow::localFlowStep(n, other) or
|
||||
DataFlow::localFlowStep(other, n)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other |
|
||||
// guard constraining `sub`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `other`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
|
||||
p <= 1 and
|
||||
q <= 0
|
||||
)
|
||||
or
|
||||
exists(DataFlow::Node other, float p, float q |
|
||||
// linear access of `n`
|
||||
exprIsSubLeftOrLess(sub, other) and
|
||||
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
|
||||
p >= 1 and
|
||||
q >= 0
|
||||
)
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
not isFromMacroDefinition(ro) and
|
||||
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {
|
||||
not isFromMacroDefinition(sub) and
|
||||
ro.getLesserOperand().getValue().toInt() = 0 and
|
||||
ro.getGreaterOperand() = sub and
|
||||
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
|
||||
exprMightOverflowNegatively(sub.getFullyConverted()) and // generally catches false positives involving constants
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand())) // generally catches false positives where there's a relation between the left and right operands
|
||||
// generally catches false positives involving constants
|
||||
exprMightOverflowNegatively(sub.getFullyConverted())
|
||||
}
|
||||
|
||||
from RelationalOperation ro, SubExpr sub
|
||||
where
|
||||
interestingSubExpr(sub, ro) and
|
||||
not isFromMacroDefinition(ro) and
|
||||
// generally catches false positives where there's a relation between the left and right operands
|
||||
not exprIsSubLeftOrLess(sub, DataFlow::exprNode(sub.getRightOperand()))
|
||||
select ro, "Unsigned subtraction can never be negative."
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Cleartext storage of sensitive information in file
|
||||
* @description Storing sensitive information in cleartext can expose it
|
||||
* to an attacker.
|
||||
* @kind problem
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
@@ -17,6 +17,19 @@ import semmle.code.cpp.security.SensitiveExprs
|
||||
import semmle.code.cpp.security.FileWrite
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* Taint flow from a sensitive expression to a `FileWrite` sink.
|
||||
*/
|
||||
class FromSensitiveConfiguration extends TaintTracking::Configuration {
|
||||
FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { any(FileWrite w).getASource() = sink.asExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An operation on a filename.
|
||||
@@ -43,12 +56,17 @@ predicate isFileName(GVN gvn) {
|
||||
)
|
||||
}
|
||||
|
||||
from FileWrite w, SensitiveExpr source, Expr mid, Expr dest
|
||||
from
|
||||
FromSensitiveConfiguration config, SensitiveExpr source, DataFlow::PathNode sourceNode, Expr mid,
|
||||
DataFlow::PathNode midNode, FileWrite w, Expr dest
|
||||
where
|
||||
DataFlow::localFlow(DataFlow::exprNode(source), DataFlow::exprNode(mid)) and
|
||||
config.hasFlowPath(sourceNode, midNode) and
|
||||
sourceNode.getNode().asExpr() = source and
|
||||
midNode.getNode().asExpr() = mid and
|
||||
mid = w.getASource() and
|
||||
dest = w.getDest() and
|
||||
not isFileName(globalValueNumber(source)) and // file names are not passwords
|
||||
not exists(string convChar | convChar = w.getSourceConvChar(mid) | not convChar = ["s", "S"]) // ignore things written with other conversion characters
|
||||
select w, "This write into file '" + dest.toString() + "' may contain unencrypted data from $@",
|
||||
source, "this source."
|
||||
select w, sourceNode, midNode,
|
||||
"This write into file '" + dest.toString() + "' may contain unencrypted data from $@", source,
|
||||
"this source."
|
||||
|
||||
@@ -105,8 +105,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
|
||||
* practice it usually isn't very important which query reports a result as
|
||||
* long as its reported exactly once.
|
||||
*
|
||||
* We do exclude function calls that specify a constant socket, which is
|
||||
* likely to mean standard input, standard output or a similar channel.
|
||||
* We do exclude function calls that specify an apparently constant socket,
|
||||
* which is likely to mean standard input, standard output or a similar channel.
|
||||
*/
|
||||
abstract class NetworkSendRecv extends FunctionCall {
|
||||
SendRecv target;
|
||||
@@ -125,6 +125,13 @@ abstract class NetworkSendRecv extends FunctionCall {
|
||||
v.getInitializer().getExpr() instanceof Literal and
|
||||
g = globalValueNumber(v.getAnAccess())
|
||||
)
|
||||
or
|
||||
// result of a function call with literal inputs (likely constant)
|
||||
exists(FunctionCall fc |
|
||||
forex(Expr arg | arg = fc.getAnArgument() | arg instanceof Literal) and
|
||||
g = globalValueNumber(fc)
|
||||
)
|
||||
// (this is far from exhaustive)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -147,18 +154,28 @@ class NetworkRecv extends NetworkSendRecv {
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that is an argument or return value from an encryption or
|
||||
* decryption call.
|
||||
* An expression that is an argument or return value from an encryption /
|
||||
* decryption call. This is quite inclusive to minimize false positives, for
|
||||
* example `SecureZeroMemory` is not an encryption routine but a clue that
|
||||
* encryption may be present.
|
||||
*/
|
||||
class Encrypted extends Expr {
|
||||
Encrypted() {
|
||||
exists(FunctionCall fc |
|
||||
fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and
|
||||
fc.getTarget()
|
||||
.getName()
|
||||
.toLowerCase()
|
||||
.regexpMatch(".*(crypt|encode|decode|hash|securezero).*") and
|
||||
(
|
||||
this = fc or
|
||||
this = fc.getAnArgument()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Type t |
|
||||
this.getType().refersTo(t) and
|
||||
t.getName().toLowerCase().regexpMatch(".*(crypt|encode|decode|hash|securezero).*")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,7 @@ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall {
|
||||
class NullDaclConfig extends DataFlow::Configuration {
|
||||
NullDaclConfig() { this = "NullDaclConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(NullValue nullExpr | source.asExpr() = nullExpr)
|
||||
}
|
||||
override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() |
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/return-stack-allocated-memory` query has been improved to produce fewer false positives. The
|
||||
query has also been converted to a `path-problem` query.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* The `cpp/cleartext-storage-file` query has been upgraded with non-local taint flow and has been converted to a `path-problem` query.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: newQuery
|
||||
---
|
||||
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
|
||||
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.6.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.6
|
||||
1
cpp/ql/src/change-notes/released/0.0.7.md
Normal file
1
cpp/ql/src/change-notes/released/0.0.7.md
Normal file
@@ -0,0 +1 @@
|
||||
## 0.0.7
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.5
|
||||
lastReleaseVersion: 0.0.7
|
||||
|
||||
@@ -24,10 +24,10 @@ class CallUsedToHandleErrors extends FunctionCall {
|
||||
not exists(this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call throwing an exception
|
||||
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
|
||||
this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr
|
||||
or
|
||||
// call logging a message, possibly an error
|
||||
exists(FormattingFunction ff | ff = this.(ControlFlowNode).getASuccessor())
|
||||
this.(ControlFlowNode).getASuccessor() instanceof FormattingFunction
|
||||
or
|
||||
// enabling recursive search
|
||||
exists(CallUsedToHandleErrors fr | getTarget() = fr.getEnclosingFunction())
|
||||
@@ -37,9 +37,9 @@ class CallUsedToHandleErrors extends FunctionCall {
|
||||
/** Holds if the conditions for a call outside the wrapper function are met. */
|
||||
predicate conditionsOutsideWrapper(FunctionCall fcp) {
|
||||
fcp.getNumberOfArguments() > 0 and
|
||||
not exists(ConditionalStmt cdtmp | fcp.getEnclosingStmt().getParentStmt*() = cdtmp) and
|
||||
not exists(Loop lptmp | fcp.getEnclosingStmt().getParentStmt*() = lptmp) and
|
||||
not exists(ReturnStmt rttmp | fcp.getEnclosingStmt().getParentStmt*() = rttmp) and
|
||||
not fcp.getEnclosingStmt().getParentStmt*() instanceof ConditionalStmt and
|
||||
not fcp.getEnclosingStmt().getParentStmt*() instanceof Loop and
|
||||
not fcp.getEnclosingStmt().getParentStmt*() instanceof ReturnStmt and
|
||||
not exists(FunctionCall fctmp2 | fcp = fctmp2.getAnArgument().getAChild*()) and
|
||||
not exists(Assignment astmp | fcp = astmp.getRValue().getAChild*()) and
|
||||
not exists(Initializer intmp | fcp = intmp.getExpr().getAChild*()) and
|
||||
|
||||
@@ -53,7 +53,15 @@ where
|
||||
fctmp.getTarget().hasGlobalOrStdName("fopen") or
|
||||
fctmp.getTarget().hasGlobalOrStdName("open")
|
||||
) and
|
||||
not fctmp.getArgument(1).getValue().matches("r%") and
|
||||
(
|
||||
fctmp.getArgument(1).getValue().matches("%a%") or
|
||||
fctmp.getArgument(1).getValue().matches("%w%") or
|
||||
// unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes:
|
||||
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
|
||||
// this may introduce false negatives
|
||||
fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT") or
|
||||
fctmp.getArgument(1).getValueText().matches("%O_CREAT%")
|
||||
) and
|
||||
fctmp.getNumberOfArguments() = 2 and
|
||||
not fctmp.getArgument(0).getValue() = "/dev/null" and
|
||||
fcsnd = fctmp
|
||||
|
||||
@@ -92,7 +92,7 @@ where
|
||||
) and
|
||||
exists(Variable vrtmp |
|
||||
vrtmp = fc.getArgument(0).(VariableAccess).getTarget() and
|
||||
vrtmp = fctmp.getArgument(0).(AddressOfExpr).getAddressable().(Variable) and
|
||||
vrtmp = fctmp.getArgument(0).(AddressOfExpr).getAddressable() and
|
||||
not vrtmp instanceof Field
|
||||
)
|
||||
) and
|
||||
|
||||
@@ -26,7 +26,7 @@ class CallMayNotReturn extends FunctionCall {
|
||||
// call to another function that may not return
|
||||
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
|
||||
or
|
||||
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
|
||||
this.(ControlFlowNode).getASuccessor() instanceof ThrowExpr
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ predicate similarArguments(FunctionCall fc, FunctionCall fc1) {
|
||||
|
||||
from FunctionCall fc, FunctionCall fc1
|
||||
where
|
||||
not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and
|
||||
not fc.getASuccessor*() instanceof CallMayNotReturn and
|
||||
not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and
|
||||
(
|
||||
// detecting a repeated call situation within one function
|
||||
|
||||
@@ -15,6 +15,6 @@ from EqualityOperation e, PointerToMemberType t, Class c
|
||||
where
|
||||
e.getAnOperand().getType() = t and
|
||||
t.getClass() = c and
|
||||
exists(VirtualFunction f | c.getAMemberFunction() = f)
|
||||
c.getAMemberFunction() instanceof VirtualFunction
|
||||
select e,
|
||||
"AV Rule 97.1: Neither operand of an equality operator shall be a pointer to a virtual member function."
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-queries
|
||||
version: 0.0.6-dev
|
||||
version: 0.0.8-dev
|
||||
groups: cpp
|
||||
dependencies:
|
||||
codeql/cpp-all: "*"
|
||||
|
||||
@@ -570,6 +570,9 @@ postWithInFlow
|
||||
| test.cpp:481:24:481:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:481:24:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:482:8:482:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:489:7:489:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:491:5:491:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| test.cpp:494:5:494:5 | x [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| true_upon_entry.cpp:9:7:9:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| true_upon_entry.cpp:10:12:10:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
| true_upon_entry.cpp:10:27:10:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. |
|
||||
|
||||
@@ -481,4 +481,16 @@ void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) {
|
||||
writes_to_content(s->content);
|
||||
int* p_content = s->content;
|
||||
sink(*p_content);
|
||||
}
|
||||
}
|
||||
|
||||
bool unknown();
|
||||
|
||||
void regression_with_phi_flow(int clean1) {
|
||||
int x = 0;
|
||||
while (unknown()) {
|
||||
x = clean1;
|
||||
if (unknown()) { }
|
||||
sink(x); // clean
|
||||
x = source();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1403,6 +1403,8 @@ subpaths
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:29:15:29:18 | ReturnValue [c] | A.cpp:48:12:48:18 | call to make [c] |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | c [post update] | A.cpp:55:5:55:5 | b [post update] [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | c [post update] | A.cpp:57:11:57:24 | new [post update] [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | ReturnValue [c] | A.cpp:64:10:64:15 | call to setOnB [c] |
|
||||
@@ -1420,6 +1422,7 @@ subpaths
|
||||
| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:13:46:16 | box1 [post update] [elem2] | B.cpp:17:16:17:27 | new [post update] [box1, elem2] |
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:11:17:17 | ReturnValue [elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:11:10:17 | ReturnValue | D.cpp:22:25:22:31 | call to getElem |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:11:10:17 | ReturnValue | D.cpp:22:25:22:31 | call to getElem |
|
||||
| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | elem [post update] | D.cpp:37:8:37:10 | box [post update] [elem] |
|
||||
| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | elem [post update] | D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] |
|
||||
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | a [post update] | by_reference.cpp:20:5:20:8 | this [post update] [a] |
|
||||
|
||||
@@ -10,35 +10,29 @@ edges
|
||||
| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c |
|
||||
| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] |
|
||||
| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... |
|
||||
| A.cpp:43:10:43:12 | & ... | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c |
|
||||
| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [c] |
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c |
|
||||
| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make [c] |
|
||||
| A.cpp:49:10:49:10 | b [c] | A.cpp:49:13:49:13 | c |
|
||||
| A.cpp:49:13:49:13 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:55:5:55:5 | ref arg b [c] | A.cpp:56:10:56:10 | b [c] |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c |
|
||||
| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | ref arg b [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] |
|
||||
| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get |
|
||||
| A.cpp:56:13:56:15 | call to get | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:57:11:57:24 | call to B [c] | A.cpp:57:11:57:24 | new [c] |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] |
|
||||
| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c |
|
||||
| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] |
|
||||
| A.cpp:57:28:57:30 | call to get | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:64:10:64:15 | call to setOnB [c] | A.cpp:66:10:66:11 | b2 [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB [c] |
|
||||
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c |
|
||||
| A.cpp:66:10:66:11 | b2 [c] | A.cpp:66:14:66:14 | c |
|
||||
| A.cpp:66:14:66:14 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:73:10:73:19 | call to setOnBWrap [c] | A.cpp:75:10:75:11 | b2 [c] |
|
||||
| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
|
||||
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c |
|
||||
| A.cpp:75:10:75:11 | b2 [c] | A.cpp:75:14:75:14 | c |
|
||||
| A.cpp:75:14:75:14 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:78:27:78:27 | c | A.cpp:81:21:81:21 | c |
|
||||
| A.cpp:81:10:81:15 | call to setOnB [c] | A.cpp:82:12:82:24 | ... ? ... : ... [c] |
|
||||
| A.cpp:81:21:81:21 | c | A.cpp:81:10:81:15 | call to setOnB [c] |
|
||||
@@ -54,9 +48,7 @@ edges
|
||||
| A.cpp:103:14:103:14 | c [a] | A.cpp:107:12:107:13 | c1 [a] |
|
||||
| A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [a] |
|
||||
| A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a |
|
||||
| A.cpp:107:16:107:16 | a | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a |
|
||||
| A.cpp:120:16:120:16 | a | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:124:14:124:14 | b [c] | A.cpp:131:8:131:8 | ref arg b [c] |
|
||||
| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:124:14:124:14 | b [c] |
|
||||
| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:131:8:131:8 | ref arg b [c] |
|
||||
@@ -64,7 +56,6 @@ edges
|
||||
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | ref arg b [c] |
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] |
|
||||
| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c |
|
||||
| A.cpp:132:13:132:13 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... |
|
||||
| A.cpp:140:13:140:13 | b [c] | A.cpp:151:18:151:18 | ref arg b [c] |
|
||||
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:140:13:140:13 | b [c] |
|
||||
@@ -88,15 +79,12 @@ edges
|
||||
| A.cpp:152:10:152:10 | d [b, c] | A.cpp:152:13:152:13 | b [c] |
|
||||
| A.cpp:152:10:152:10 | d [b] | A.cpp:152:13:152:13 | b |
|
||||
| A.cpp:152:10:152:10 | d [post update] [b, c] | A.cpp:153:10:153:10 | d [b, c] |
|
||||
| A.cpp:152:13:152:13 | b | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:152:13:152:13 | b [c] | A.cpp:152:13:152:13 | ref arg b [c] |
|
||||
| A.cpp:152:13:152:13 | b [c] | A.cpp:173:26:173:26 | o [c] |
|
||||
| A.cpp:152:13:152:13 | ref arg b [c] | A.cpp:152:10:152:10 | d [post update] [b, c] |
|
||||
| A.cpp:153:10:153:10 | d [b, c] | A.cpp:153:13:153:13 | b [c] |
|
||||
| A.cpp:153:13:153:13 | b [c] | A.cpp:153:16:153:16 | c |
|
||||
| A.cpp:153:16:153:16 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:154:10:154:10 | b [c] | A.cpp:154:13:154:13 | c |
|
||||
| A.cpp:154:13:154:13 | c | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b |
|
||||
| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 [head] |
|
||||
| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] |
|
||||
@@ -123,7 +111,6 @@ edges
|
||||
| A.cpp:167:47:167:50 | next [head] | A.cpp:169:12:169:12 | l [head] |
|
||||
| A.cpp:167:47:167:50 | next [next, head] | A.cpp:167:44:167:44 | l [next, head] |
|
||||
| A.cpp:169:12:169:12 | l [head] | A.cpp:169:15:169:18 | head |
|
||||
| A.cpp:169:15:169:18 | head | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:173:26:173:26 | o | A.cpp:173:26:173:26 | o |
|
||||
| A.cpp:173:26:173:26 | o [c] | A.cpp:173:26:173:26 | o [c] |
|
||||
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... |
|
||||
@@ -182,7 +169,6 @@ edges
|
||||
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] |
|
||||
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:25:22:31 | call to getElem |
|
||||
| D.cpp:22:25:22:31 | call to getElem | realistic.cpp:41:17:41:17 | o |
|
||||
| D.cpp:28:15:28:24 | new | D.cpp:30:5:30:20 | ... = ... |
|
||||
| D.cpp:30:5:30:5 | b [post update] [box, elem] | D.cpp:31:14:31:14 | b [box, elem] |
|
||||
| D.cpp:30:5:30:20 | ... = ... | D.cpp:30:8:30:10 | box [post update] [elem] |
|
||||
@@ -215,20 +201,16 @@ edges
|
||||
| D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] |
|
||||
| D.cpp:64:10:64:17 | this [boxfield, box, elem] | D.cpp:64:10:64:17 | boxfield [box, elem] |
|
||||
| D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem |
|
||||
| D.cpp:64:25:64:28 | elem | realistic.cpp:41:17:41:17 | o |
|
||||
| E.cpp:19:27:19:27 | p [data, buffer] | E.cpp:21:10:21:10 | p [data, buffer] |
|
||||
| E.cpp:21:10:21:10 | p [data, buffer] | E.cpp:21:13:21:16 | data [buffer] |
|
||||
| E.cpp:21:13:21:16 | data [buffer] | E.cpp:21:18:21:23 | buffer |
|
||||
| E.cpp:21:18:21:23 | buffer | realistic.cpp:41:17:41:17 | o |
|
||||
| E.cpp:28:21:28:23 | ref arg raw | E.cpp:31:10:31:12 | raw |
|
||||
| E.cpp:29:21:29:21 | b [post update] [buffer] | E.cpp:32:10:32:10 | b [buffer] |
|
||||
| E.cpp:29:24:29:29 | ref arg buffer | E.cpp:29:21:29:21 | b [post update] [buffer] |
|
||||
| E.cpp:30:21:30:21 | p [post update] [data, buffer] | E.cpp:33:18:33:19 | & ... [data, buffer] |
|
||||
| E.cpp:30:23:30:26 | data [post update] [buffer] | E.cpp:30:21:30:21 | p [post update] [data, buffer] |
|
||||
| E.cpp:30:28:30:33 | ref arg buffer | E.cpp:30:23:30:26 | data [post update] [buffer] |
|
||||
| E.cpp:31:10:31:12 | raw | realistic.cpp:41:17:41:17 | o |
|
||||
| E.cpp:32:10:32:10 | b [buffer] | E.cpp:32:13:32:18 | buffer |
|
||||
| E.cpp:32:13:32:18 | buffer | realistic.cpp:41:17:41:17 | o |
|
||||
| E.cpp:33:18:33:19 | & ... [data, buffer] | E.cpp:19:27:19:27 | p [data, buffer] |
|
||||
| aliasing.cpp:8:23:8:23 | s [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] |
|
||||
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:8:23:8:23 | s [m1] |
|
||||
@@ -243,21 +225,17 @@ edges
|
||||
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | aliasing.cpp:29:8:29:9 | s1 [m1] |
|
||||
| aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | aliasing.cpp:30:8:30:9 | s2 [m1] |
|
||||
| aliasing.cpp:29:8:29:9 | s1 [m1] | aliasing.cpp:29:11:29:12 | m1 |
|
||||
| aliasing.cpp:29:11:29:12 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:30:8:30:9 | s2 [m1] | aliasing.cpp:30:11:30:12 | m1 |
|
||||
| aliasing.cpp:30:11:30:12 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | aliasing.cpp:62:8:62:12 | copy2 [m1] |
|
||||
| aliasing.cpp:60:3:60:22 | ... = ... | aliasing.cpp:60:3:60:4 | s2 [post update] [m1] |
|
||||
| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | ... = ... |
|
||||
| aliasing.cpp:62:8:62:12 | copy2 [m1] | aliasing.cpp:62:14:62:15 | m1 |
|
||||
| aliasing.cpp:62:14:62:15 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w [s, m1] |
|
||||
| aliasing.cpp:92:3:92:23 | ... = ... | aliasing.cpp:92:5:92:5 | s [post update] [m1] |
|
||||
| aliasing.cpp:92:5:92:5 | s [post update] [m1] | aliasing.cpp:92:3:92:3 | w [post update] [s, m1] |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... |
|
||||
| aliasing.cpp:93:8:93:8 | w [s, m1] | aliasing.cpp:93:10:93:10 | s [m1] |
|
||||
| aliasing.cpp:93:10:93:10 | s [m1] | aliasing.cpp:93:12:93:13 | m1 |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:158:17:158:20 | ref arg data |
|
||||
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:164:17:164:20 | ref arg data |
|
||||
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:175:15:175:22 | ref arg & ... |
|
||||
@@ -272,13 +250,11 @@ edges
|
||||
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:4:106:5 | pa [inner post update] |
|
||||
| aliasing.cpp:158:15:158:15 | s [post update] [data] | aliasing.cpp:159:9:159:9 | s [data] |
|
||||
| aliasing.cpp:158:17:158:20 | ref arg data | aliasing.cpp:158:15:158:15 | s [post update] [data] |
|
||||
| aliasing.cpp:159:8:159:14 | * ... | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:159:9:159:9 | s [data] | aliasing.cpp:159:11:159:14 | data |
|
||||
| aliasing.cpp:159:11:159:14 | data | aliasing.cpp:159:8:159:14 | * ... |
|
||||
| aliasing.cpp:164:15:164:15 | s [post update] [data] | aliasing.cpp:165:8:165:8 | s [data] |
|
||||
| aliasing.cpp:164:17:164:20 | ref arg data | aliasing.cpp:164:15:164:15 | s [post update] [data] |
|
||||
| aliasing.cpp:165:8:165:8 | s [data] | aliasing.cpp:165:10:165:13 | data |
|
||||
| aliasing.cpp:165:8:165:16 | access to array | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:165:10:165:13 | data | aliasing.cpp:165:8:165:16 | access to array |
|
||||
| aliasing.cpp:175:15:175:22 | ref arg & ... | aliasing.cpp:175:21:175:22 | m1 [inner post update] |
|
||||
| aliasing.cpp:175:16:175:17 | s2 [post update] [s, m1] | aliasing.cpp:176:8:176:9 | s2 [s, m1] |
|
||||
@@ -286,33 +262,24 @@ edges
|
||||
| aliasing.cpp:175:21:175:22 | m1 [inner post update] | aliasing.cpp:175:19:175:19 | s [post update] [m1] |
|
||||
| aliasing.cpp:176:8:176:9 | s2 [s, m1] | aliasing.cpp:176:11:176:11 | s [m1] |
|
||||
| aliasing.cpp:176:11:176:11 | s [m1] | aliasing.cpp:176:13:176:14 | m1 |
|
||||
| aliasing.cpp:176:13:176:14 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:187:15:187:22 | ref arg & ... | aliasing.cpp:187:21:187:22 | m1 [inner post update] |
|
||||
| aliasing.cpp:187:16:187:17 | s2 [post update] [s, m1] | aliasing.cpp:189:8:189:11 | s2_2 [s, m1] |
|
||||
| aliasing.cpp:187:19:187:19 | s [post update] [m1] | aliasing.cpp:187:16:187:17 | s2 [post update] [s, m1] |
|
||||
| aliasing.cpp:187:21:187:22 | m1 [inner post update] | aliasing.cpp:187:19:187:19 | s [post update] [m1] |
|
||||
| aliasing.cpp:189:8:189:11 | s2_2 [s, m1] | aliasing.cpp:189:13:189:13 | s [m1] |
|
||||
| aliasing.cpp:189:13:189:13 | s [m1] | aliasing.cpp:189:15:189:16 | m1 |
|
||||
| aliasing.cpp:189:15:189:16 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| aliasing.cpp:200:15:200:24 | ref arg & ... | aliasing.cpp:200:23:200:24 | m1 [inner post update] |
|
||||
| aliasing.cpp:200:16:200:18 | ps2 [post update] [s, m1] | aliasing.cpp:201:8:201:10 | ps2 [s, m1] |
|
||||
| aliasing.cpp:200:21:200:21 | s [post update] [m1] | aliasing.cpp:200:16:200:18 | ps2 [post update] [s, m1] |
|
||||
| aliasing.cpp:200:23:200:24 | m1 [inner post update] | aliasing.cpp:200:21:200:21 | s [post update] [m1] |
|
||||
| aliasing.cpp:201:8:201:10 | ps2 [s, m1] | aliasing.cpp:201:13:201:13 | s [m1] |
|
||||
| aliasing.cpp:201:13:201:13 | s [m1] | aliasing.cpp:201:15:201:16 | m1 |
|
||||
| aliasing.cpp:201:15:201:16 | m1 | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... |
|
||||
| arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... |
|
||||
| arrays.cpp:7:8:7:13 | access to array | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:8:8:8:13 | access to array | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:9:8:9:11 | * ... | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:10:8:10:15 | * ... | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array |
|
||||
| arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:17:8:17:13 | access to array |
|
||||
| arrays.cpp:16:8:16:13 | access to array | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:17:8:17:13 | access to array | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | arrays.cpp:37:8:37:8 | o [nested, arr, data] |
|
||||
| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | arrays.cpp:38:8:38:8 | o [nested, arr, data] |
|
||||
| arrays.cpp:36:3:36:17 | access to array [post update] [data] | arrays.cpp:36:12:36:14 | arr [inner post update] [data] |
|
||||
@@ -336,7 +303,6 @@ edges
|
||||
| arrays.cpp:38:8:38:22 | access to array [data] | arrays.cpp:38:24:38:27 | data |
|
||||
| arrays.cpp:38:10:38:15 | nested [arr, data] | arrays.cpp:38:17:38:19 | arr [data] |
|
||||
| arrays.cpp:38:17:38:19 | arr [data] | arrays.cpp:38:8:38:22 | access to array [data] |
|
||||
| arrays.cpp:38:24:38:27 | data | realistic.cpp:41:17:41:17 | o |
|
||||
| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | arrays.cpp:43:8:43:8 | o [indirect, arr, data] |
|
||||
| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | arrays.cpp:44:8:44:8 | o [indirect, arr, data] |
|
||||
| arrays.cpp:42:3:42:20 | access to array [post update] [data] | arrays.cpp:42:15:42:17 | arr [inner post update] [data] |
|
||||
@@ -360,7 +326,6 @@ edges
|
||||
| arrays.cpp:44:8:44:25 | access to array [data] | arrays.cpp:44:27:44:30 | data |
|
||||
| arrays.cpp:44:10:44:17 | indirect [arr, data] | arrays.cpp:44:20:44:22 | arr [data] |
|
||||
| arrays.cpp:44:20:44:22 | arr [data] | arrays.cpp:44:8:44:25 | access to array [data] |
|
||||
| arrays.cpp:44:27:44:30 | data | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... |
|
||||
| by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:11:39:11:39 | s [a] |
|
||||
| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:5:12:5 | s [post update] [a] |
|
||||
@@ -387,23 +352,19 @@ edges
|
||||
| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | ref arg s [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:35:9:35:19 | this [a] |
|
||||
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:51:10:51:20 | call to getDirectly |
|
||||
| by_reference.cpp:51:10:51:20 | call to getDirectly | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:56:3:56:3 | ref arg s [a] | by_reference.cpp:57:8:57:8 | s [a] |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value |
|
||||
| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | ref arg s [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:39:9:39:21 | this [a] |
|
||||
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly |
|
||||
| by_reference.cpp:57:10:57:22 | call to getIndirectly | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:62:3:62:3 | ref arg s [a] | by_reference.cpp:63:8:63:8 | s [a] |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value |
|
||||
| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | ref arg s [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:43:9:43:27 | this [a] |
|
||||
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
|
||||
| by_reference.cpp:63:10:63:28 | call to getThroughNonMember | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:68:17:68:18 | ref arg & ... [a] | by_reference.cpp:69:22:69:23 | & ... [a] |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value |
|
||||
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
|
||||
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:31:46:31:46 | s [a] |
|
||||
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
|
||||
| by_reference.cpp:83:31:83:35 | inner [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] |
|
||||
@@ -455,20 +416,14 @@ edges
|
||||
| by_reference.cpp:108:24:108:24 | a [inner post update] | by_reference.cpp:108:16:108:21 | pouter [post update] [a] |
|
||||
| by_reference.cpp:110:8:110:12 | outer [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested [a] |
|
||||
| by_reference.cpp:110:14:110:25 | inner_nested [a] | by_reference.cpp:110:27:110:27 | a |
|
||||
| by_reference.cpp:110:27:110:27 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:111:8:111:12 | outer [inner_ptr, a] | by_reference.cpp:111:14:111:22 | inner_ptr [a] |
|
||||
| by_reference.cpp:111:14:111:22 | inner_ptr [a] | by_reference.cpp:111:25:111:25 | a |
|
||||
| by_reference.cpp:111:25:111:25 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:112:8:112:12 | outer [a] | by_reference.cpp:112:14:112:14 | a |
|
||||
| by_reference.cpp:112:14:112:14 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:114:8:114:13 | pouter [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested [a] |
|
||||
| by_reference.cpp:114:16:114:27 | inner_nested [a] | by_reference.cpp:114:29:114:29 | a |
|
||||
| by_reference.cpp:114:29:114:29 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:115:8:115:13 | pouter [inner_ptr, a] | by_reference.cpp:115:16:115:24 | inner_ptr [a] |
|
||||
| by_reference.cpp:115:16:115:24 | inner_ptr [a] | by_reference.cpp:115:27:115:27 | a |
|
||||
| by_reference.cpp:115:27:115:27 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:116:8:116:13 | pouter [a] | by_reference.cpp:116:16:116:16 | a |
|
||||
| by_reference.cpp:116:16:116:16 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | by_reference.cpp:130:8:130:12 | outer [inner_nested, a] |
|
||||
| by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] |
|
||||
| by_reference.cpp:123:21:123:36 | ref arg * ... [a] | by_reference.cpp:123:28:123:36 | inner_ptr [inner post update] [a] |
|
||||
@@ -485,20 +440,14 @@ edges
|
||||
| by_reference.cpp:128:23:128:23 | ref arg a | by_reference.cpp:128:15:128:20 | pouter [post update] [a] |
|
||||
| by_reference.cpp:130:8:130:12 | outer [inner_nested, a] | by_reference.cpp:130:14:130:25 | inner_nested [a] |
|
||||
| by_reference.cpp:130:14:130:25 | inner_nested [a] | by_reference.cpp:130:27:130:27 | a |
|
||||
| by_reference.cpp:130:27:130:27 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:131:8:131:12 | outer [inner_ptr, a] | by_reference.cpp:131:14:131:22 | inner_ptr [a] |
|
||||
| by_reference.cpp:131:14:131:22 | inner_ptr [a] | by_reference.cpp:131:25:131:25 | a |
|
||||
| by_reference.cpp:131:25:131:25 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:132:8:132:12 | outer [a] | by_reference.cpp:132:14:132:14 | a |
|
||||
| by_reference.cpp:132:14:132:14 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:134:8:134:13 | pouter [inner_nested, a] | by_reference.cpp:134:16:134:27 | inner_nested [a] |
|
||||
| by_reference.cpp:134:16:134:27 | inner_nested [a] | by_reference.cpp:134:29:134:29 | a |
|
||||
| by_reference.cpp:134:29:134:29 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:135:8:135:13 | pouter [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [a] |
|
||||
| by_reference.cpp:135:16:135:24 | inner_ptr [a] | by_reference.cpp:135:27:135:27 | a |
|
||||
| by_reference.cpp:135:27:135:27 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| by_reference.cpp:136:8:136:13 | pouter [a] | by_reference.cpp:136:16:136:16 | a |
|
||||
| by_reference.cpp:136:16:136:16 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | this [a_] |
|
||||
| complex.cpp:9:20:9:21 | this [a_] | complex.cpp:9:20:9:21 | a_ |
|
||||
| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [b_] |
|
||||
@@ -542,31 +491,26 @@ edges
|
||||
| complex.cpp:65:7:65:8 | b3 [inner, f, a_] | complex.cpp:40:17:40:17 | b [inner, f, a_] |
|
||||
| complex.cpp:65:7:65:8 | b3 [inner, f, b_] | complex.cpp:40:17:40:17 | b [inner, f, b_] |
|
||||
| conflated.cpp:19:19:19:21 | ref arg raw | conflated.cpp:20:8:20:10 | raw |
|
||||
| conflated.cpp:20:8:20:10 | raw | realistic.cpp:41:17:41:17 | o |
|
||||
| conflated.cpp:29:3:29:4 | pa [post update] [x] | conflated.cpp:30:8:30:9 | pa [x] |
|
||||
| conflated.cpp:29:3:29:22 | ... = ... | conflated.cpp:29:3:29:4 | pa [post update] [x] |
|
||||
| conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:29:3:29:22 | ... = ... |
|
||||
| conflated.cpp:30:8:30:9 | pa [x] | conflated.cpp:30:12:30:12 | x |
|
||||
| conflated.cpp:30:12:30:12 | x | realistic.cpp:41:17:41:17 | o |
|
||||
| conflated.cpp:36:3:36:4 | pa [post update] [x] | conflated.cpp:37:8:37:9 | pa [x] |
|
||||
| conflated.cpp:36:3:36:22 | ... = ... | conflated.cpp:36:3:36:4 | pa [post update] [x] |
|
||||
| conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:36:3:36:22 | ... = ... |
|
||||
| conflated.cpp:37:8:37:9 | pa [x] | conflated.cpp:37:12:37:12 | x |
|
||||
| conflated.cpp:37:12:37:12 | x | realistic.cpp:41:17:41:17 | o |
|
||||
| conflated.cpp:54:3:54:4 | ll [post update] [next, y] | conflated.cpp:55:8:55:9 | ll [next, y] |
|
||||
| conflated.cpp:54:3:54:28 | ... = ... | conflated.cpp:54:7:54:10 | next [post update] [y] |
|
||||
| conflated.cpp:54:7:54:10 | next [post update] [y] | conflated.cpp:54:3:54:4 | ll [post update] [next, y] |
|
||||
| conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:54:3:54:28 | ... = ... |
|
||||
| conflated.cpp:55:8:55:9 | ll [next, y] | conflated.cpp:55:12:55:15 | next [y] |
|
||||
| conflated.cpp:55:12:55:15 | next [y] | conflated.cpp:55:18:55:18 | y |
|
||||
| conflated.cpp:55:18:55:18 | y | realistic.cpp:41:17:41:17 | o |
|
||||
| conflated.cpp:60:3:60:4 | ll [post update] [next, y] | conflated.cpp:61:8:61:9 | ll [next, y] |
|
||||
| conflated.cpp:60:3:60:28 | ... = ... | conflated.cpp:60:7:60:10 | next [post update] [y] |
|
||||
| conflated.cpp:60:7:60:10 | next [post update] [y] | conflated.cpp:60:3:60:4 | ll [post update] [next, y] |
|
||||
| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:3:60:28 | ... = ... |
|
||||
| conflated.cpp:61:8:61:9 | ll [next, y] | conflated.cpp:61:12:61:15 | next [y] |
|
||||
| conflated.cpp:61:12:61:15 | next [y] | conflated.cpp:61:18:61:18 | y |
|
||||
| conflated.cpp:61:18:61:18 | y | realistic.cpp:41:17:41:17 | o |
|
||||
| constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:22:18:23 | this [a_] |
|
||||
| constructors.cpp:18:22:18:23 | this [a_] | constructors.cpp:18:22:18:23 | a_ |
|
||||
| constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | this [b_] |
|
||||
@@ -611,21 +555,18 @@ edges
|
||||
| qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:22:5:22:38 | ... = ... |
|
||||
| qualifiers.cpp:23:10:23:14 | outer [inner, a] | qualifiers.cpp:23:16:23:20 | inner [a] |
|
||||
| qualifiers.cpp:23:16:23:20 | inner [a] | qualifiers.cpp:23:23:23:23 | a |
|
||||
| qualifiers.cpp:23:23:23:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] | qualifiers.cpp:28:10:28:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] | qualifiers.cpp:27:5:27:9 | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value |
|
||||
| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:28:10:28:14 | outer [inner, a] | qualifiers.cpp:28:16:28:20 | inner [a] |
|
||||
| qualifiers.cpp:28:16:28:20 | inner [a] | qualifiers.cpp:28:23:28:23 | a |
|
||||
| qualifiers.cpp:28:23:28:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] | qualifiers.cpp:33:10:33:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] | qualifiers.cpp:32:17:32:21 | ref arg outer [inner, a] |
|
||||
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value |
|
||||
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
|
||||
| qualifiers.cpp:33:10:33:14 | outer [inner, a] | qualifiers.cpp:33:16:33:20 | inner [a] |
|
||||
| qualifiers.cpp:33:16:33:20 | inner [a] | qualifiers.cpp:33:23:33:23 | a |
|
||||
| qualifiers.cpp:33:23:33:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| qualifiers.cpp:37:19:37:35 | ref arg * ... [a] | qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] |
|
||||
| qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] | qualifiers.cpp:38:10:38:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:37:26:37:33 | call to getInner [inner post update] [a] | qualifiers.cpp:37:20:37:24 | ref arg outer [inner, a] |
|
||||
@@ -633,7 +574,6 @@ edges
|
||||
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
|
||||
| qualifiers.cpp:38:10:38:14 | outer [inner, a] | qualifiers.cpp:38:16:38:20 | inner [a] |
|
||||
| qualifiers.cpp:38:16:38:20 | inner [a] | qualifiers.cpp:38:23:38:23 | a |
|
||||
| qualifiers.cpp:38:23:38:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| qualifiers.cpp:42:5:42:40 | ... = ... | qualifiers.cpp:42:6:42:22 | * ... [post update] [a] |
|
||||
| qualifiers.cpp:42:6:42:22 | * ... [post update] [a] | qualifiers.cpp:42:13:42:20 | call to getInner [inner post update] [a] |
|
||||
| qualifiers.cpp:42:7:42:11 | ref arg outer [inner, a] | qualifiers.cpp:43:10:43:14 | outer [inner, a] |
|
||||
@@ -641,14 +581,12 @@ edges
|
||||
| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:42:5:42:40 | ... = ... |
|
||||
| qualifiers.cpp:43:10:43:14 | outer [inner, a] | qualifiers.cpp:43:16:43:20 | inner [a] |
|
||||
| qualifiers.cpp:43:16:43:20 | inner [a] | qualifiers.cpp:43:23:43:23 | a |
|
||||
| qualifiers.cpp:43:23:43:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| qualifiers.cpp:47:5:47:42 | ... = ... | qualifiers.cpp:47:15:47:22 | call to getInner [post update] [a] |
|
||||
| qualifiers.cpp:47:6:47:11 | ref arg & ... [inner, a] | qualifiers.cpp:48:10:48:14 | outer [inner, a] |
|
||||
| qualifiers.cpp:47:15:47:22 | call to getInner [post update] [a] | qualifiers.cpp:47:6:47:11 | ref arg & ... [inner, a] |
|
||||
| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:5:47:42 | ... = ... |
|
||||
| qualifiers.cpp:48:10:48:14 | outer [inner, a] | qualifiers.cpp:48:16:48:20 | inner [a] |
|
||||
| qualifiers.cpp:48:16:48:20 | inner [a] | qualifiers.cpp:48:23:48:23 | a |
|
||||
| qualifiers.cpp:48:23:48:23 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o |
|
||||
| realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, userInput, bufferLen] | realistic.cpp:61:21:61:23 | foo [bar, baz, userInput, bufferLen] |
|
||||
| realistic.cpp:53:9:53:18 | access to array [post update] [baz, userInput, bufferLen] | realistic.cpp:53:13:53:15 | bar [inner post update] [baz, userInput, bufferLen] |
|
||||
@@ -756,7 +694,6 @@ edges
|
||||
| struct_init.c:31:23:31:23 | ref arg a | struct_init.c:31:14:31:21 | nestedAB [post update] [a] |
|
||||
| struct_init.c:33:8:33:12 | outer [pointerAB, a] | struct_init.c:33:14:33:22 | pointerAB [a] |
|
||||
| struct_init.c:33:14:33:22 | pointerAB [a] | struct_init.c:33:25:33:25 | a |
|
||||
| struct_init.c:33:25:33:25 | a | realistic.cpp:41:17:41:17 | o |
|
||||
| struct_init.c:36:10:36:24 | & ... [a] | struct_init.c:14:24:14:25 | ab [a] |
|
||||
| struct_init.c:36:11:36:15 | outer [nestedAB, a] | struct_init.c:36:17:36:24 | nestedAB [a] |
|
||||
| struct_init.c:36:17:36:24 | nestedAB [a] | struct_init.c:36:10:36:24 | & ... [a] |
|
||||
|
||||
@@ -18,10 +18,6 @@
|
||||
| test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 |
|
||||
| test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer |
|
||||
| test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer |
|
||||
| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer |
|
||||
| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer |
|
||||
| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer |
|
||||
| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer |
|
||||
| test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 |
|
||||
| test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer |
|
||||
| test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer |
|
||||
|
||||
@@ -352,7 +352,7 @@ void test_strlen(bool cond1, bool cond2)
|
||||
if (cond1)
|
||||
buffer[0] = 0;
|
||||
if (cond1)
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
@@ -361,7 +361,7 @@ void test_strlen(bool cond1, bool cond2)
|
||||
if (cond1)
|
||||
buffer[0] = 0;
|
||||
if (cond2)
|
||||
strlen(buffer); // BAD
|
||||
strlen(buffer); // BAD [NOT DETECTED]
|
||||
}
|
||||
|
||||
{
|
||||
@@ -389,7 +389,7 @@ void test_strlen(bool cond1, bool cond2)
|
||||
|
||||
if (init != 0)
|
||||
{
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ void test_strlen(bool cond1, bool cond2)
|
||||
{
|
||||
// ...
|
||||
} else {
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,231 @@
|
||||
| test.cpp:17:2:17:12 | return ... | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
|
||||
| test.cpp:25:2:25:12 | return ... | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |
|
||||
| test.cpp:47:2:47:11 | return ... | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc |
|
||||
| test.cpp:54:2:54:16 | return ... | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc |
|
||||
| test.cpp:92:2:92:12 | return ... | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc |
|
||||
| test.cpp:112:2:112:12 | return ... | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr |
|
||||
| test.cpp:119:2:119:19 | return ... | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr |
|
||||
| test.cpp:171:3:171:24 | return ... | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal |
|
||||
edges
|
||||
| test.cpp:17:9:17:11 | & ... | test.cpp:17:9:17:11 | StoreValue |
|
||||
| test.cpp:17:10:17:11 | Unary | test.cpp:17:9:17:11 | & ... |
|
||||
| test.cpp:17:10:17:11 | mc | test.cpp:17:10:17:11 | Unary |
|
||||
| test.cpp:23:17:23:19 | & ... | test.cpp:23:17:23:19 | StoreValue |
|
||||
| test.cpp:23:17:23:19 | Store | test.cpp:25:9:25:11 | Load |
|
||||
| test.cpp:23:17:23:19 | StoreValue | test.cpp:23:17:23:19 | Store |
|
||||
| test.cpp:23:18:23:19 | Unary | test.cpp:23:17:23:19 | & ... |
|
||||
| test.cpp:23:18:23:19 | mc | test.cpp:23:18:23:19 | Unary |
|
||||
| test.cpp:25:9:25:11 | Load | test.cpp:25:9:25:11 | ptr |
|
||||
| test.cpp:25:9:25:11 | ptr | test.cpp:25:9:25:11 | StoreValue |
|
||||
| test.cpp:39:17:39:18 | (reference to) | test.cpp:39:17:39:18 | StoreValue |
|
||||
| test.cpp:39:17:39:18 | Store | test.cpp:41:10:41:12 | Load |
|
||||
| test.cpp:39:17:39:18 | StoreValue | test.cpp:39:17:39:18 | Store |
|
||||
| test.cpp:39:17:39:18 | Unary | test.cpp:39:17:39:18 | (reference to) |
|
||||
| test.cpp:39:17:39:18 | mc | test.cpp:39:17:39:18 | Unary |
|
||||
| test.cpp:41:9:41:12 | & ... | test.cpp:41:9:41:12 | StoreValue |
|
||||
| test.cpp:41:10:41:12 | (reference dereference) | test.cpp:41:10:41:12 | Unary |
|
||||
| test.cpp:41:10:41:12 | Load | test.cpp:41:10:41:12 | ref |
|
||||
| test.cpp:41:10:41:12 | Unary | test.cpp:41:9:41:12 | & ... |
|
||||
| test.cpp:41:10:41:12 | Unary | test.cpp:41:10:41:12 | (reference dereference) |
|
||||
| test.cpp:41:10:41:12 | ref | test.cpp:41:10:41:12 | Unary |
|
||||
| test.cpp:47:9:47:10 | (reference to) | test.cpp:47:9:47:10 | StoreValue |
|
||||
| test.cpp:47:9:47:10 | Unary | test.cpp:47:9:47:10 | (reference to) |
|
||||
| test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | Unary |
|
||||
| test.cpp:54:9:54:15 | & ... | test.cpp:54:9:54:15 | StoreValue |
|
||||
| test.cpp:54:11:54:12 | Unary | test.cpp:54:14:54:14 | a |
|
||||
| test.cpp:54:11:54:12 | mc | test.cpp:54:11:54:12 | Unary |
|
||||
| test.cpp:54:14:54:14 | Unary | test.cpp:54:9:54:15 | & ... |
|
||||
| test.cpp:54:14:54:14 | a | test.cpp:54:14:54:14 | Unary |
|
||||
| test.cpp:89:3:89:11 | Store | test.cpp:92:9:92:11 | Load |
|
||||
| test.cpp:89:9:89:11 | & ... | test.cpp:89:9:89:11 | StoreValue |
|
||||
| test.cpp:89:9:89:11 | StoreValue | test.cpp:89:3:89:11 | Store |
|
||||
| test.cpp:89:10:89:11 | Unary | test.cpp:89:9:89:11 | & ... |
|
||||
| test.cpp:89:10:89:11 | mc | test.cpp:89:10:89:11 | Unary |
|
||||
| test.cpp:92:9:92:11 | Load | test.cpp:92:9:92:11 | ptr |
|
||||
| test.cpp:92:9:92:11 | ptr | test.cpp:92:9:92:11 | StoreValue |
|
||||
| test.cpp:112:9:112:11 | Unary | test.cpp:112:9:112:11 | array to pointer conversion |
|
||||
| test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | Unary |
|
||||
| test.cpp:112:9:112:11 | array to pointer conversion | test.cpp:112:9:112:11 | StoreValue |
|
||||
| test.cpp:119:9:119:18 | & ... | test.cpp:119:9:119:18 | StoreValue |
|
||||
| test.cpp:119:11:119:13 | Left | test.cpp:119:11:119:17 | access to array |
|
||||
| test.cpp:119:11:119:13 | Unary | test.cpp:119:11:119:13 | array to pointer conversion |
|
||||
| test.cpp:119:11:119:13 | arr | test.cpp:119:11:119:13 | Unary |
|
||||
| test.cpp:119:11:119:13 | array to pointer conversion | test.cpp:119:11:119:13 | Left |
|
||||
| test.cpp:119:11:119:17 | Unary | test.cpp:119:9:119:18 | & ... |
|
||||
| test.cpp:119:11:119:17 | access to array | test.cpp:119:11:119:17 | Unary |
|
||||
| test.cpp:134:2:134:14 | Store | test.cpp:135:2:135:4 | Load |
|
||||
| test.cpp:134:8:134:10 | Left | test.cpp:134:8:134:14 | ... + ... |
|
||||
| test.cpp:134:8:134:10 | Unary | test.cpp:134:8:134:10 | array to pointer conversion |
|
||||
| test.cpp:134:8:134:10 | arr | test.cpp:134:8:134:10 | Unary |
|
||||
| test.cpp:134:8:134:10 | array to pointer conversion | test.cpp:134:8:134:10 | Left |
|
||||
| test.cpp:134:8:134:14 | ... + ... | test.cpp:134:8:134:14 | StoreValue |
|
||||
| test.cpp:134:8:134:14 | StoreValue | test.cpp:134:2:134:14 | Store |
|
||||
| test.cpp:135:2:135:4 | Left | test.cpp:135:2:135:6 | PointerAdd |
|
||||
| test.cpp:135:2:135:4 | Load | test.cpp:135:2:135:4 | ptr |
|
||||
| test.cpp:135:2:135:4 | ptr | test.cpp:135:2:135:4 | Left |
|
||||
| test.cpp:135:2:135:6 | PointerAdd | test.cpp:135:2:135:6 | StoreValue |
|
||||
| test.cpp:135:2:135:6 | Store | test.cpp:137:9:137:11 | Load |
|
||||
| test.cpp:135:2:135:6 | StoreValue | test.cpp:135:2:135:6 | Store |
|
||||
| test.cpp:137:9:137:11 | Load | test.cpp:137:9:137:11 | ptr |
|
||||
| test.cpp:137:9:137:11 | ptr | test.cpp:137:9:137:11 | StoreValue |
|
||||
| test.cpp:170:26:170:41 | (void *)... | test.cpp:170:26:170:41 | StoreValue |
|
||||
| test.cpp:170:26:170:41 | Store | test.cpp:171:10:171:23 | Load |
|
||||
| test.cpp:170:26:170:41 | StoreValue | test.cpp:170:26:170:41 | Store |
|
||||
| test.cpp:170:34:170:41 | & ... | test.cpp:170:34:170:41 | Unary |
|
||||
| test.cpp:170:34:170:41 | Unary | test.cpp:170:26:170:41 | (void *)... |
|
||||
| test.cpp:170:35:170:41 | Unary | test.cpp:170:34:170:41 | & ... |
|
||||
| test.cpp:170:35:170:41 | myLocal | test.cpp:170:35:170:41 | Unary |
|
||||
| test.cpp:171:10:171:23 | Load | test.cpp:171:10:171:23 | pointerToLocal |
|
||||
| test.cpp:171:10:171:23 | pointerToLocal | test.cpp:171:10:171:23 | StoreValue |
|
||||
| test.cpp:176:25:176:34 | Store | test.cpp:177:10:177:23 | Load |
|
||||
| test.cpp:176:25:176:34 | StoreValue | test.cpp:176:25:176:34 | Store |
|
||||
| test.cpp:176:25:176:34 | Unary | test.cpp:176:25:176:34 | array to pointer conversion |
|
||||
| test.cpp:176:25:176:34 | array to pointer conversion | test.cpp:176:25:176:34 | StoreValue |
|
||||
| test.cpp:176:25:176:34 | localArray | test.cpp:176:25:176:34 | Unary |
|
||||
| test.cpp:177:10:177:23 | (void *)... | test.cpp:177:10:177:23 | StoreValue |
|
||||
| test.cpp:177:10:177:23 | Load | test.cpp:177:10:177:23 | pointerToLocal |
|
||||
| test.cpp:177:10:177:23 | Unary | test.cpp:177:10:177:23 | (void *)... |
|
||||
| test.cpp:177:10:177:23 | pointerToLocal | test.cpp:177:10:177:23 | Unary |
|
||||
| test.cpp:182:21:182:27 | (reference to) | test.cpp:182:21:182:27 | StoreValue |
|
||||
| test.cpp:182:21:182:27 | Store | test.cpp:183:10:183:19 | Load |
|
||||
| test.cpp:182:21:182:27 | StoreValue | test.cpp:182:21:182:27 | Store |
|
||||
| test.cpp:182:21:182:27 | Unary | test.cpp:182:21:182:27 | (reference to) |
|
||||
| test.cpp:182:21:182:27 | myLocal | test.cpp:182:21:182:27 | Unary |
|
||||
| test.cpp:183:10:183:19 | (reference dereference) | test.cpp:183:10:183:19 | Unary |
|
||||
| test.cpp:183:10:183:19 | (reference to) | test.cpp:183:10:183:19 | StoreValue |
|
||||
| test.cpp:183:10:183:19 | Load | test.cpp:183:10:183:19 | refToLocal |
|
||||
| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference dereference) |
|
||||
| test.cpp:183:10:183:19 | Unary | test.cpp:183:10:183:19 | (reference to) |
|
||||
| test.cpp:183:10:183:19 | refToLocal | test.cpp:183:10:183:19 | Unary |
|
||||
| test.cpp:189:16:189:16 | (reference to) | test.cpp:189:16:189:16 | StoreValue |
|
||||
| test.cpp:189:16:189:16 | Store | test.cpp:190:10:190:13 | Load |
|
||||
| test.cpp:189:16:189:16 | StoreValue | test.cpp:189:16:189:16 | Store |
|
||||
| test.cpp:189:16:189:16 | Unary | test.cpp:189:16:189:16 | (reference to) |
|
||||
| test.cpp:189:16:189:16 | p | test.cpp:189:16:189:16 | Unary |
|
||||
| test.cpp:190:10:190:13 | (reference dereference) | test.cpp:190:10:190:13 | Unary |
|
||||
| test.cpp:190:10:190:13 | (reference to) | test.cpp:190:10:190:13 | StoreValue |
|
||||
| test.cpp:190:10:190:13 | Load | test.cpp:190:10:190:13 | pRef |
|
||||
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference dereference) |
|
||||
| test.cpp:190:10:190:13 | Unary | test.cpp:190:10:190:13 | (reference to) |
|
||||
| test.cpp:190:10:190:13 | pRef | test.cpp:190:10:190:13 | Unary |
|
||||
nodes
|
||||
| test.cpp:17:9:17:11 | & ... | semmle.label | & ... |
|
||||
| test.cpp:17:9:17:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:17:10:17:11 | Unary | semmle.label | Unary |
|
||||
| test.cpp:17:10:17:11 | mc | semmle.label | mc |
|
||||
| test.cpp:23:17:23:19 | & ... | semmle.label | & ... |
|
||||
| test.cpp:23:17:23:19 | Store | semmle.label | Store |
|
||||
| test.cpp:23:17:23:19 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:23:18:23:19 | Unary | semmle.label | Unary |
|
||||
| test.cpp:23:18:23:19 | mc | semmle.label | mc |
|
||||
| test.cpp:25:9:25:11 | Load | semmle.label | Load |
|
||||
| test.cpp:25:9:25:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:25:9:25:11 | ptr | semmle.label | ptr |
|
||||
| test.cpp:39:17:39:18 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:39:17:39:18 | Store | semmle.label | Store |
|
||||
| test.cpp:39:17:39:18 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:39:17:39:18 | Unary | semmle.label | Unary |
|
||||
| test.cpp:39:17:39:18 | mc | semmle.label | mc |
|
||||
| test.cpp:41:9:41:12 | & ... | semmle.label | & ... |
|
||||
| test.cpp:41:9:41:12 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:41:10:41:12 | (reference dereference) | semmle.label | (reference dereference) |
|
||||
| test.cpp:41:10:41:12 | Load | semmle.label | Load |
|
||||
| test.cpp:41:10:41:12 | Unary | semmle.label | Unary |
|
||||
| test.cpp:41:10:41:12 | Unary | semmle.label | Unary |
|
||||
| test.cpp:41:10:41:12 | ref | semmle.label | ref |
|
||||
| test.cpp:47:9:47:10 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:47:9:47:10 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:47:9:47:10 | Unary | semmle.label | Unary |
|
||||
| test.cpp:47:9:47:10 | mc | semmle.label | mc |
|
||||
| test.cpp:54:9:54:15 | & ... | semmle.label | & ... |
|
||||
| test.cpp:54:9:54:15 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:54:11:54:12 | Unary | semmle.label | Unary |
|
||||
| test.cpp:54:11:54:12 | mc | semmle.label | mc |
|
||||
| test.cpp:54:14:54:14 | Unary | semmle.label | Unary |
|
||||
| test.cpp:54:14:54:14 | a | semmle.label | a |
|
||||
| test.cpp:89:3:89:11 | Store | semmle.label | Store |
|
||||
| test.cpp:89:9:89:11 | & ... | semmle.label | & ... |
|
||||
| test.cpp:89:9:89:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:89:10:89:11 | Unary | semmle.label | Unary |
|
||||
| test.cpp:89:10:89:11 | mc | semmle.label | mc |
|
||||
| test.cpp:92:9:92:11 | Load | semmle.label | Load |
|
||||
| test.cpp:92:9:92:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:92:9:92:11 | ptr | semmle.label | ptr |
|
||||
| test.cpp:112:9:112:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:112:9:112:11 | Unary | semmle.label | Unary |
|
||||
| test.cpp:112:9:112:11 | arr | semmle.label | arr |
|
||||
| test.cpp:112:9:112:11 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
| test.cpp:119:9:119:18 | & ... | semmle.label | & ... |
|
||||
| test.cpp:119:9:119:18 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:119:11:119:13 | Left | semmle.label | Left |
|
||||
| test.cpp:119:11:119:13 | Unary | semmle.label | Unary |
|
||||
| test.cpp:119:11:119:13 | arr | semmle.label | arr |
|
||||
| test.cpp:119:11:119:13 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
| test.cpp:119:11:119:17 | Unary | semmle.label | Unary |
|
||||
| test.cpp:119:11:119:17 | access to array | semmle.label | access to array |
|
||||
| test.cpp:134:2:134:14 | Store | semmle.label | Store |
|
||||
| test.cpp:134:8:134:10 | Left | semmle.label | Left |
|
||||
| test.cpp:134:8:134:10 | Unary | semmle.label | Unary |
|
||||
| test.cpp:134:8:134:10 | arr | semmle.label | arr |
|
||||
| test.cpp:134:8:134:10 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
| test.cpp:134:8:134:14 | ... + ... | semmle.label | ... + ... |
|
||||
| test.cpp:134:8:134:14 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:135:2:135:4 | Left | semmle.label | Left |
|
||||
| test.cpp:135:2:135:4 | Load | semmle.label | Load |
|
||||
| test.cpp:135:2:135:4 | ptr | semmle.label | ptr |
|
||||
| test.cpp:135:2:135:6 | PointerAdd | semmle.label | PointerAdd |
|
||||
| test.cpp:135:2:135:6 | Store | semmle.label | Store |
|
||||
| test.cpp:135:2:135:6 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:137:9:137:11 | Load | semmle.label | Load |
|
||||
| test.cpp:137:9:137:11 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:137:9:137:11 | ptr | semmle.label | ptr |
|
||||
| test.cpp:170:26:170:41 | (void *)... | semmle.label | (void *)... |
|
||||
| test.cpp:170:26:170:41 | Store | semmle.label | Store |
|
||||
| test.cpp:170:26:170:41 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:170:34:170:41 | & ... | semmle.label | & ... |
|
||||
| test.cpp:170:34:170:41 | Unary | semmle.label | Unary |
|
||||
| test.cpp:170:35:170:41 | Unary | semmle.label | Unary |
|
||||
| test.cpp:170:35:170:41 | myLocal | semmle.label | myLocal |
|
||||
| test.cpp:171:10:171:23 | Load | semmle.label | Load |
|
||||
| test.cpp:171:10:171:23 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:171:10:171:23 | pointerToLocal | semmle.label | pointerToLocal |
|
||||
| test.cpp:176:25:176:34 | Store | semmle.label | Store |
|
||||
| test.cpp:176:25:176:34 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:176:25:176:34 | Unary | semmle.label | Unary |
|
||||
| test.cpp:176:25:176:34 | array to pointer conversion | semmle.label | array to pointer conversion |
|
||||
| test.cpp:176:25:176:34 | localArray | semmle.label | localArray |
|
||||
| test.cpp:177:10:177:23 | (void *)... | semmle.label | (void *)... |
|
||||
| test.cpp:177:10:177:23 | Load | semmle.label | Load |
|
||||
| test.cpp:177:10:177:23 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:177:10:177:23 | Unary | semmle.label | Unary |
|
||||
| test.cpp:177:10:177:23 | pointerToLocal | semmle.label | pointerToLocal |
|
||||
| test.cpp:182:21:182:27 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:182:21:182:27 | Store | semmle.label | Store |
|
||||
| test.cpp:182:21:182:27 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:182:21:182:27 | Unary | semmle.label | Unary |
|
||||
| test.cpp:182:21:182:27 | myLocal | semmle.label | myLocal |
|
||||
| test.cpp:183:10:183:19 | (reference dereference) | semmle.label | (reference dereference) |
|
||||
| test.cpp:183:10:183:19 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:183:10:183:19 | Load | semmle.label | Load |
|
||||
| test.cpp:183:10:183:19 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:183:10:183:19 | Unary | semmle.label | Unary |
|
||||
| test.cpp:183:10:183:19 | Unary | semmle.label | Unary |
|
||||
| test.cpp:183:10:183:19 | refToLocal | semmle.label | refToLocal |
|
||||
| test.cpp:189:16:189:16 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:189:16:189:16 | Store | semmle.label | Store |
|
||||
| test.cpp:189:16:189:16 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:189:16:189:16 | Unary | semmle.label | Unary |
|
||||
| test.cpp:189:16:189:16 | p | semmle.label | p |
|
||||
| test.cpp:190:10:190:13 | (reference dereference) | semmle.label | (reference dereference) |
|
||||
| test.cpp:190:10:190:13 | (reference to) | semmle.label | (reference to) |
|
||||
| test.cpp:190:10:190:13 | Load | semmle.label | Load |
|
||||
| test.cpp:190:10:190:13 | StoreValue | semmle.label | StoreValue |
|
||||
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
|
||||
| test.cpp:190:10:190:13 | Unary | semmle.label | Unary |
|
||||
| test.cpp:190:10:190:13 | pRef | semmle.label | pRef |
|
||||
#select
|
||||
| test.cpp:17:9:17:11 | StoreValue | test.cpp:17:10:17:11 | mc | test.cpp:17:9:17:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:17:10:17:11 | mc | mc |
|
||||
| test.cpp:25:9:25:11 | StoreValue | test.cpp:23:18:23:19 | mc | test.cpp:25:9:25:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:23:18:23:19 | mc | mc |
|
||||
| test.cpp:41:9:41:12 | StoreValue | test.cpp:39:17:39:18 | mc | test.cpp:41:9:41:12 | StoreValue | May return stack-allocated memory from $@. | test.cpp:39:17:39:18 | mc | mc |
|
||||
| test.cpp:47:9:47:10 | StoreValue | test.cpp:47:9:47:10 | mc | test.cpp:47:9:47:10 | StoreValue | May return stack-allocated memory from $@. | test.cpp:47:9:47:10 | mc | mc |
|
||||
| test.cpp:54:9:54:15 | StoreValue | test.cpp:54:11:54:12 | mc | test.cpp:54:9:54:15 | StoreValue | May return stack-allocated memory from $@. | test.cpp:54:11:54:12 | mc | mc |
|
||||
| test.cpp:92:9:92:11 | StoreValue | test.cpp:89:10:89:11 | mc | test.cpp:92:9:92:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:89:10:89:11 | mc | mc |
|
||||
| test.cpp:112:9:112:11 | StoreValue | test.cpp:112:9:112:11 | arr | test.cpp:112:9:112:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:112:9:112:11 | arr | arr |
|
||||
| test.cpp:119:9:119:18 | StoreValue | test.cpp:119:11:119:13 | arr | test.cpp:119:9:119:18 | StoreValue | May return stack-allocated memory from $@. | test.cpp:119:11:119:13 | arr | arr |
|
||||
| test.cpp:137:9:137:11 | StoreValue | test.cpp:134:8:134:10 | arr | test.cpp:137:9:137:11 | StoreValue | May return stack-allocated memory from $@. | test.cpp:134:8:134:10 | arr | arr |
|
||||
| test.cpp:171:10:171:23 | StoreValue | test.cpp:170:35:170:41 | myLocal | test.cpp:171:10:171:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:170:35:170:41 | myLocal | myLocal |
|
||||
| test.cpp:177:10:177:23 | StoreValue | test.cpp:176:25:176:34 | localArray | test.cpp:177:10:177:23 | StoreValue | May return stack-allocated memory from $@. | test.cpp:176:25:176:34 | localArray | localArray |
|
||||
| test.cpp:183:10:183:19 | StoreValue | test.cpp:182:21:182:27 | myLocal | test.cpp:183:10:183:19 | StoreValue | May return stack-allocated memory from $@. | test.cpp:182:21:182:27 | myLocal | myLocal |
|
||||
| test.cpp:190:10:190:13 | StoreValue | test.cpp:189:16:189:16 | p | test.cpp:190:10:190:13 | StoreValue | May return stack-allocated memory from $@. | test.cpp:189:16:189:16 | p | p |
|
||||
|
||||
@@ -38,7 +38,7 @@ MyClass *test4()
|
||||
MyClass mc;
|
||||
MyClass &ref = mc;
|
||||
|
||||
return &ref; // BAD [NOT DETECTED]
|
||||
return &ref; // BAD
|
||||
}
|
||||
|
||||
MyClass &test5()
|
||||
@@ -134,7 +134,7 @@ char *testArray4()
|
||||
ptr = arr + 1;
|
||||
ptr++;
|
||||
|
||||
return ptr; // BAD [NOT DETECTED]
|
||||
return ptr; // BAD
|
||||
}
|
||||
|
||||
char *testArray5()
|
||||
@@ -174,20 +174,20 @@ void *conversionBeforeDataFlow() {
|
||||
void *arrayConversionBeforeDataFlow() {
|
||||
int localArray[4];
|
||||
int *pointerToLocal = localArray; // has conversion
|
||||
return pointerToLocal; // BAD [NOT DETECTED]
|
||||
return pointerToLocal; // BAD
|
||||
}
|
||||
|
||||
int &dataFlowThroughReference() {
|
||||
int myLocal;
|
||||
int &refToLocal = myLocal; // has conversion
|
||||
return refToLocal; // BAD [NOT DETECTED]
|
||||
return refToLocal; // BAD
|
||||
}
|
||||
|
||||
int *&conversionInFlow() {
|
||||
int myLocal;
|
||||
int *p = &myLocal;
|
||||
int *&pRef = p; // has conversion in the middle of data flow
|
||||
return pRef; // BAD [NOT DETECTED]
|
||||
return pRef; // BAD
|
||||
}
|
||||
|
||||
namespace std {
|
||||
@@ -215,4 +215,9 @@ auto make_read_port()
|
||||
auto port = std::shared_ptr<int>(new int);
|
||||
auto ptr = port.get();
|
||||
return ptr; // GOOD
|
||||
}
|
||||
|
||||
void* get_sp() {
|
||||
int p;
|
||||
return (void*)&p; // GOOD: The function name makes it sound like the programmer intended to get the value of the stack pointer.
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql
|
||||
@@ -1,21 +0,0 @@
|
||||
| tests2.cpp:17:3:17:8 | call to wcscpy | This 'call to wcscpy' operation requires 12 bytes but the destination is only 8 bytes. |
|
||||
| tests2.cpp:22:3:22:8 | call to wcscpy | This 'call to wcscpy' operation requires 16 bytes but the destination is only 12 bytes. |
|
||||
| tests2.cpp:27:3:27:8 | call to wcscpy | This 'call to wcscpy' operation requires 20 bytes but the destination is only 16 bytes. |
|
||||
| tests2.cpp:31:3:31:8 | call to wcscpy | This 'call to wcscpy' operation requires 24 bytes but the destination is only 20 bytes. |
|
||||
| tests2.cpp:36:3:36:8 | call to wcscpy | This 'call to wcscpy' operation requires 28 bytes but the destination is only 24 bytes. |
|
||||
| tests2.cpp:41:3:41:8 | call to wcscpy | This 'call to wcscpy' operation requires 32 bytes but the destination is only 28 bytes. |
|
||||
| tests2.cpp:46:3:46:8 | call to wcscpy | This 'call to wcscpy' operation requires 36 bytes but the destination is only 32 bytes. |
|
||||
| tests.c:54:3:54:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:58:3:58:9 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:62:17:62:24 | buffer10 | This 'scanf string argument' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:63:17:63:24 | buffer10 | This 'scanf string argument' operation requires 12 bytes but the destination is only 10 bytes. |
|
||||
| tests.c:86:3:86:8 | call to strcpy | This 'call to strcpy' operation requires 6 bytes but the destination is only 5 bytes. |
|
||||
| tests.c:93:3:93:8 | call to strcpy | This 'call to strcpy' operation requires 6 bytes but the destination is only 5 bytes. |
|
||||
| tests.c:120:3:120:9 | call to sprintf | This 'call to sprintf' operation requires 17 bytes but the destination is only 1 bytes. |
|
||||
| tests.c:121:3:121:9 | call to sprintf | This 'call to sprintf' operation requires 17 bytes but the destination is only 16 bytes. |
|
||||
| tests.c:136:2:136:8 | call to sprintf | This 'call to sprintf' operation requires 11 bytes but the destination is only 10 bytes. |
|
||||
| unions.c:26:2:26:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 15 bytes. |
|
||||
| unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. |
|
||||
| unions.c:32:2:32:7 | call to strcpy | This 'call to strcpy' operation requires 31 bytes but the destination is only 25 bytes. |
|
||||
| var_size_struct.cpp:22:3:22:8 | call to strcpy | This 'call to strcpy' operation requires 10 bytes but the destination is only 9 bytes. |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user