mirror of
https://github.com/github/codeql.git
synced 2026-05-26 17:11:24 +02:00
Compare commits
965 Commits
redsun82/c
...
mbg/go/dep
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a44413acb6 | ||
|
|
789a444174 | ||
|
|
d842107633 | ||
|
|
87f32dc49f | ||
|
|
0fc2875527 | ||
|
|
2c6af0cdb7 | ||
|
|
11f20457e2 | ||
|
|
37151791b4 | ||
|
|
3cbce80d0b | ||
|
|
7599fdd8fa | ||
|
|
0c9cd09140 | ||
|
|
f52e3dcb7f | ||
|
|
a7c166d161 | ||
|
|
546d59ff9d | ||
|
|
83519a9fcc | ||
|
|
4534d67107 | ||
|
|
9c610e8bab | ||
|
|
f8626cd417 | ||
|
|
d39c8d155c | ||
|
|
2d9b249367 | ||
|
|
4cc6a07620 | ||
|
|
99f5dcaaa4 | ||
|
|
cdfa58645a | ||
|
|
28fe20e3e4 | ||
|
|
75a7507017 | ||
|
|
10c9b747a5 | ||
|
|
8a2be0910c | ||
|
|
2918d30697 | ||
|
|
825d3709d8 | ||
|
|
193cd46a76 | ||
|
|
7a8d2392ee | ||
|
|
542bdf0792 | ||
|
|
3c110f2eb8 | ||
|
|
c49e2ab2da | ||
|
|
82e4fc9f0f | ||
|
|
8c02130bcf | ||
|
|
791a92b146 | ||
|
|
f69e5f5ffc | ||
|
|
55b15a261a | ||
|
|
eb84b1441a | ||
|
|
f0842e430d | ||
|
|
18e33b193e | ||
|
|
ea4d4751f3 | ||
|
|
122b7ebba8 | ||
|
|
584d8c5377 | ||
|
|
7dadbc43fb | ||
|
|
b0c8fcda35 | ||
|
|
f0bfd7053e | ||
|
|
db9bb83898 | ||
|
|
f83b80a584 | ||
|
|
101d2ddd4f | ||
|
|
0396756cd9 | ||
|
|
74fb46c849 | ||
|
|
bf76cab7e0 | ||
|
|
c809cce170 | ||
|
|
ace2ff5775 | ||
|
|
11665bea0a | ||
|
|
f9d62a0efc | ||
|
|
5c6d187ef2 | ||
|
|
e2a8d58e02 | ||
|
|
cb812b47ed | ||
|
|
9e278b9fa4 | ||
|
|
017a956d5e | ||
|
|
abeb3141b1 | ||
|
|
6149608c03 | ||
|
|
b362b4657f | ||
|
|
15e9bb9cc1 | ||
|
|
96f6832a6f | ||
|
|
606aef38cb | ||
|
|
b32a6407b9 | ||
|
|
4a1157bff9 | ||
|
|
378eb18db5 | ||
|
|
579da1dbd6 | ||
|
|
7b61a5fffa | ||
|
|
0ba9b80d08 | ||
|
|
12dc65d170 | ||
|
|
b5592ad42f | ||
|
|
0cd7c37209 | ||
|
|
f2b45b8726 | ||
|
|
1c8ee0af89 | ||
|
|
a31c10c4fa | ||
|
|
587ad5c600 | ||
|
|
4d33190241 | ||
|
|
84c788a027 | ||
|
|
a22ec2d9c6 | ||
|
|
f6b6a007b1 | ||
|
|
1f2cca7d00 | ||
|
|
9fa30a3884 | ||
|
|
9c5765a48c | ||
|
|
66e9d7671d | ||
|
|
f4fea6d635 | ||
|
|
f1eb6511a7 | ||
|
|
402d58bc3a | ||
|
|
ef1fe6cabc | ||
|
|
7807804f4d | ||
|
|
218c2a59eb | ||
|
|
a46bd4c4ca | ||
|
|
507174e44f | ||
|
|
479e735e77 | ||
|
|
fb738f2d02 | ||
|
|
e823d80f0c | ||
|
|
3b1d6cd3d9 | ||
|
|
cbe34f101b | ||
|
|
4ec18c8a79 | ||
|
|
4901cdf929 | ||
|
|
bc0b87632d | ||
|
|
f35d28de45 | ||
|
|
cce44b1f54 | ||
|
|
4d4862899e | ||
|
|
9673b81677 | ||
|
|
704a06e1fa | ||
|
|
d8891e34d1 | ||
|
|
850c1ec12d | ||
|
|
b08533b322 | ||
|
|
c37b7c1389 | ||
|
|
38421cec94 | ||
|
|
d251b3f9f7 | ||
|
|
329a7dee1c | ||
|
|
b4c979f586 | ||
|
|
a34d6d484a | ||
|
|
7fdda87b06 | ||
|
|
b5aa972bd1 | ||
|
|
57efa05215 | ||
|
|
f8b104d174 | ||
|
|
d889fa8d39 | ||
|
|
a2d31be152 | ||
|
|
4f833ca7fe | ||
|
|
191dae47fd | ||
|
|
6f57e5a13e | ||
|
|
d49efefefa | ||
|
|
011739cbd9 | ||
|
|
6eb2aad7da | ||
|
|
2629369c93 | ||
|
|
f0b39099e3 | ||
|
|
c006777714 | ||
|
|
3159b299f7 | ||
|
|
6d6852fb8d | ||
|
|
341a1191a3 | ||
|
|
f0f5fc7eac | ||
|
|
bd3bcf981a | ||
|
|
c9ce2c8043 | ||
|
|
8b04d0a2b9 | ||
|
|
7893768cb2 | ||
|
|
8160ef6e81 | ||
|
|
6e4dbe8e22 | ||
|
|
620ae33e0c | ||
|
|
92dac0341c | ||
|
|
8a21a4ff92 | ||
|
|
59e3c14a5e | ||
|
|
6fcd35885e | ||
|
|
2ffb638b7e | ||
|
|
489b8431ea | ||
|
|
c9a2816bfe | ||
|
|
414bab1f30 | ||
|
|
1144bb99b4 | ||
|
|
7b426186aa | ||
|
|
630a8446ad | ||
|
|
b1bcbec37d | ||
|
|
1d9a93a731 | ||
|
|
4ee236d73f | ||
|
|
25f182302d | ||
|
|
f5f6d64d9d | ||
|
|
52b6539697 | ||
|
|
a9420d46c8 | ||
|
|
6cb69535a5 | ||
|
|
5efc8ac1a4 | ||
|
|
3906f2560d | ||
|
|
62155876c5 | ||
|
|
748c53a791 | ||
|
|
cf6cfe2a1e | ||
|
|
8a3bd8408b | ||
|
|
3229630598 | ||
|
|
ac71f9cd8e | ||
|
|
d2230c531d | ||
|
|
118def8d28 | ||
|
|
a0c647ce83 | ||
|
|
9892836f14 | ||
|
|
89ae0e3bf3 | ||
|
|
05a16dc100 | ||
|
|
ad1801827b | ||
|
|
203952fa47 | ||
|
|
c8b8e25fbb | ||
|
|
7a515c101a | ||
|
|
d13d7173ed | ||
|
|
14301e0af4 | ||
|
|
c20abf6d58 | ||
|
|
521066578b | ||
|
|
3594dba83c | ||
|
|
32de2113a6 | ||
|
|
a3eb0100a6 | ||
|
|
9068315f03 | ||
|
|
b2a9cecd69 | ||
|
|
4e04d27d32 | ||
|
|
49b8b0bca3 | ||
|
|
b4743155f6 | ||
|
|
5267671b15 | ||
|
|
4484d5bfa9 | ||
|
|
16a11b48ad | ||
|
|
1408c245e0 | ||
|
|
ff3d795a8f | ||
|
|
f96a42c075 | ||
|
|
8983ac9212 | ||
|
|
dd3debc2d5 | ||
|
|
a1028d604c | ||
|
|
b0e9238ddf | ||
|
|
b02c19b5bf | ||
|
|
936702a0e5 | ||
|
|
353ee8baa0 | ||
|
|
f5ae5bed47 | ||
|
|
2c7291d27e | ||
|
|
513dcf1cb4 | ||
|
|
c93852d87a | ||
|
|
daf0cf1c1b | ||
|
|
dd3f754cb3 | ||
|
|
a359a24c9e | ||
|
|
372b5870b1 | ||
|
|
92122fef58 | ||
|
|
d9955ce93c | ||
|
|
537e7a8ec3 | ||
|
|
701cff3ca4 | ||
|
|
a2a9575587 | ||
|
|
19871a2653 | ||
|
|
771d9345b5 | ||
|
|
ca53a8e787 | ||
|
|
1b2bd30a29 | ||
|
|
f88daff45f | ||
|
|
49efd574a0 | ||
|
|
fa8cbeeb44 | ||
|
|
c878af2b9d | ||
|
|
5b07e8c9c4 | ||
|
|
b5fda88bd3 | ||
|
|
63771110a5 | ||
|
|
018ccb3354 | ||
|
|
d7a2c7da18 | ||
|
|
b2cbac3250 | ||
|
|
443c183e41 | ||
|
|
e9901305b2 | ||
|
|
5843fdbdd8 | ||
|
|
90a7a58929 | ||
|
|
a286631018 | ||
|
|
9688d84f3e | ||
|
|
ef80ff416f | ||
|
|
4846cf4791 | ||
|
|
a7a4e43991 | ||
|
|
a05ffdbc81 | ||
|
|
a76d736136 | ||
|
|
98a20f9820 | ||
|
|
37ffe82ac9 | ||
|
|
0728692e93 | ||
|
|
b82d8c2252 | ||
|
|
659afb5f30 | ||
|
|
e0444c531b | ||
|
|
b52fff2f81 | ||
|
|
d2130a589b | ||
|
|
9dfd87c284 | ||
|
|
c7f6f2c8e1 | ||
|
|
18a1075e70 | ||
|
|
f5f61193a0 | ||
|
|
1236e2b829 | ||
|
|
a0b533bd40 | ||
|
|
4570d7e46e | ||
|
|
27b6f12b3c | ||
|
|
ba07daa50a | ||
|
|
1635ef9ad9 | ||
|
|
5a0bae27ac | ||
|
|
f4388c80d0 | ||
|
|
a4f5e9aaf5 | ||
|
|
f6fe469e02 | ||
|
|
3e9332edfa | ||
|
|
f8388c521e | ||
|
|
2c29f21004 | ||
|
|
615b0a0310 | ||
|
|
4c7b66c66a | ||
|
|
77e7898f71 | ||
|
|
f458149655 | ||
|
|
57f84873b4 | ||
|
|
21fe142955 | ||
|
|
ba520c60d2 | ||
|
|
09833e2541 | ||
|
|
2f96e32ec9 | ||
|
|
3a03bb5a0b | ||
|
|
74a350a432 | ||
|
|
c52709a5f0 | ||
|
|
7a74efcc82 | ||
|
|
ff554055a6 | ||
|
|
6678e79239 | ||
|
|
c89ce067a3 | ||
|
|
b267bd11e0 | ||
|
|
b49b84e072 | ||
|
|
39ceadaa26 | ||
|
|
656a7bc378 | ||
|
|
9e7a5214f3 | ||
|
|
e9cccb46c0 | ||
|
|
1a4cfba93a | ||
|
|
e592fd60ff | ||
|
|
dba4b5e5a9 | ||
|
|
db3d177300 | ||
|
|
1211dc8f3c | ||
|
|
f4758fe3e5 | ||
|
|
b22227d0f4 | ||
|
|
109b6a1d79 | ||
|
|
c1c1f60241 | ||
|
|
04ce4057e1 | ||
|
|
5b5c1de05b | ||
|
|
2a814dd37c | ||
|
|
a72eb87c93 | ||
|
|
a45a3e427c | ||
|
|
e41b5f2bc0 | ||
|
|
b169ccf29a | ||
|
|
b2fc68ff81 | ||
|
|
a07d03f49b | ||
|
|
26a8a4b3d2 | ||
|
|
b2269fb5f5 | ||
|
|
7e8e855f28 | ||
|
|
93a0198326 | ||
|
|
9bdac9d1cf | ||
|
|
b12b36f302 | ||
|
|
8debce0349 | ||
|
|
2db5f0def5 | ||
|
|
fd6f9cd2d5 | ||
|
|
86fe68bb61 | ||
|
|
85945dba29 | ||
|
|
7459eed435 | ||
|
|
ab30c786a5 | ||
|
|
6c488e6e71 | ||
|
|
f3ef6ef3c9 | ||
|
|
8ad6952dda | ||
|
|
d15e388f5c | ||
|
|
8c8499229d | ||
|
|
bc38b79c9a | ||
|
|
4ef8ff9a0f | ||
|
|
a8fa1a76c4 | ||
|
|
895399ff05 | ||
|
|
23a04613c0 | ||
|
|
711d49770f | ||
|
|
e78d0571f4 | ||
|
|
13cde4d700 | ||
|
|
d10d5fd05e | ||
|
|
ed3a6fd799 | ||
|
|
ed2a14a3ec | ||
|
|
6e0ce9a885 | ||
|
|
99e1a07b8e | ||
|
|
2b47ac83e8 | ||
|
|
b3cbdb5c1a | ||
|
|
e6b1e8ec56 | ||
|
|
92cced201e | ||
|
|
26aa938acc | ||
|
|
2e8091f0fb | ||
|
|
46d330cb21 | ||
|
|
37e0c30842 | ||
|
|
f02da68c55 | ||
|
|
718c0abdb6 | ||
|
|
7a9a259c03 | ||
|
|
89fd9694ce | ||
|
|
6e56c549b2 | ||
|
|
0665c39a07 | ||
|
|
1183e50435 | ||
|
|
5ad332e37f | ||
|
|
ecd0ce65fe | ||
|
|
266624dd0f | ||
|
|
86c8c3c8c0 | ||
|
|
6362884d16 | ||
|
|
43ac75ed62 | ||
|
|
5b4632b432 | ||
|
|
cc9c4149d7 | ||
|
|
3de191177c | ||
|
|
ae9025334e | ||
|
|
4662e42584 | ||
|
|
bd07350bc3 | ||
|
|
94afc82304 | ||
|
|
a3ed83bfff | ||
|
|
2654affeee | ||
|
|
257a1b0179 | ||
|
|
eadf922280 | ||
|
|
d52b668149 | ||
|
|
7e75c1d242 | ||
|
|
513ae2ab54 | ||
|
|
b837c56bec | ||
|
|
45b84ffb31 | ||
|
|
4244a6569c | ||
|
|
a4c61f6945 | ||
|
|
7d6e2060e5 | ||
|
|
265e8b3623 | ||
|
|
014c27ee8a | ||
|
|
05a58323c1 | ||
|
|
cd807533f2 | ||
|
|
463f79bed2 | ||
|
|
be260befd4 | ||
|
|
a0ea0c9e47 | ||
|
|
78641b4dde | ||
|
|
b5b6f06005 | ||
|
|
b2cc01c490 | ||
|
|
97d62950a8 | ||
|
|
1bf6101967 | ||
|
|
50bf9ae756 | ||
|
|
8d5d219c0f | ||
|
|
223ab5e60c | ||
|
|
bdeeb3217e | ||
|
|
fdb0c6ebb5 | ||
|
|
f4bbbc346f | ||
|
|
89e9ee43c0 | ||
|
|
c26a07bb10 | ||
|
|
b9f073e596 | ||
|
|
523ec9d633 | ||
|
|
95a84ad655 | ||
|
|
c1c0828082 | ||
|
|
27e2c4d580 | ||
|
|
3a6a537986 | ||
|
|
6cfc950159 | ||
|
|
afb6d30762 | ||
|
|
72103adacc | ||
|
|
60ceb89f01 | ||
|
|
d88bc8e408 | ||
|
|
a9d7662bb7 | ||
|
|
2c84b49ced | ||
|
|
32365fd673 | ||
|
|
c7a9cc5a42 | ||
|
|
5d3b5424ba | ||
|
|
b85ab3c0ab | ||
|
|
b27d374578 | ||
|
|
a6c1ffc45d | ||
|
|
f6bdfba3b3 | ||
|
|
c831a8c2d9 | ||
|
|
c481be8ea7 | ||
|
|
a4dbee3b13 | ||
|
|
e22d6656fe | ||
|
|
d8f34dba17 | ||
|
|
5e82eb9b24 | ||
|
|
fbd877a118 | ||
|
|
2dc783d91f | ||
|
|
0b81fbbb2b | ||
|
|
9ed8b75c5d | ||
|
|
ac5233d19c | ||
|
|
840097f121 | ||
|
|
3a8f77d6f4 | ||
|
|
2b0b8402ce | ||
|
|
f0f4311b65 | ||
|
|
70a8364a38 | ||
|
|
19b8e0db9c | ||
|
|
be8195ab7d | ||
|
|
f47dd2bbc6 | ||
|
|
dbb9a26f78 | ||
|
|
f55ace8311 | ||
|
|
3cd737e40d | ||
|
|
2cd1d2fd2f | ||
|
|
8f859647c4 | ||
|
|
51a33c279d | ||
|
|
d93b2edc0d | ||
|
|
aba2cb487e | ||
|
|
141b470002 | ||
|
|
34b40a14e8 | ||
|
|
d5a238768c | ||
|
|
4f8166a661 | ||
|
|
203788d4f1 | ||
|
|
1bccf42556 | ||
|
|
3910a348fd | ||
|
|
398f29a995 | ||
|
|
f3802ec60f | ||
|
|
c653d939d9 | ||
|
|
34ebed1a24 | ||
|
|
6d330891db | ||
|
|
7589d0a18a | ||
|
|
f5a06bef4a | ||
|
|
4226fd29f5 | ||
|
|
ab5f6717b6 | ||
|
|
afc98cacbe | ||
|
|
7affcf40c2 | ||
|
|
6c18b4de40 | ||
|
|
4e8343664f | ||
|
|
5e76d5ff3f | ||
|
|
6d461d6b50 | ||
|
|
4282005e32 | ||
|
|
05d5c1dda7 | ||
|
|
ce9c8e6e9f | ||
|
|
a6d728a66d | ||
|
|
e1d27f340e | ||
|
|
c1ebe920a1 | ||
|
|
ca667b5131 | ||
|
|
4df8db0d7e | ||
|
|
10f3a83fcb | ||
|
|
9ca4773227 | ||
|
|
872b6d8bee | ||
|
|
b89e70b5a0 | ||
|
|
801a34f6a1 | ||
|
|
9beac51586 | ||
|
|
5b31350e83 | ||
|
|
93d9ae73b7 | ||
|
|
e5f02852e1 | ||
|
|
5b5c17100c | ||
|
|
0e6bac73a7 | ||
|
|
af97b0edc2 | ||
|
|
ee1af432fe | ||
|
|
5e6118ef3f | ||
|
|
1149617f7b | ||
|
|
06ab918985 | ||
|
|
ae2e8b1292 | ||
|
|
0a3343a07d | ||
|
|
e80c192cf2 | ||
|
|
62c8f28e74 | ||
|
|
a7173e0c05 | ||
|
|
46cd62bd51 | ||
|
|
f432498574 | ||
|
|
1af6b37fc4 | ||
|
|
bfe934118d | ||
|
|
c5e3be2c4c | ||
|
|
6f1fcbf41b | ||
|
|
8fd62252fd | ||
|
|
431fc8880e | ||
|
|
e82fe9d919 | ||
|
|
e228aac61f | ||
|
|
6f9e06c59e | ||
|
|
8393ccf39d | ||
|
|
6133f01c81 | ||
|
|
69b5853477 | ||
|
|
e60d0c88f1 | ||
|
|
9d4b168977 | ||
|
|
6c779c7fa5 | ||
|
|
f209e3a0fe | ||
|
|
2201974844 | ||
|
|
02a1b1efcb | ||
|
|
7c22fe269f | ||
|
|
ffd32efba2 | ||
|
|
31bf86fd1b | ||
|
|
0eb602aad2 | ||
|
|
7670a2bd77 | ||
|
|
5d40075944 | ||
|
|
eac8a79d49 | ||
|
|
97a11de1e3 | ||
|
|
4b281fdf12 | ||
|
|
d903448695 | ||
|
|
f9cecfb666 | ||
|
|
98a7cd24c0 | ||
|
|
0ce0e834ed | ||
|
|
cdd379113e | ||
|
|
47873c20de | ||
|
|
c9a761f202 | ||
|
|
906e9de5ee | ||
|
|
17735a9a43 | ||
|
|
80ce55ab10 | ||
|
|
edf79a3730 | ||
|
|
0b900711bf | ||
|
|
0f5aa857b8 | ||
|
|
9c7fc58337 | ||
|
|
6d9e489e7c | ||
|
|
0924dec545 | ||
|
|
a2d83274bc | ||
|
|
7b04cf1a73 | ||
|
|
8fbd720fe5 | ||
|
|
49ccb8ce2b | ||
|
|
429c4eac96 | ||
|
|
ee78b7dc96 | ||
|
|
7cac226ad9 | ||
|
|
4e77b1b9b8 | ||
|
|
45eff3dac8 | ||
|
|
78bfdfd931 | ||
|
|
49de716f10 | ||
|
|
fa36d9f84e | ||
|
|
0ceb2f3f72 | ||
|
|
57e15b9a91 | ||
|
|
107d142b24 | ||
|
|
6264f46970 | ||
|
|
61faeef1d3 | ||
|
|
5c33af32e3 | ||
|
|
65102a073a | ||
|
|
f587273828 | ||
|
|
0d0ce32ef2 | ||
|
|
fc98cd8d08 | ||
|
|
19cb187436 | ||
|
|
6cea93919e | ||
|
|
a8d4d6b563 | ||
|
|
c375f24598 | ||
|
|
3ca287454a | ||
|
|
8442146a0f | ||
|
|
278a1efb4b | ||
|
|
18c96fd7d4 | ||
|
|
9231119b07 | ||
|
|
a4c845c418 | ||
|
|
cc72314219 | ||
|
|
7860857b55 | ||
|
|
b797df6ad5 | ||
|
|
3a75500f54 | ||
|
|
0d23ab07db | ||
|
|
2c6db00cbc | ||
|
|
e002f2088f | ||
|
|
35c75c00ba | ||
|
|
312471e9db | ||
|
|
d37425ae3e | ||
|
|
5cf052dec1 | ||
|
|
22b61852a1 | ||
|
|
d6a14e63ba | ||
|
|
d0091e1b3c | ||
|
|
e630bf86bd | ||
|
|
459f00ab41 | ||
|
|
78389c8897 | ||
|
|
af49301332 | ||
|
|
00f644888c | ||
|
|
acb4d9f681 | ||
|
|
35438294d1 | ||
|
|
be39c4c0cd | ||
|
|
875c7da87c | ||
|
|
b308c5438f | ||
|
|
50bdc658ba | ||
|
|
5cfa6e83b3 | ||
|
|
3252bd39d2 | ||
|
|
738ab6fba7 | ||
|
|
d295acc3c3 | ||
|
|
989081ba4a | ||
|
|
118ac07b71 | ||
|
|
9f83b67a7c | ||
|
|
e2d94127d6 | ||
|
|
5d3ea2f4d3 | ||
|
|
2bb9e2f7be | ||
|
|
e2e6fd0683 | ||
|
|
19c529e87b | ||
|
|
3cf1a16a13 | ||
|
|
e302616135 | ||
|
|
f9ffee010f | ||
|
|
2743fc0be1 | ||
|
|
e8f1ec68db | ||
|
|
60d07cf30d | ||
|
|
03321ff910 | ||
|
|
4a8ffea0f6 | ||
|
|
f48b643375 | ||
|
|
12dcd751d3 | ||
|
|
29ba013580 | ||
|
|
db5c58180e | ||
|
|
f5780ae369 | ||
|
|
4fb133a43d | ||
|
|
d10cdfb7f1 | ||
|
|
69a1c7e1e8 | ||
|
|
452bbf7289 | ||
|
|
924a8eac5c | ||
|
|
1ebdcdfa8c | ||
|
|
db1f399067 | ||
|
|
e8ddac08b7 | ||
|
|
e9fcd985f9 | ||
|
|
d638ee9741 | ||
|
|
7c35835e25 | ||
|
|
a773042c5d | ||
|
|
0f5bd3799e | ||
|
|
3de9356141 | ||
|
|
352610d651 | ||
|
|
fd5b5baa8f | ||
|
|
92124a9033 | ||
|
|
5ac80353d2 | ||
|
|
cb766de37e | ||
|
|
b456a8c4e5 | ||
|
|
132a8b8b53 | ||
|
|
d729ab501b | ||
|
|
d5ee91b1e8 | ||
|
|
aaa67a2da9 | ||
|
|
ffeece1179 | ||
|
|
050a9e155f | ||
|
|
8ce2d3954e | ||
|
|
cc131a09a1 | ||
|
|
0b43203349 | ||
|
|
ae4cf302f2 | ||
|
|
511308746c | ||
|
|
a0e963f769 | ||
|
|
b3f4c68a1d | ||
|
|
0b5745c24b | ||
|
|
f4575d9d03 | ||
|
|
4d0635dc8a | ||
|
|
d87e9ec095 | ||
|
|
f74913aa4d | ||
|
|
671bea58af | ||
|
|
d9e7c89af0 | ||
|
|
84e70e166e | ||
|
|
fa18fd2782 | ||
|
|
cbbf7c2578 | ||
|
|
051da9d407 | ||
|
|
32131cf9ae | ||
|
|
50b3571124 | ||
|
|
61eea66c51 | ||
|
|
2f9961888a | ||
|
|
7a2391f848 | ||
|
|
55d022f6eb | ||
|
|
8af8c6d95a | ||
|
|
9a96372f53 | ||
|
|
2bc035cfcf | ||
|
|
d224f85b24 | ||
|
|
59fc7aa8e1 | ||
|
|
e7df1b220c | ||
|
|
eea70069e7 | ||
|
|
c2628fe1df | ||
|
|
a774c65162 | ||
|
|
b996dc3b62 | ||
|
|
a6714809c4 | ||
|
|
a9a0cb928e | ||
|
|
dcc5572767 | ||
|
|
5c19aad012 | ||
|
|
4227dd7d73 | ||
|
|
07932590b5 | ||
|
|
8e392cf8de | ||
|
|
6ff6d0f6bd | ||
|
|
56802035df | ||
|
|
7c58098f12 | ||
|
|
7c0aa78e39 | ||
|
|
b5c7bc1b33 | ||
|
|
3815503314 | ||
|
|
065388df91 | ||
|
|
d1a3294f06 | ||
|
|
762d2ef793 | ||
|
|
a20737308a | ||
|
|
c73d081a32 | ||
|
|
50cd200ec5 | ||
|
|
edec76ae10 | ||
|
|
186e42b1fe | ||
|
|
e5da0b90ce | ||
|
|
d39263dcac | ||
|
|
72d7223fd0 | ||
|
|
d097946e1f | ||
|
|
5a9b562f19 | ||
|
|
dacc9e26e9 | ||
|
|
f8bdf924db | ||
|
|
b7bc94b987 | ||
|
|
046d0d4938 | ||
|
|
e5ba1c7a84 | ||
|
|
b89b68dfdb | ||
|
|
166c77d776 | ||
|
|
09edc29979 | ||
|
|
fbc4f0b84f | ||
|
|
d575d3c9e4 | ||
|
|
f9e094de61 | ||
|
|
174f89fbcb | ||
|
|
ea562de3e6 | ||
|
|
125cc91ba6 | ||
|
|
1c801bd856 | ||
|
|
58862f4ace | ||
|
|
e3e1bcd63f | ||
|
|
2e90499df4 | ||
|
|
a1980ee23c | ||
|
|
ec40ea800d | ||
|
|
b01b40b51b | ||
|
|
b34fa7abc0 | ||
|
|
f7c74664fa | ||
|
|
417e79c3c0 | ||
|
|
3aee4a88aa | ||
|
|
fd7d216fe3 | ||
|
|
e382f7cd43 | ||
|
|
4b9d102f46 | ||
|
|
a0f8b5829a | ||
|
|
30b93d18b7 | ||
|
|
51052c74bb | ||
|
|
6ea6f30cc5 | ||
|
|
91f9247c2b | ||
|
|
4f9d8271a2 | ||
|
|
387d08a1b3 | ||
|
|
1c922f0f45 | ||
|
|
e1047dc40b | ||
|
|
63a2c9da76 | ||
|
|
c4633c7e23 | ||
|
|
aa9d299230 | ||
|
|
d8e943ea05 | ||
|
|
f104205538 | ||
|
|
0752dbea9b | ||
|
|
b5045b3407 | ||
|
|
d51361cd35 | ||
|
|
2505272af7 | ||
|
|
2d84f8a739 | ||
|
|
702d6d80c4 | ||
|
|
dc247e03e0 | ||
|
|
84df8f91a9 | ||
|
|
40c8c3a526 | ||
|
|
4c1fa58367 | ||
|
|
a81989d2d8 | ||
|
|
9f47996448 | ||
|
|
728a4aff22 | ||
|
|
3aba4d3e1e | ||
|
|
55ff71b760 | ||
|
|
89e080cd99 | ||
|
|
311690cffe | ||
|
|
f52a427295 | ||
|
|
16fbe8d96f | ||
|
|
eea11dbf5f | ||
|
|
666678a582 | ||
|
|
117c41bd55 | ||
|
|
2f4c728bb9 | ||
|
|
a8541b9f76 | ||
|
|
9f1e60ca6d | ||
|
|
0159f5b422 | ||
|
|
29c22e6fcf | ||
|
|
d9787efc10 | ||
|
|
572da264d3 | ||
|
|
3f4b2b7cc8 | ||
|
|
b0ef0f06eb | ||
|
|
ed11a32f42 | ||
|
|
827ea4c769 | ||
|
|
7bf05297cf | ||
|
|
08298f48d0 | ||
|
|
6c9a75eab3 | ||
|
|
b4e6d3009e | ||
|
|
ba5318f63f | ||
|
|
eb246f6f71 | ||
|
|
869b7e09d7 | ||
|
|
8c34b7eaea | ||
|
|
66379deadd | ||
|
|
c6adc51220 | ||
|
|
c5cb86ac24 | ||
|
|
ed9ed43923 | ||
|
|
1caf18ede1 | ||
|
|
7d479704e8 | ||
|
|
039b5af2e0 | ||
|
|
c5ee0f3c22 | ||
|
|
ff4c11f503 | ||
|
|
0b293eaba5 | ||
|
|
61485908b9 | ||
|
|
fe7426740b | ||
|
|
bd3fa7fb21 | ||
|
|
e18b049d10 | ||
|
|
1e77891271 | ||
|
|
fea05331aa | ||
|
|
526990e015 | ||
|
|
e7fbd28505 | ||
|
|
8c13faf3d8 | ||
|
|
a6fb45b9cb | ||
|
|
82476b9efd | ||
|
|
b2feaaceea | ||
|
|
ef114c4a07 | ||
|
|
a08878f419 | ||
|
|
e719dd912d | ||
|
|
bab2a79055 | ||
|
|
215602c963 | ||
|
|
76ca1a576f | ||
|
|
0d03c813d0 | ||
|
|
b2b5199055 | ||
|
|
d8c4d6deb4 | ||
|
|
e6eacca50b | ||
|
|
f1186432c1 | ||
|
|
fc1b9277b3 | ||
|
|
b2ef60c165 | ||
|
|
a6b68ec7de | ||
|
|
c26a56a332 | ||
|
|
3a9a559d25 | ||
|
|
9363bc318a | ||
|
|
81b1e73e18 | ||
|
|
f51ee4c04f | ||
|
|
5d3ec35e29 | ||
|
|
2100dc1288 | ||
|
|
4645bd766a | ||
|
|
a551a55ca0 | ||
|
|
3c35e1e6ee | ||
|
|
76f2c6a9f1 | ||
|
|
1605438333 | ||
|
|
6c773a7473 | ||
|
|
fffb4c03b0 | ||
|
|
6b022edf06 | ||
|
|
de6d9f4d50 | ||
|
|
c5e5b8a585 | ||
|
|
af82da5db3 | ||
|
|
c4c8dbcf7d | ||
|
|
d3d608fa33 | ||
|
|
6c751ce934 | ||
|
|
4dac80a998 | ||
|
|
64d68feab3 | ||
|
|
4926d278a2 | ||
|
|
d8346ef106 | ||
|
|
8009ddebce | ||
|
|
61e8ad264f | ||
|
|
26919a6c6e | ||
|
|
5b0ef40a3e | ||
|
|
dd99a2d3bd | ||
|
|
f6732a927b | ||
|
|
13a93c7e32 | ||
|
|
e610465ee8 | ||
|
|
71dec0b23e | ||
|
|
9fa630faf5 | ||
|
|
cd6a151d9b | ||
|
|
83d53baf82 | ||
|
|
462d639627 | ||
|
|
2dcf3c7c45 | ||
|
|
5d2268fa80 | ||
|
|
de8e535c3a | ||
|
|
1b683f6359 | ||
|
|
f7201023de | ||
|
|
bda522052b | ||
|
|
9802ad77dc | ||
|
|
235822d782 | ||
|
|
b108d47b26 | ||
|
|
5fb28b9f6d | ||
|
|
76f15a890c | ||
|
|
318d1cd392 | ||
|
|
125c6534b7 | ||
|
|
6587ad435e | ||
|
|
0a83c11f42 | ||
|
|
900a5cd9d7 | ||
|
|
502ea82c91 | ||
|
|
2bbf24b3ea | ||
|
|
f429b9038c | ||
|
|
067c98d3ee | ||
|
|
4212d1b5b6 | ||
|
|
5ba5007076 | ||
|
|
f7097136f1 | ||
|
|
8545c7d36f | ||
|
|
8c9c66c002 | ||
|
|
ba68fe9a0f | ||
|
|
fb0380bfbc | ||
|
|
cc486ddb08 | ||
|
|
72df584e9b | ||
|
|
c9dc54abf8 | ||
|
|
58f2bd4000 | ||
|
|
5992dc3b0a | ||
|
|
e01519f547 | ||
|
|
74a312735c | ||
|
|
8b10ad49d7 | ||
|
|
ba8658491a | ||
|
|
86bb0e8af2 | ||
|
|
daa5525a10 | ||
|
|
b4b20d7d3f | ||
|
|
18b949c0a9 | ||
|
|
9619ae8a2d | ||
|
|
c9932e187a | ||
|
|
9ac95266c7 | ||
|
|
3c74e12b9c | ||
|
|
99a05ed5a4 | ||
|
|
732c818916 | ||
|
|
45b5efad25 | ||
|
|
4f63528844 | ||
|
|
d0daacd17e | ||
|
|
a02016a95f | ||
|
|
38af3ac925 | ||
|
|
bea8502cc5 | ||
|
|
ca393a9afe | ||
|
|
71bac5eda8 | ||
|
|
67dc01b636 | ||
|
|
57b4534d30 | ||
|
|
74ce7cd188 | ||
|
|
9cc6e9c8a9 | ||
|
|
7c8177de97 | ||
|
|
73b3398b46 | ||
|
|
938b47c2ad | ||
|
|
422352c632 | ||
|
|
48dc280e6c | ||
|
|
5d29240f27 | ||
|
|
eb4841230a | ||
|
|
b7ceeb399f | ||
|
|
ec7e41cb30 | ||
|
|
9edfd7a6fb | ||
|
|
f24f7d5146 | ||
|
|
30a07763e8 | ||
|
|
33aa6c94df | ||
|
|
65ff72719e | ||
|
|
e42002e1d7 | ||
|
|
adf01e76cd | ||
|
|
021aa13ee2 | ||
|
|
791a7e242e | ||
|
|
2baca58b27 | ||
|
|
fd4233e30e | ||
|
|
84ffbbec33 | ||
|
|
95743d7109 | ||
|
|
92daa7d42c | ||
|
|
358617f533 | ||
|
|
a98f4c29d3 | ||
|
|
ff93045938 | ||
|
|
88d36aa574 | ||
|
|
0270fac4e7 | ||
|
|
d32e09ac37 | ||
|
|
8b64a72fe1 | ||
|
|
e6b363b81b | ||
|
|
eba120444e | ||
|
|
97cd083f65 | ||
|
|
6e5734adca | ||
|
|
575da5c31c | ||
|
|
8c4dbca23c | ||
|
|
26f3b40d35 |
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@@ -25,18 +25,11 @@ updates:
|
||||
allow:
|
||||
- dependency-name: "golang.org/x/mod"
|
||||
- dependency-name: "golang.org/x/tools"
|
||||
exclude-paths:
|
||||
- "go/ql/**"
|
||||
groups:
|
||||
extractor-dependencies:
|
||||
patterns:
|
||||
- "golang.org/x/*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
- package-ecosystem: "gomod"
|
||||
directory: "go/ql/test"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
ignore:
|
||||
- dependency-name: "*"
|
||||
reviewers:
|
||||
- "github/codeql-go"
|
||||
|
||||
2
.github/workflows/query-list.yml
vendored
2
.github/workflows/query-list.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
with:
|
||||
python-version: 3.8
|
||||
- name: Download CodeQL CLI
|
||||
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
|
||||
# Look under the `codeql` directory, as this is where we checked out the `github/codeql` repo
|
||||
uses: ./codeql/.github/actions/fetch-codeql
|
||||
- name: Build code scanning query list
|
||||
run: |
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -76,3 +76,6 @@ node_modules/
|
||||
# some upgrade/downgrade checks create these files
|
||||
**/upgrades/*/*.dbscheme.stats
|
||||
**/downgrades/*/*.dbscheme.stats
|
||||
|
||||
# Mergetool files
|
||||
*.orig
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
# Catch-all for anything which isn't matched by a line lower down
|
||||
* @github/code-scanning-alert-coverage
|
||||
|
||||
# CodeQL language libraries
|
||||
/actions/ @github/codeql-dynamic
|
||||
/cpp/ @github/codeql-c-analysis
|
||||
/csharp/ @github/codeql-csharp
|
||||
@@ -7,8 +11,10 @@
|
||||
/java/ @github/codeql-java
|
||||
/javascript/ @github/codeql-javascript
|
||||
/python/ @github/codeql-python
|
||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||
/ruby/ @github/codeql-ruby
|
||||
/rust/ @github/codeql-rust
|
||||
/shared/ @github/codeql-shared-libraries-reviewers
|
||||
/swift/ @github/codeql-swift
|
||||
/misc/codegen/ @github/codeql-swift
|
||||
/java/kotlin-extractor/ @github/codeql-kotlin
|
||||
@@ -25,9 +31,6 @@
|
||||
/docs/codeql/ql-language-reference/ @github/codeql-frontend-reviewers
|
||||
/docs/query-*-style-guide.md @github/codeql-analysis-reviewers
|
||||
|
||||
# QL for QL reviewers
|
||||
/ql/ @github/codeql-ql-for-ql-reviewers
|
||||
|
||||
# Bazel (excluding BUILD.bazel files)
|
||||
MODULE.bazel @github/codeql-ci-reviewers
|
||||
.bazelversion @github/codeql-ci-reviewers
|
||||
|
||||
763
Cargo.lock
generated
763
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
70
MODULE.bazel
70
MODULE.bazel
@@ -89,8 +89,8 @@ use_repo(
|
||||
"vendor_py__cc-1.2.14",
|
||||
"vendor_py__clap-4.5.30",
|
||||
"vendor_py__regex-1.11.1",
|
||||
"vendor_py__tree-sitter-0.20.4",
|
||||
"vendor_py__tree-sitter-graph-0.7.0",
|
||||
"vendor_py__tree-sitter-0.24.7",
|
||||
"vendor_py__tree-sitter-graph-0.12.0",
|
||||
)
|
||||
|
||||
# deps for ruby+rust
|
||||
@@ -98,54 +98,54 @@ use_repo(
|
||||
tree_sitter_extractors_deps = use_extension("//misc/bazel/3rdparty:tree_sitter_extractors_extension.bzl", "r")
|
||||
use_repo(
|
||||
tree_sitter_extractors_deps,
|
||||
"vendor_ts__anyhow-1.0.99",
|
||||
"vendor_ts__anyhow-1.0.100",
|
||||
"vendor_ts__argfile-0.2.1",
|
||||
"vendor_ts__chalk-ir-0.104.0",
|
||||
"vendor_ts__chrono-0.4.41",
|
||||
"vendor_ts__clap-4.5.44",
|
||||
"vendor_ts__chrono-0.4.42",
|
||||
"vendor_ts__clap-4.5.48",
|
||||
"vendor_ts__dunce-1.0.5",
|
||||
"vendor_ts__either-1.15.0",
|
||||
"vendor_ts__encoding-0.2.33",
|
||||
"vendor_ts__figment-0.10.19",
|
||||
"vendor_ts__flate2-1.1.0",
|
||||
"vendor_ts__flate2-1.1.2",
|
||||
"vendor_ts__glob-0.3.3",
|
||||
"vendor_ts__globset-0.4.15",
|
||||
"vendor_ts__globset-0.4.16",
|
||||
"vendor_ts__itertools-0.14.0",
|
||||
"vendor_ts__lazy_static-1.5.0",
|
||||
"vendor_ts__mustache-0.9.0",
|
||||
"vendor_ts__num-traits-0.2.19",
|
||||
"vendor_ts__num_cpus-1.17.0",
|
||||
"vendor_ts__proc-macro2-1.0.97",
|
||||
"vendor_ts__quote-1.0.40",
|
||||
"vendor_ts__ra_ap_base_db-0.0.300",
|
||||
"vendor_ts__ra_ap_cfg-0.0.300",
|
||||
"vendor_ts__ra_ap_hir-0.0.300",
|
||||
"vendor_ts__ra_ap_hir_def-0.0.300",
|
||||
"vendor_ts__ra_ap_hir_expand-0.0.300",
|
||||
"vendor_ts__ra_ap_hir_ty-0.0.300",
|
||||
"vendor_ts__ra_ap_ide_db-0.0.300",
|
||||
"vendor_ts__ra_ap_intern-0.0.300",
|
||||
"vendor_ts__ra_ap_load-cargo-0.0.300",
|
||||
"vendor_ts__ra_ap_parser-0.0.300",
|
||||
"vendor_ts__ra_ap_paths-0.0.300",
|
||||
"vendor_ts__ra_ap_project_model-0.0.300",
|
||||
"vendor_ts__ra_ap_span-0.0.300",
|
||||
"vendor_ts__ra_ap_stdx-0.0.300",
|
||||
"vendor_ts__ra_ap_syntax-0.0.300",
|
||||
"vendor_ts__ra_ap_vfs-0.0.300",
|
||||
"vendor_ts__proc-macro2-1.0.101",
|
||||
"vendor_ts__quote-1.0.41",
|
||||
"vendor_ts__ra_ap_base_db-0.0.301",
|
||||
"vendor_ts__ra_ap_cfg-0.0.301",
|
||||
"vendor_ts__ra_ap_hir-0.0.301",
|
||||
"vendor_ts__ra_ap_hir_def-0.0.301",
|
||||
"vendor_ts__ra_ap_hir_expand-0.0.301",
|
||||
"vendor_ts__ra_ap_hir_ty-0.0.301",
|
||||
"vendor_ts__ra_ap_ide_db-0.0.301",
|
||||
"vendor_ts__ra_ap_intern-0.0.301",
|
||||
"vendor_ts__ra_ap_load-cargo-0.0.301",
|
||||
"vendor_ts__ra_ap_parser-0.0.301",
|
||||
"vendor_ts__ra_ap_paths-0.0.301",
|
||||
"vendor_ts__ra_ap_project_model-0.0.301",
|
||||
"vendor_ts__ra_ap_span-0.0.301",
|
||||
"vendor_ts__ra_ap_stdx-0.0.301",
|
||||
"vendor_ts__ra_ap_syntax-0.0.301",
|
||||
"vendor_ts__ra_ap_vfs-0.0.301",
|
||||
"vendor_ts__rand-0.9.2",
|
||||
"vendor_ts__rayon-1.10.0",
|
||||
"vendor_ts__regex-1.11.1",
|
||||
"vendor_ts__serde-1.0.219",
|
||||
"vendor_ts__serde_json-1.0.142",
|
||||
"vendor_ts__serde_with-3.14.0",
|
||||
"vendor_ts__syn-2.0.104",
|
||||
"vendor_ts__toml-0.9.5",
|
||||
"vendor_ts__rayon-1.11.0",
|
||||
"vendor_ts__regex-1.11.3",
|
||||
"vendor_ts__serde-1.0.228",
|
||||
"vendor_ts__serde_json-1.0.145",
|
||||
"vendor_ts__serde_with-3.14.1",
|
||||
"vendor_ts__syn-2.0.106",
|
||||
"vendor_ts__toml-0.9.7",
|
||||
"vendor_ts__tracing-0.1.41",
|
||||
"vendor_ts__tracing-flame-0.2.0",
|
||||
"vendor_ts__tracing-subscriber-0.3.19",
|
||||
"vendor_ts__tree-sitter-0.24.6",
|
||||
"vendor_ts__tree-sitter-embedded-template-0.23.2",
|
||||
"vendor_ts__tracing-subscriber-0.3.20",
|
||||
"vendor_ts__tree-sitter-0.25.9",
|
||||
"vendor_ts__tree-sitter-embedded-template-0.25.0",
|
||||
"vendor_ts__tree-sitter-json-0.24.8",
|
||||
"vendor_ts__tree-sitter-ql-0.23.1",
|
||||
"vendor_ts__tree-sitter-ruby-0.23.1",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
name: "actions"
|
||||
aliases: []
|
||||
display_name: "GitHub Actions"
|
||||
version: 0.0.1
|
||||
column_kind: "utf16"
|
||||
@@ -8,9 +7,11 @@ build_modes:
|
||||
- none
|
||||
default_queries:
|
||||
- codeql/actions-queries
|
||||
file_coverage_languages: []
|
||||
# Actions workflows are not reported separately by the GitHub API, so we can't
|
||||
# associate them with a specific language.
|
||||
github_api_languages: []
|
||||
scc_languages: []
|
||||
scc_languages:
|
||||
- YAML
|
||||
file_types:
|
||||
- name: workflow
|
||||
display_name: GitHub Actions workflow files
|
||||
|
||||
10
actions/extractor/tools/baseline-config.json
Normal file
10
actions/extractor/tools/baseline-config.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"paths": [
|
||||
".github/workflows/*.yml",
|
||||
".github/workflows/*.yaml",
|
||||
".github/reusable_workflows/**/*.yml",
|
||||
".github/reusable_workflows/**/*.yaml",
|
||||
"**/action.yml",
|
||||
"**/action.yaml"
|
||||
]
|
||||
}
|
||||
2
actions/extractor/tools/configure-baseline.cmd
Executable file
2
actions/extractor/tools/configure-baseline.cmd
Executable file
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
type "%CODEQL_EXTRACTOR_ACTIONS_ROOT%\tools\baseline-config.json"
|
||||
3
actions/extractor/tools/configure-baseline.sh
Executable file
3
actions/extractor/tools/configure-baseline.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat "$CODEQL_EXTRACTOR_ACTIONS_ROOT/tools/baseline-config.json"
|
||||
@@ -1,3 +1,4 @@
|
||||
ql/actions/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvPathInjectionCritical.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvVarInjectionCritical.ql
|
||||
ql/actions/ql/src/Security/CWE-094/CodeInjectionCritical.ql
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
ql/actions/ql/src/Debug/SyntaxError.ql
|
||||
ql/actions/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvPathInjectionCritical.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvPathInjectionMedium.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvVarInjectionCritical.ql
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
ql/actions/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvPathInjectionCritical.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvPathInjectionMedium.ql
|
||||
ql/actions/ql/src/Security/CWE-077/EnvVarInjectionCritical.ql
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
## 0.4.18
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.17
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.4.16
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
actions/ql/lib/change-notes/released/0.4.17.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.17.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.17
|
||||
|
||||
No user-facing changes.
|
||||
3
actions/ql/lib/change-notes/released/0.4.18.md
Normal file
3
actions/ql/lib/change-notes/released/0.4.18.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.4.18
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.4.16
|
||||
lastReleaseVersion: 0.4.18
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-all
|
||||
version: 0.4.17-dev
|
||||
version: 0.4.19-dev
|
||||
library: true
|
||||
warnOnImplicitThis: true
|
||||
dependencies:
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
## 0.6.10
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.6.9
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Actions analysis now reports file coverage information on the CodeQL status page.
|
||||
|
||||
## 0.6.8
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
13
actions/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql
Normal file
13
actions/ql/src/Diagnostics/SuccessfullyExtractedFiles.ql
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @id actions/diagnostics/successfully-extracted-files
|
||||
* @name Extracted files
|
||||
* @description List all files that were extracted.
|
||||
* @kind diagnostic
|
||||
* @tags successfully-extracted-files
|
||||
*/
|
||||
|
||||
private import codeql.Locations
|
||||
|
||||
from File f
|
||||
where exists(f.getRelativePath())
|
||||
select f, ""
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
- run: |
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm build
|
||||
|
||||
- uses: completely/fakeaction@v2
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
- run: |
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm build
|
||||
|
||||
- uses: completely/fakeaction@v2
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-node@v1
|
||||
- run: |
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm install # scripts in package.json from PR would be executed here
|
||||
npm build
|
||||
|
||||
- uses: completely/fakeaction@v2
|
||||
|
||||
3
actions/ql/src/change-notes/released/0.6.10.md
Normal file
3
actions/ql/src/change-notes/released/0.6.10.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.6.10
|
||||
|
||||
No user-facing changes.
|
||||
5
actions/ql/src/change-notes/released/0.6.9.md
Normal file
5
actions/ql/src/change-notes/released/0.6.9.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.6.9
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Actions analysis now reports file coverage information on the CodeQL status page.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.6.8
|
||||
lastReleaseVersion: 0.6.10
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/actions-queries
|
||||
version: 0.6.9-dev
|
||||
version: 0.6.11-dev
|
||||
library: false
|
||||
warnOnImplicitThis: true
|
||||
groups: [actions, queries]
|
||||
|
||||
@@ -177,6 +177,12 @@ def insert_overlay_caller_annotations(lines):
|
||||
out_lines.append(line)
|
||||
return out_lines
|
||||
|
||||
explicitly_global = set([
|
||||
"java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll",
|
||||
"java/ql/lib/semmle/code/java/dispatch/DispatchFlow.qll",
|
||||
"java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll",
|
||||
"java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll",
|
||||
])
|
||||
|
||||
def annotate_as_appropriate(filename, lines):
|
||||
'''
|
||||
@@ -196,6 +202,9 @@ def annotate_as_appropriate(filename, lines):
|
||||
((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and
|
||||
any("implements DataFlow::ConfigSig" in line for line in lines))):
|
||||
return None
|
||||
elif filename in explicitly_global:
|
||||
# These files are explicitly global and should not be annotated.
|
||||
return None
|
||||
elif not any(line for line in lines if line.strip()):
|
||||
return None
|
||||
|
||||
|
||||
@@ -7,12 +7,10 @@ ql/cpp/ql/src/Diagnostics/ExtractedFiles.ql
|
||||
ql/cpp/ql/src/Diagnostics/ExtractionWarnings.ql
|
||||
ql/cpp/ql/src/Diagnostics/FailedExtractorInvocations.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Arithmetic/IntMultToLong.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Format/SnprintfOverflow.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.ql
|
||||
ql/cpp/ql/src/Likely Bugs/Memory Management/ReturnStackAllocatedMemory.ql
|
||||
@@ -30,7 +28,6 @@ ql/cpp/ql/src/Security/CWE/CWE-120/VeryLikelyOverrunWrite.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-134/UncontrolledFormatString.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-190/ComparisonWithWiderType.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql
|
||||
@@ -43,7 +40,6 @@ ql/cpp/ql/src/Security/CWE/CWE-367/TOCTOUFilesystemRace.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-468/SuspiciousAddWithSizeof.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-611/XXE.ql
|
||||
ql/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
## 5.6.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 5.6.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The predicate `getAContructorCall` in the class `SslContextClass` has been deprecated. Use `getAConstructorCall` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added predicates `getTransitiveNumberOfVlaDimensionStmts`, `getTransitiveVlaDimensionStmt`, and `getParentVlaDecl` to `VlaDeclStmt` for handling `VlaDeclStmt`s whose base type is defined in terms of another `VlaDeclStmt` via a `typedef`.
|
||||
|
||||
## 5.5.0
|
||||
|
||||
### New Features
|
||||
|
||||
@@ -35,7 +35,7 @@ class CustomOptions extends Options {
|
||||
override predicate returnsNull(Call call) { Options.super.returnsNull(call) }
|
||||
|
||||
/**
|
||||
* Holds if a call to this function will never return.
|
||||
* Holds if a call to the function `f` will never return.
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
|
||||
* `longjmp`, `error`, `__builtin_unreachable` and any function with a
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* Added predicates `getTransitiveNumberOfVlaDimensionStmts`, `getTransitiveVlaDimensionStmt`, and `getParentVlaDecl` to `VlaDeclStmt` for handling `VlaDeclStmt`s whose base type defined in terms of an other `VlaDeclStmt` via a `typedef`.
|
||||
4
cpp/ql/lib/change-notes/2025-09-18-guards.md
Normal file
4
cpp/ql/lib/change-notes/2025-09-18-guards.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The "Guards" libraries (`semmle.code.cpp.controlflow.Guards` and `semmle.code.cpp.controlflow.IRGuards`) have been totally rewritten to recognize many more guards. The API remains unchanged, but the `GuardCondition` class now extends `Element` instead of `Expr`.
|
||||
4
cpp/ql/lib/change-notes/2025-10-07-bmn-ga.md
Normal file
4
cpp/ql/lib/change-notes/2025-10-07-bmn-ga.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
* The C/C++ "build-mode: none" support is now General Availability (GA).
|
||||
9
cpp/ql/lib/change-notes/released/5.6.0.md
Normal file
9
cpp/ql/lib/change-notes/released/5.6.0.md
Normal file
@@ -0,0 +1,9 @@
|
||||
## 5.6.0
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
* The predicate `getAContructorCall` in the class `SslContextClass` has been deprecated. Use `getAConstructorCall` instead.
|
||||
|
||||
### New Features
|
||||
|
||||
* Added predicates `getTransitiveNumberOfVlaDimensionStmts`, `getTransitiveVlaDimensionStmt`, and `getParentVlaDecl` to `VlaDeclStmt` for handling `VlaDeclStmt`s whose base type is defined in terms of another `VlaDeclStmt` via a `typedef`.
|
||||
3
cpp/ql/lib/change-notes/released/5.6.1.md
Normal file
3
cpp/ql/lib/change-notes/released/5.6.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 5.6.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 5.5.0
|
||||
lastReleaseVersion: 5.6.1
|
||||
|
||||
@@ -127,7 +127,7 @@ abstract class CryptographicAlgorithm extends CryptographicArtifact {
|
||||
/**
|
||||
* Normalizes a raw name into a normalized name as found in `CryptoAlgorithmNames.qll`.
|
||||
* Subclassess should override for more api-specific normalization.
|
||||
* By deafult, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
* By default, converts a raw name to upper-case with no hyphen, underscore, hash, or space.
|
||||
*/
|
||||
bindingset[s]
|
||||
string normalizeName(string s) {
|
||||
|
||||
@@ -652,14 +652,14 @@ module KeyGeneration {
|
||||
* Trace from EVP_PKEY_CTX* at algorithm sink to keygen,
|
||||
* users can then extrapolatae the matching algorithm from the alg sink to the keygen
|
||||
*/
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize implements DataFlow::ConfigSig {
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSizeConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { isEVP_PKEY_CTX_Source(source, _) }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) { isKeyGen_EVP_PKEY_CTX_Sink(sink, _) }
|
||||
}
|
||||
|
||||
module EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize_Flow =
|
||||
DataFlow::Global<EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSize>;
|
||||
DataFlow::Global<EVP_PKEY_CTX_Ptr_Source_to_KeyGenOperationWithNoSizeConfig>;
|
||||
|
||||
/**
|
||||
* UNKNOWN key sizes to general purpose key generation functions (i.e., that take in no key size and assume
|
||||
|
||||
@@ -59,7 +59,7 @@ private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false positive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
|
||||
@@ -49,7 +49,7 @@ private string privateNormalizeFunctionName(Function f, string algType) {
|
||||
*
|
||||
* The predicate attempts to restrict normalization to what looks like an openssl
|
||||
* library by looking for functions only in an openssl path (see `isPossibleOpenSSLFunction`).
|
||||
* This may give false postive functions if a directory erronously appears to be openssl;
|
||||
* This may give false positive functions if a directory erronously appears to be openssl;
|
||||
* however, we take the stance that if a function
|
||||
* exists strongly mapping to a known function name in a directory such as these,
|
||||
* regardless of whether its actually a part of openSSL or not, we will analyze it as though it were.
|
||||
|
||||
@@ -31,7 +31,7 @@ predicate knownPassthroughFunction(Function f, int inInd, int outInd) {
|
||||
|
||||
/**
|
||||
* `c` is a call to a function that preserves the algorithm but changes its form.
|
||||
* `onExpr` is the input argument passing through to, `outExpr` is the next expression in a dataflow step associated with `c`
|
||||
* `inExpr` is the input argument passing through to, `outExpr` is the next expression in a dataflow step associated with `c`
|
||||
*/
|
||||
predicate knownPassthoughCall(Call c, Expr inExpr, Expr outExpr) {
|
||||
exists(int inInd, int outInd |
|
||||
|
||||
@@ -14,8 +14,8 @@ module CryptoInput implements InputSig<Language::Location> {
|
||||
result = node.asExpr() or
|
||||
result = node.asParameter() or
|
||||
result = node.asVariable() or
|
||||
result = node.asDefiningArgument()
|
||||
// TODO: do we need asIndirectExpr()?
|
||||
result = node.asDefiningArgument() or
|
||||
result = node.asIndirectExpr()
|
||||
}
|
||||
|
||||
string locationToFileBaseNameAndLineNumberString(Location location) {
|
||||
@@ -53,7 +53,7 @@ module ArtifactFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module ArtifactFlow = DataFlow::Global<ArtifactFlowConfig>;
|
||||
module ArtifactFlow = TaintTracking::Global<ArtifactFlowConfig>;
|
||||
|
||||
/**
|
||||
* An artifact output to node input configuration
|
||||
@@ -93,7 +93,13 @@ module GenericDataSourceFlow = TaintTracking::Global<GenericDataSourceFlowConfig
|
||||
|
||||
private class ConstantDataSource extends Crypto::GenericConstantSourceInstance instanceof OpenSslGenericSourceCandidateLiteral
|
||||
{
|
||||
override DataFlow::Node getOutputNode() { result.asExpr() = this }
|
||||
override DataFlow::Node getOutputNode() {
|
||||
// OpenSSL algorithms may be referenced either by string name or by numeric ID:
|
||||
// String names (e.g. "AES-256-CBC") appear in the AST as character pointer
|
||||
// literals. For these we must use `asIndirectExpr`. Numeric IDs (e.g. NID_aes_256_cbc)
|
||||
// appear as integer literals. For these, we must use `asExpr` to get the "value" node.
|
||||
[result.asIndirectExpr(), result.asExpr()] = this
|
||||
}
|
||||
|
||||
override predicate flowsTo(Crypto::FlowAwareElement other) {
|
||||
// TODO: separate config to avoid blowing up data-flow analysis
|
||||
@@ -103,28 +109,4 @@ private class ConstantDataSource extends Crypto::GenericConstantSourceInstance i
|
||||
override string getAdditionalDescription() { result = this.toString() }
|
||||
}
|
||||
|
||||
module ArtifactUniversalFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source = any(Crypto::ArtifactInstance artifact).getOutputNode()
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(Crypto::FlowAwareElement other).getInputNode()
|
||||
}
|
||||
|
||||
predicate isBarrierOut(DataFlow::Node node) {
|
||||
node = any(Crypto::FlowAwareElement element).getInputNode()
|
||||
}
|
||||
|
||||
predicate isBarrierIn(DataFlow::Node node) {
|
||||
node = any(Crypto::FlowAwareElement element).getOutputNode()
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node1.(AdditionalFlowInputStep).getOutput() = node2
|
||||
}
|
||||
}
|
||||
|
||||
module ArtifactUniversalFlow = DataFlow::Global<ArtifactUniversalFlowConfig>;
|
||||
|
||||
import OpenSSL.OpenSSL
|
||||
|
||||
@@ -14,9 +14,13 @@ private import PaddingAlgorithmInstance
|
||||
*/
|
||||
module KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() instanceof KnownOpenSslAlgorithmExpr and
|
||||
(
|
||||
source.asExpr() instanceof KnownOpenSslAlgorithmExpr or
|
||||
source.asIndirectExpr() instanceof KnownOpenSslAlgorithmExpr
|
||||
) and
|
||||
// No need to flow direct operations to AVCs
|
||||
not source.asExpr() instanceof OpenSslDirectAlgorithmOperationCall
|
||||
not source.asExpr() instanceof OpenSslDirectAlgorithmOperationCall and
|
||||
not source.asIndirectExpr() instanceof OpenSslDirectAlgorithmOperationCall
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
@@ -46,10 +50,12 @@ module KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig implements DataFlow::
|
||||
}
|
||||
|
||||
module KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow =
|
||||
DataFlow::Global<KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig>;
|
||||
TaintTracking::Global<KnownOpenSslAlgorithmToAlgorithmValueConsumerConfig>;
|
||||
|
||||
module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof OpenSslPaddingLiteral }
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr() instanceof OpenSslSpecialPaddingLiteral
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(PaddingAlgorithmValueConsumer c | c.getInputNode() = sink)
|
||||
@@ -61,7 +67,7 @@ module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig implements DataF
|
||||
}
|
||||
|
||||
module RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow =
|
||||
DataFlow::Global<RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig>;
|
||||
TaintTracking::Global<RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerConfig>;
|
||||
|
||||
class OpenSslAlgorithmAdditionalFlowStep extends AdditionalFlowInputStep {
|
||||
OpenSslAlgorithmAdditionalFlowStep() { exists(AlgorithmPassthroughCall c | c.getInNode() = this) }
|
||||
|
||||
@@ -53,7 +53,8 @@ class KnownOpenSslBlockModeConstantAlgorithmInstance extends OpenSslAlgorithmIns
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
|
||||
@@ -2,12 +2,10 @@ import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import KnownAlgorithmConstants
|
||||
private import Crypto::KeyOpAlg as KeyOpAlg
|
||||
private import OpenSSLAlgorithmInstanceBase
|
||||
private import PaddingAlgorithmInstance
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
|
||||
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperationBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
private import OpenSSLAlgorithmInstances
|
||||
private import AlgToAVCFlow
|
||||
private import BlockAlgorithmInstance
|
||||
|
||||
/**
|
||||
* Given a `KnownOpenSslCipherAlgorithmExpr`, converts this to a cipher family type.
|
||||
@@ -79,7 +77,8 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
@@ -97,10 +96,13 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
|
||||
}
|
||||
|
||||
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() {
|
||||
//TODO: the padding is either self, or it flows through getter ctx to a set padding call
|
||||
// like EVP_PKEY_CTX_set_rsa_padding
|
||||
result = this
|
||||
// TODO or trace through getter ctx to set padding
|
||||
or
|
||||
exists(OperationStep s |
|
||||
this.getAvc().(AvcContextCreationStep).flowsToOperationStep(s) and
|
||||
s.getAlgorithmValueConsumerForInput(PaddingAlgorithmIO()) =
|
||||
result.(OpenSslAlgorithmInstance).getAvc()
|
||||
)
|
||||
}
|
||||
|
||||
override string getRawAlgorithmName() {
|
||||
@@ -117,7 +119,7 @@ class KnownOpenSslCipherConstantAlgorithmInstance extends OpenSslAlgorithmInstan
|
||||
knownOpenSslConstantToCipherFamilyType(this, result)
|
||||
or
|
||||
not knownOpenSslConstantToCipherFamilyType(this, _) and
|
||||
result = Crypto::KeyOpAlg::TUnknownKeyOperationAlgorithmType()
|
||||
result = Crypto::KeyOpAlg::TOtherKeyOperationAlgorithmType()
|
||||
}
|
||||
|
||||
override OpenSslAlgorithmValueConsumer getAvc() { result = getterCall }
|
||||
|
||||
@@ -21,7 +21,8 @@ class KnownOpenSslEllipticCurveConstantAlgorithmInstance extends OpenSslAlgorith
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
|
||||
@@ -59,7 +59,8 @@ class KnownOpenSslHashConstantAlgorithmInstance extends OpenSslAlgorithmInstance
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
|
||||
@@ -37,7 +37,8 @@ class KnownOpenSslKeyAgreementConstantAlgorithmInstance extends OpenSslAlgorithm
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
|
||||
@@ -171,9 +171,15 @@ class KnownOpenSslKeyAgreementAlgorithmExpr extends Expr instanceof KnownOpenSsl
|
||||
}
|
||||
|
||||
predicate knownOpenSslAlgorithmOperationCall(Call c, string normalized, string algType) {
|
||||
c.getTarget().getName() in ["EVP_RSA_gen", "RSA_generate_key_ex", "RSA_generate_key", "RSA_new"] and
|
||||
c.getTarget().getName() in [
|
||||
"EVP_RSA_gen", "RSA_generate_key_ex", "RSA_generate_key", "RSA_new", "RSA_sign", "RSA_verify"
|
||||
] and
|
||||
normalized = "RSA" and
|
||||
algType = "ASYMMETRIC_ENCRYPTION"
|
||||
or
|
||||
c.getTarget().getName() in ["DSA_do_sign", "DSA_do_verify"] and
|
||||
normalized = "DSA" and
|
||||
algType = "SIGNATURE"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,12 +2,13 @@ import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import KnownAlgorithmConstants
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstanceBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
|
||||
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
|
||||
private import Crypto::KeyOpAlg as KeyOpAlg
|
||||
private import AlgToAVCFlow
|
||||
|
||||
class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
|
||||
Crypto::MacAlgorithmInstance instanceof KnownOpenSslMacAlgorithmExpr
|
||||
Crypto::KeyOperationAlgorithmInstance instanceof KnownOpenSslMacAlgorithmExpr
|
||||
{
|
||||
OpenSslAlgorithmValueConsumer getterCall;
|
||||
|
||||
@@ -21,7 +22,8 @@ class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
@@ -33,17 +35,34 @@ class KnownOpenSslMacConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
|
||||
|
||||
override OpenSslAlgorithmValueConsumer getAvc() { result = getterCall }
|
||||
|
||||
override string getRawMacAlgorithmName() {
|
||||
override string getRawAlgorithmName() {
|
||||
result = this.(Literal).getValue().toString()
|
||||
or
|
||||
result = this.(Call).getTarget().getName()
|
||||
}
|
||||
|
||||
override Crypto::MacType getMacType() {
|
||||
this instanceof KnownOpenSslHMacAlgorithmExpr and result = Crypto::HMAC()
|
||||
or
|
||||
this instanceof KnownOpenSslCMacAlgorithmExpr and result = Crypto::CMAC()
|
||||
override Crypto::KeyOpAlg::AlgorithmType getAlgorithmType() {
|
||||
if this instanceof KnownOpenSslHMacAlgorithmExpr
|
||||
then result = KeyOpAlg::TMac(KeyOpAlg::HMAC())
|
||||
else
|
||||
if this instanceof KnownOpenSslCMacAlgorithmExpr
|
||||
then result = KeyOpAlg::TMac(KeyOpAlg::CMAC())
|
||||
else result = KeyOpAlg::TMac(KeyOpAlg::OtherMacAlgorithmType())
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getKeySizeConsumer() {
|
||||
// TODO: trace to any key size initializer?
|
||||
none()
|
||||
}
|
||||
|
||||
override int getKeySizeFixed() {
|
||||
// TODO: are there known fixed key sizes to consider?
|
||||
none()
|
||||
}
|
||||
|
||||
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
|
||||
|
||||
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
|
||||
}
|
||||
|
||||
class KnownOpenSslHMacConstantAlgorithmInstance extends Crypto::HmacAlgorithmInstance,
|
||||
@@ -60,9 +79,13 @@ class KnownOpenSslHMacConstantAlgorithmInstance extends Crypto::HmacAlgorithmIns
|
||||
// where the current AVC traces to a HashAlgorithmIO consuming operation step.
|
||||
// TODO: need to consider getting reset values, tracing down to the first set for now
|
||||
exists(OperationStep s, AvcContextCreationStep avc |
|
||||
avc = this.getAvc() and
|
||||
avc = super.getAvc() and
|
||||
avc.flowsToOperationStep(s) and
|
||||
s.getAlgorithmValueConsumerForInput(HashAlgorithmIO()) = result
|
||||
)
|
||||
}
|
||||
|
||||
override Crypto::ModeOfOperationAlgorithmInstance getModeOfOperationAlgorithm() { none() }
|
||||
|
||||
override Crypto::PaddingAlgorithmInstance getPaddingAlgorithm() { none() }
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import cpp
|
||||
private import experimental.quantum.Language
|
||||
private import OpenSSLAlgorithmInstanceBase
|
||||
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperationBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.KnownAlgorithmConstants
|
||||
private import AlgToAVCFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.DirectAlgorithmValueConsumer
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumerBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
private import codeql.quantum.experimental.Standardization::Types::KeyOpAlg as KeyOpAlg
|
||||
|
||||
/**
|
||||
@@ -18,13 +18,14 @@ private import codeql.quantum.experimental.Standardization::Types::KeyOpAlg as K
|
||||
* # define RSA_PKCS1_WITH_TLS_PADDING 7
|
||||
* # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8
|
||||
*/
|
||||
class OpenSslPaddingLiteral extends Literal {
|
||||
class OpenSslSpecialPaddingLiteral extends Literal {
|
||||
// TODO: we can be more specific about where the literal is in a larger expression
|
||||
// to avoid literals that are clealy not representing an algorithm, e.g., array indices.
|
||||
OpenSslPaddingLiteral() { this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8] }
|
||||
OpenSslSpecialPaddingLiteral() { this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8] }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` has the given `type`.
|
||||
* Given a `KnownOpenSslPaddingAlgorithmExpr`, converts this to a padding family type.
|
||||
* Does not bind if there is no mapping (no mapping to 'unknown' or 'other').
|
||||
*/
|
||||
@@ -45,9 +46,6 @@ predicate knownOpenSslConstantToPaddingFamilyType(
|
||||
)
|
||||
}
|
||||
|
||||
//abstract class OpenSslPaddingAlgorithmInstance extends OpenSslAlgorithmInstance, Crypto::PaddingAlgorithmInstance{}
|
||||
// TODO: need to alter this to include known padding constants which don't have the
|
||||
// same mechanics as those with known nids
|
||||
class KnownOpenSslPaddingConstantAlgorithmInstance extends OpenSslAlgorithmInstance,
|
||||
Crypto::PaddingAlgorithmInstance instanceof Expr
|
||||
{
|
||||
@@ -66,7 +64,8 @@ class KnownOpenSslPaddingConstantAlgorithmInstance extends OpenSslAlgorithmInsta
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink) and
|
||||
isPaddingSpecificConsumer = false
|
||||
@@ -79,12 +78,13 @@ class KnownOpenSslPaddingConstantAlgorithmInstance extends OpenSslAlgorithmInsta
|
||||
isPaddingSpecificConsumer = false
|
||||
or
|
||||
// Possibility 3: padding-specific literal
|
||||
this instanceof OpenSslPaddingLiteral and
|
||||
this instanceof OpenSslSpecialPaddingLiteral and
|
||||
exists(DataFlow::Node src, DataFlow::Node sink |
|
||||
// Sink is an argument to a CipherGetterCall
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a padding-specific consumer
|
||||
RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
) and
|
||||
@@ -124,44 +124,6 @@ class KnownOpenSslPaddingConstantAlgorithmInstance extends OpenSslAlgorithmInsta
|
||||
}
|
||||
}
|
||||
|
||||
// // Values used for EVP_PKEY_CTX_set_rsa_padding, these are
|
||||
// // not the same as 'typical' constants found in the set of known algorithm constants
|
||||
// // they do not have an NID
|
||||
// // TODO: what about setting the padding directly?
|
||||
// class KnownRSAPaddingConstant extends OpenSslPaddingAlgorithmInstance, Crypto::PaddingAlgorithmInstance instanceof Literal
|
||||
// {
|
||||
// KnownRSAPaddingConstant() {
|
||||
// // from rsa.h in openssl:
|
||||
// // # define RSA_PKCS1_PADDING 1
|
||||
// // # define RSA_NO_PADDING 3
|
||||
// // # define RSA_PKCS1_OAEP_PADDING 4
|
||||
// // # define RSA_X931_PADDING 5
|
||||
// // /* EVP_PKEY_ only */
|
||||
// // # define RSA_PKCS1_PSS_PADDING 6
|
||||
// // # define RSA_PKCS1_WITH_TLS_PADDING 7
|
||||
// // /* internal RSA_ only */
|
||||
// // # define RSA_PKCS1_NO_IMPLICIT_REJECT_PADDING 8
|
||||
// this instanceof Literal and
|
||||
// this.getValue().toInt() in [0, 1, 3, 4, 5, 6, 7, 8]
|
||||
// // TODO: trace to padding-specific consumers
|
||||
// RsaPaddingAlgorithmToPaddingAlgorithmValueConsumerFlow
|
||||
// }
|
||||
// override string getRawPaddingAlgorithmName() { result = this.(Literal).getValue().toString() }
|
||||
// override Crypto::TPaddingType getPaddingType() {
|
||||
// if this.(Literal).getValue().toInt() in [1, 6, 7, 8]
|
||||
// then result = Crypto::PKCS1_v1_5()
|
||||
// else
|
||||
// if this.(Literal).getValue().toInt() = 3
|
||||
// then result = Crypto::NoPadding()
|
||||
// else
|
||||
// if this.(Literal).getValue().toInt() = 4
|
||||
// then result = Crypto::OAEP()
|
||||
// else
|
||||
// if this.(Literal).getValue().toInt() = 5
|
||||
// then result = Crypto::ANSI_X9_23()
|
||||
// else result = Crypto::OtherPadding()
|
||||
// }
|
||||
// }
|
||||
class OaepPaddingAlgorithmInstance extends Crypto::OaepPaddingAlgorithmInstance,
|
||||
KnownOpenSslPaddingConstantAlgorithmInstance
|
||||
{
|
||||
@@ -170,10 +132,18 @@ class OaepPaddingAlgorithmInstance extends Crypto::OaepPaddingAlgorithmInstance,
|
||||
}
|
||||
|
||||
override Crypto::HashAlgorithmInstance getOaepEncodingHashAlgorithm() {
|
||||
none() //TODO
|
||||
exists(OperationStep s |
|
||||
this.getAvc().(AvcContextCreationStep).flowsToOperationStep(s) and
|
||||
s.getAlgorithmValueConsumerForInput(HashAlgorithmOaepIO()) =
|
||||
result.(OpenSslAlgorithmInstance).getAvc()
|
||||
)
|
||||
}
|
||||
|
||||
override Crypto::HashAlgorithmInstance getMgf1HashAlgorithm() {
|
||||
none() //TODO
|
||||
exists(OperationStep s |
|
||||
this.getAvc().(AvcContextCreationStep).flowsToOperationStep(s) and
|
||||
s.getAlgorithmValueConsumerForInput(HashAlgorithmMgf1IO()) =
|
||||
result.(OpenSslAlgorithmInstance).getAvc()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ class KnownOpenSslSignatureConstantAlgorithmInstance extends OpenSslAlgorithmIns
|
||||
// Sink is an argument to a signature getter call
|
||||
sink = getterCall.getInputNode() and
|
||||
// Source is `this`
|
||||
src.asExpr() = this and
|
||||
// NOTE: src literals can be ints or strings, so need to consider asExpr and asIndirectExpr
|
||||
this = [src.asExpr(), src.asIndirectExpr()] and
|
||||
// This traces to a getter
|
||||
KnownOpenSslAlgorithmToAlgorithmValueConsumerFlow::flow(src, sink)
|
||||
)
|
||||
|
||||
@@ -12,15 +12,17 @@ class EvpCipherAlgorithmValueConsumer extends CipherAlgorithmValueConsumer {
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpCipherAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asIndirectExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() in [
|
||||
"EVP_get_cipherbyname", "EVP_get_cipherbyobj", "EVP_get_cipherbynid"
|
||||
] and
|
||||
this.(Call).getTarget().getName() in ["EVP_get_cipherbyname", "EVP_get_cipherbyobj"] and
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() = "EVP_get_cipherbynid" and
|
||||
// algorithm is an NID (int), use asExpr()
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() in ["EVP_CIPHER_fetch", "EVP_ASYM_CIPHER_fetch"] and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class DirectAlgorithmValueConsumer extends OpenSslAlgorithmValueConsumer instanc
|
||||
*/
|
||||
override DataFlow::Node getResultNode() {
|
||||
this instanceof OpenSslDirectAlgorithmFetchCall and
|
||||
result.asExpr() = this
|
||||
result.asIndirectExpr() = this
|
||||
// NOTE: if instanceof OpenSslDirectAlgorithmOperationCall then there is no algorithm generated
|
||||
// the algorithm is directly used
|
||||
}
|
||||
|
||||
@@ -12,14 +12,19 @@ class EvpEllipticCurveAlgorithmConsumer extends EllipticCurveValueConsumer {
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpEllipticCurveAlgorithmConsumer() {
|
||||
resultNode.asExpr() = this.(Call) and // in all cases the result is the return
|
||||
resultNode.asIndirectExpr() = this.(Call) and // in all cases the result is the return
|
||||
(
|
||||
this.(Call).getTarget().getName() in ["EVP_EC_gen", "EC_KEY_new_by_curve_name"] and
|
||||
this.(Call).getTarget().getName() = "EVP_EC_gen" and
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() = "EC_KEY_new_by_curve_name" and
|
||||
// algorithm is an NID (int), use asExpr()
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() in [
|
||||
"EC_KEY_new_by_curve_name_ex", "EVP_PKEY_CTX_set_ec_paramgen_curve_nid"
|
||||
] and
|
||||
// algorithm is an NID (int), use asExpr
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(2)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@ abstract class HashAlgorithmValueConsumer extends OpenSslAlgorithmValueConsumer
|
||||
/**
|
||||
* An EVP_Q_Digest directly consumes algorithm constant values
|
||||
*/
|
||||
class Evp_Q_Digest_Algorithm_Consumer extends HashAlgorithmValueConsumer {
|
||||
Evp_Q_Digest_Algorithm_Consumer() { this.(Call).getTarget().getName() = "EVP_Q_digest" }
|
||||
class Evp_Q_Digest_Algorithm_Consumer extends HashAlgorithmValueConsumer instanceof Call {
|
||||
Evp_Q_Digest_Algorithm_Consumer() { super.getTarget().getName() = "EVP_Q_digest" }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputNode() {
|
||||
result.asExpr() = this.(Call).getArgument(1)
|
||||
result.asIndirectExpr() = super.getArgument(1)
|
||||
}
|
||||
|
||||
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
|
||||
@@ -42,7 +42,7 @@ class EvpPkeySetCtxALgorithmConsumer extends HashAlgorithmValueConsumer {
|
||||
"EVP_PKEY_CTX_set_rsa_mgf1_md_name", "EVP_PKEY_CTX_set_rsa_oaep_md_name",
|
||||
"EVP_PKEY_CTX_set_dsa_paramgen_md_props"
|
||||
] and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
}
|
||||
|
||||
override DataFlow::Node getResultNode() { none() }
|
||||
@@ -64,18 +64,18 @@ class EvpDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpDigestAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asIndirectExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() in [
|
||||
"EVP_get_digestbyname", "EVP_get_digestbynid", "EVP_get_digestbyobj"
|
||||
] and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(0)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() = "EVP_MD_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
or
|
||||
this.(Call).getTarget().getName() = "EVP_DigestSignInit_ex" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(2)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(2)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -87,3 +87,21 @@ class EvpDigestAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
|
||||
exists(OpenSslAlgorithmInstance i | i.getAvc() = this and result = i)
|
||||
}
|
||||
}
|
||||
|
||||
class RsaSignOrVerifyHashAlgorithmValueConsumer extends HashAlgorithmValueConsumer {
|
||||
DataFlow::Node valueArgNode;
|
||||
|
||||
RsaSignOrVerifyHashAlgorithmValueConsumer() {
|
||||
this.(Call).getTarget().getName() in ["RSA_sign", "RSA_verify"] and
|
||||
// arg 0 is an int, use asExpr
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(0)
|
||||
}
|
||||
|
||||
override DataFlow::Node getResultNode() { none() }
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputNode() { result = valueArgNode }
|
||||
|
||||
override Crypto::AlgorithmInstance getAKnownAlgorithmSource() {
|
||||
exists(OpenSslAlgorithmInstance i | i.getAvc() = this and result = i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,10 @@ class EvpKemAlgorithmValueConsumer extends KemAlgorithmValueConsumer {
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpKemAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asIndirectExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() = "EVP_KEM_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ class EvpKeyExchangeAlgorithmValueConsumer extends KeyExchangeAlgorithmValueCons
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpKeyExchangeAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asIndirectExpr() = this and
|
||||
(
|
||||
this.(Call).getTarget().getName() = "EVP_KEYEXCH_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class EvpPKeyAlgorithmConsumer extends PKeyValueConsumer {
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpPKeyAlgorithmConsumer() {
|
||||
resultNode.asExpr() = this.(Call) and // in all cases the result is the return
|
||||
resultNode.asIndirectExpr() = this.(Call) and // in all cases the result is the return
|
||||
(
|
||||
// NOTE: some of these consumers are themselves key gen operations,
|
||||
// in these cases, the operation will be created separately for the same function.
|
||||
@@ -19,6 +19,7 @@ class EvpPKeyAlgorithmConsumer extends PKeyValueConsumer {
|
||||
"EVP_PKEY_CTX_new_id", "EVP_PKEY_new_raw_private_key", "EVP_PKEY_new_raw_public_key",
|
||||
"EVP_PKEY_new_mac_key"
|
||||
] and
|
||||
// Algorithm is an int, use asExpr
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(0)
|
||||
or
|
||||
this.(Call).getTarget().getName() in [
|
||||
@@ -26,7 +27,8 @@ class EvpPKeyAlgorithmConsumer extends PKeyValueConsumer {
|
||||
"EVP_PKEY_new_raw_public_key_ex", "EVP_PKEY_CTX_ctrl", "EVP_PKEY_CTX_ctrl_uint64",
|
||||
"EVP_PKEY_CTX_ctrl_str", "EVP_PKEY_CTX_set_group_name"
|
||||
] and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
// AAlgorithm is a char*, use asIndirectExpr
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
or
|
||||
// argInd 2 is 'type' which can be RSA, or EC
|
||||
// if RSA argInd 3 is the key size, else if EC argInd 3 is the curve name
|
||||
@@ -38,10 +40,10 @@ class EvpPKeyAlgorithmConsumer extends PKeyValueConsumer {
|
||||
// Elliptic curve case
|
||||
// If the argInd 3 is a derived type (pointer or array) then assume it is a curve name
|
||||
if this.(Call).getArgument(3).getType().getUnderlyingType() instanceof DerivedType
|
||||
then valueArgNode.asExpr() = this.(Call).getArgument(3)
|
||||
then valueArgNode.asIndirectExpr() = this.(Call).getArgument(3)
|
||||
else
|
||||
// All other cases
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(2)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(2)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,8 +14,9 @@ class Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer extends PaddingAlgorit
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
Evp_PKey_Ctx_set_rsa_padding_AlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asDefiningArgument() = this.(Call).getArgument(0) and
|
||||
this.(Call).getTarget().getName() = "EVP_PKEY_CTX_set_rsa_padding" and
|
||||
// algorithm is an int, use asExpr
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@ class EvpSignatureAlgorithmValueConsumer extends SignatureAlgorithmValueConsumer
|
||||
DataFlow::Node resultNode;
|
||||
|
||||
EvpSignatureAlgorithmValueConsumer() {
|
||||
resultNode.asExpr() = this and
|
||||
resultNode.asIndirectExpr() = this and
|
||||
(
|
||||
// EVP_SIGNATURE
|
||||
this.(Call).getTarget().getName() = "EVP_SIGNATURE_fetch" and
|
||||
valueArgNode.asExpr() = this.(Call).getArgument(1)
|
||||
valueArgNode.asIndirectExpr() = this.(Call).getArgument(1)
|
||||
// EVP_PKEY_get1_DSA, EVP_PKEY_get1_RSA
|
||||
// DSA_SIG_new, DSA_SIG_get0, RSA_sign ?
|
||||
// DSA_SIG_new, DSA_SIG_get0 ?
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
107
cpp/ql/lib/experimental/quantum/OpenSSL/ArtifactPassthrough.qll
Normal file
107
cpp/ql/lib/experimental/quantum/OpenSSL/ArtifactPassthrough.qll
Normal file
@@ -0,0 +1,107 @@
|
||||
private import experimental.quantum.Language
|
||||
|
||||
/**
|
||||
* A call to `BN_bn2bin`.
|
||||
* Commonly used to extract partial bytes from a signature,
|
||||
* e.g., a signature from DSA_do_sign, passed to DSA_do_verify
|
||||
* - int BN_bn2bin(const BIGNUM *a, unsigned char *to);
|
||||
*/
|
||||
class BnBn2BinCalStep extends AdditionalFlowInputStep {
|
||||
Call call;
|
||||
|
||||
BnBn2BinCalStep() {
|
||||
call.getTarget().getName() = "BN_bn2bin" and
|
||||
call.getArgument(0) = this.asIndirectExpr()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result.asDefiningArgument() = call.getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `BN_bin2bn`.
|
||||
* Commonly used to convert to a signature for DSA_do_verify
|
||||
* - BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
|
||||
*/
|
||||
class BnBin2BnCallStep extends AdditionalFlowInputStep {
|
||||
Call call;
|
||||
|
||||
BnBin2BnCallStep() {
|
||||
call.getTarget().getName() = "BN_bin2bn" and
|
||||
call.getArgument(0) = this.asIndirectExpr()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result.asDefiningArgument() = call.getArgument(2) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `RSA_set0_key` or `DSA_SIG_set0`.
|
||||
* Often used in combination with BN_bin2bn, to construct a signature.
|
||||
*/
|
||||
class RsaSet0KeyCallStep extends AdditionalFlowInputStep {
|
||||
Call call;
|
||||
|
||||
RsaSet0KeyCallStep() {
|
||||
(call.getTarget().getName() = "RSA_set0_key" or call.getTarget().getName() = "DSA_SIG_set0") and
|
||||
this.asIndirectExpr() in [call.getArgument(1), call.getArgument(2), call.getArgument(3)]
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result.asDefiningArgument() = call.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `d2i_DSA_SIG`. This is a pass through of a signature of one form to another.
|
||||
* - DSA_SIG *d2i_DSA_SIG(DSA_SIG **sig, const unsigned char **pp, long length);
|
||||
*/
|
||||
class D2iDsaSigCallStep extends AdditionalFlowInputStep {
|
||||
Call call;
|
||||
|
||||
D2iDsaSigCallStep() {
|
||||
call.getTarget().getName() = "d2i_DSA_SIG" and
|
||||
this.asIndirectExpr() = call.getArgument(1)
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() {
|
||||
// If arg 0 specified, the same pointer is returned, if not specified
|
||||
// a new allocation is returned.
|
||||
result.asDefiningArgument() = call.getArgument(0) or
|
||||
result.asIndirectExpr() = call
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DSA_SIG_get0`.
|
||||
* Converts a DSA_Sig into its components, which are commonly used with BN_bn2Bin to
|
||||
* construct a char* signature.
|
||||
* - void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
|
||||
*/
|
||||
class DsaSigGet0CallStep extends AdditionalFlowInputStep {
|
||||
Call call;
|
||||
|
||||
DsaSigGet0CallStep() {
|
||||
call.getTarget().getName() = "DSA_SIG_get0" and
|
||||
this.asIndirectExpr() = call.getArgument(0)
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() {
|
||||
result.asDefiningArgument() = call.getArgument(1)
|
||||
or
|
||||
result.asDefiningArgument() = call.getArgument(2)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_get1_RSA` or `EVP_PKEY_get1_DSA`
|
||||
* - RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
|
||||
* - DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
|
||||
* A key input is converted into a key output, a key is not generated.
|
||||
*/
|
||||
class EvpPkeyGet1RsaOrDsa extends AdditionalFlowInputStep {
|
||||
Call c;
|
||||
|
||||
EvpPkeyGet1RsaOrDsa() {
|
||||
c.getTarget().getName() = ["EVP_PKEY_get1_RSA", "EVP_PKEY_get1_DSA"] and
|
||||
this.asIndirectExpr() = c.getArgument(0)
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput() { result.asIndirectExpr() = c }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
|
||||
/**
|
||||
@@ -13,7 +13,9 @@ module AvcToCallArgConfig implements DataFlow::ConfigSig {
|
||||
* Trace to any call accepting the algorithm.
|
||||
* NOTE: users must restrict this set to the operations they are interested in.
|
||||
*/
|
||||
predicate isSink(DataFlow::Node sink) { exists(Call c | c.getAnArgument() = sink.asExpr()) }
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(Call c | c.getAnArgument() = [sink.asIndirectExpr(), sink.asExpr()])
|
||||
}
|
||||
}
|
||||
|
||||
module AvcToCallArgFlow = DataFlow::Global<AvcToCallArgConfig>;
|
||||
module AvcToCallArgFlow = TaintTracking::Global<AvcToCallArgConfig>;
|
||||
|
||||
@@ -4,4 +4,5 @@ module OpenSslModel {
|
||||
import Operations.OpenSSLOperations
|
||||
import Random
|
||||
import GenericSourceCandidateLiteral
|
||||
import ArtifactPassthrough
|
||||
}
|
||||
|
||||
@@ -3,24 +3,48 @@ private import OpenSSLOperationBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
import EVPPKeyCtxInitializer
|
||||
|
||||
/**
|
||||
* A base class for all final cipher operation steps.
|
||||
*/
|
||||
abstract class FinalCipherOperationStep extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A base configuration for all EVP cipher operations.
|
||||
*/
|
||||
abstract class EvpCipherOperationFinalStep extends FinalCipherOperationStep {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for all EVP cipher operations.
|
||||
*/
|
||||
abstract class EvpCipherInitializer extends OperationStep {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = PrimaryAlgorithmIO() and
|
||||
// Constants that are not equal to zero or
|
||||
// non-constants (e.g., variable accesses, which require data-flow to determine the value)
|
||||
// A zero (null) value typically indicates use of this operation step to initialize
|
||||
// other out parameters in a multi-step initialization.
|
||||
(exists(result.asExpr().getValue()) implies result.asExpr().getValue().toInt() != 0)
|
||||
(
|
||||
exists(result.asIndirectExpr().getValue())
|
||||
implies
|
||||
result.asIndirectExpr().getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -38,11 +62,15 @@ abstract class EvpEXInitializer extends EvpCipherInitializer {
|
||||
// non-constants (e.g., variable accesses, which require data-flow to determine the value)
|
||||
// A zero (null) value typically indicates use of this operation step to initialize
|
||||
// other out parameters in a multi-step initialization.
|
||||
result.asExpr() = this.getArgument(3) and type = KeyIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = KeyIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(4) and type = IVorNonceIO()
|
||||
result.asIndirectExpr() = this.getArgument(4) and type = IVorNonceIO()
|
||||
) and
|
||||
(exists(result.asExpr().getValue()) implies result.asExpr().getValue().toInt() != 0)
|
||||
(
|
||||
exists(result.asIndirectExpr().getValue())
|
||||
implies
|
||||
result.asIndirectExpr().getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +81,9 @@ abstract class EvpEX2Initializer extends EvpCipherInitializer {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result = super.getInput(type)
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = KeyIO()
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = KeyIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = IVorNonceIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = IVorNonceIO()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +118,7 @@ class Evp_Cipher_EX2_or_Simple_Init_Call extends EvpEX2Initializer {
|
||||
result = super.getInput(type)
|
||||
or
|
||||
this.getTarget().getName().toLowerCase().matches("%cipherinit%") and
|
||||
// the key op subtype is an int, use asExpr
|
||||
result.asExpr() = this.getArgument(4) and
|
||||
type = KeyOperationSubtypeIO()
|
||||
}
|
||||
@@ -107,13 +136,13 @@ class EvpPkeyEncryptDecryptInit extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = OsslParamIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = OsslParamIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -125,6 +154,7 @@ class EvpCipherInitSKeyCall extends EvpEX2Initializer {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result = super.getInput(type)
|
||||
or
|
||||
// the key op subtype is an int, use asExpr
|
||||
result.asExpr() = this.getArgument(5) and
|
||||
type = KeyOperationSubtypeIO()
|
||||
}
|
||||
@@ -141,35 +171,20 @@ class EvpCipherUpdateCall extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(1) and type = CiphertextIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = CiphertextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A base configuration for all EVP cipher operations.
|
||||
*/
|
||||
abstract class EvpCipherOperationFinalStep extends OperationStep {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A Call to EVP_Cipher.
|
||||
*/
|
||||
@@ -179,13 +194,13 @@ class EvpCipherCall extends EvpCipherOperationFinalStep {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
super.getInput(type) = result
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
super.getOutput(type) = result
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = CiphertextIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = CiphertextIO()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,28 +231,50 @@ class EvpCipherFinalCall extends EvpCipherOperationFinalStep {
|
||||
*/
|
||||
class EvpPKeyCipherOperation extends EvpCipherOperationFinalStep {
|
||||
EvpPKeyCipherOperation() {
|
||||
this.getTarget().getName() in ["EVP_PKEY_encrypt", "EVP_PKEY_decrypt"]
|
||||
this.getTarget().getName() in ["EVP_PKEY_encrypt", "EVP_PKEY_decrypt"] and
|
||||
// TODO: for now ignore this operation entirely if it is setting the cipher text to null
|
||||
// this needs to be re-evalauted if this scenario sets other values worth tracking
|
||||
(
|
||||
exists(this.(Call).getArgument(1).getValue())
|
||||
implies
|
||||
this.(Call).getArgument(1).getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
super.getInput(type) = result
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
super.getOutput(type) = result
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = CiphertextIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and
|
||||
type = CiphertextIO() and
|
||||
this.getStepType() = FinalStep()
|
||||
// TODO: could indicate text lengths here, as well
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() {
|
||||
// When the output buffer is null, the step is not a final step
|
||||
// it is used to get the buffer size, if 0 consider it an initialization step
|
||||
// NOTE/TODO: not tracing 0 to the arg, just looking for 0 directly in param
|
||||
// the assumption is this is the common case, but we may want to make this more
|
||||
// robust and support a dataflow.
|
||||
result = FinalStep() and
|
||||
(exists(super.getArgument(1).getValue()) implies super.getArgument(1).getValue().toInt() != 0)
|
||||
or
|
||||
result = InitializerStep() and
|
||||
super.getArgument(1).getValue().toInt() = 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An EVP cipher operation instance.
|
||||
* Any operation step that is a final operation step for EVP cipher operation steps.
|
||||
*/
|
||||
class EvpCipherOperationInstance extends Crypto::KeyOperationInstance instanceof EvpCipherOperationFinalStep
|
||||
class OpenSslCipherOperationInstance extends Crypto::KeyOperationInstance instanceof FinalCipherOperationStep
|
||||
{
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
super.getPrimaryAlgorithmValueConsumer() = result
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
/**
|
||||
* Initializers for EVP PKey
|
||||
* These are used to create a Pkey context or set properties on a Pkey context
|
||||
* e.g., key size, hash algorithms, curves, padding schemes, etc.
|
||||
* Meant to capture more general purpose initializers that aren't necessarily
|
||||
* tied to a specific operation. If tied to an operation (i.e., in the docs)
|
||||
* we recommend defining defining all together in the same operation definition qll.
|
||||
* including:
|
||||
* https://docs.openssl.org/3.0/man3/EVP_PKEY_CTX_ctrl/
|
||||
* https://docs.openssl.org/3.0/man3/EVP_EncryptInit/#synopsis
|
||||
@@ -26,14 +31,16 @@ class EvpNewKeyCtx extends OperationStep instanceof Call {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = keyArg and type = KeyIO()
|
||||
result.asIndirectExpr() = keyArg and type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_PKEY_CTX_new_from_pkey" and
|
||||
result.asExpr() = this.getArgument(0) and
|
||||
result.asIndirectExpr() = this.getArgument(0) and
|
||||
type = OsslLibContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = ContextIO() }
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asIndirectExpr() = this and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = ContextCreationStep() }
|
||||
}
|
||||
@@ -47,13 +54,13 @@ class EvpCtxSetEcParamgenCurveNidInitializer extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -71,23 +78,46 @@ class EvpCtxSetEcParamgenCurveNidInitializer extends OperationStep {
|
||||
* - `EVP_PKEY_CTX_set_ecdh_kdf_md`
|
||||
*/
|
||||
class EvpCtxSetHashInitializer extends OperationStep {
|
||||
boolean isOaep;
|
||||
boolean isMgf1;
|
||||
|
||||
EvpCtxSetHashInitializer() {
|
||||
this.getTarget().getName() in [
|
||||
"EVP_PKEY_CTX_set_signature_md", "EVP_PKEY_CTX_set_rsa_mgf1_md_name",
|
||||
"EVP_PKEY_CTX_set_rsa_mgf1_md", "EVP_PKEY_CTX_set_rsa_oaep_md_name",
|
||||
"EVP_PKEY_CTX_set_rsa_oaep_md", "EVP_PKEY_CTX_set_dsa_paramgen_md",
|
||||
"EVP_PKEY_CTX_set_signature_md", "EVP_PKEY_CTX_set_dsa_paramgen_md",
|
||||
"EVP_PKEY_CTX_set_dh_kdf_md", "EVP_PKEY_CTX_set_ecdh_kdf_md"
|
||||
]
|
||||
] and
|
||||
isOaep = false and
|
||||
isMgf1 = false
|
||||
or
|
||||
this.getTarget().getName() in [
|
||||
"EVP_PKEY_CTX_set_rsa_mgf1_md_name", "EVP_PKEY_CTX_set_rsa_mgf1_md"
|
||||
] and
|
||||
isOaep = false and
|
||||
isMgf1 = true
|
||||
or
|
||||
this.getTarget().getName() in [
|
||||
"EVP_PKEY_CTX_set_rsa_oaep_md_name",
|
||||
"EVP_PKEY_CTX_set_rsa_oaep_md"
|
||||
] and
|
||||
isOaep = true and
|
||||
isMgf1 = false
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = HashAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = HashAlgorithmIO() and
|
||||
isOaep = false and
|
||||
isMgf1 = false
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = HashAlgorithmOaepIO() and isOaep = true
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = HashAlgorithmMgf1IO() and isMgf1 = true
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -106,13 +136,13 @@ class EvpCtxSetKeySizeInitializer extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = KeySizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -122,16 +152,16 @@ class EvpCtxSetMacKeyInitializer extends OperationStep {
|
||||
EvpCtxSetMacKeyInitializer() { this.getTarget().getName() = "EVP_PKEY_CTX_set_mac_key" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = KeySizeIO()
|
||||
or
|
||||
// the raw key that is configured into the output key
|
||||
result.asExpr() = this.getArgument(1) and type = KeyIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -143,13 +173,14 @@ class EvpCtxSetPaddingInitializer extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
// The algorithm is an int: use asExpr
|
||||
result.asExpr() = this.getArgument(1) and type = PaddingAlgorithmIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -161,13 +192,13 @@ class EvpCtxSetSaltLengthInitializer extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = SaltLengthIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
|
||||
@@ -6,6 +6,13 @@ private import experimental.quantum.Language
|
||||
private import OpenSSLOperationBase
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
|
||||
/**
|
||||
* A base class for final digest operations.
|
||||
*/
|
||||
abstract class FinalDigestOperation extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to and EVP digest initializer, such as:
|
||||
* - `EVP_DigestInit`
|
||||
@@ -18,13 +25,13 @@ class EvpDigestInitVariantCalls extends OperationStep instanceof Call {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and
|
||||
result.asDefiningArgument() = this.getArgument(0) and
|
||||
type = ContextIO()
|
||||
}
|
||||
|
||||
@@ -38,56 +45,49 @@ class EvpDigestUpdateCall extends OperationStep instanceof Call {
|
||||
EvpDigestUpdateCall() { this.getTarget().getName() = "EVP_DigestUpdate" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and
|
||||
result.asDefiningArgument() = this.getArgument(0) and
|
||||
type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for final digest operations.
|
||||
*/
|
||||
abstract class EvpFinalDigestOperationStep extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_Q_digest`
|
||||
* https://docs.openssl.org/3.0/man3/EVP_DigestInit/#synopsis
|
||||
*/
|
||||
class EvpQDigestOperation extends EvpFinalDigestOperationStep instanceof Call {
|
||||
class EvpQDigestOperation extends FinalDigestOperation instanceof Call {
|
||||
EvpQDigestOperation() { this.getTarget().getName() = "EVP_Q_digest" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PrimaryAlgorithmIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and
|
||||
result.asDefiningArgument() = this.getArgument(0) and
|
||||
type = ContextIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(5) and type = DigestIO()
|
||||
}
|
||||
}
|
||||
|
||||
class EvpDigestOperation extends EvpFinalDigestOperationStep instanceof Call {
|
||||
class EvpDigestOperation extends FinalDigestOperation instanceof Call {
|
||||
EvpDigestOperation() { this.getTarget().getName() = "EVP_Digest" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(4) and type = PrimaryAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(4) and type = PrimaryAlgorithmIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(0) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
@@ -98,27 +98,28 @@ class EvpDigestOperation extends EvpFinalDigestOperationStep instanceof Call {
|
||||
/**
|
||||
* A call to EVP_DigestFinal variants
|
||||
*/
|
||||
class EvpDigestFinalCall extends EvpFinalDigestOperationStep instanceof Call {
|
||||
class EvpDigestFinalCall extends FinalDigestOperation instanceof Call {
|
||||
EvpDigestFinalCall() {
|
||||
this.getTarget().getName() in ["EVP_DigestFinal", "EVP_DigestFinal_ex", "EVP_DigestFinalXOF"]
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and
|
||||
result.asDefiningArgument() = this.getArgument(0) and
|
||||
type = ContextIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = DigestIO()
|
||||
//result.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = this.getArgument(1)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An openssl digest final hash operation instance
|
||||
*/
|
||||
class EvpDigestFinalOperationInstance extends Crypto::HashOperationInstance instanceof EvpFinalDigestOperationStep
|
||||
class OpenSslDigestFinalOperationInstance extends Crypto::HashOperationInstance instanceof FinalDigestOperation
|
||||
{
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
super.getPrimaryAlgorithmValueConsumer() = result
|
||||
|
||||
@@ -13,10 +13,12 @@ class ECKeyGen extends OperationStep instanceof Call {
|
||||
ECKeyGen() { this.(Call).getTarget().getName() = "EC_KEY_generate_key" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.(Call).getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.(Call).getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this and type = KeyIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = ContextCreationStep() }
|
||||
}
|
||||
@@ -33,16 +35,19 @@ class EvpKeyGenInitialize extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for final key generation operation steps.
|
||||
*/
|
||||
abstract class KeyGenFinalOperationStep extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
@@ -54,26 +59,26 @@ class EvpPKeyQKeyGen extends KeyGenFinalOperationStep instanceof Call {
|
||||
EvpPKeyQKeyGen() { this.getTarget().getName() = "EVP_PKEY_Q_keygen" }
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this and type = KeyIO()
|
||||
result.asDefiningArgument() = this and type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
// When arg 3 is a derived type, it is a curve name, otherwise it is a key size for RSA if provided
|
||||
// and arg 2 is the algorithm type
|
||||
this.getArgument(3).getType().getUnderlyingType() instanceof DerivedType and
|
||||
result.asExpr() = this.getArgument(3) and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = PrimaryAlgorithmIO()
|
||||
or
|
||||
not this.getArgument(3).getType().getUnderlyingType() instanceof DerivedType and
|
||||
result.asExpr() = this.getArgument(2) and
|
||||
result.asIndirectExpr() = this.getArgument(2) and
|
||||
type = PrimaryAlgorithmIO()
|
||||
or
|
||||
not this.getArgument(3).getType().getUnderlyingType() instanceof DerivedType and
|
||||
result.asExpr() = this.getArgument(3) and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = KeySizeIO()
|
||||
}
|
||||
}
|
||||
@@ -84,7 +89,9 @@ class EvpPKeyQKeyGen extends KeyGenFinalOperationStep instanceof Call {
|
||||
class EvpRsaGen extends KeyGenFinalOperationStep instanceof Call {
|
||||
EvpRsaGen() { this.getTarget().getName() = "EVP_RSA_gen" }
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this and type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = KeySizeIO()
|
||||
@@ -97,7 +104,9 @@ class EvpRsaGen extends KeyGenFinalOperationStep instanceof Call {
|
||||
class RsaGenerateKey extends KeyGenFinalOperationStep instanceof Call {
|
||||
RsaGenerateKey() { this.getTarget().getName() = "RSA_generate_key" }
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) { result.asExpr() = this and type = KeyIO() }
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this and type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = KeySizeIO()
|
||||
@@ -117,7 +126,7 @@ class RsaGenerateKeyEx extends KeyGenFinalOperationStep instanceof Call {
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
// arg 0 comes in as a blank RSA key, which we consider a context,
|
||||
// on output it is considered a key
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,13 +137,13 @@ class EvpPkeyGen extends KeyGenFinalOperationStep instanceof Call {
|
||||
EvpPkeyGen() { this.getTarget().getName() in ["EVP_PKEY_generate", "EVP_PKEY_keygen"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = KeyIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,18 +155,14 @@ class EvpNewMacKey extends KeyGenFinalOperationStep {
|
||||
EvpNewMacKey() { this.getTarget().getName() = "EVP_PKEY_new_mac_key" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
// the raw key that is configured into the output key
|
||||
result.asExpr() = this.getArgument(2) and type = KeyIO()
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = KeyIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = KeySizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this and type = KeyIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this and type = KeyIO()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +170,7 @@ class EvpNewMacKey extends KeyGenFinalOperationStep {
|
||||
/**
|
||||
* An `KeyGenerationOperationInstance` for the for all key gen final operation steps.
|
||||
*/
|
||||
class KeyGenOperationInstance extends Crypto::KeyGenerationOperationInstance instanceof KeyGenFinalOperationStep
|
||||
class OpenSslKeyGenOperationInstance extends Crypto::KeyGenerationOperationInstance instanceof KeyGenFinalOperationStep
|
||||
{
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
super.getPrimaryAlgorithmValueConsumer() = result
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
private import experimental.quantum.Language
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
import semmle.code.cpp.dataflow.new.TaintTracking
|
||||
// Importing these intializers here to ensure the are part of any model that is
|
||||
// using OpenSslOperationBase. This further ensures that initializers are tied to opeartions
|
||||
// even if only importing the operation by itself.
|
||||
@@ -58,7 +58,11 @@ newtype TIOType =
|
||||
// For OSSL_PARAM and OSSL_LIB_CTX use of OsslParamIO and OsslLibContextIO
|
||||
ContextIO() or
|
||||
DigestIO() or
|
||||
// For OAEP and MGF1 hashes, there is a special IO type for these hashes
|
||||
// it is recommended to set the most explicit type known, not both
|
||||
HashAlgorithmIO() or
|
||||
HashAlgorithmOaepIO() or
|
||||
HashAlgorithmMgf1IO() or
|
||||
IVorNonceIO() or
|
||||
KeyIO() or
|
||||
KeyOperationSubtypeIO() or
|
||||
@@ -71,11 +75,13 @@ newtype TIOType =
|
||||
PaddingAlgorithmIO() or
|
||||
// Plaintext also includes a message for digest, signature, verification, and mac generation
|
||||
PlaintextIO() or
|
||||
PlaintextSizeIO() or
|
||||
PrimaryAlgorithmIO() or
|
||||
RandomSourceIO() or
|
||||
SaltLengthIO() or
|
||||
SeedIO() or
|
||||
SignatureIO()
|
||||
SignatureIO() or
|
||||
SignatureSizeIO()
|
||||
|
||||
private string ioTypeToString(TIOType t) {
|
||||
t = CiphertextIO() and result = "CiphertextIO"
|
||||
@@ -104,6 +110,8 @@ private string ioTypeToString(TIOType t) {
|
||||
or
|
||||
t = PlaintextIO() and result = "PlaintextIO"
|
||||
or
|
||||
t = PlaintextSizeIO() and result = "PlaintextSizeIO"
|
||||
or
|
||||
t = PrimaryAlgorithmIO() and result = "PrimaryAlgorithmIO"
|
||||
or
|
||||
t = RandomSourceIO() and result = "RandomSourceIO"
|
||||
@@ -113,6 +121,8 @@ private string ioTypeToString(TIOType t) {
|
||||
t = SeedIO() and result = "SeedIO"
|
||||
or
|
||||
t = SignatureIO() and result = "SignatureIO"
|
||||
or
|
||||
t = SignatureSizeIO() and result = "SignatureSizeIO"
|
||||
}
|
||||
|
||||
class IOType extends TIOType {
|
||||
@@ -123,13 +133,13 @@ class IOType extends TIOType {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: add more initializers as needed
|
||||
/**
|
||||
* The type of step in an `OperationStep`.
|
||||
* - `ContextCreationStep`: the creation of a context from an algorithm or key.
|
||||
* for example `EVP_MD_CTX_create(EVP_sha256())` or `EVP_PKEY_CTX_new(pkey, NULL)`
|
||||
* - `InitializerStep`: the initialization of an operation through some sort of shared/accumulated context
|
||||
* for example `EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)`
|
||||
* - `InitializerStep`: the initialization of an operation or state through some sort of shared/accumulated context
|
||||
* for example `EVP_DigestInit_ex(ctx, EVP_sha256(), NULL)`, may also be used for pass through
|
||||
* configuration, for example `EVP_PKEY_get1_RSA(key)` where a pkey is input into an RSA key return.
|
||||
* - `UpdateStep`: any operation that has and update/final paradigm, the update represents an intermediate step in an operation,
|
||||
* such as `EVP_DigestUpdate(ctx, data, len)`
|
||||
* - `FinalStep`: an ultimate operation step. This may be an explicit 'final' in an update/final paradigm, but not necessarily.
|
||||
@@ -189,7 +199,7 @@ abstract class OperationStep extends Call {
|
||||
*/
|
||||
predicate flowsToOperationStep(OperationStep sink) {
|
||||
sink = this or
|
||||
OperationStepFlow::flow(this.getAnOutput(), sink.getAnInput())
|
||||
OperationStepCtxFlow::flow(this.getAnOutput(), [sink.getAnInput(), sink.getAnOutput()])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +208,7 @@ abstract class OperationStep extends Call {
|
||||
*/
|
||||
predicate flowsFromOperationStep(OperationStep source) {
|
||||
source = this or
|
||||
OperationStepFlow::flow(source.getAnOutput(), this.getAnInput())
|
||||
OperationStepCtxFlow::flow(source.getAnOutput(), [this.getAnInput(), this.getAnOutput()])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,10 +230,13 @@ abstract class OperationStep extends Call {
|
||||
result.setsValue(type) and
|
||||
(
|
||||
// Do not consider a 'reset' to occur on updates
|
||||
// but only for resets that are part of the same update/finalize
|
||||
// progression (e.g., an update for an unrelated finalize is ignored)
|
||||
result.getStepType() = UpdateStep()
|
||||
or
|
||||
not exists(OperationStep reset |
|
||||
result != reset and
|
||||
result != this and
|
||||
reset.setsValue(type) and
|
||||
reset.flowsToOperationStep(this) and
|
||||
result.flowsToOperationStep(reset)
|
||||
@@ -245,8 +258,11 @@ abstract class OperationStep extends Call {
|
||||
|
||||
/**
|
||||
* Gets an AVC for the primary algorithm for this operation.
|
||||
* A primary algorithm is an AVC that flows to a ctx input directly or
|
||||
* an AVC that flows to a primary algorithm input directly.
|
||||
* A primary algorithm is an AVC that either:
|
||||
* 0) `this` is an AVC (consider direct algorithm consumers like RSA_sign (algorithm is implicit) or EVP_PKEY_new_mac_key (NID is first arg) )
|
||||
* 1) flows to a ctx input directly or
|
||||
* 2) flows to a primary algorithm input directly or
|
||||
* 3) flows to a key input directly (algorithm held in a key will be considered primary)
|
||||
* See `AvcContextCreationStep` for details about resetting scenarios.
|
||||
* Gets the first OperationStep an AVC flows to. If a context input,
|
||||
* the AVC is considered primary.
|
||||
@@ -254,19 +270,24 @@ abstract class OperationStep extends Call {
|
||||
* operation step (dominating operation step, see `getDominatingInitializersToStep`).
|
||||
*/
|
||||
Crypto::AlgorithmValueConsumer getPrimaryAlgorithmValueConsumer() {
|
||||
exists(DataFlow::Node src, DataFlow::Node sink, IOType t, OperationStep avcSucc |
|
||||
(t = PrimaryAlgorithmIO() or t = ContextIO()) and
|
||||
avcSucc.flowsToOperationStep(this) and
|
||||
src.asExpr() = result and
|
||||
sink = avcSucc.getInput(t) and
|
||||
this instanceof Crypto::AlgorithmValueConsumer and result = this
|
||||
or
|
||||
exists(
|
||||
DataFlow::Node src, DataFlow::Node sink, IOType srcIntype, OperationStep avcConsumingPred
|
||||
|
|
||||
(srcIntype = ContextIO() or srcIntype = PrimaryAlgorithmIO() or srcIntype = KeyIO()) and
|
||||
avcConsumingPred.flowsToOperationStep(this) and
|
||||
src.asIndirectExpr() = result and
|
||||
sink = avcConsumingPred.getInput(srcIntype) and
|
||||
AvcToOperationStepFlow::flow(src, sink) and
|
||||
(
|
||||
// Case 1: the avcSucc step is a dominating initialization step
|
||||
t = PrimaryAlgorithmIO() and
|
||||
avcSucc = this.getDominatingInitializersToStep(PrimaryAlgorithmIO())
|
||||
// Case 1: the avcConsumingPred step is a dominating primary algorithm initialization step
|
||||
// or dominating key initialization step
|
||||
(srcIntype = PrimaryAlgorithmIO() or srcIntype = KeyIO()) and
|
||||
avcConsumingPred = this.getDominatingInitializersToStep(srcIntype)
|
||||
or
|
||||
// Case 2: the succ is a context input (any avcSucc is valid)
|
||||
t = ContextIO()
|
||||
// Case 2: the pred is a context input
|
||||
srcIntype = ContextIO()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -277,9 +298,11 @@ abstract class OperationStep extends Call {
|
||||
* TODO: generalize to use this for `getPrimaryAlgorithmValueConsumer`
|
||||
*/
|
||||
Crypto::AlgorithmValueConsumer getAlgorithmValueConsumerForInput(IOType type) {
|
||||
result = this and this.setsValue(type)
|
||||
or
|
||||
exists(DataFlow::Node src, DataFlow::Node sink |
|
||||
AvcToOperationStepFlow::flow(src, sink) and
|
||||
src.asExpr() = result and
|
||||
src.asIndirectExpr() = result and
|
||||
sink = this.getInput(type)
|
||||
)
|
||||
}
|
||||
@@ -357,7 +380,7 @@ private class CtxCopyOutArgCall extends CtxPassThroughCall {
|
||||
|
||||
CtxCopyOutArgCall() {
|
||||
this.getTarget().getName().toLowerCase().matches("%copy%") and
|
||||
n1.asExpr() = this.getAnArgument() and
|
||||
n1.asIndirectExpr() = this.getAnArgument() and
|
||||
n1.getType() instanceof CtxType and
|
||||
n2.asDefiningArgument() = this.getAnArgument() and
|
||||
n2.getType() instanceof CtxType and
|
||||
@@ -378,16 +401,18 @@ private class CtxCopyReturnCall extends CtxPassThroughCall, CtxPointerExpr {
|
||||
|
||||
CtxCopyReturnCall() {
|
||||
this.getTarget().getName().toLowerCase().matches("%dup%") and
|
||||
n1.asExpr() = this.getAnArgument() and
|
||||
n1.asIndirectExpr() = this.getAnArgument() and
|
||||
n1.getType() instanceof CtxType
|
||||
}
|
||||
|
||||
override DataFlow::Node getNode1() { result = n1 }
|
||||
|
||||
override DataFlow::Node getNode2() { result.asExpr() = this }
|
||||
override DataFlow::Node getNode2() { result.asIndirectExpr() = this }
|
||||
}
|
||||
|
||||
// TODO: is this still needed?
|
||||
// TODO: is this still needed? It appears to be (tests fail without it) but
|
||||
// I don't know why as EVP_PKEY_paramgen is an operation step and we pass through
|
||||
// operation steps already.
|
||||
/**
|
||||
* A call to `EVP_PKEY_paramgen` acts as a kind of pass through.
|
||||
* It's output pkey is eventually used in a new operation generating
|
||||
@@ -401,34 +426,10 @@ private class CtxParamGenCall extends CtxPassThroughCall {
|
||||
|
||||
CtxParamGenCall() {
|
||||
this.getTarget().getName() = "EVP_PKEY_paramgen" and
|
||||
n1.asExpr() = this.getArgument(0) and
|
||||
(
|
||||
n2.asExpr() = this.getArgument(1)
|
||||
or
|
||||
n2.asDefiningArgument() = this.getArgument(1)
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getNode1() { result = n1 }
|
||||
|
||||
override DataFlow::Node getNode2() { result = n2 }
|
||||
}
|
||||
|
||||
//TODO: I am not sure CallArgToCtxRet is needed anymore
|
||||
/**
|
||||
* If the current node is an argument to a function
|
||||
* that returns a pointer type, immediately flow through.
|
||||
* NOTE: this passthrough is required if we allow
|
||||
* intermediate steps to go into variables that are not a CTX type.
|
||||
* See for example `CtxParamGenCall`.
|
||||
*/
|
||||
private class CallArgToCtxRet extends CtxPassThroughCall, CtxPointerExpr {
|
||||
DataFlow::Node n1;
|
||||
DataFlow::Node n2;
|
||||
|
||||
CallArgToCtxRet() {
|
||||
this.getAnArgument() = n1.asExpr() and
|
||||
n2.asExpr() = this
|
||||
//Arg 0 is *ctx
|
||||
n1.asIndirectExpr() = this.getArgument(0) and
|
||||
//Arg 1 is **pkey
|
||||
n2.asDefiningArgument() = this.getArgument(1)
|
||||
}
|
||||
|
||||
override DataFlow::Node getNode1() { result = n1 }
|
||||
@@ -439,7 +440,7 @@ private class CallArgToCtxRet extends CtxPassThroughCall, CtxPointerExpr {
|
||||
/**
|
||||
* A flow configuration from any non-final `OperationStep` to any other `OperationStep`.
|
||||
*/
|
||||
module OperationStepFlowConfig implements DataFlow::ConfigSig {
|
||||
module OperationStepCtxFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(OperationStep s |
|
||||
s.getAnOutput() = source or
|
||||
@@ -455,22 +456,39 @@ module OperationStepFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(CtxClearCall c | c.getAnArgument() = node.asExpr())
|
||||
exists(CtxClearCall c | c.getAnArgument() = [node.asExpr(), node.asIndirectExpr()])
|
||||
}
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node1.(AdditionalFlowInputStep).getOutput() = node2
|
||||
or
|
||||
exists(CtxPassThroughCall c | c.getNode1() = node1 and c.getNode2() = node2)
|
||||
or
|
||||
// Flow out through all outputs from an operation step if more than one output
|
||||
// is defined.
|
||||
exists(OperationStep s | s.getAnInput() = node1 and s.getAnOutput() = node2)
|
||||
// Flow only through context and key inputs and outputs
|
||||
// keys and context generally hold unifying context that link multiple steps
|
||||
// Flow only out of finalize operations through key outputs, otherwise stop at final operations
|
||||
exists(OperationStep s, IOType inType, IOType outType |
|
||||
(s.getStepType() = FinalStep() implies outType = KeyIO()) and
|
||||
(
|
||||
inType = ContextIO()
|
||||
or
|
||||
inType = KeyIO()
|
||||
) and
|
||||
(
|
||||
outType = ContextIO()
|
||||
or
|
||||
outType = KeyIO()
|
||||
) and
|
||||
s.getInput(inType) = node1 and
|
||||
s.getOutput(outType) = node2
|
||||
)
|
||||
// TODO: consideration for additional alises defined as follows:
|
||||
// if an output from an operation step itself flows from the output of another operation step
|
||||
// then the source of that flow's outputs (all of them) are potential aliases
|
||||
}
|
||||
}
|
||||
|
||||
module OperationStepFlow = DataFlow::Global<OperationStepFlowConfig>;
|
||||
module OperationStepCtxFlow = TaintTracking::Global<OperationStepCtxFlowConfig>;
|
||||
|
||||
/**
|
||||
* A flow from AVC to the first `OperationStep` the AVC reaches as an input.
|
||||
@@ -483,7 +501,7 @@ module AvcToOperationStepFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSink(DataFlow::Node sink) { exists(OperationStep s | s.getAnInput() = sink) }
|
||||
|
||||
predicate isBarrier(DataFlow::Node node) {
|
||||
exists(CtxClearCall c | c.getAnArgument() = node.asExpr())
|
||||
exists(CtxClearCall c | c.getAnArgument() = [node.asExpr(), node.asIndirectExpr()])
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,7 +514,7 @@ module AvcToOperationStepFlowConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module AvcToOperationStepFlow = DataFlow::Global<AvcToOperationStepFlowConfig>;
|
||||
module AvcToOperationStepFlow = TaintTracking::Global<AvcToOperationStepFlowConfig>;
|
||||
|
||||
module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr().getValue().toInt() in [0, 1] }
|
||||
@@ -506,7 +524,7 @@ module EncValToInitEncArgConfig implements DataFlow::ConfigSig {
|
||||
}
|
||||
}
|
||||
|
||||
module EncValToInitEncArgFlow = DataFlow::Global<EncValToInitEncArgConfig>;
|
||||
module EncValToInitEncArgFlow = TaintTracking::Global<EncValToInitEncArgConfig>;
|
||||
|
||||
private Crypto::KeyOperationSubtype intToCipherOperationSubtype(int i) {
|
||||
i = 0 and
|
||||
|
||||
@@ -6,12 +6,25 @@ private import experimental.quantum.Language
|
||||
private import experimental.quantum.OpenSSL.AvcFlow
|
||||
private import experimental.quantum.OpenSSL.AlgorithmValueConsumers.OpenSSLAlgorithmValueConsumers
|
||||
private import experimental.quantum.OpenSSL.Operations.OpenSSLOperations
|
||||
private import experimental.quantum.OpenSSL.AlgorithmInstances.OpenSSLAlgorithmInstances
|
||||
|
||||
// TODO: verification functions
|
||||
/**
|
||||
* A base class for final signature operations.
|
||||
* The operation must be known to always be a signature operation,
|
||||
* and not a MAC operation. Used for both verification and signing.
|
||||
* NOTE: even an operation that may be a mac or signature but is known to take in
|
||||
* only signature configurations should extend `SignatureOrMacFinalOperation`.
|
||||
*/
|
||||
abstract class EvpSignatureFinalOperation extends OperationStep {
|
||||
abstract class SignatureFinalOperation extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A base class for final signature or MAC operations.
|
||||
* The operation must be known to always be a signature or MAC operation.
|
||||
* Used for both verification or signing.
|
||||
*/
|
||||
abstract class SignatureOrMacFinalOperation extends OperationStep {
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
@@ -24,36 +37,32 @@ class EvpSignatureDigestInitializer extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
|
||||
result.asExpr() = this.getArgument(3) and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = OsslLibContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = HashAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = HashAlgorithmIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestSignInit" and
|
||||
result.asExpr() = this.getArgument(4) and
|
||||
result.asIndirectExpr() = this.getArgument(4) and
|
||||
type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
|
||||
result.asExpr() = this.getArgument(5) and
|
||||
result.asIndirectExpr() = this.getArgument(5) and
|
||||
type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
|
||||
result.asExpr() = this.getArgument(6) and
|
||||
result.asIndirectExpr() = this.getArgument(6) and
|
||||
type = OsslParamIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
// EVP_PKEY_CTX
|
||||
result.asExpr() = this.getArgument(1) and type = ContextIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestSignInit_ex" and
|
||||
result.asExpr() = this.getArgument(6) and
|
||||
type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -66,13 +75,13 @@ class EvpSignInit extends OperationStep {
|
||||
EvpSignInit() { this.getTarget().getName() in ["EVP_SignInit", "EVP_SignInit_ex"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = HashAlgorithmIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = HashAlgorithmIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -94,22 +103,22 @@ class EvpPkeySignInit extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
this.getTarget().getName() in ["EVP_PKEY_sign_init_ex2", "EVP_PKEY_sign_message_init"] and
|
||||
result.asExpr() = this.getArgument(1) and
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = PrimaryAlgorithmIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_PKEY_sign_init_ex" and
|
||||
result.asExpr() = this.getArgument(1) and
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = OsslParamIO()
|
||||
or
|
||||
// Argument 2 (0 based) only exists for EVP_PKEY_sign_init_ex2 and EVP_PKEY_sign_message_init
|
||||
result.asExpr() = this.getArgument(2) and type = OsslParamIO()
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = OsslParamIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
@@ -126,13 +135,13 @@ class EvpSignatureUpdateCall extends OperationStep {
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
@@ -141,73 +150,496 @@ class EvpSignatureUpdateCall extends OperationStep {
|
||||
/**
|
||||
* A call to EVP_SignFinal or EVP_SignFinal_ex.
|
||||
*/
|
||||
class EvpSignFinal extends EvpSignatureFinalOperation {
|
||||
class EvpSignFinal extends SignatureFinalOperation {
|
||||
EvpSignFinal() { this.getTarget().getName() in ["EVP_SignFinal_ex", "EVP_SignFinal"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = KeyIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = KeyIO()
|
||||
or
|
||||
// params above 3 (0-based) only exist for EVP_SignFinal_ex
|
||||
result.asExpr() = this.getArgument(4) and
|
||||
result.asIndirectExpr() = this.getArgument(4) and
|
||||
type = OsslLibContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(2) and type = SignatureSizeIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestSign or EVP_PKEY_sign.
|
||||
* A call to EVP_PKEY_sign.
|
||||
*/
|
||||
class EvpDigestSign extends EvpSignatureFinalOperation {
|
||||
EvpDigestSign() { this.getTarget().getName() in ["EVP_DigestSign", "EVP_PKEY_sign"] }
|
||||
class EvpPkeySign extends SignatureFinalOperation {
|
||||
EvpPkeySign() {
|
||||
this.getTarget().getName() = "EVP_PKEY_sign" and
|
||||
// Setting signature to NULL is not a final sign step but an
|
||||
// intermediary step used to get the required buffer size.
|
||||
// not tracking these calls.
|
||||
(
|
||||
exists(this.(Call).getArgument(1).getValue())
|
||||
implies
|
||||
this.(Call).getArgument(1).getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestSignFinal or EVP_PKEY_sign_message_final.
|
||||
* A call to EVP_DigestSign.
|
||||
* This is a mac or sign operation.
|
||||
*/
|
||||
class EvpDigestAndPkeySignFinal extends EvpSignatureFinalOperation {
|
||||
EvpDigestAndPkeySignFinal() {
|
||||
this.getTarget().getName() in [
|
||||
"EVP_DigestSignFinal",
|
||||
"EVP_PKEY_sign_message_final"
|
||||
]
|
||||
}
|
||||
class EvpDigestSign extends SignatureOrMacFinalOperation {
|
||||
EvpDigestSign() { this.getTarget().getName() = "EVP_DigestSign" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asExpr() = this.getArgument(0) and type = ContextIO()
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_PKEY_sign_message_final.
|
||||
*/
|
||||
class EvpPkeySignFinal extends SignatureFinalOperation {
|
||||
EvpPkeySignFinal() {
|
||||
this.getTarget().getName() = "EVP_PKEY_sign_message_final" and
|
||||
// Setting signature to NULL is not a final sign step but an
|
||||
// intermediary step used to get the required buffer size.
|
||||
// not tracking these calls.
|
||||
(
|
||||
exists(this.(Call).getArgument(1).getValue())
|
||||
implies
|
||||
this.(Call).getArgument(1).getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestSignFinal.
|
||||
* This is a mac or sign operation.
|
||||
*/
|
||||
class EvpDigestSignFinal extends SignatureOrMacFinalOperation {
|
||||
EvpDigestSignFinal() {
|
||||
this.getTarget().getName() = "EVP_DigestSignFinal" and
|
||||
// Setting signature to NULL is not a final sign step but an
|
||||
// intermediary step used to get the required buffer size.
|
||||
// not tracking these calls.
|
||||
(
|
||||
exists(this.(Call).getArgument(1).getValue())
|
||||
implies
|
||||
this.(Call).getArgument(1).getValue().toInt() != 0
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = SignatureIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An EVP signature operation instance.
|
||||
* A call to EVP_DigestVerifyInit or EVP_DigestVerifyInit_ex.
|
||||
*/
|
||||
class EvpSignatureOperationInstance extends Crypto::SignatureOperationInstance instanceof EvpSignatureFinalOperation
|
||||
class EvpDigestVerifyInit extends OperationStep {
|
||||
EvpDigestVerifyInit() {
|
||||
this.getTarget().getName() in ["EVP_DigestVerifyInit", "EVP_DigestVerifyInit_ex"]
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = HashAlgorithmIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = OsslLibContextIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
|
||||
result.asIndirectExpr() = this.getArgument(5) and
|
||||
type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestVerifyInit" and
|
||||
result.asIndirectExpr() = this.getArgument(4) and
|
||||
type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_DigestVerifyInit_ex" and
|
||||
result.asIndirectExpr() = this.getArgument(6) and
|
||||
type = OsslParamIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asDefiningArgument() = this.getArgument(1) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestVerifyUpdate.
|
||||
*/
|
||||
class EvpDigestVerifyUpdate extends OperationStep {
|
||||
EvpDigestVerifyUpdate() { this.getTarget().getName() = "EVP_DigestVerifyUpdate" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestVerifyFinal
|
||||
*/
|
||||
class EvpDigestVerifyFinal extends SignatureFinalOperation {
|
||||
EvpDigestVerifyFinal() { this.getTarget().getName() = "EVP_DigestVerifyFinal" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to EVP_DigestVerify
|
||||
*/
|
||||
class EvpDigestVerify extends SignatureFinalOperation {
|
||||
EvpDigestVerify() { this.getTarget().getName() = "EVP_DigestVerify" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_verify_init`, `EVP_PKEY_verify_init_ex`,
|
||||
* `EVP_PKEY_verify_init_ex2`, or `EVP_PKEY_verify_message_init`
|
||||
* https://docs.openssl.org/master/man3/EVP_PKEY_verify/#synopsis
|
||||
*/
|
||||
class EvpVerifyInit extends OperationStep {
|
||||
EvpVerifyInit() {
|
||||
this.getTarget().getName() in [
|
||||
"EVP_PKEY_verify_init", "EVP_PKEY_verify_init_ex", "EVP_PKEY_verify_init_ex2",
|
||||
"EVP_PKEY_verify_message_init"
|
||||
]
|
||||
}
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
this.getTarget().getName() = "EVP_PKEY_verify_init_ex" and
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = OsslParamIO()
|
||||
or
|
||||
this.getTarget().getName() in ["EVP_PKEY_verify_init_ex2", "EVP_PKEY_verify_message_init"] and
|
||||
result.asIndirectExpr() = this.getArgument(1) and
|
||||
type = PrimaryAlgorithmIO()
|
||||
or
|
||||
this.getTarget().getName() in ["EVP_PKEY_verify_init_ex2", "EVP_PKEY_verify_message_init"] and
|
||||
result.asIndirectExpr() = this.getArgument(2) and
|
||||
type = OsslParamIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_CTX_set_signature`
|
||||
* https://docs.openssl.org/master/man3/EVP_PKEY_verify/
|
||||
*/
|
||||
class EvpCtxSetSignatureInitializer extends OperationStep {
|
||||
EvpCtxSetSignatureInitializer() { this.getTarget().getName() = "EVP_PKEY_CTX_set_signature" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_verify_message_update`.
|
||||
*/
|
||||
class EvpVerifyMessageUpdate extends OperationStep {
|
||||
EvpVerifyMessageUpdate() { this.getTarget().getName() = "EVP_PKEY_verify_message_update" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = PlaintextSizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_verify_message_final`.
|
||||
*/
|
||||
class EvpVerifyMessageFinal extends SignatureFinalOperation {
|
||||
EvpVerifyMessageFinal() { this.getTarget().getName() = "EVP_PKEY_verify_message_final" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_PKEY_verify`
|
||||
*/
|
||||
class EvpVerify extends SignatureFinalOperation {
|
||||
EvpVerify() { this.getTarget().getName() = "EVP_PKEY_verify" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = PlaintextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(4) and type = PlaintextSizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `RSA_sign` or `RSA_verify`.
|
||||
* https://docs.openssl.org/3.0/man3/RSA_sign/
|
||||
*/
|
||||
class RsaSignorVerify extends SignatureFinalOperation {
|
||||
RsaSignorVerify() { this.getTarget().getName() in ["RSA_sign", "RSA_verify"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
// Arg 0 is an NID (so asExpr not asIndirectExpr)
|
||||
result.asExpr() = this.getArgument(0) and type = HashAlgorithmIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = PlaintextSizeIO()
|
||||
or
|
||||
this.getTarget().getName() = "RSA_verify" and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = SignatureIO()
|
||||
or
|
||||
this.getTarget().getName() = "RSA_verify" and
|
||||
result.asIndirectExpr() = this.getArgument(4) and
|
||||
type = SignatureSizeIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(5) and type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
this.getTarget().getName() = "RSA_sign" and
|
||||
result.asDefiningArgument() = this.getArgument(3) and
|
||||
type = SignatureIO()
|
||||
or
|
||||
this.getTarget().getName() = "RSA_sign" and
|
||||
type = SignatureSizeIO() and
|
||||
result.asDefiningArgument() = this.getArgument(4)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `DSA_do_sign` or `DSA_do_verify`
|
||||
*/
|
||||
class DsaDoSignOrVerify extends SignatureFinalOperation {
|
||||
DsaDoSignOrVerify() { this.getTarget().getName() in ["DSA_do_sign", "DSA_do_verify"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = PlaintextIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(1) and type = PlaintextSizeIO()
|
||||
or
|
||||
this.getTarget().getName() = "DSA_do_sign" and
|
||||
result.asIndirectExpr() = this.getArgument(2) and
|
||||
type = KeyIO()
|
||||
or
|
||||
this.getTarget().getName() = "DSA_do_verify" and
|
||||
result.asIndirectExpr() = this.getArgument(2) and
|
||||
type = SignatureIO()
|
||||
or
|
||||
this.getTarget().getName() = "DSA_do_verify" and
|
||||
result.asIndirectExpr() = this.getArgument(3) and
|
||||
type = KeyIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
this.getTarget().getName() = "DSA_do_sign" and
|
||||
result.asIndirectExpr() = this and
|
||||
type = SignatureIO()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Call to `EVP_VerifyInit` or `EVP_VerifyInit_ex`
|
||||
* - int EVP_VerifyInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl);
|
||||
* - int EVP_VerifyInit(EVP_MD_CTX *ctx, const EVP_MD *type);
|
||||
*/
|
||||
class EVP_VerifyInitCall extends OperationStep {
|
||||
EVP_VerifyInitCall() { this.getTarget().getName() in ["EVP_VerifyInit", "EVP_VerifyInit_ex"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = HashAlgorithmIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = InitializerStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_VerifyUpdate`
|
||||
* - int EVP_VerifyUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt);
|
||||
*/
|
||||
class EVP_VerifyUpdateCall extends OperationStep {
|
||||
EVP_VerifyUpdateCall() { this.getTarget().getName() = "EVP_VerifyUpdate" }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = PlaintextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(2) and type = PlaintextSizeIO()
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = UpdateStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `EVP_VerifyFinal` or `EVP_VerifyFinal_ex`
|
||||
* - int EVP_VerifyFinal_ex(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
|
||||
* unsigned int siglen, EVP_PKEY *pkey,
|
||||
* OSSL_LIB_CTX *libctx, const char *propq);
|
||||
*- int EVP_VerifyFinal(EVP_MD_CTX *ctx, unsigned char *sigbuf, unsigned int siglen,
|
||||
* EVP_PKEY *pkey); *
|
||||
*/
|
||||
class EVP_VerifyFinalCall extends SignatureFinalOperation {
|
||||
EVP_VerifyFinalCall() { this.getTarget().getName() in ["EVP_VerifyFinal", "EVP_VerifyFinal_ex"] }
|
||||
|
||||
override DataFlow::Node getInput(IOType type) {
|
||||
result.asIndirectExpr() = this.getArgument(0) and type = ContextIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(1) and type = SignatureIO()
|
||||
or
|
||||
result.asExpr() = this.getArgument(2) and type = SignatureSizeIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(3) and type = KeyIO()
|
||||
or
|
||||
result.asIndirectExpr() = this.getArgument(4) and type = OsslLibContextIO()
|
||||
// TODO: arg 5 propq?
|
||||
}
|
||||
|
||||
override DataFlow::Node getOutput(IOType type) {
|
||||
result.asDefiningArgument() = this.getArgument(0) and type = ContextIO()
|
||||
}
|
||||
|
||||
override OperationStepType getStepType() { result = FinalStep() }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instance of a signature operation.
|
||||
* This is an OpenSSL specific class that extends the base SignatureOperationInstance.
|
||||
*/
|
||||
class OpenSslSignatureOperationInstance extends Crypto::SignatureOperationInstance instanceof SignatureFinalOperation
|
||||
{
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
super.getPrimaryAlgorithmValueConsumer() = result
|
||||
@@ -217,7 +649,7 @@ class EvpSignatureOperationInstance extends Crypto::SignatureOperationInstance i
|
||||
* Signing, verification or unknown.
|
||||
*/
|
||||
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||
// TODO: if this KeyOperationSubtype does not match initialization call's KeyOperationSubtype then we found a bug
|
||||
// NOTE: if this KeyOperationSubtype does not match initialization call's KeyOperationSubtype then we found a bug
|
||||
if super.getTarget().getName().toLowerCase().matches("%sign%")
|
||||
then result instanceof Crypto::TSignMode
|
||||
else
|
||||
@@ -227,14 +659,70 @@ class EvpSignatureOperationInstance extends Crypto::SignatureOperationInstance i
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() {
|
||||
// TODO: some signing operations may have explicit nonce generators
|
||||
none()
|
||||
// some signing operations may have explicit nonce generators
|
||||
super.getDominatingInitializersToStep(IVorNonceIO()).getInput(IVorNonceIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
|
||||
super.getDominatingInitializersToStep(KeyIO()).getInput(KeyIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getSignatureConsumer() {
|
||||
super.getDominatingInitializersToStep(SignatureIO()).getInput(SignatureIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::ArtifactOutputDataFlowNode getOutputArtifact() {
|
||||
super.getOutputStepFlowingToStep(SignatureIO()).getOutput(SignatureIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getInputConsumer() {
|
||||
super.getDominatingInitializersToStep(PlaintextIO()).getInput(PlaintextIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() {
|
||||
super
|
||||
.getDominatingInitializersToStep(HashAlgorithmIO())
|
||||
.getAlgorithmValueConsumerForInput(HashAlgorithmIO()) = result
|
||||
or
|
||||
// Handle cases where the hash is set through the primary algorithm
|
||||
// RSA-SHA256 for example
|
||||
// NOTE: assuming the hash would not be overridden, or if it is it is undefined
|
||||
// i.e., if the above dominating initializer exists and the primary algorithm
|
||||
// specifies a hash, consider both valid hash AVCs.
|
||||
// TODO: can this behavior be build into the get dominating initializers?
|
||||
super.getPrimaryAlgorithmValueConsumer() = result and
|
||||
exists(OpenSslAlgorithmInstance i |
|
||||
i.getAvc() = result and i instanceof Crypto::HashAlgorithmInstance
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasHashAlgorithmConsumer() {
|
||||
exists(super.getDominatingInitializersToStep(HashAlgorithmIO()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for signature or MAC operation instances.
|
||||
* This is an OpenSSL specific class that extends the base SignatureOrMacOperationInstance.
|
||||
*/
|
||||
class OpenSslSignatureOrMacOperationInstance extends Crypto::SignatureOrMacOperationInstance instanceof SignatureOrMacFinalOperation
|
||||
{
|
||||
override Crypto::AlgorithmValueConsumer getAnAlgorithmValueConsumer() {
|
||||
super.getPrimaryAlgorithmValueConsumer() = result
|
||||
}
|
||||
|
||||
/**
|
||||
* Keys provided in the initialization call or in a context are found by this method.
|
||||
* Keys in explicit arguments are found by overridden methods in extending classes.
|
||||
* Signing, verification or unknown.
|
||||
*/
|
||||
override Crypto::KeyOperationSubtype getKeyOperationSubtype() {
|
||||
result instanceof Crypto::TSignMode or result instanceof Crypto::TMacMode
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getNonceConsumer() {
|
||||
// some signing operations may have explicit nonce generators
|
||||
super.getDominatingInitializersToStep(IVorNonceIO()).getInput(IVorNonceIO()) = result
|
||||
}
|
||||
|
||||
override Crypto::ConsumerInputDataFlowNode getKeyConsumer() {
|
||||
super.getDominatingInitializersToStep(KeyIO()).getInput(KeyIO()) = result
|
||||
}
|
||||
@@ -247,14 +735,24 @@ class EvpSignatureOperationInstance extends Crypto::SignatureOperationInstance i
|
||||
super.getDominatingInitializersToStep(PlaintextIO()).getInput(PlaintextIO()) = result
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: only signing operations for now, change when verificaiton is added
|
||||
*/
|
||||
override Crypto::ConsumerInputDataFlowNode getSignatureConsumer() { none() }
|
||||
|
||||
override Crypto::AlgorithmValueConsumer getHashAlgorithmValueConsumer() {
|
||||
super
|
||||
.getDominatingInitializersToStep(HashAlgorithmIO())
|
||||
.getAlgorithmValueConsumerForInput(HashAlgorithmIO()) = result
|
||||
or
|
||||
// Handle cases where the hash is set through the primary algorithm
|
||||
// RSA-SHA256 for example
|
||||
// NOTE: assuming the hash would not be overridden, or if it is it is undefined
|
||||
// i.e., if the above dominating initializer exists and the primary algorithm
|
||||
// specifies a hash, consider both valid hash AVCs.
|
||||
// TODO: can this behavior be build into the get dominating initializers?
|
||||
super.getPrimaryAlgorithmValueConsumer() = result and
|
||||
exists(OpenSslAlgorithmInstance i |
|
||||
i.getAvc() = result and i instanceof Crypto::HashAlgorithmInstance
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasHashAlgorithmConsumer() {
|
||||
exists(super.getDominatingInitializersToStep(HashAlgorithmIO()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,10 +298,11 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
else
|
||||
if strictlyNegative(x)
|
||||
then upper = true and delta = -1
|
||||
else
|
||||
if negative(x)
|
||||
then upper = true and delta = 0
|
||||
else none()
|
||||
else (
|
||||
negative(x) and
|
||||
upper = true and
|
||||
delta = 0
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Operand x |
|
||||
@@ -321,10 +322,11 @@ private predicate boundFlowStep(Instruction i, NonPhiOperand op, int delta, bool
|
||||
else
|
||||
if strictlyNegative(x)
|
||||
then upper = false and delta = 1
|
||||
else
|
||||
if negative(x)
|
||||
then upper = false and delta = 0
|
||||
else none()
|
||||
else (
|
||||
negative(x) and
|
||||
upper = false and
|
||||
delta = 0
|
||||
)
|
||||
)
|
||||
or
|
||||
i.(RemInstruction).getRightOperand() = op and positive(op) and delta = -1 and upper = true
|
||||
@@ -410,7 +412,7 @@ private predicate boundFlowStepPhi(
|
||||
or
|
||||
exists(IRGuardCondition guard, boolean testIsTrue |
|
||||
guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
|
||||
guard.controlsEdge(op2.getPredecessorBlock(), op2.getUse().getBlock(), testIsTrue) and
|
||||
guard.controlsBranchEdge(op2.getPredecessorBlock(), op2.getUse().getBlock(), testIsTrue) and
|
||||
reason = TCondReason(guard)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 5.5.1-dev
|
||||
version: 5.6.2-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -198,7 +198,7 @@ class ConceptIdExpr extends Expr, @concept_id {
|
||||
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument passed to the concept.
|
||||
* Gets template argument at index `index` passed to the concept, if any.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
@@ -219,7 +219,7 @@ class ConceptIdExpr extends Expr, @concept_id {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the kind of the `i`th template argument value passed to the concept.
|
||||
* Gets the kind of the template argument value at index `index` passed to the concept, if any.
|
||||
*
|
||||
* For example, if:
|
||||
* ```cpp
|
||||
|
||||
@@ -223,8 +223,8 @@ class Declaration extends Locatable, @declaration {
|
||||
final Locatable getATemplateArgumentKind() { result = this.getTemplateArgumentKind(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument used to instantiate this declaration from a
|
||||
* template.
|
||||
* Gets the template argument at index `index` used to instantiate this declaration from a
|
||||
* template, if any.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
@@ -245,9 +245,9 @@ class Declaration extends Locatable, @declaration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th template argument value used to instantiate this declaration
|
||||
* from a template. When called on a template, this will return the `i`th template
|
||||
* parameter value if it exists.
|
||||
* Gets the template argument value at index `index` used to instantiate this declaration
|
||||
* from a template. When called on a template, this will return the template
|
||||
* parameter value at index `index` if it exists.
|
||||
*
|
||||
* For example:
|
||||
*
|
||||
|
||||
@@ -87,6 +87,7 @@ class ElementBase extends @element {
|
||||
*/
|
||||
class Element extends ElementBase {
|
||||
/** Gets the primary file where this element occurs. */
|
||||
pragma[nomagic]
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/**
|
||||
|
||||
@@ -877,7 +877,7 @@ class FormatLiteral extends Literal instanceof StringLiteral {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the char type required by the nth conversion specifier.
|
||||
* Gets the char type required by the `n`th conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char` for `printf`, `char` or `wchar_t` for `wprintf`).
|
||||
* - the `%C` format character reverses wideness.
|
||||
@@ -922,7 +922,7 @@ class FormatLiteral extends Literal instanceof StringLiteral {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string type required by the nth conversion specifier.
|
||||
* Gets the string type required by the `n`th conversion specifier.
|
||||
* - in the base case this is the default for the formatting function
|
||||
* (e.g. `char *` for `printf`, `char *` or `wchar_t *` for `wprintf`).
|
||||
* - the `%S` format character reverses wideness on some platforms.
|
||||
|
||||
@@ -101,7 +101,7 @@ predicate postDominates(ControlFlowNode postDominator, ControlFlowNode node) {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is an immediate dominator of `node` in the control-flow
|
||||
* Holds if `dom` is an immediate dominator of `node` in the control-flow
|
||||
* graph of basic blocks.
|
||||
*/
|
||||
predicate bbIDominates(BasicBlock dom, BasicBlock node) =
|
||||
@@ -117,7 +117,7 @@ private predicate bb_predecessor(BasicBlock succ, BasicBlock pred) { bb_successo
|
||||
private predicate bb_exit(ExitBasicBlock exit) { any() }
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow
|
||||
* Holds if `pDom` is an immediate post-dominator of `node` in the control-flow
|
||||
* graph of basic blocks.
|
||||
*/
|
||||
predicate bbIPostDominates(BasicBlock pDom, BasicBlock node) =
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1042,8 +1042,8 @@ private predicate subEdgeIncludingDestructors(Pos p1, Node n1, Node n2, Pos p2)
|
||||
* - `MicrosoftTryFinallyStmt`: On the edge following the `__finally` block for
|
||||
* the case where an exception was thrown and needs to be propagated.
|
||||
*/
|
||||
DestructorCall getSynthesisedDestructorCallAfterNode(Node n, int i) {
|
||||
synthetic_destructor_call(n, i, result)
|
||||
DestructorCall getSynthesisedDestructorCallAfterNode(Node node, int index) {
|
||||
synthetic_destructor_call(node, index, result)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -834,8 +834,10 @@ class ContentSet instanceof Content {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,9 @@ private module StepsInput implements Impl::Private::StepsInputSig {
|
||||
result.getStaticCallTarget().getUnderlyingCallable() = sc
|
||||
}
|
||||
|
||||
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) { none() }
|
||||
DataFlowCallable getSourceNodeEnclosingCallable(Input::SourceBase source) { none() }
|
||||
|
||||
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponentStack s) { none() }
|
||||
|
||||
Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) { none() }
|
||||
}
|
||||
|
||||
@@ -2273,8 +2273,10 @@ class ContentSet instanceof Content {
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
super.hasLocationInfo(path, sl, sc, el, ec)
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -498,7 +498,9 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
|
||||
|
||||
int getArgumentIndex() { result = p.getIndex() }
|
||||
|
||||
override Node getNode() { finalParameterNodeHasParameterAndIndex(result, p, indirectionIndex) }
|
||||
override FinalParameterNode getNode() {
|
||||
finalParameterNodeHasParameterAndIndex(result, p, indirectionIndex)
|
||||
}
|
||||
|
||||
override int getIndirection() { result = indirectionIndex + 1 }
|
||||
|
||||
@@ -1000,7 +1002,7 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
|
||||
result instanceof FalseEdge
|
||||
}
|
||||
|
||||
class GuardValue = Boolean;
|
||||
class GuardValue = IRGuards::GuardValue;
|
||||
|
||||
class Guard instanceof IRGuards::IRGuardCondition {
|
||||
string toString() { result = super.toString() }
|
||||
@@ -1008,7 +1010,7 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
|
||||
predicate hasValueBranchEdge(IRCfg::BasicBlock bb1, IRCfg::BasicBlock bb2, GuardValue branch) {
|
||||
exists(EdgeKind kind |
|
||||
super.getBlock() = bb1 and
|
||||
kind = getConditionalEdge(branch) and
|
||||
kind = getConditionalEdge(branch.asBooleanValue()) and
|
||||
bb1.getSuccessor(kind) = bb2
|
||||
)
|
||||
}
|
||||
@@ -1021,7 +1023,7 @@ private module DataFlowIntegrationInput implements SsaImpl::DataFlowIntegrationI
|
||||
}
|
||||
|
||||
predicate guardDirectlyControlsBlock(Guard guard, IRCfg::BasicBlock bb, GuardValue branch) {
|
||||
guard.(IRGuards::IRGuardCondition).controls(bb, branch)
|
||||
guard.(IRGuards::IRGuardCondition).valueControls(bb, branch)
|
||||
}
|
||||
|
||||
predicate keepAllPhiInputBackEdges() { any() }
|
||||
@@ -1048,25 +1050,35 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate guardChecks(
|
||||
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def,
|
||||
DataFlowIntegrationInput::GuardValue branch, int indirectionIndex
|
||||
private predicate guardChecksInstr(
|
||||
IRGuards::Guards_v1::Guard g, IRGuards::GuardsInput::Expr instr, boolean branch,
|
||||
int indirectionIndex
|
||||
) {
|
||||
exists(UseImpl use |
|
||||
guardChecksNode(g, use.getNode(), branch, indirectionIndex) and
|
||||
ssaDefReachesCertainUse(def, use)
|
||||
exists(Node node |
|
||||
nodeHasInstruction(node, instr, indirectionIndex) and
|
||||
guardChecksNode(g, node, branch, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate guardChecksWithWrappers(
|
||||
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def, IRGuards::GuardValue val,
|
||||
int indirectionIndex
|
||||
) {
|
||||
IRGuards::Guards_v1::ValidationWrapperWithState<int, guardChecksInstr/4>::guardChecksDef(g, def,
|
||||
val, indirectionIndex)
|
||||
}
|
||||
|
||||
Node getABarrierNode(int indirectionIndex) {
|
||||
// Only get the SynthNodes from the shared implementation, as the ExprNodes cannot
|
||||
// be matched on SourceVariable.
|
||||
result.(SsaSynthNode).getSynthNode() =
|
||||
DataFlowIntegrationImpl::BarrierGuardDefWithState<int, guardChecks/4>::getABarrierNode(indirectionIndex)
|
||||
DataFlowIntegrationImpl::BarrierGuardDefWithState<int, guardChecksWithWrappers/4>::getABarrierNode(indirectionIndex)
|
||||
or
|
||||
// Calculate the guarded UseImpls corresponding to ExprNodes directly.
|
||||
exists(DataFlowIntegrationInput::Guard g, boolean branch, Definition def, IRBlock bb |
|
||||
guardChecks(g, def, branch, indirectionIndex) and
|
||||
exists(
|
||||
DataFlowIntegrationInput::Guard g, IRGuards::GuardValue branch, Definition def, IRBlock bb
|
||||
|
|
||||
guardChecksWithWrappers(g, def, branch, indirectionIndex) and
|
||||
exists(UseImpl use |
|
||||
ssaDefReachesCertainUse(def, use) and
|
||||
use.getBlock() = bb and
|
||||
@@ -1124,7 +1136,15 @@ predicate ssaFlow(Node nodeFrom, Node nodeTo) {
|
||||
*/
|
||||
class PhiNode extends Definition instanceof SsaImpl::PhiNode {
|
||||
/** Gets a definition that is an input to this phi node. */
|
||||
final Definition getAnInput() { phiHasInputFromBlock(this, result, _) }
|
||||
final Definition getAnInput() { this.hasInputFromBlock(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if `input` is an input to this phi node along the edge originating
|
||||
* in `bb`.
|
||||
*/
|
||||
final predicate hasInputFromBlock(Definition input, IRBlock bb) {
|
||||
phiHasInputFromBlock(this, input, bb)
|
||||
}
|
||||
}
|
||||
|
||||
/** An static single assignment (SSA) definition. */
|
||||
@@ -1149,10 +1169,53 @@ class Definition extends SsaImpl::Definition {
|
||||
exists(SourceVariable sv, IRBlock bb, int i, UseImpl use |
|
||||
ssaDefReachesRead(sv, this, bb, i) and
|
||||
use.hasIndexInBlock(bb, i, sv) and
|
||||
result = use.getNode().asOperand()
|
||||
use = TDirectUseImpl(result, 0)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition defines the parameter `p` upon entry into the
|
||||
* enclosing function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isParameterDefinition(Parameter p) {
|
||||
this.getIndirectionIndex() = 0 and
|
||||
getDefImpl(this).getValue().asInstruction().(InitializeParameterInstruction).getParameter() = p
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition defines the `indirectionIndex`'th indirection of
|
||||
* parameter `p` upon entry into the enclosing function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isIndirectParameterDefinition(Parameter p, int indirectionIndex) {
|
||||
this.getIndirectionIndex() = indirectionIndex and
|
||||
indirectionIndex > 0 and
|
||||
getDefImpl(this).getValue().asInstruction().(InitializeParameterInstruction).getParameter() = p
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition defines the implicit `this` parameter upon entry into
|
||||
* the enclosing member function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isThisDefinition() {
|
||||
this.getIndirectionIndex() = 0 and
|
||||
getDefImpl(this).getValue().asInstruction().(InitializeParameterInstruction).hasIndex(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this definition defines the implicit `*this` parameter (i.e., the
|
||||
* indirection of the `this` parameter) upon entry into the enclosing member
|
||||
* function.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
predicate isIndirectThisDefinition(int indirectionIndex) {
|
||||
this.getIndirectionIndex() = indirectionIndex and
|
||||
indirectionIndex > 0 and
|
||||
getDefImpl(this).getValue().asInstruction().(InitializeParameterInstruction).hasIndex(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an `Operand` that represents an indirect use of this definition.
|
||||
*
|
||||
@@ -1167,10 +1230,11 @@ class Definition extends SsaImpl::Definition {
|
||||
* value that was defined by the definition.
|
||||
*/
|
||||
Operand getAnIndirectUse(int indirectionIndex) {
|
||||
indirectionIndex > 0 and
|
||||
exists(SourceVariable sv, IRBlock bb, int i, UseImpl use |
|
||||
ssaDefReachesRead(sv, this, bb, i) and
|
||||
use.hasIndexInBlock(bb, i, sv) and
|
||||
result = use.getNode().asIndirectOperand(indirectionIndex)
|
||||
use = TDirectUseImpl(result, indirectionIndex)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,11 +52,18 @@ class GotoEdge extends EdgeKindImpl, TGotoEdge {
|
||||
final override string toString() { result = "Goto" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A "true" or "false" edge representing a successor of a conditional branch.
|
||||
*/
|
||||
abstract private class BooleanEdgeKindImpl extends EdgeKindImpl { }
|
||||
|
||||
final class BooleanEdge = BooleanEdgeKindImpl;
|
||||
|
||||
/**
|
||||
* A "true" edge, representing the successor of a conditional branch when the
|
||||
* condition is non-zero.
|
||||
*/
|
||||
class TrueEdge extends EdgeKindImpl, TTrueEdge {
|
||||
class TrueEdge extends BooleanEdgeKindImpl, TTrueEdge {
|
||||
final override string toString() { result = "True" }
|
||||
}
|
||||
|
||||
@@ -64,7 +71,7 @@ class TrueEdge extends EdgeKindImpl, TTrueEdge {
|
||||
* A "false" edge, representing the successor of a conditional branch when the
|
||||
* condition is zero.
|
||||
*/
|
||||
class FalseEdge extends EdgeKindImpl, TFalseEdge {
|
||||
class FalseEdge extends BooleanEdgeKindImpl, TFalseEdge {
|
||||
final override string toString() { result = "False" }
|
||||
}
|
||||
|
||||
@@ -95,19 +102,48 @@ class SehExceptionEdge extends ExceptionEdgeImpl, TSehExceptionEdge {
|
||||
final override string toString() { result = "SEH Exception" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An edge from a `Switch` instruction to one of the cases, or to the default
|
||||
* branch.
|
||||
*/
|
||||
abstract private class SwitchEdgeKindImpl extends EdgeKindImpl {
|
||||
/**
|
||||
* Gets the smallest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
string getMinValue() { none() }
|
||||
|
||||
/**
|
||||
* Gets the largest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
string getMaxValue() { none() }
|
||||
|
||||
/**
|
||||
* Gets the unique value of the switch expression for which control will
|
||||
* flow along this edge, if any.
|
||||
*/
|
||||
final string getValue() { result = unique( | | [this.getMinValue(), this.getMaxValue()]) }
|
||||
|
||||
/** Holds if this edge is the default edge. */
|
||||
predicate isDefault() { none() }
|
||||
}
|
||||
|
||||
final class SwitchEdge = SwitchEdgeKindImpl;
|
||||
|
||||
/**
|
||||
* A "default" edge, representing the successor of a `Switch` instruction when
|
||||
* none of the case values matches the condition value.
|
||||
*/
|
||||
class DefaultEdge extends EdgeKindImpl, TDefaultEdge {
|
||||
class DefaultEdge extends SwitchEdgeKindImpl, TDefaultEdge {
|
||||
final override string toString() { result = "Default" }
|
||||
|
||||
final override predicate isDefault() { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A "case" edge, representing the successor of a `Switch` instruction when the
|
||||
* the condition value matches a corresponding `case` label.
|
||||
*/
|
||||
class CaseEdge extends EdgeKindImpl, TCaseEdge {
|
||||
class CaseEdge extends SwitchEdgeKindImpl, TCaseEdge {
|
||||
string minValue;
|
||||
string maxValue;
|
||||
|
||||
@@ -119,24 +155,9 @@ class CaseEdge extends EdgeKindImpl, TCaseEdge {
|
||||
else result = "Case[" + minValue + ".." + maxValue + "]"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the smallest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
final string getMinValue() { result = minValue }
|
||||
final override string getMinValue() { result = minValue }
|
||||
|
||||
/**
|
||||
* Gets the largest value of the switch expression for which control will flow along this edge.
|
||||
*/
|
||||
final string getMaxValue() { result = maxValue }
|
||||
|
||||
/**
|
||||
* Gets the unique value of the switch expression for which control will
|
||||
* flow along this edge, if any.
|
||||
*/
|
||||
final string getValue() {
|
||||
minValue = maxValue and
|
||||
result = minValue
|
||||
}
|
||||
final override string getMaxValue() { result = maxValue }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1084,6 +1084,12 @@ class BinaryInstruction extends Instruction {
|
||||
or
|
||||
op1 = this.getRightOperand() and op2 = this.getLeftOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left or right
|
||||
* operand of this binary instruction.
|
||||
*/
|
||||
Instruction getAnInput() { result = this.getLeft() or result = this.getRight() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,7 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
TUniqueValueNumber(Instruction instr) { uniqueValueNumber(instr) }
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which converts data of type `T` to data of type `U`
|
||||
@@ -129,12 +129,14 @@ private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
|
||||
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
|
||||
)
|
||||
or
|
||||
count(instr.getEnclosingIRFunction()) != 1
|
||||
}
|
||||
|
||||
private predicate variableAddressValueNumber(
|
||||
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -144,7 +146,7 @@ private predicate variableAddressValueNumber(
|
||||
private predicate initializeParameterValueNumber(
|
||||
InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -154,7 +156,7 @@ private predicate initializeParameterValueNumber(
|
||||
private predicate constantValueNumber(
|
||||
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getResultIRType()) = type and
|
||||
instr.getValue() = value
|
||||
}
|
||||
@@ -162,7 +164,7 @@ private predicate constantValueNumber(
|
||||
private predicate stringConstantValueNumber(
|
||||
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
instr.getValue().getValue() = value
|
||||
}
|
||||
@@ -171,7 +173,7 @@ private predicate fieldAddressValueNumber(
|
||||
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field,
|
||||
TValueNumber objectAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getField()) = field and
|
||||
tvalueNumber(instr.getObjectAddress()) = objectAddress
|
||||
}
|
||||
@@ -182,7 +184,7 @@ private predicate binaryValueNumber0(
|
||||
TValueNumber valueNumber
|
||||
) {
|
||||
not instr instanceof PointerArithmeticInstruction and
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
(
|
||||
isLeft = true and
|
||||
@@ -206,7 +208,7 @@ private predicate pointerArithmeticValueNumber0(
|
||||
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
|
||||
boolean isLeft, TValueNumber valueNumber
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getElementSize() = elementSize and
|
||||
(
|
||||
@@ -229,7 +231,7 @@ private predicate pointerArithmeticValueNumber(
|
||||
private predicate unaryValueNumber(
|
||||
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
not instr instanceof InheritanceConversionInstruction and
|
||||
not instr instanceof CopyInstruction and
|
||||
not instr instanceof FieldAddressInstruction and
|
||||
@@ -242,7 +244,7 @@ private predicate inheritanceConversionValueNumber(
|
||||
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
|
||||
Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
tvalueNumber(instr.getUnary()) = operand and
|
||||
unique( | | instr.getBaseClass()) = baseClass and
|
||||
@@ -254,7 +256,7 @@ private predicate loadTotalOverlapValueNumber0(
|
||||
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber,
|
||||
boolean isAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
(
|
||||
isAddress = true and
|
||||
@@ -277,8 +279,7 @@ private predicate loadTotalOverlapValueNumber(
|
||||
* Holds if `instr` should be assigned a unique value number because this library does not know how
|
||||
* to determine if two instances of that instruction are equivalent.
|
||||
*/
|
||||
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
private predicate uniqueValueNumber(Instruction instr) {
|
||||
not instr.getResultIRType() instanceof IRVoidType and
|
||||
(
|
||||
not numberableInstruction(instr)
|
||||
@@ -294,10 +295,8 @@ cached
|
||||
TValueNumber tvalueNumber(Instruction instr) {
|
||||
result = nonUniqueValueNumber(instr)
|
||||
or
|
||||
exists(IRFunction irFunc |
|
||||
uniqueValueNumber(instr, irFunc) and
|
||||
result = TUniqueValueNumber(irFunc, instr)
|
||||
)
|
||||
uniqueValueNumber(instr) and
|
||||
result = TUniqueValueNumber(instr)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,68 +310,64 @@ TValueNumber tvalueNumberOfOperand(Operand op) { result = tvalueNumber(op.getDef
|
||||
* value number.
|
||||
*/
|
||||
private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
exists(IRFunction irFunc |
|
||||
irFunc = instr.getEnclosingIRFunction() and
|
||||
(
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result =
|
||||
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() |
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result = TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1084,6 +1084,12 @@ class BinaryInstruction extends Instruction {
|
||||
or
|
||||
op1 = this.getRightOperand() and op2 = this.getLeftOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left or right
|
||||
* operand of this binary instruction.
|
||||
*/
|
||||
Instruction getAnInput() { result = this.getLeft() or result = this.getRight() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,7 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
TUniqueValueNumber(Instruction instr) { uniqueValueNumber(instr) }
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which converts data of type `T` to data of type `U`
|
||||
@@ -129,12 +129,14 @@ private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
|
||||
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
|
||||
)
|
||||
or
|
||||
count(instr.getEnclosingIRFunction()) != 1
|
||||
}
|
||||
|
||||
private predicate variableAddressValueNumber(
|
||||
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -144,7 +146,7 @@ private predicate variableAddressValueNumber(
|
||||
private predicate initializeParameterValueNumber(
|
||||
InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -154,7 +156,7 @@ private predicate initializeParameterValueNumber(
|
||||
private predicate constantValueNumber(
|
||||
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getResultIRType()) = type and
|
||||
instr.getValue() = value
|
||||
}
|
||||
@@ -162,7 +164,7 @@ private predicate constantValueNumber(
|
||||
private predicate stringConstantValueNumber(
|
||||
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
instr.getValue().getValue() = value
|
||||
}
|
||||
@@ -171,7 +173,7 @@ private predicate fieldAddressValueNumber(
|
||||
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field,
|
||||
TValueNumber objectAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getField()) = field and
|
||||
tvalueNumber(instr.getObjectAddress()) = objectAddress
|
||||
}
|
||||
@@ -182,7 +184,7 @@ private predicate binaryValueNumber0(
|
||||
TValueNumber valueNumber
|
||||
) {
|
||||
not instr instanceof PointerArithmeticInstruction and
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
(
|
||||
isLeft = true and
|
||||
@@ -206,7 +208,7 @@ private predicate pointerArithmeticValueNumber0(
|
||||
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
|
||||
boolean isLeft, TValueNumber valueNumber
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getElementSize() = elementSize and
|
||||
(
|
||||
@@ -229,7 +231,7 @@ private predicate pointerArithmeticValueNumber(
|
||||
private predicate unaryValueNumber(
|
||||
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
not instr instanceof InheritanceConversionInstruction and
|
||||
not instr instanceof CopyInstruction and
|
||||
not instr instanceof FieldAddressInstruction and
|
||||
@@ -242,7 +244,7 @@ private predicate inheritanceConversionValueNumber(
|
||||
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
|
||||
Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
tvalueNumber(instr.getUnary()) = operand and
|
||||
unique( | | instr.getBaseClass()) = baseClass and
|
||||
@@ -254,7 +256,7 @@ private predicate loadTotalOverlapValueNumber0(
|
||||
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber,
|
||||
boolean isAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
(
|
||||
isAddress = true and
|
||||
@@ -277,8 +279,7 @@ private predicate loadTotalOverlapValueNumber(
|
||||
* Holds if `instr` should be assigned a unique value number because this library does not know how
|
||||
* to determine if two instances of that instruction are equivalent.
|
||||
*/
|
||||
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
private predicate uniqueValueNumber(Instruction instr) {
|
||||
not instr.getResultIRType() instanceof IRVoidType and
|
||||
(
|
||||
not numberableInstruction(instr)
|
||||
@@ -294,10 +295,8 @@ cached
|
||||
TValueNumber tvalueNumber(Instruction instr) {
|
||||
result = nonUniqueValueNumber(instr)
|
||||
or
|
||||
exists(IRFunction irFunc |
|
||||
uniqueValueNumber(instr, irFunc) and
|
||||
result = TUniqueValueNumber(irFunc, instr)
|
||||
)
|
||||
uniqueValueNumber(instr) and
|
||||
result = TUniqueValueNumber(instr)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,68 +310,64 @@ TValueNumber tvalueNumberOfOperand(Operand op) { result = tvalueNumber(op.getDef
|
||||
* value number.
|
||||
*/
|
||||
private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
exists(IRFunction irFunc |
|
||||
irFunc = instr.getEnclosingIRFunction() and
|
||||
(
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result =
|
||||
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() |
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result = TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ CppType getEllipsisVariablePRValueType() {
|
||||
CppType getEllipsisVariableGLValueType() { result = getTypeForGLValue(any(UnknownType t)) }
|
||||
|
||||
/**
|
||||
* Holds if the function returns a value, as opposed to returning `void`.
|
||||
* Holds if the function `func` returns a value, as opposed to returning `void`.
|
||||
*/
|
||||
predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instanceof VoidType }
|
||||
|
||||
|
||||
@@ -601,7 +601,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
* The IR translation of an implicit `return` statement generated by the extractor to handle control
|
||||
* flow that reaches the end of a non-`void`-returning function body. Such control flow
|
||||
* produces undefined behavior in C++ but not in C. However even in C using the return value is
|
||||
* undefined behaviour. We make it return uninitialized memory to get as much flow as possible.
|
||||
* undefined behavior. We make it return uninitialized memory to get as much flow as possible.
|
||||
*/
|
||||
class TranslatedNoValueReturnStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
|
||||
TranslatedNoValueReturnStmt() {
|
||||
|
||||
@@ -1084,6 +1084,12 @@ class BinaryInstruction extends Instruction {
|
||||
or
|
||||
op1 = this.getRightOperand() and op2 = this.getLeftOperand()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result provides the value of the left or right
|
||||
* operand of this binary instruction.
|
||||
*/
|
||||
Instruction getAnInput() { result = this.getLeft() or result = this.getRight() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,7 +41,7 @@ newtype TValueNumber =
|
||||
) {
|
||||
loadTotalOverlapValueNumber(_, irFunc, type, memOperand, operand)
|
||||
} or
|
||||
TUniqueValueNumber(IRFunction irFunc, Instruction instr) { uniqueValueNumber(instr, irFunc) }
|
||||
TUniqueValueNumber(Instruction instr) { uniqueValueNumber(instr) }
|
||||
|
||||
/**
|
||||
* A `ConvertInstruction` which converts data of type `T` to data of type `U`
|
||||
@@ -129,12 +129,14 @@ private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
|
||||
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
|
||||
)
|
||||
or
|
||||
count(instr.getEnclosingIRFunction()) != 1
|
||||
}
|
||||
|
||||
private predicate variableAddressValueNumber(
|
||||
VariableAddressInstruction instr, IRFunction irFunc, Language::AST ast
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -144,7 +146,7 @@ private predicate variableAddressValueNumber(
|
||||
private predicate initializeParameterValueNumber(
|
||||
InitializeParameterInstruction instr, IRFunction irFunc, Language::AST var
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
@@ -154,7 +156,7 @@ private predicate initializeParameterValueNumber(
|
||||
private predicate constantValueNumber(
|
||||
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getResultIRType()) = type and
|
||||
instr.getValue() = value
|
||||
}
|
||||
@@ -162,7 +164,7 @@ private predicate constantValueNumber(
|
||||
private predicate stringConstantValueNumber(
|
||||
StringConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
instr.getValue().getValue() = value
|
||||
}
|
||||
@@ -171,7 +173,7 @@ private predicate fieldAddressValueNumber(
|
||||
FieldAddressInstruction instr, IRFunction irFunc, Language::Field field,
|
||||
TValueNumber objectAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
unique( | | instr.getField()) = field and
|
||||
tvalueNumber(instr.getObjectAddress()) = objectAddress
|
||||
}
|
||||
@@ -182,7 +184,7 @@ private predicate binaryValueNumber0(
|
||||
TValueNumber valueNumber
|
||||
) {
|
||||
not instr instanceof PointerArithmeticInstruction and
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
(
|
||||
isLeft = true and
|
||||
@@ -206,7 +208,7 @@ private predicate pointerArithmeticValueNumber0(
|
||||
PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize,
|
||||
boolean isLeft, TValueNumber valueNumber
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getElementSize() = elementSize and
|
||||
(
|
||||
@@ -229,7 +231,7 @@ private predicate pointerArithmeticValueNumber(
|
||||
private predicate unaryValueNumber(
|
||||
UnaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
not instr instanceof InheritanceConversionInstruction and
|
||||
not instr instanceof CopyInstruction and
|
||||
not instr instanceof FieldAddressInstruction and
|
||||
@@ -242,7 +244,7 @@ private predicate inheritanceConversionValueNumber(
|
||||
InheritanceConversionInstruction instr, IRFunction irFunc, Opcode opcode,
|
||||
Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
tvalueNumber(instr.getUnary()) = operand and
|
||||
unique( | | instr.getBaseClass()) = baseClass and
|
||||
@@ -254,7 +256,7 @@ private predicate loadTotalOverlapValueNumber0(
|
||||
LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber,
|
||||
boolean isAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
unique( | | instr.getEnclosingIRFunction()) = irFunc and
|
||||
instr.getResultIRType() = type and
|
||||
(
|
||||
isAddress = true and
|
||||
@@ -277,8 +279,7 @@ private predicate loadTotalOverlapValueNumber(
|
||||
* Holds if `instr` should be assigned a unique value number because this library does not know how
|
||||
* to determine if two instances of that instruction are equivalent.
|
||||
*/
|
||||
private predicate uniqueValueNumber(Instruction instr, IRFunction irFunc) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
private predicate uniqueValueNumber(Instruction instr) {
|
||||
not instr.getResultIRType() instanceof IRVoidType and
|
||||
(
|
||||
not numberableInstruction(instr)
|
||||
@@ -294,10 +295,8 @@ cached
|
||||
TValueNumber tvalueNumber(Instruction instr) {
|
||||
result = nonUniqueValueNumber(instr)
|
||||
or
|
||||
exists(IRFunction irFunc |
|
||||
uniqueValueNumber(instr, irFunc) and
|
||||
result = TUniqueValueNumber(irFunc, instr)
|
||||
)
|
||||
uniqueValueNumber(instr) and
|
||||
result = TUniqueValueNumber(instr)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,68 +310,64 @@ TValueNumber tvalueNumberOfOperand(Operand op) { result = tvalueNumber(op.getDef
|
||||
* value number.
|
||||
*/
|
||||
private TValueNumber nonUniqueValueNumber(Instruction instr) {
|
||||
exists(IRFunction irFunc |
|
||||
irFunc = instr.getEnclosingIRFunction() and
|
||||
(
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result =
|
||||
TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
exists(IRFunction irFunc | irFunc = instr.getEnclosingIRFunction() |
|
||||
exists(Language::AST ast |
|
||||
variableAddressValueNumber(instr, irFunc, ast) and
|
||||
result = TVariableAddressValueNumber(irFunc, ast)
|
||||
)
|
||||
or
|
||||
exists(Language::AST var |
|
||||
initializeParameterValueNumber(instr, irFunc, var) and
|
||||
result = TInitializeParameterValueNumber(irFunc, var)
|
||||
)
|
||||
or
|
||||
exists(string value, IRType type |
|
||||
constantValueNumber(instr, irFunc, type, value) and
|
||||
result = TConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(IRType type, string value |
|
||||
stringConstantValueNumber(instr, irFunc, type, value) and
|
||||
result = TStringConstantValueNumber(irFunc, type, value)
|
||||
)
|
||||
or
|
||||
exists(Language::Field field, TValueNumber objectAddress |
|
||||
fieldAddressValueNumber(instr, irFunc, field, objectAddress) and
|
||||
result = TFieldAddressValueNumber(irFunc, field, objectAddress)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
binaryValueNumber(instr, irFunc, opcode, leftOperand, rightOperand) and
|
||||
result = TBinaryValueNumber(irFunc, opcode, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, TValueNumber operand |
|
||||
unaryValueNumber(instr, irFunc, opcode, operand) and
|
||||
result = TUnaryValueNumber(irFunc, opcode, operand)
|
||||
)
|
||||
or
|
||||
exists(
|
||||
Opcode opcode, Language::Class baseClass, Language::Class derivedClass, TValueNumber operand
|
||||
|
|
||||
inheritanceConversionValueNumber(instr, irFunc, opcode, baseClass, derivedClass, operand) and
|
||||
result = TInheritanceConversionValueNumber(irFunc, opcode, baseClass, derivedClass, operand)
|
||||
)
|
||||
or
|
||||
exists(Opcode opcode, int elementSize, TValueNumber leftOperand, TValueNumber rightOperand |
|
||||
pointerArithmeticValueNumber(instr, irFunc, opcode, elementSize, leftOperand, rightOperand) and
|
||||
result = TPointerArithmeticValueNumber(irFunc, opcode, elementSize, leftOperand, rightOperand)
|
||||
)
|
||||
or
|
||||
exists(IRType type, TValueNumber memOperand, TValueNumber operand |
|
||||
loadTotalOverlapValueNumber(instr, irFunc, type, memOperand, operand) and
|
||||
result = TLoadTotalOverlapValueNumber(irFunc, type, memOperand, operand)
|
||||
)
|
||||
or
|
||||
// The value number of a copy is just the value number of its source value.
|
||||
result = tvalueNumber(instr.(CongruentCopyInstruction).getSourceValue())
|
||||
or
|
||||
// The value number of a type-preserving conversion is just the value
|
||||
// number of the unconverted value.
|
||||
result = tvalueNumber(instr.(TypePreservingConvertInstruction).getUnary())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ Type getVariableType(Variable v) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the database contains a `case` label with the specified minimum and maximum value.
|
||||
* Holds if the database contains a `switchCase` label with the specified minimum `minValue`
|
||||
* and maximum `maxValue` value.
|
||||
*/
|
||||
predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) {
|
||||
minValue = switchCase.getExpr().getFullyConverted().getValue() and
|
||||
|
||||
@@ -371,7 +371,7 @@ class FunctionOutput extends TFunctionOutput {
|
||||
/**
|
||||
* Holds if this is the output value pointed to by a pointer parameter to a function, or the
|
||||
* output value referred to by a reference parameter to a function, where the parameter has
|
||||
* index `index`.
|
||||
* index `i`.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
@@ -389,7 +389,7 @@ class FunctionOutput extends TFunctionOutput {
|
||||
/**
|
||||
* Holds if this is the output value pointed to by a pointer parameter (through `ind` number
|
||||
* of indirections) to a function, or the output value referred to by a reference parameter to
|
||||
* a function, where the parameter has index `index`.
|
||||
* a function, where the parameter has index `i`.
|
||||
*
|
||||
* Example:
|
||||
* ```
|
||||
|
||||
@@ -307,13 +307,12 @@ class SemStoreExpr extends SemUnaryExpr {
|
||||
}
|
||||
|
||||
class SemConditionalExpr extends SemKnownExpr {
|
||||
SemExpr condition;
|
||||
SemExpr trueResult;
|
||||
SemExpr falseResult;
|
||||
|
||||
SemConditionalExpr() {
|
||||
opcode instanceof Opcode::Conditional and
|
||||
Specific::conditionalExpr(this, type, condition, trueResult, falseResult)
|
||||
Specific::conditionalExpr(this, type, any(SemExpr condition), trueResult, falseResult)
|
||||
}
|
||||
|
||||
final SemExpr getBranchExpr(boolean branch) {
|
||||
|
||||
@@ -259,7 +259,7 @@ module SemanticExprConfig {
|
||||
}
|
||||
|
||||
predicate guardHasBranchEdge(Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch) {
|
||||
guard.controlsEdge(bb1, bb2, branch)
|
||||
guard.controlsBranchEdge(bb1, bb2, branch)
|
||||
}
|
||||
|
||||
Guard comparisonGuard(Expr e) { getSemanticExpr(result) = e }
|
||||
|
||||
@@ -21,7 +21,9 @@ class FileWrite extends Expr {
|
||||
Expr getDest() { fileWrite(this, _, result) }
|
||||
|
||||
/**
|
||||
* Gets the conversion character for this write, if it exists and is known. For example in the following code the write of `value1` has conversion character `"s"`, whereas the write of `value2` has no conversion specifier.
|
||||
* Gets the conversion character from `source` for this write, if it exists and is known.
|
||||
* For example in the following code the write of `value1` has conversion character `"s"`, whereas
|
||||
* the write of `value2` has no conversion specifier.
|
||||
* ```
|
||||
* fprintf(file, "%s", value1);
|
||||
* stream << value2;
|
||||
|
||||
@@ -191,11 +191,19 @@ module BoostorgAsio {
|
||||
class SslContextClass extends Class {
|
||||
SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" }
|
||||
|
||||
ConstructorCall getAContructorCall() {
|
||||
/**
|
||||
* Gets a constructor call, if any.
|
||||
*/
|
||||
ConstructorCall getAConstructorCall() {
|
||||
this.getAConstructor().getACallToThisFunction() = result and
|
||||
not result.getLocation().getFile().toString().matches("%/boost/asio/%") and
|
||||
result.fromSource()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getAConstructorCall` instead.
|
||||
*/
|
||||
deprecated ConstructorCall getAContructorCall() { result = this.getAConstructorCall() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +376,7 @@ module BoostorgAsio {
|
||||
*/
|
||||
default predicate isSink(DataFlow::Node sink) {
|
||||
exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() |
|
||||
c.getAContructorCall() = cc and
|
||||
c.getAConstructorCall() = cc and
|
||||
cc.getArgument(0) = e
|
||||
)
|
||||
}
|
||||
@@ -468,7 +476,7 @@ module BoostorgAsio {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
exists(SslContextClass c, ConstructorCall cc |
|
||||
cc = source.asExpr() and
|
||||
c.getAContructorCall() = cc
|
||||
c.getAConstructorCall() = cc
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -164,12 +164,17 @@ predicate valueOccurrenceCount(string value, int n) {
|
||||
n > 20
|
||||
}
|
||||
|
||||
predicate occurenceCount(Literal lit, string value, int n) {
|
||||
predicate occurrenceCount(Literal lit, string value, int n) {
|
||||
valueOccurrenceCount(value, n) and
|
||||
value = lit.getValue() and
|
||||
nonTrivialValue(_, lit)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `occurrenceCount` instead.
|
||||
*/
|
||||
deprecated predicate occurenceCount = occurrenceCount/3;
|
||||
|
||||
/*
|
||||
* Literals repeated frequently
|
||||
*/
|
||||
@@ -178,7 +183,7 @@ predicate check(Literal lit, string value, int n, File f) {
|
||||
// Check that the literal is nontrivial
|
||||
not trivial(lit) and
|
||||
// Check that it is repeated a number of times
|
||||
occurenceCount(lit, value, n) and
|
||||
occurrenceCount(lit, value, n) and
|
||||
n > 20 and
|
||||
f = lit.getFile() and
|
||||
// Exclude generated files
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user