mirror of
https://github.com/github/codeql.git
synced 2026-05-17 20:57:07 +02:00
Compare commits
415 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa6b89dc34 | ||
|
|
42cf76027a | ||
|
|
651d207d0d | ||
|
|
b4f400fb23 | ||
|
|
6b27dcabc5 | ||
|
|
79e246f961 | ||
|
|
8b06b311a0 | ||
|
|
187fdf67b0 | ||
|
|
98e8858dc6 | ||
|
|
283eb51db8 | ||
|
|
dc3d87f2fc | ||
|
|
0e0ff565d5 | ||
|
|
2d151f71cf | ||
|
|
c0868bcb9e | ||
|
|
54520003f8 | ||
|
|
8174fb51ae | ||
|
|
6b459de95f | ||
|
|
6c768263d2 | ||
|
|
9b8bf96a6f | ||
|
|
114740c148 | ||
|
|
787febae6e | ||
|
|
f24313a215 | ||
|
|
b17fb86961 | ||
|
|
0a2df6c00d | ||
|
|
bc59e65222 | ||
|
|
9f22da4557 | ||
|
|
8c3b44a525 | ||
|
|
a9844b2eda | ||
|
|
4348de3120 | ||
|
|
2427f0ada9 | ||
|
|
5879e58741 | ||
|
|
f06a20f666 | ||
|
|
0fe0544769 | ||
|
|
6267946768 | ||
|
|
1b11abfec7 | ||
|
|
5478155155 | ||
|
|
d566141273 | ||
|
|
d73b28efe4 | ||
|
|
af38a2b9c5 | ||
|
|
a7cb2d6d7c | ||
|
|
a6003533a4 | ||
|
|
7dd263b413 | ||
|
|
f5cfd93d8d | ||
|
|
33fcbc958d | ||
|
|
ccda1c8d3d | ||
|
|
c66f67dfac | ||
|
|
d687dd9deb | ||
|
|
1710f8db7c | ||
|
|
231465143d | ||
|
|
546d750045 | ||
|
|
b2500a0c26 | ||
|
|
83ccddff7a | ||
|
|
efe2fb502e | ||
|
|
2acde22f43 | ||
|
|
0ee209e6a4 | ||
|
|
fb8895bdc7 | ||
|
|
c57f8a6d6e | ||
|
|
495a1fcf3b | ||
|
|
b11b714152 | ||
|
|
10627738d0 | ||
|
|
e15481a622 | ||
|
|
ce18aca62b | ||
|
|
60ae3e58b8 | ||
|
|
78334af354 | ||
|
|
6a54a6d3e5 | ||
|
|
9440aab3d0 | ||
|
|
93ce34ad58 | ||
|
|
88734f1f8a | ||
|
|
a7cdf528dd | ||
|
|
a91599e7fd | ||
|
|
e5cbac5c13 | ||
|
|
f9da1dc03e | ||
|
|
0e40717358 | ||
|
|
f84301e476 | ||
|
|
f9d7f8ba11 | ||
|
|
595634126f | ||
|
|
f57454951b | ||
|
|
1246de466a | ||
|
|
7f538e82c0 | ||
|
|
02978c97f1 | ||
|
|
c17eca90a1 | ||
|
|
b051b7546d | ||
|
|
d2d119eb75 | ||
|
|
edf1df1577 | ||
|
|
c37d655fe8 | ||
|
|
7fd1d64d97 | ||
|
|
63a2670fcd | ||
|
|
fda8605aae | ||
|
|
e1c25c81f6 | ||
|
|
2044f5fe89 | ||
|
|
cc0961a988 | ||
|
|
d595f20cb1 | ||
|
|
d9ae5933d4 | ||
|
|
280382e91e | ||
|
|
e14259126e | ||
|
|
d3f6362ba2 | ||
|
|
e822510d6b | ||
|
|
6648c8414f | ||
|
|
dbd0c7e80a | ||
|
|
f50d0e373a | ||
|
|
5040d3e26c | ||
|
|
5ac5aa0c2a | ||
|
|
4a631b42d4 | ||
|
|
7adf1d9958 | ||
|
|
5f269b2d87 | ||
|
|
50cba92f5f | ||
|
|
ada0115d6a | ||
|
|
3cd62234d4 | ||
|
|
c6b4e29b93 | ||
|
|
60fe0176ed | ||
|
|
3a5962aa34 | ||
|
|
01f58758f1 | ||
|
|
56bb9dcde0 | ||
|
|
c35fc82218 | ||
|
|
b8877f1d5f | ||
|
|
91e4f7ad83 | ||
|
|
487b8c52c6 | ||
|
|
e2f271bddb | ||
|
|
078dc7b6c0 | ||
|
|
287ce4e683 | ||
|
|
5ccad6ffc2 | ||
|
|
3e04f53ed2 | ||
|
|
23a2bf1756 | ||
|
|
654f2ae290 | ||
|
|
7bc729a7dc | ||
|
|
56b80ae13a | ||
|
|
bb3e3a541d | ||
|
|
936094d0b6 | ||
|
|
f9106b3bfe | ||
|
|
7f21f145e2 | ||
|
|
b11d5c5075 | ||
|
|
18eb60b98e | ||
|
|
f71e5ac338 | ||
|
|
7656936cad | ||
|
|
f737830f18 | ||
|
|
ae4b55de9a | ||
|
|
b21e832ee2 | ||
|
|
9fba643fb0 | ||
|
|
1158708ea4 | ||
|
|
ce8ca5979b | ||
|
|
16c065274d | ||
|
|
bee2ddaf26 | ||
|
|
cb349348e7 | ||
|
|
e194021c3b | ||
|
|
969fe6e4f1 | ||
|
|
e8c8360ad1 | ||
|
|
f1dcec8369 | ||
|
|
54bb9d185f | ||
|
|
df42707050 | ||
|
|
3f185364f9 | ||
|
|
b155a0f5fb | ||
|
|
344466a8c1 | ||
|
|
f92456fcad | ||
|
|
41a48078f7 | ||
|
|
8e546a30b0 | ||
|
|
2bbd55519b | ||
|
|
635a3cb1ec | ||
|
|
5596bc8827 | ||
|
|
12bc1fc656 | ||
|
|
a96c53f9b8 | ||
|
|
14621760bb | ||
|
|
74167e478a | ||
|
|
6918dad1db | ||
|
|
1366638f06 | ||
|
|
3037b2b197 | ||
|
|
1df1b0c28e | ||
|
|
aa04e9c77f | ||
|
|
faaca21996 | ||
|
|
4fc27aaa51 | ||
|
|
06dd5f3616 | ||
|
|
9df5d4b0c2 | ||
|
|
14488cb62e | ||
|
|
fac638ffab | ||
|
|
b5bbf990b0 | ||
|
|
5acd1ca26d | ||
|
|
98005edd9d | ||
|
|
7422947e78 | ||
|
|
a01a9dc5cc | ||
|
|
9707b34124 | ||
|
|
e80837681f | ||
|
|
dde42a5723 | ||
|
|
376ed7a4d2 | ||
|
|
a1d92bfa50 | ||
|
|
1bc73ab592 | ||
|
|
f0fb47cde0 | ||
|
|
8d072863df | ||
|
|
7cc6f2f4d8 | ||
|
|
36e36a414e | ||
|
|
73aa223b08 | ||
|
|
4d186e0edc | ||
|
|
edbef289a7 | ||
|
|
e016098f86 | ||
|
|
3879e57f18 | ||
|
|
a295dfd2c5 | ||
|
|
09e7124bb1 | ||
|
|
ab519d4abf | ||
|
|
7c6e28d917 | ||
|
|
994fe1bea5 | ||
|
|
d4e4bc6a0b | ||
|
|
c65c7e700e | ||
|
|
52ca696ff4 | ||
|
|
6d6379fc09 | ||
|
|
a4b3b1e8c8 | ||
|
|
709fd6382a | ||
|
|
6b7337d766 | ||
|
|
1f7383498a | ||
|
|
bfc7fb7c8a | ||
|
|
6ef16bb728 | ||
|
|
02b58a8319 | ||
|
|
a0d5049132 | ||
|
|
4bd922e442 | ||
|
|
36fe86f730 | ||
|
|
59542fc367 | ||
|
|
934fd9f3d6 | ||
|
|
2ed648d798 | ||
|
|
09d08a7547 | ||
|
|
9560165921 | ||
|
|
41f5d65e0c | ||
|
|
976aa22fac | ||
|
|
ba4fa0a246 | ||
|
|
9857a85817 | ||
|
|
d3c6d83786 | ||
|
|
0f268cac40 | ||
|
|
02a060fbfa | ||
|
|
4f51257e56 | ||
|
|
67d4099e3f | ||
|
|
91578258f7 | ||
|
|
f09eb67af0 | ||
|
|
6411d1c7dd | ||
|
|
e05bbb0f10 | ||
|
|
e7390f3ea5 | ||
|
|
fcfab26267 | ||
|
|
664453707a | ||
|
|
6beb396d93 | ||
|
|
2a30dee8df | ||
|
|
c887dc89dc | ||
|
|
b1e7649d02 | ||
|
|
243af36167 | ||
|
|
fce805834e | ||
|
|
bc78219653 | ||
|
|
a709783fe5 | ||
|
|
9e73ed71b9 | ||
|
|
c2116f0d91 | ||
|
|
4f53411397 | ||
|
|
56fb63adbc | ||
|
|
229eea00dc | ||
|
|
3397533045 | ||
|
|
bf048e7e49 | ||
|
|
45b207c21b | ||
|
|
28b4a78430 | ||
|
|
0a496c1d3d | ||
|
|
8d655c74ae | ||
|
|
7fb752784a | ||
|
|
ef347b3870 | ||
|
|
75842fec1c | ||
|
|
2ea148016c | ||
|
|
d577ee8849 | ||
|
|
7d8a8de53d | ||
|
|
919d7cbf01 | ||
|
|
f6a87574f0 | ||
|
|
7d3e637eb0 | ||
|
|
7ee0ba36af | ||
|
|
d0a0d2300e | ||
|
|
d85f4b540c | ||
|
|
e7f19e97cb | ||
|
|
3c00d4be6d | ||
|
|
00779c518c | ||
|
|
d63d838534 | ||
|
|
d1cc53cd36 | ||
|
|
d3fcfb0957 | ||
|
|
d05b11f00d | ||
|
|
0ba7633e4d | ||
|
|
3bb3de23ce | ||
|
|
bdda3ae477 | ||
|
|
3caf4e52a7 | ||
|
|
26f030045a | ||
|
|
7121a18eba | ||
|
|
b418968efb | ||
|
|
679db191f5 | ||
|
|
a342fa36c6 | ||
|
|
67b1487384 | ||
|
|
417dac7ad6 | ||
|
|
9ff3d2ef1f | ||
|
|
0d62191d84 | ||
|
|
e836fa7512 | ||
|
|
47e15a6f75 | ||
|
|
a637eb651f | ||
|
|
a43125c3e0 | ||
|
|
b80cf30cee | ||
|
|
4739a6334e | ||
|
|
b58c263fd0 | ||
|
|
d8c7537557 | ||
|
|
dfbccc4bcf | ||
|
|
43d14ce011 | ||
|
|
fc91ff1a69 | ||
|
|
1130d0c6f9 | ||
|
|
374f7ab65d | ||
|
|
c4d7672ea7 | ||
|
|
0462eb4b50 | ||
|
|
2cc235d61b | ||
|
|
104eafec2f | ||
|
|
88c69e2c9c | ||
|
|
a3bd072590 | ||
|
|
fd489271b7 | ||
|
|
b638961a4f | ||
|
|
b173752de9 | ||
|
|
52b8a6bb56 | ||
|
|
d25bd598db | ||
|
|
3b0d1599ad | ||
|
|
ab9aa7d338 | ||
|
|
80144a00c8 | ||
|
|
bebac21e19 | ||
|
|
ec0663e587 | ||
|
|
d2a431e6f3 | ||
|
|
939db5a7cd | ||
|
|
1c2dd3e7b9 | ||
|
|
dfcf767090 | ||
|
|
dbeb2dfa0e | ||
|
|
08f5c2b6a6 | ||
|
|
60076cb734 | ||
|
|
4712a8f913 | ||
|
|
ace8fa88f2 | ||
|
|
ca72c8ebfe | ||
|
|
05b9519e9a | ||
|
|
10166be535 | ||
|
|
3ed40d5da1 | ||
|
|
1c5322274a | ||
|
|
dcad2a3431 | ||
|
|
610be85c8c | ||
|
|
9babb4366b | ||
|
|
adc15cad07 | ||
|
|
8bd8975795 | ||
|
|
a12a72e90f | ||
|
|
11ca7b74a3 | ||
|
|
90ad5cfac5 | ||
|
|
6a1ab51d66 | ||
|
|
d4023fe95a | ||
|
|
b2a82ae598 | ||
|
|
959776b775 | ||
|
|
d69e584cc2 | ||
|
|
8fd3a417c2 | ||
|
|
2c51f86f1b | ||
|
|
6d7ac885ec | ||
|
|
477be260f3 | ||
|
|
2e65f6b660 | ||
|
|
2870209299 | ||
|
|
76a69f4ff2 | ||
|
|
f3020f776e | ||
|
|
4a367d3fdb | ||
|
|
5283c6cd48 | ||
|
|
2d6bf0aff3 | ||
|
|
84ea4cf1d1 | ||
|
|
344bec3865 | ||
|
|
d813635f3e | ||
|
|
43df9538bf | ||
|
|
feb8a8c4fd | ||
|
|
20aa4e1f6d | ||
|
|
9d8d953292 | ||
|
|
6c53ad80c7 | ||
|
|
064b1099eb | ||
|
|
09ca6652fb | ||
|
|
73cbdee691 | ||
|
|
a374540c55 | ||
|
|
d991fa84b1 | ||
|
|
9d95291124 | ||
|
|
909ff428ac | ||
|
|
ab7a094439 | ||
|
|
d64067aaae | ||
|
|
d31c9950f9 | ||
|
|
d261f1b6d2 | ||
|
|
f2d7b6ebe9 | ||
|
|
3eb163f656 | ||
|
|
1a25f0a068 | ||
|
|
1232694340 | ||
|
|
6c6d7e4fff | ||
|
|
6cb6b1c07d | ||
|
|
0eb0bf988e | ||
|
|
f3889e715e | ||
|
|
ae44b90456 | ||
|
|
e2dd0ea083 | ||
|
|
fb78e14db1 | ||
|
|
72092529d1 | ||
|
|
f3c90114df | ||
|
|
54e2215db4 | ||
|
|
737a816e6f | ||
|
|
9c98aaf4bd | ||
|
|
7107cec503 | ||
|
|
044dcfbf66 | ||
|
|
41edd61e2e | ||
|
|
5d5bfc215e | ||
|
|
c403bb1cad | ||
|
|
d1f7eef7eb | ||
|
|
f034abc275 | ||
|
|
588defd6b6 | ||
|
|
4877659578 | ||
|
|
e069041bd5 | ||
|
|
fcd53ae631 | ||
|
|
de36151c4a | ||
|
|
03fd5498d9 | ||
|
|
2d7f09d321 | ||
|
|
a2a798e59c | ||
|
|
93f4ee8813 | ||
|
|
bc752e1a98 | ||
|
|
f338a4f0d6 | ||
|
|
03e69e9945 | ||
|
|
228189db5a | ||
|
|
b67bc7b612 | ||
|
|
051dd191ac | ||
|
|
e00807d66b | ||
|
|
0855543ac4 | ||
|
|
e6dddd90b7 | ||
|
|
5d8e34a55f | ||
|
|
17560cf92e | ||
|
|
9cc39ae875 | ||
|
|
a47db56a68 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -46,3 +46,4 @@
|
||||
*.jpg -text
|
||||
*.jpeg -text
|
||||
*.gif -text
|
||||
*.dll -text
|
||||
|
||||
@@ -36,6 +36,7 @@ In all three cases, when multiple files of the same type are found, the project/
|
||||
|
||||
* Arguments passed using `in` are now extracted.
|
||||
* Fixed a bug where the `dynamic` type name was not extracted correctly in certain circumstances.
|
||||
* Fixed a bug where method type signatures were extracted incorrectly in some circumstances.
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
|
||||
20
change-notes/1.20/analysis-cpp.md
Normal file
20
change-notes/1.20/analysis-cpp.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Improvements to C/C++ analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
* The logic for identifying auto-generated files via `#line` directives has been improved.
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
| Suspicious pointer scaling (`cpp/suspicious-pointer-scaling`) | Fewer false positives | False positives involving types that are not uniquely named in the snapshot have been fixed. |
|
||||
| Unused static variable (`cpp/unused-static-variable`) | Fewer false positive results | Variables with the attribute `unused` are now excluded from the query. |
|
||||
| Resource not released in destructor (`cpp/resource-not-released-in-destructor`) | Fewer false positive results | Fix false positives where a resource is released via a virtual method call. |
|
||||
|
||||
## Changes to QL libraries
|
||||
25
change-notes/1.20/analysis-csharp.md
Normal file
25
change-notes/1.20/analysis-csharp.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# Improvements to C# analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| *@name of query (Query ID)* | *Impact on results* | *How/why the query has changed* |
|
||||
|------------------------------|------------------------|-----------------------------------|
|
||||
| Off-by-one comparison against container length (cs/index-out-of-bounds) | Fewer false positives | Results have been removed when there are additional guards on the index. |
|
||||
| Dereferenced variable is always null (cs/dereferenced-value-is-always-null) | Improved results | The query has been rewritten from scratch, and the analysis is now based on static single assignment (SSA) forms. The query is now enabled by default in LGTM. |
|
||||
| Dereferenced variable may be null (cs/dereferenced-value-may-be-null) | Improved results | The query has been rewritten from scratch, and the analysis is now based on static single assignment (SSA) forms. The query is now enabled by default in LGTM. |
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
* Fix extraction of `for` statements where the condition declares new variables using `is`.
|
||||
* Initializers of `stackalloc` arrays are now extracted.
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
## Changes to the autobuilder
|
||||
20
change-notes/1.20/analysis-java.md
Normal file
20
change-notes/1.20/analysis-java.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Improvements to Java analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------|-----------|--------------------------------------------------------------------|
|
||||
| Double-checked locking is not thread-safe (`java/unsafe-double-checked-locking`) | reliability, correctness, concurrency, external/cwe/cwe-609 | Identifies wrong implementations of double-checked locking that does not use the `volatile` keyword. |
|
||||
| Race condition in double-checked locking object initialization (`java/unsafe-double-checked-locking-init-order`) | reliability, correctness, concurrency, external/cwe/cwe-609 | Identifies wrong implementations of double-checked locking that performs additional initialization after exposing the constructed object. |
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|----------------------------|------------------------|------------------------------------------------------------------|
|
||||
|
||||
## Changes to QL libraries
|
||||
|
||||
|
||||
35
change-notes/1.20/analysis-javascript.md
Normal file
35
change-notes/1.20/analysis-javascript.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Improvements to JavaScript analysis
|
||||
|
||||
## General improvements
|
||||
|
||||
* Support for popular libraries has been improved. Consequently, queries may produce better results on code bases that use the following features:
|
||||
- client-side code, for example [React](https://reactjs.org/)
|
||||
- cookies and webstorage, for example [js-cookie](https://github.com/js-cookie/js-cookie)
|
||||
- server-side code, for example [hapi](https://hapijs.com/)
|
||||
* File classification has been improved to recognize additional generated files, for example files from [HTML Tidy](html-tidy.org).
|
||||
|
||||
* The taint tracking library now recognizes flow through persistent storage, this may give more results for the security queries.
|
||||
|
||||
## New queries
|
||||
|
||||
| **Query** | **Tags** | **Purpose** |
|
||||
|-----------------------------------------------|------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Double escaping or unescaping (`js/double-escaping`) | correctness, security, external/cwe/cwe-116 | Highlights potential double escaping or unescaping of special characters, indicating a possible violation of [CWE-116](https://cwe.mitre.org/data/definitions/116.html). Results are shown on LGTM by default. |
|
||||
| Incomplete regular expression for hostnames (`js/incomplete-hostname-regexp`) | correctness, security, external/cwe/cwe-020 | Highlights hostname sanitizers that are likely to be incomplete, indicating a violation of [CWE-020](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default.|
|
||||
| Incomplete URL substring sanitization | correctness, security, external/cwe/cwe-020 | Highlights URL sanitizers that are likely to be incomplete, indicating a violation of [CWE-020](https://cwe.mitre.org/data/definitions/20.html). Results shown on LGTM by default. |
|
||||
| Incorrect suffix check (`js/incorrect-suffix-check`) | correctness, security, external/cwe/cwe-020 | Highlights error-prone suffix checks based on `indexOf`, indicating a potential violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. |
|
||||
| Loop iteration skipped due to shifting (`js/loop-iteration-skipped-due-to-shifting`) | correctness | Highlights code that removes an element from an array while iterating over it, causing the loop to skip over some elements. Results are shown on LGTM by default. |
|
||||
| Useless comparison test (`js/useless-comparison-test`) | correctness | Highlights code that is unreachable due to a numeric comparison that is always true or always false. Results are shown on LGTM by default. |
|
||||
|
||||
## Changes to existing queries
|
||||
|
||||
| **Query** | **Expected impact** | **Change** |
|
||||
|--------------------------------------------|------------------------------|------------------------------------------------------------------------------|
|
||||
| Client-side cross-site scripting | More true-positive results, fewer false-positive results. | This rule now recognizes WinJS functions that are vulnerable to HTML injection, and no longer flags certain safe uses of jQuery. |
|
||||
| Insecure randomness | More results | This rule now flags insecure uses of `crypto.pseudoRandomBytes`. |
|
||||
| Uncontrolled data used in network request | More results | This rule now recognizes host values that are vulnerable to injection. |
|
||||
| Unused parameter | Fewer false-positive results | This rule no longer flags parameters with leading underscore. |
|
||||
| Unused variable, import, function or class | Fewer false-positive results | This rule now flags fewer variables that are implictly used by JSX elements, and no longer flags variables with leading underscore. |
|
||||
| Uncontrolled data used in path expression | Fewer false-positive results | This rule now recognizes the Express `root` option, which prevents path traversal. |
|
||||
|
||||
## Changes to QL libraries
|
||||
22
change-notes/1.20/extractor-javascript.md
Normal file
22
change-notes/1.20/extractor-javascript.md
Normal file
@@ -0,0 +1,22 @@
|
||||
[[ condition: enterprise-only ]]
|
||||
|
||||
# Improvements to JavaScript analysis
|
||||
|
||||
> NOTES
|
||||
>
|
||||
> Please describe your changes in terms that are suitable for
|
||||
> customers to read. These notes will have only minor tidying up
|
||||
> before they are published as part of the release notes.
|
||||
>
|
||||
> This file is written for lgtm users and should contain *only*
|
||||
> notes about changes that affect lgtm enterprise users. Add
|
||||
> any other customer-facing changes to the `studio-java.md`
|
||||
> file.
|
||||
>
|
||||
|
||||
## General improvements
|
||||
|
||||
## Changes to code extraction
|
||||
|
||||
* The extractor now supports [Nullish Coalescing](https://github.com/tc39/proposal-nullish-coalescing) expressions.
|
||||
* The TypeScript extractor now handles the control-flow of logical operators and destructuring assignments more accurately.
|
||||
@@ -94,5 +94,9 @@
|
||||
"C++ IR Dominance": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/Dominance.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/Dominance.qll"
|
||||
],
|
||||
"C++ IR PrintDominance": [
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/reachability/PrintDominance.qll",
|
||||
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/reachability/PrintDominance.qll"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,4 +25,5 @@ where v.isStatic()
|
||||
and not v instanceof MemberVariable
|
||||
and not declarationHasSideEffects(v)
|
||||
and not v.getAnAttribute().hasName("used")
|
||||
and not v.getAnAttribute().hasName("unused")
|
||||
select v, "Static variable " + v.getName() + " is never read"
|
||||
|
||||
@@ -1,199 +0,0 @@
|
||||
|
||||
import cpp
|
||||
import CPython.Extensions
|
||||
|
||||
/* A call to an argument parsing function */
|
||||
class PyArgParseTupleCall extends FunctionCall {
|
||||
|
||||
PyArgParseTupleCall() {
|
||||
this.getTarget().hasGlobalName("PyArg_Parse") or
|
||||
this.getTarget().hasGlobalName("PyArg_ParseTuple") or
|
||||
this.getTarget().hasGlobalName("PyArg_VaParse") or
|
||||
this.getTarget().hasGlobalName("PyArg_ParseTupleAndKeywords") or
|
||||
this.getTarget().hasGlobalName("PyArg_VaParseAndKeywords")
|
||||
}
|
||||
|
||||
private int getFormatIndex() {
|
||||
exists(Function f | f = this.getTarget() |
|
||||
(f.hasGlobalName("PyArg_Parse") or f.hasGlobalName("PyArg_ParseTuple") or f.hasGlobalName("PyArg_VaParse")) and result = 1
|
||||
or
|
||||
(f.hasGlobalName("PyArg_ParseTupleAndKeywords") or f.hasGlobalName("PyArg_VaParseAndKeywords")) and result = 2
|
||||
)
|
||||
}
|
||||
|
||||
private string getFormatString() {
|
||||
result = this.getArgument(this.getFormatIndex()).(StringLiteral).getValue()
|
||||
}
|
||||
|
||||
string getArgumentFormat() {
|
||||
exists(string fmt | fmt = this.getFormatString() |
|
||||
exists(int i | fmt.charAt(i) = ";" or fmt.charAt(i) = ":" | result = fmt.prefix(i))
|
||||
or
|
||||
not exists(int i | fmt.charAt(i) = ";" or fmt.charAt(i) = ":") and result = fmt
|
||||
)
|
||||
}
|
||||
|
||||
string getPyArgumentType(int index) {
|
||||
parse_format_string(this.getArgumentFormat(), index, _, result) and result != "typed"
|
||||
or
|
||||
exists(int cindex, PythonClass cls | parse_format_string(this.getArgumentFormat(), index, cindex, "typed") |
|
||||
cls.getAnAccess() = this.getArgument(this.getFormatIndex() * 2 + cindex).(AddressOfExpr).getOperand() and
|
||||
result = cls.getTpName()
|
||||
)
|
||||
or
|
||||
exists(int cindex | parse_format_string(this.getArgumentFormat(), index, cindex, "typed") and
|
||||
not exists(PythonClass cls | cls.getAnAccess() = this.getArgument(this.getFormatIndex() * 2 + cindex).(AddressOfExpr).getOperand())
|
||||
and result = "object"
|
||||
)
|
||||
}
|
||||
|
||||
predicate pyArgumentIsOptional(int index) {
|
||||
exists(string suffix | split_format_string(this.getArgumentFormat(), _, _, suffix, index, _) |
|
||||
suffix.charAt(0) = "|")
|
||||
}
|
||||
|
||||
predicate pyArgumentIsKwOnly(int index) {
|
||||
exists(string suffix | split_format_string(this.getArgumentFormat(), _, _, suffix, index, _) |
|
||||
suffix.charAt(0) = "$")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PyUnpackTupleCall extends FunctionCall {
|
||||
|
||||
PyUnpackTupleCall() {
|
||||
this.getTarget().hasGlobalName("PyArg_UnpackTuple")
|
||||
}
|
||||
|
||||
int getMinSize() {
|
||||
result = this.getArgument(2).getValue().toInt()
|
||||
}
|
||||
|
||||
int getMaxSize() {
|
||||
result = this.getArgument(3).getValue().toInt()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
predicate limiting_format(string text, string limit) {
|
||||
text = "t#" and limit = "read-only"
|
||||
or
|
||||
(text = "B" or text = "H" or text = "I" or text = "k" or text = "K") and limit = "non-negative"
|
||||
or
|
||||
(text = "c" or text = "C") and limit = "length-one"
|
||||
}
|
||||
|
||||
predicate format_string(string text, string type, int cargs) {
|
||||
tuple_format(text, type, cargs) or simple_format(text, type, cargs)
|
||||
}
|
||||
|
||||
private
|
||||
predicate simple_format(string text, string type, int cargs) {
|
||||
text = "s" and (type = "str" or type = "unicode") and cargs = 1
|
||||
or
|
||||
text = "s#" and (type = "str" or type = "unicode") and cargs = 2
|
||||
or
|
||||
text = "s*" and (type = "str" or type = "unicode") and cargs = 1
|
||||
or
|
||||
text = "z" and (type = "str" or type = "unicode" or type = "NoneType") and cargs = 1
|
||||
or
|
||||
text = "z#" and (type = "str" or type = "unicode" or type = "NoneType" or type = "buffer") and cargs = 2
|
||||
or
|
||||
text = "z*" and (type = "str" or type = "unicode" or type = "NoneType" or type = "buffer") and cargs = 1
|
||||
or
|
||||
text = "u" and type = "unicode" and cargs = 1
|
||||
or
|
||||
text = "u#" and type = "unicode" and cargs = 2
|
||||
or
|
||||
text = "O" and type = "object" and cargs = 1
|
||||
or
|
||||
text = "p" and type = "object" and cargs = 1
|
||||
or
|
||||
text = "O&" and type = "object" and cargs = 2
|
||||
or
|
||||
text = "O!" and type = "typed" and cargs = 2
|
||||
or
|
||||
(text = "b" or text = "h" or text = "i" or text = "l" or text = "L" or text = "n") and type = "int" and cargs = 1
|
||||
or
|
||||
(text = "B" or text = "H" or text = "I" or text = "k" or text = "K") and type = "int" and cargs = 1
|
||||
or
|
||||
text = "c" and (type = "bytes" or type = "bytearray") and cargs = 1
|
||||
or
|
||||
text = "C" and type = "unicode" and cargs = 1
|
||||
or
|
||||
text = "D" and type = "complex" and cargs = 1
|
||||
or
|
||||
(text = "f" or text = "d") and type = "float" and cargs = 1
|
||||
or
|
||||
text = "S" and type = "str" and cargs = 1
|
||||
or
|
||||
text = "U" and type = "unicode" and cargs = 1
|
||||
or
|
||||
text = "t#" and type = "buffer" and cargs = 2
|
||||
or
|
||||
text = "w" and type = "buffer" and cargs = 1
|
||||
or
|
||||
text = "w#" and type = "buffer" and cargs = 2
|
||||
or
|
||||
text = "w*" and type = "buffer" and cargs = 1
|
||||
or
|
||||
(text = "es" or text = "et") and (type = "str" or type = "unicode" or type = "buffer") and cargs = 2
|
||||
or
|
||||
(text = "es#" or text = "et#") and (type = "str" or type = "unicode" or type = "buffer") and cargs = 3
|
||||
or
|
||||
text = "y" and type = "bytes" and cargs = 1
|
||||
or
|
||||
text = "y*" and (type = "bytes" or type = "bytearray" or type = "buffer") and cargs = 1
|
||||
or
|
||||
text = "y#" and (type = "bytes" or type = "bytearray" or type = "buffer") and cargs = 2
|
||||
}
|
||||
|
||||
private
|
||||
predicate tuple_format(string text, string type, int cargs) {
|
||||
type = "tuple" and
|
||||
exists(PyArgParseTupleCall call | exists(call.getArgumentFormat().indexOf(text)))
|
||||
and
|
||||
exists(string body | text = "(" + body + ")" | tuple_body(body, _, cargs))
|
||||
}
|
||||
|
||||
private
|
||||
predicate tuple_body(string body, int pyargs, int cargs) {
|
||||
body = "" and cargs = 0 and pyargs = 0
|
||||
or
|
||||
(exists(PyArgParseTupleCall call | exists(call.getArgumentFormat().indexOf(body))) and
|
||||
exists(string p, int pargs, string s, int sargs, int pyargsm1 | pyargs = pyargsm1+1 and tuple_body(p, pyargsm1, pargs) and
|
||||
format_string(s, _, sargs) and body = p + s and cargs = pargs + sargs)
|
||||
)
|
||||
}
|
||||
|
||||
predicate format_token(string token, int delta, int cdelta) {
|
||||
format_string(token, _, cdelta) and delta = 1
|
||||
or
|
||||
token = "|" and delta = 0 and cdelta = 0
|
||||
or
|
||||
token = "$" and delta = 0 and cdelta = 0
|
||||
}
|
||||
|
||||
predicate split_format_string(string full, string prefix, string text, string suffix, int index, int cindex) {
|
||||
exists(PyArgParseTupleCall call | call.getArgumentFormat() = full) and
|
||||
full = prefix + text + suffix and
|
||||
(suffix = "" or exists(string s | suffix.prefix(s.length()) = s | format_token(s, _, _))) and
|
||||
format_token(text, _, _) and
|
||||
(prefix = "" and index = 0 and cindex = 0 and suffix = full.suffix(text.length())
|
||||
or
|
||||
exists(string prefixm1, string suffixm1, string textm1, int im1, int cim1, int prev, int cprev |
|
||||
full = prefixm1 + textm1 + suffixm1 and
|
||||
split_format_string(full, prefixm1, textm1, suffixm1, im1, cim1) and
|
||||
format_token(textm1, prev, cprev) and
|
||||
index = im1+prev and
|
||||
cindex = cim1+cprev and
|
||||
prefix = prefixm1 + textm1 and
|
||||
suffix = suffixm1.suffix(text.length()) and
|
||||
text = suffixm1.prefix(text.length())
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate parse_format_string(string full, int index, int cindex, string type) {
|
||||
exists(string prefix, string text, string suffix | split_format_string(full, prefix, text, suffix, index, cindex) and format_string(text, type, _))
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @name Parameter type trap file generator
|
||||
* @description Generate trap files (in CSV form) describing CPython extension function parameter types.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/argument-type-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
import CPython.Extensions
|
||||
|
||||
from TypedPythonExtensionFunction func, int arg, PythonClass cls
|
||||
where func.getArgumentType(arg) = cls
|
||||
select "ext_argtype", func.getTrapID(), arg, cls.getTrapID()
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* @name py_cobject_sources() trap file generator
|
||||
* @description Generate trap files (in CSV form) for CPython objects.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/c-object-sources-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
import CPython.Extensions
|
||||
|
||||
from CObject c
|
||||
select "py_cobject_sources", c.getTrapID(), 1
|
||||
@@ -1,14 +0,0 @@
|
||||
/**
|
||||
* @name py_cobject() trap file generator
|
||||
* @description Generate trap files (in CSV form) for CPython objects.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/c-object-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
import CPython.Extensions
|
||||
|
||||
|
||||
from CObject c
|
||||
select "py_cobjects", c.getTrapID()
|
||||
@@ -1,893 +0,0 @@
|
||||
import cpp
|
||||
import CPython.ArgParse
|
||||
|
||||
|
||||
/* Root class of all 'C' objects */
|
||||
abstract class CObject extends Element {
|
||||
|
||||
abstract string getTrapID();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
A Python class is an instance of PyTypeObject.
|
||||
*/
|
||||
class PythonClass extends Variable, CObject {
|
||||
|
||||
PythonClass() {
|
||||
getType().hasName("PyTypeObject")
|
||||
}
|
||||
|
||||
/** Gets the function table (if any) associated with the class. */
|
||||
PythonFunctionTable getFunctionTable() {
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = getInitializer().getExpr()
|
||||
and tt.hasName("PyTypeObject")
|
||||
and f.hasName("tp_methods")
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and result.getAnAccess() = l.getFieldExpr(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the getset table (if any) associated with the class. */
|
||||
PythonGetSetTable getGetSetTable() {
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = getInitializer().getExpr()
|
||||
and tt.hasName("PyTypeObject")
|
||||
and f.hasName("tp_getset")
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and result.getAnAccess() = l.getFieldExpr(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the Python module (if any) containing this class. */
|
||||
PythonModule getModule() {
|
||||
result = getFile()
|
||||
}
|
||||
|
||||
Expr getSlot(string name) {
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = getInitializer().getExpr()
|
||||
and tt.hasName("PyTypeObject")
|
||||
and f.hasName(name)
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and l.getFieldExpr(f) = result
|
||||
)
|
||||
}
|
||||
|
||||
string getTpName() {
|
||||
exists(StringLiteral lit |
|
||||
lit = this.getSlot("tp_name") |
|
||||
result = lit.getValue()
|
||||
)
|
||||
}
|
||||
|
||||
Expr getSizeOf() {
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = getInitializer().getExpr()
|
||||
and tt.hasName("PyTypeObject")
|
||||
and f.hasName("tp_basicsize")
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and l.getFieldExpr(f) = result
|
||||
)
|
||||
}
|
||||
|
||||
override string getTrapID() {
|
||||
/* This needs to be kept in sync with extractor-python/semmle/passes/type.py */
|
||||
result = "C_type$" + this.getTpName()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A call to a Py_InitModule function. These functions register a Python module.
|
||||
*/
|
||||
class Py_InitModuleCall extends FunctionCall {
|
||||
Py_InitModuleCall() {
|
||||
// Py_InitModule itself is actually a macro, ultimately defined to be something like Py_InitModule4_64.
|
||||
getTarget().getName().matches("Py\\_Init%")
|
||||
}
|
||||
|
||||
/** Gets the name of the module being registered. */
|
||||
string getModuleName() {
|
||||
result = getArgument(0).(StringLiteral).getValue()
|
||||
}
|
||||
|
||||
/** Gets the function table associated with this Py_InitModule call. */
|
||||
PythonFunctionTable getFunctionTable() {
|
||||
exists(VariableAccess va |
|
||||
va = getArgument(1)
|
||||
and result = va.getTarget()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
A Python module, represented by the file containing an initialising call for it.
|
||||
*/
|
||||
class PythonModule extends File {
|
||||
PythonModule() {
|
||||
exists(PythonModuleDefinition def | def.getFile() = this)
|
||||
or
|
||||
exists(FunctionCall c | c.getFile() = this |
|
||||
c.getTarget().getName().matches("Py\\_InitModule%")
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a Python class that is in this module. */
|
||||
PythonClass getAClass() {
|
||||
result.getFile() = this
|
||||
}
|
||||
|
||||
/** Gets the function table associated with the module. */
|
||||
PythonFunctionTable getFunctionTable() {
|
||||
result = this.getDefinition().getFunctionTable()
|
||||
or
|
||||
exists(FunctionCall c | c.getFile() = this |
|
||||
c.getTarget().getName().matches("Py\\_InitModule%") and
|
||||
c.getAnArgument() = result.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the Py_InitModule call that was used to register the module. */
|
||||
//private
|
||||
PythonModuleDefinition getDefinition() {
|
||||
result.getFile() = this
|
||||
}
|
||||
|
||||
/** Gets the name of the module. */
|
||||
string getModuleName() {
|
||||
result = this.getDefinition().getModuleName()
|
||||
or
|
||||
exists(FunctionCall c |c.getFile() = this |
|
||||
c.getTarget().getName().matches("Py\\_InitModule%") and
|
||||
c.getArgument(0).getValue() = result
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The function table for a Python module.
|
||||
*/
|
||||
class PythonFunctionTable extends Variable {
|
||||
|
||||
PythonFunctionTable() {
|
||||
not(this instanceof Parameter)
|
||||
and exists(ArrayType at | at = getType().getUnspecifiedType() and at.getBaseType().hasName("PyMethodDef"))
|
||||
}
|
||||
|
||||
/** Gets an entry in the table. */
|
||||
PythonFunctionTableEntry getATableEntry() {
|
||||
result = getInitializer().getExpr().getAChild()
|
||||
and exists(result.getRegisteredFunctionName())
|
||||
}
|
||||
|
||||
/** Gets the class (if any) for which this is the function table. */
|
||||
PythonClass getClass() {
|
||||
result.getFunctionTable() = this
|
||||
or
|
||||
exists(FunctionAccess getattr, Call find_method |
|
||||
result.getSlot("tp_getattr") = getattr |
|
||||
find_method.getEnclosingFunction() = getattr.getTarget() and
|
||||
find_method.getArgument(0) = this.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the module (if any) for which this is the function table. */
|
||||
PythonModule getModule() {
|
||||
result.getFunctionTable() = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
The getset table for a Python module or type
|
||||
*/
|
||||
class PythonGetSetTable extends Variable {
|
||||
|
||||
PythonGetSetTable() {
|
||||
not(this instanceof Parameter) and
|
||||
exists(ArrayType at | at = getType() and at.getBaseType().hasName("PyGetSetDef"))
|
||||
}
|
||||
|
||||
/** Gets the class (if any) for which this is the function table. */
|
||||
PythonClass getClass() {
|
||||
result.getGetSetTable() = this
|
||||
}
|
||||
|
||||
/** Gets an entry in the table. */
|
||||
PythonGetSetTableEntry getATableEntry() {
|
||||
result = getInitializer().getExpr().getAChild()
|
||||
and exists(result.getRegisteredPropertyName())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PythonModuleDefinition extends Variable {
|
||||
|
||||
PythonModuleDefinition() {
|
||||
not(this instanceof Parameter)
|
||||
and exists(Type moddef_t | moddef_t = this.getType() and moddef_t.hasName("PyModuleDef"))
|
||||
}
|
||||
|
||||
/** Gets the function table (if any) associated with the class. */
|
||||
PythonFunctionTable getFunctionTable() {
|
||||
exists(ClassAggregateLiteral l, Type moddef_t, Field f |
|
||||
l = this.getInitializer().getExpr()
|
||||
and moddef_t.hasName("PyModuleDef")
|
||||
and f.hasName("m_methods")
|
||||
and f.getDeclaringType() = moddef_t
|
||||
and result.getAnAccess() = l.getFieldExpr(f)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the function table (if any) associated with the class. */
|
||||
string getModuleName() {
|
||||
exists(ClassAggregateLiteral l, Type moddef_t, Field f |
|
||||
l = this.getInitializer().getExpr()
|
||||
and moddef_t.hasName("PyModuleDef")
|
||||
and f.hasName("m_name")
|
||||
and f.getDeclaringType() = moddef_t
|
||||
and result = l.getFieldExpr(f).getValue()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** A special (__xxx__) method implemented in C
|
||||
*/
|
||||
class PythonSpecialMethod extends Function {
|
||||
|
||||
PythonSpecialMethod() {
|
||||
class_special_methods(_, _, this)
|
||||
}
|
||||
|
||||
PythonClass getClass() {
|
||||
class_special_methods(result, _, this)
|
||||
}
|
||||
|
||||
string getPyName() {
|
||||
class_special_methods(_, result, this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
predicate class_special_methods(PythonClass cls, string name, Function method) {
|
||||
|
||||
exists(string slot, FunctionAccess fa |
|
||||
special_methods(name, slot) and cls.getSlot(slot) = fa and fa.getTarget() = method
|
||||
or
|
||||
number_methods(name, slot) and
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = cls.getSlot("tp_as_number")
|
||||
and tt.hasName("PyNumberMethods")
|
||||
and f.hasName(slot)
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and l.getFieldExpr(f) = fa
|
||||
and fa.getTarget() = method
|
||||
)
|
||||
or
|
||||
sequence_methods(name, slot) and
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = cls.getSlot("tp_as_sequence")
|
||||
and tt.hasName("PySequenceMethods")
|
||||
and f.hasName(slot)
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and l.getFieldExpr(f) = fa
|
||||
and fa.getTarget() = method
|
||||
)
|
||||
or
|
||||
mapping_methods(name, slot) and
|
||||
exists(ClassAggregateLiteral l, TypedefType tt, Field f |
|
||||
l = cls.getSlot("tp_as_mapping")
|
||||
and tt.hasName("PyMappingMethods")
|
||||
and f.hasName(slot)
|
||||
and f.getDeclaringType() = tt.getBaseType()
|
||||
and l.getFieldExpr(f) = fa
|
||||
and fa.getTarget() = method
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
predicate special_methods(string name, string slot_name) {
|
||||
name = "__getattr__" and slot_name = "tp_getattr"
|
||||
or
|
||||
name = "__hash__" and slot_name = "tp_hash"
|
||||
or
|
||||
name = "__call__" and slot_name = "tp_call"
|
||||
or
|
||||
name = "__str__" and slot_name = "tp_str"
|
||||
or
|
||||
name = "__getattribute__" and slot_name = "tp_getattro"
|
||||
or
|
||||
name = "__setattro__" and slot_name = "tp_setattro"
|
||||
or
|
||||
name = "__iter__" and slot_name = "tp_iter"
|
||||
or
|
||||
name = "__descr_get__" and slot_name = "tp_descr_get"
|
||||
or
|
||||
name = "__descr_set__" and slot_name = "tp_descr_set"
|
||||
}
|
||||
|
||||
predicate number_methods(string name, string slot_name) {
|
||||
name = "__add__" and slot_name = "nb_add"
|
||||
or
|
||||
name = "__sub__" and slot_name = "nb_subtract"
|
||||
or
|
||||
name = "__mul__" and slot_name = "nb_multiply"
|
||||
or
|
||||
name = "__mod__" and slot_name = "nb_remainder"
|
||||
or
|
||||
name = "__pow__" and slot_name = "nb_power"
|
||||
or
|
||||
name = "__neg__" and slot_name = "nb_negative"
|
||||
or
|
||||
name = "__pos__" and slot_name = "nb_positive"
|
||||
or
|
||||
name = "__abs__" and slot_name = "nb_absolute"
|
||||
or
|
||||
name = "__bool__" and slot_name = "nb_bool"
|
||||
or
|
||||
name = "__bool__" and slot_name = "nb_bool"
|
||||
or
|
||||
name = "__invert__" and slot_name = "nb_invert"
|
||||
or
|
||||
name = "__lshift__" and slot_name = "nb_lshift"
|
||||
or
|
||||
name = "__rshift__" and slot_name = "nb_rshift"
|
||||
or
|
||||
name = "__and__" and slot_name = "nb_and"
|
||||
or
|
||||
name = "__xor__" and slot_name = "nb_xor"
|
||||
or
|
||||
name = "__or__" and slot_name = "nb_or"
|
||||
or
|
||||
name = "__int__" and slot_name = "nb_int"
|
||||
or
|
||||
name = "__long__" and slot_name = "nb_long"
|
||||
or
|
||||
name = "__float__" and slot_name = "nb_float"
|
||||
or
|
||||
name = "__iadd__" and slot_name = "nb_inplace_add"
|
||||
or
|
||||
name = "__isub__" and slot_name = "nb_inplace_subtract"
|
||||
or
|
||||
name = "__imul__" and slot_name = "nb_inplace_multiply"
|
||||
or
|
||||
name = "__imod__" and slot_name = "nb_inplace_remainder"
|
||||
or
|
||||
name = "__ilshift__" and slot_name = "nb_inplace_lshift"
|
||||
or
|
||||
name = "__irshift__" and slot_name = "nb_inplace_rshift"
|
||||
or
|
||||
name = "__iand__" and slot_name = "nb_inplace_and"
|
||||
or
|
||||
name = "__ixor__" and slot_name = "nb_inplace_xor"
|
||||
or
|
||||
name = "__ior__" and slot_name = "nb_inplace_or"
|
||||
or
|
||||
name = "__index__" and slot_name = "nb_index"
|
||||
}
|
||||
|
||||
predicate sequence_methods(string name, string slot_name) {
|
||||
name = "__len__" and slot_name = "sq_length"
|
||||
or
|
||||
name = "__add__" and slot_name = "sq_concat"
|
||||
or
|
||||
name = "__mul__" and slot_name = "sq_repeat"
|
||||
or
|
||||
name = "__getitem__" and slot_name = "sq_item"
|
||||
or
|
||||
name = "__setitem__" and slot_name = "sq_ass_item"
|
||||
or
|
||||
name = "__contains__" and slot_name = "sq_contains"
|
||||
or
|
||||
name = "__iadd__" and slot_name = "sq_inplace_concat"
|
||||
or
|
||||
name = "__imul__" and slot_name = "sq_inplace_repeat"
|
||||
}
|
||||
|
||||
predicate mapping_methods(string name, string slot_name) {
|
||||
name = "__len__" and slot_name = "mp_length"
|
||||
or
|
||||
name = "__getitem__" and slot_name = "mp_subscript"
|
||||
or
|
||||
name = "__setitem__" and slot_name = "mp_ass_subscript"
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
An entry in the getset table for a Python class.
|
||||
This is the C code item that corresponds 1-to-1 with the Python-level property
|
||||
*/
|
||||
class PythonGetSetTableEntry extends AggregateLiteral {
|
||||
|
||||
PythonGetSetTableEntry() {
|
||||
this.getUnderlyingType().hasName("PyGetSetDef")
|
||||
and
|
||||
this.getChild(0) instanceof StringLiteral
|
||||
}
|
||||
|
||||
Function getGetter() {
|
||||
exists(FunctionAccess fa | fa = getChild(1) and result = fa.getTarget())
|
||||
}
|
||||
|
||||
Function getSetter() {
|
||||
exists(FunctionAccess fa | fa = getChild(2) and result = fa.getTarget())
|
||||
}
|
||||
|
||||
StringLiteral getRegisteredPropertyName() {
|
||||
result = this.getChild(0)
|
||||
}
|
||||
|
||||
PythonGetSetTable getTable() {
|
||||
result.getATableEntry() = this
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
An entry in the function table for a Python class or module.
|
||||
This is the C code item that corresponds 1-to-1 with the Python-level function.
|
||||
*/
|
||||
class PythonFunctionTableEntry extends AggregateLiteral {
|
||||
|
||||
PythonFunctionTableEntry() {
|
||||
this.getUnderlyingType().hasName("PyMethodDef")
|
||||
and
|
||||
this.getChild(0) instanceof StringLiteral
|
||||
}
|
||||
|
||||
/** Gets the doc string to be associated with the function being registered. */
|
||||
string getDocString() {
|
||||
result = getChild(3).(StringLiteral).getValueText()
|
||||
}
|
||||
|
||||
/** Gets the flags for the function being registered. */
|
||||
int getFlags() {
|
||||
result = getChild(2).getValue().toInt()
|
||||
}
|
||||
|
||||
/** Gets the function being registered. */
|
||||
Function getFunction() {
|
||||
exists(FunctionAccess fa | fa = getChild(1) and result = fa.getTarget())
|
||||
}
|
||||
|
||||
/** Gets the module containing the function table. */
|
||||
PythonModule getModule() {
|
||||
result = getTable().getModule()
|
||||
}
|
||||
|
||||
/** Gets the name with which the function should be referenced from Python. */
|
||||
StringLiteral getRegisteredFunctionName() {
|
||||
result = this.getChild(0)
|
||||
}
|
||||
|
||||
/** Gets the function table containing this entry. */
|
||||
PythonFunctionTable getTable() {
|
||||
result.getATableEntry() = this
|
||||
}
|
||||
|
||||
/** Gets a flag associated with this function. */
|
||||
string getAFlag() {
|
||||
exists(int f | f = this.getFlags() |
|
||||
(f % 2 = 1 and result = "METH_VARARGS")
|
||||
or ((f / 2) % 2 = 1 and result = "METH_KEYWORDS")
|
||||
or ((f / 4) % 2 = 1 and result = "METH_NOARGS")
|
||||
or ((f / 8) % 2 = 1 and result = "METH_O")
|
||||
or ((f / 16) % 2 = 1 and result = "METH_CLASS")
|
||||
or ((f / 32) % 2 = 1 and result = "METH_STATIC")
|
||||
or ((f / 64) % 2 = 1 and result = "METH_COEXIST")
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
library class PythonBuildReturnCall extends FunctionCall {
|
||||
PythonBuildReturnCall() {
|
||||
exists(string name | name = getTarget().getName() |
|
||||
name = "Py_BuildValue"
|
||||
or name = "Py_VaBuildValue"
|
||||
)
|
||||
}
|
||||
|
||||
string getFormatString() {
|
||||
result = getArgument(0).(StringLiteral).getValue()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
An extension function for Python (written in C).
|
||||
*/
|
||||
class PythonExtensionFunction extends Function {
|
||||
PythonExtensionFunction() {
|
||||
exists(PythonFunctionTableEntry e | e.getFunction() = this)
|
||||
and exists(getAParameter())
|
||||
}
|
||||
|
||||
/** Gets a function table entry registering this function. */
|
||||
PythonFunctionTableEntry getATableEntry() {
|
||||
result.getFunction() = this
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TypedPythonExtensionProperty extends PythonGetSetTableEntry, CObject {
|
||||
PythonClass getPropertyType() {
|
||||
result = py_return_type(this.getGetter())
|
||||
}
|
||||
|
||||
private string trapClass() {
|
||||
result = this.getClass().getTrapID()
|
||||
}
|
||||
|
||||
override string getTrapID() {
|
||||
result = this.trapClass() + "$" + this.getPyName()
|
||||
}
|
||||
|
||||
string getPyName() {
|
||||
result = this.getRegisteredPropertyName().getValue()
|
||||
}
|
||||
|
||||
/** Gets the class containing this function. */
|
||||
PythonClass getClass() {
|
||||
result = this.getTable().getClass()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* An extension function for Python (written in C); Python facing aspect */
|
||||
abstract class TypedPythonExtensionFunction extends PythonFunctionTableEntry, CObject {
|
||||
|
||||
override Location getLocation() {
|
||||
result = this.getRegisteredFunctionName().getLocation()
|
||||
}
|
||||
|
||||
override
|
||||
string toString() {
|
||||
result = "MethodDef " + this.getRegisteredFunctionName().getValue()
|
||||
}
|
||||
|
||||
abstract PythonClass getArgumentType(int index);
|
||||
|
||||
abstract predicate argumentIsOptional(int index);
|
||||
|
||||
abstract predicate argumentIsKwOnly(int index);
|
||||
|
||||
PythonExtensionFunction getCode() {
|
||||
result.getATableEntry() = this
|
||||
}
|
||||
|
||||
predicate isMethod() {
|
||||
exists(this.getTable().getClass()) and not this.getAFlag() = "METH_STATIC"
|
||||
}
|
||||
|
||||
int c_index(int index) {
|
||||
index in [0..20] and result in [-1..20]
|
||||
and
|
||||
(if this.isMethod() then
|
||||
result = index - 1
|
||||
else
|
||||
result = index
|
||||
)
|
||||
}
|
||||
|
||||
string getPyName() {
|
||||
result = this.getRegisteredFunctionName().getValue()
|
||||
}
|
||||
|
||||
PythonClass getReturnType() {
|
||||
result = py_return_type(this.getCode())
|
||||
}
|
||||
|
||||
|
||||
/** Gets the module containing this function. */
|
||||
override PythonModule getModule() {
|
||||
result = getTable().getModule()
|
||||
}
|
||||
|
||||
/** Gets the class containing this function. */
|
||||
PythonClass getClass() {
|
||||
result = getTable().getClass()
|
||||
}
|
||||
|
||||
//private
|
||||
string trapModule() {
|
||||
result = this.getModule().getModuleName()
|
||||
}
|
||||
|
||||
//private
|
||||
string trapClass() {
|
||||
result = this.getClass().getTrapID()
|
||||
}
|
||||
|
||||
/* A globally unique name for use in trap files.
|
||||
*/
|
||||
override string getTrapID() {
|
||||
result = "C_builtin_function_or_method$" + this.trapModule() + "." + this.getPyName()
|
||||
or
|
||||
result = this.trapClass() + "$" + this.getPyName()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
predicate src_dest_pair(Element src, ControlFlowNode dest) {
|
||||
exists(LocalScopeVariable v, ControlFlowNode def |
|
||||
definitionUsePair(v, def, dest) and
|
||||
exprDefinition(v, def, src) and
|
||||
not exists(AddressOfExpr addr | addr.getOperand() = v.getAnAccess())
|
||||
)
|
||||
or
|
||||
exists(Parameter p | dest = p.getAnAccess() and not definitionUsePair(_, _, dest) and src = p)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate local_flows_to(Element src, ControlFlowNode dest) {
|
||||
not unreachable(src) and not unreachable(dest) and
|
||||
(src = dest
|
||||
or
|
||||
src_dest_pair(src, dest)
|
||||
or
|
||||
exists(Element mid | local_flows_to(src, mid) and src_dest_pair(mid, dest))
|
||||
)
|
||||
}
|
||||
|
||||
PythonClass py_return_type(Function f) {
|
||||
exists(ReturnStmt ret |
|
||||
ret.getEnclosingFunction() = f and
|
||||
result = python_type(ret.getExpr()) and
|
||||
not ret.getExpr().getValue() = "0"
|
||||
)
|
||||
or
|
||||
exists(Macro m | m.getAnInvocation().getEnclosingFunction() = f and m.getName() = "Py_RETURN_NONE" and result.getTpName() = "NoneType")
|
||||
or
|
||||
exists(Macro m | m.getAnInvocation().getEnclosingFunction() = f and m.getName() = "Py_RETURN_TRUE" and result.getTpName() = "bool")
|
||||
or
|
||||
exists(Macro m | m.getAnInvocation().getEnclosingFunction() = f and m.getName() = "Py_RETURN_FALSE" and result.getTpName() = "bool")
|
||||
}
|
||||
|
||||
PythonClass python_type_from_size(Expr e) {
|
||||
exists(Type t, string name |
|
||||
t = e.getUnderlyingType().(PointerType).getBaseType() and name = t.getName() and name.matches("Py\\_%Object") |
|
||||
exists(PythonClass cls | cls.getSizeOf().getValueText() = "sizeof(" + t.getName() + ")" |
|
||||
result = cls and not result.getTpName() = "int" and not result.getTpName() = "bool"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate py_bool(Expr e) {
|
||||
exists(MacroInvocation mi, string name |
|
||||
mi.getExpr() = e and name = mi.getMacroName() |
|
||||
name = "Py_False" or name = "Py_True"
|
||||
)
|
||||
}
|
||||
|
||||
PythonClass python_type_from_name(Expr e) {
|
||||
exists(Type t, string name |
|
||||
t = e.getUnderlyingType().(PointerType).getBaseType() and name = t.getName() |
|
||||
name = "PyBytesObject" and result.getTpName() = "bytes"
|
||||
or
|
||||
name = "PyTupleObject" and result.getTpName() = "tuple"
|
||||
or
|
||||
name = "PyLongObject" and result.getTpName() = "int" and not py_bool(e)
|
||||
or
|
||||
name = "PyIntObject" and result.getTpName() = "int" and not py_bool(e)
|
||||
or
|
||||
name = "PyStringObject" and result.getTpName() = "str" and cpython_major_version() = 2
|
||||
or
|
||||
name = "PyStringObject" and result.getTpName() = "bytes" and cpython_major_version() = 3
|
||||
or
|
||||
name = "PyUnicodeObject" and result.getTpName() = "unicode" and cpython_major_version() = 2
|
||||
or
|
||||
name = "PyUnicodeObject" and result.getTpName() = "str" and cpython_major_version() = 3
|
||||
)
|
||||
}
|
||||
|
||||
PythonClass python_type(Expr e) {
|
||||
result = python_type_from_size(e)
|
||||
or
|
||||
result = python_type_from_name(e)
|
||||
or
|
||||
call_to_new(e, result)
|
||||
or
|
||||
exists(Element src | result = python_type(src) and local_flows_to(src, e))
|
||||
or
|
||||
result = type_from_build_value(e)
|
||||
or
|
||||
result = type_from_call(e)
|
||||
or
|
||||
py_bool(e) and result.getTpName() = "bool"
|
||||
or
|
||||
call_to_type(e, result)
|
||||
or
|
||||
exists(MacroInvocation mi |
|
||||
mi.getExpr() = e and mi.getMacroName() = "Py_None" |
|
||||
result.getTpName() = "NoneType"
|
||||
)
|
||||
}
|
||||
|
||||
predicate build_value_function(Function f) {
|
||||
f.getName().regexpMatch("_?Py_(Va)?BuildValue(_SizeT)?")
|
||||
}
|
||||
|
||||
PythonClass type_from_build_value(Expr e) {
|
||||
exists(FunctionCall c |
|
||||
c = e |
|
||||
build_value_function(c.getTarget()) and
|
||||
result = type_from_build_value_code(c.getArgument(0).getValue())
|
||||
)
|
||||
}
|
||||
|
||||
PythonClass type_from_call(Expr e) {
|
||||
exists(Function f |
|
||||
not build_value_function(f) and
|
||||
/* Do not type to infer return type of the interpreter */
|
||||
not f.getName().matches("PyEval%") and
|
||||
f = e.(FunctionCall).getTarget() and
|
||||
result = py_return_type(f)
|
||||
)
|
||||
or
|
||||
exists(Function f |
|
||||
f = e.(FunctionCall).getTarget() and
|
||||
result.getTpName() = "dict"
|
||||
|
|
||||
f.hasName("PyEval_GetBuiltins") or
|
||||
f.hasName("PyEval_GetGlobals") or
|
||||
f.hasName("PyEval_GetLocals")
|
||||
)
|
||||
}
|
||||
|
||||
PythonClass type_from_build_value_code(string s) {
|
||||
exists(FunctionCall c | c.getArgument(0).getValue() = s)
|
||||
and
|
||||
(result = type_from_simple_code(s)
|
||||
or
|
||||
result.getTpName() = "dict" and s.charAt(0) = "{"
|
||||
or
|
||||
result.getTpName() = "tuple" and not exists(type_from_simple_code(s)) and not s.charAt(0) = "{"
|
||||
)
|
||||
}
|
||||
|
||||
private PythonClass theBytesClass() {
|
||||
cpython_major_version() = 2 and result.getTpName() = "str"
|
||||
or
|
||||
cpython_major_version() = 3 and result.getTpName() = "bytes"
|
||||
}
|
||||
|
||||
private PythonClass theUnicodeClass() {
|
||||
cpython_major_version() = 2 and result.getTpName() = "unicode"
|
||||
or
|
||||
cpython_major_version() = 3 and result.getTpName() = "str"
|
||||
}
|
||||
|
||||
PythonClass type_from_simple_code(string s) {
|
||||
(s = "s" or s = "s#" or s = "z" or s = "z#") and result.getTpName() = "str"
|
||||
or
|
||||
(s = "u" or s = "u#" or s = "U" or s = "U#" or s = "C") and result = theUnicodeClass()
|
||||
or
|
||||
(s = "y" or s = "y#" or s = "c") and result = theBytesClass()
|
||||
or
|
||||
(s = "i" or s = "I" or s = "b" or s = "B" or s = "h" or s = "H" or
|
||||
s = "k" or s = "K" or s = "l" or s = "L" or s = "n"
|
||||
) and result.getTpName() = "int"
|
||||
or
|
||||
(s = "f" or s = "d") and result.getTpName() = "float"
|
||||
or
|
||||
s = "D" and result.getTpName() = "complex"
|
||||
or
|
||||
(s = "O" or s = "O&" or s = "N") and result.getTpName() = "object"
|
||||
}
|
||||
|
||||
predicate call_to_new(FunctionCall call, PythonClass cls) {
|
||||
exists(string name |
|
||||
name = call.getTarget().getName() |
|
||||
name = "_PyObject_New" or
|
||||
name = "_PyObject_GC_New" or
|
||||
name = "_PyObject_NewVar" or
|
||||
name = "_PyObject_GC_NewVar"
|
||||
) and
|
||||
exists(AddressOfExpr addr |
|
||||
addr = call.getArgument(0) |
|
||||
addr.getAddressable() = cls
|
||||
)
|
||||
}
|
||||
|
||||
predicate call_to_type(FunctionCall call, PythonClass cls) {
|
||||
exists(AddressOfExpr aoe |
|
||||
call.getTarget().getName().matches("PyObject\\_Call%") and
|
||||
call.getArgument(0) = aoe and
|
||||
aoe.getAddressable() = cls
|
||||
)
|
||||
}
|
||||
|
||||
predicate pyargs_function(PythonFunctionTableEntry func, PyArgParseTupleCall call) {
|
||||
func.getFunction().getParameter(1).getAnAccess() = call.getArgument(0)
|
||||
}
|
||||
|
||||
|
||||
class PyArgsFunction extends TypedPythonExtensionFunction {
|
||||
|
||||
PyArgsFunction() {
|
||||
this.getAFlag() = "METH_VARARGS"
|
||||
}
|
||||
|
||||
PyArgParseTupleCall getParseArgsCall() {
|
||||
strictcount(PyArgParseTupleCall other | this.getCode().getParameter(1).getAnAccess() = other.getArgument(0)) = 1 and
|
||||
pyargs_function(this, result)
|
||||
}
|
||||
|
||||
override PythonClass getArgumentType(int index) {
|
||||
this.isMethod() and index = 0 and result = this.getTable().getClass()
|
||||
or
|
||||
result.getTpName() = this.getParseArgsCall().getPyArgumentType(this.c_index(index))
|
||||
}
|
||||
|
||||
override predicate argumentIsOptional(int index) {
|
||||
this.getParseArgsCall().pyArgumentIsOptional(this.c_index(index))
|
||||
}
|
||||
|
||||
override predicate argumentIsKwOnly(int index) {
|
||||
this.getParseArgsCall().pyArgumentIsKwOnly(this.c_index(index))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class PyOFunction extends TypedPythonExtensionFunction {
|
||||
|
||||
PyOFunction() {
|
||||
this.getAFlag() = "METH_O"
|
||||
}
|
||||
|
||||
override PythonClass getArgumentType(int index) {
|
||||
this.isMethod() and index = 0 and result = this.getTable().getClass()
|
||||
or
|
||||
/* TO DO -- Better analysis */
|
||||
this.c_index(index) = 0 and result.getTpName() = "object"
|
||||
}
|
||||
|
||||
override predicate argumentIsOptional(int index) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate argumentIsKwOnly(int index) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
class PyNoArgFunction extends TypedPythonExtensionFunction {
|
||||
|
||||
PyNoArgFunction() {
|
||||
this.getAFlag() = "METH_NOARGS"
|
||||
}
|
||||
|
||||
override PythonClass getArgumentType(int index) {
|
||||
this.isMethod() and index = 0 and result = this.getTable().getClass()
|
||||
}
|
||||
|
||||
override predicate argumentIsOptional(int index) {
|
||||
none()
|
||||
}
|
||||
|
||||
override predicate argumentIsKwOnly(int index) {
|
||||
none()
|
||||
}
|
||||
}
|
||||
|
||||
int cpython_major_version() {
|
||||
exists(MacroInvocation mi |
|
||||
mi.getMacroName() = "PY_MAJOR_VERSION" |
|
||||
result = mi.getExpr().getValue().toInt()
|
||||
)
|
||||
}
|
||||
|
||||
int cpython_minor_version() {
|
||||
exists(MacroInvocation mi |
|
||||
mi.getMacroName() = "PY_MINOR_VERSION" |
|
||||
result = mi.getExpr().getValue().toInt()
|
||||
)
|
||||
}
|
||||
|
||||
string cpython_version() {
|
||||
result = cpython_major_version().toString() + "." + cpython_minor_version().toString()
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* @name Parameter return trap file generator
|
||||
* @description Generate trap files (in CSV form) describing CPython extension functions return one of their parameters.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/parameter-return-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import CPython.Extensions
|
||||
|
||||
predicate argument_flows_to_return(Function func, int arg) {
|
||||
exists(Parameter p | p = func.getParameter(arg) |
|
||||
forall(ReturnStmt ret | ret.getEnclosingFunction() = func |
|
||||
local_flows_to(p, ret.getExpr()))
|
||||
)
|
||||
}
|
||||
|
||||
from TypedPythonExtensionFunction func, PythonExtensionFunction code, int arg
|
||||
where func.getCode() = code and argument_flows_to_return(code, arg)
|
||||
select "ext_argreturn", func.getTrapID(), arg
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @name Property type trap file generator
|
||||
* @description Generate trap files (in CSV form) describing CPython extension property types.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/property-type-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
import CPython.Extensions
|
||||
|
||||
|
||||
from TypedPythonExtensionProperty p, PythonClass cls
|
||||
where cls = p.getPropertyType()
|
||||
select "ext_proptype", p.getTrapID(), cls.getTrapID()
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* @name Return type trap file generator
|
||||
* @description Generate trap files (in CSV form) describing CPython extension function return types.
|
||||
* @kind trap
|
||||
* @id cpp/c-python/return-type-trap
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
import CPython.Extensions
|
||||
|
||||
|
||||
from TypedPythonExtensionFunction func, PythonClass cls
|
||||
where cls = func.getReturnType()
|
||||
select "ext_rettype", func.getTrapID(), cls.getTrapID()
|
||||
@@ -4,6 +4,8 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/exit-nonterminating-loop
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/loop-bounds
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/recursion
|
||||
* @problem.severity warning
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* testability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* @description Dynamic memory allocation (using malloc() or calloc()) should be confined to the initialization routines of a program.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/heap-memory
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags resources
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/thread-safety
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* concurrency
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/avoid-nested-semaphores
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* concurrency
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import Semaphores
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
* @description The use of semaphores or locks to access shared data should be avoided.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/avoid-semaphores
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags concurrency
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import Semaphores
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/out-of-order-locks
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* concurrency
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import Semaphores
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/release-locks-when-acquired
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* concurrency
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import Semaphores
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/simple-control-flow-goto
|
||||
* @problem.severity warning
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/simple-control-flow-jmp
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* portability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description In an enumerator list, the = construct should not be used to explicitly initialize members other than the first, unless all items are explicitly initialized. An exception is the pattern to use the last element of an enumerator list to get the number of possible values.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/enum-initialization
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
import cpp
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/extern-decls-in-header
|
||||
* @problem.severity warning
|
||||
* @tags maintainability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
* @description Global variables that are not accessed outside their own file should be made static to promote information hiding.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/limited-scope-file
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @precision low
|
||||
* @tags maintainability
|
||||
* modularity
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Global and file-scope variables that are accessed by only one function should be scoped within that function.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/limited-scope-function
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @precision low
|
||||
* @tags maintainability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description A local variable or parameter that hides a global variable of the same name.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/limited-scope-local-hides-global
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
import cpp
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/checking-return-values
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* reliability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/checking-parameter-values
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* reliability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import JPL_C.Tasks
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/use-of-assertions-constant
|
||||
* @problem.severity warning
|
||||
* @tags maintainability
|
||||
* reliability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.commons.Assertions
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description All functions of more than 10 lines should have at least one assertion.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/use-of-assertions-density
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* reliability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.commons.Assertions
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/use-of-assertions-non-boolean
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.commons.Assertions
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/use-of-assertions-side-effect
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.commons.Assertions
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Typedefs that indicate size and signedness should be used in place of the basic types.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/basic-int-types
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description In compound expressions with multiple sub-expressions the intended order of evaluation shall be made explicit with parentheses.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/compound-expressions
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/no-boolean-side-effects
|
||||
* @problem.severity warning
|
||||
* @tags correctness
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description The use of the preprocessor must be limited to inclusion of header files and simple macro definitions.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/preprocessor-use
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description The use of conditional compilation directives must be kept to a minimum -- e.g. for header guards only.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/preprocessor-use-ifdef
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Macros must expand to complete syntactic units -- "#define MY_IF if(" is not legal.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/preprocessor-use-partial
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Macros are not allowed to use complex preprocessor features like variable argument lists and token pasting.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/preprocessor-use-undisciplined
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Macros shall not be #define'd within a function or a block.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/macro-in-block
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description #undef shall not be used.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/use-of-undef
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/mismatched-ifdefs
|
||||
* @problem.severity warning
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Putting more than one statement on a single line hinders program understanding.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/multiple-stmts-per-line
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description There should be no more than one variable declaration per line.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/multiple-var-decls-per-line
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Function length should be limited to what can be printed on a single sheet of paper (60 lines). Number of parameters is limited to 6 or fewer.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/function-size-limits
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description The declaration of an object should contain no more than two levels of indirection.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/declaration-pointer-nesting
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Statements should contain no more than two levels of dereferencing per object.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/pointer-dereference-in-stmt
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Pointer dereference operations should not be hidden in macro definitions.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/hidden-pointer-dereference-macro
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description Pointer indirection may not be hidden by typedefs -- "typedef int* IntPtr;" is not allowed.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/hidden-pointer-indirection-typedef
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
* @description Non-constant pointers to functions should not be used.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/non-const-function-pointer
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @precision low
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/function-pointer-conversions
|
||||
* @problem.severity warning
|
||||
* @precision low
|
||||
* @tags correctness
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
* @description #include directives in a file shall only be preceded by other preprocessor directives or comments.
|
||||
* @kind problem
|
||||
* @id cpp/jpl-c/includes-first
|
||||
* @problem.severity warning
|
||||
* @problem.severity recommendation
|
||||
* @tags maintainability
|
||||
* readability
|
||||
* external/jpl
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
<queries language="cpp"/>
|
||||
@@ -3,7 +3,11 @@
|
||||
* @description Query to help investigate mysterious results with ReturnStackAllocatedObject
|
||||
* @kind table
|
||||
* @id cpp/points-to/debug
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
// This query is not suitable for production use and has been deprecated.
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.pointsto.PointsTo
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
* @description Query to force evaluation of staged points-to predicates
|
||||
* @kind table
|
||||
* @id cpp/points-to/prepared-staged-points-to
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
// This query is not suitable for production use and has been deprecated.
|
||||
|
||||
import semmle.code.cpp.pointsto.PointsTo
|
||||
|
||||
select count(int set, Element location | setlocations(set, unresolveElement(location))),
|
||||
|
||||
@@ -3,7 +3,11 @@
|
||||
* @description Count the number points-to sets with 0 or 1 incoming flow edges, and the total number of points-to sets
|
||||
* @kind table
|
||||
* @id cpp/points-to/stats
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
// This query is not suitable for production use and has been deprecated.
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.pointsto.PointsTo
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
* @name Taint test
|
||||
* @kind table
|
||||
* @id cpp/points-to/tainted-format-strings
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
// This query is not suitable for production use and has been deprecated.
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.pointsto.PointsTo
|
||||
import semmle.code.cpp.pointsto.CallGraph
|
||||
|
||||
@@ -34,7 +34,6 @@ private Type baseType(Type t) {
|
||||
)
|
||||
// Make sure that the type has a size and that it isn't ambiguous.
|
||||
and strictcount(result.getSize()) = 1
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,6 +97,7 @@ predicate defSourceType(SsaDefinition def, LocalScopeVariable v,
|
||||
| p = v and
|
||||
def.definedByParameter(p) and
|
||||
sourceType = p.getType().getUnspecifiedType() and
|
||||
strictcount(p.getType()) = 1 and
|
||||
isPointerType(sourceType) and
|
||||
sourceLoc = p.getLocation())
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ predicate defSourceType(SsaDefinition def, LocalScopeVariable v,
|
||||
| p = v and
|
||||
def.definedByParameter(p) and
|
||||
sourceType = p.getType().getUnspecifiedType() and
|
||||
strictcount(p.getType()) = 1 and
|
||||
isPointerType(sourceType) and
|
||||
sourceLoc = p.getLocation())
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ predicate defSourceType(SsaDefinition def, LocalScopeVariable v,
|
||||
| p = v and
|
||||
def.definedByParameter(p) and
|
||||
sourceType = p.getType().getUnspecifiedType() and
|
||||
strictcount(p.getType()) = 1 and
|
||||
isPointerType(sourceType) and
|
||||
sourceLoc = p.getLocation())
|
||||
}
|
||||
|
||||
5
cpp/ql/src/external/DuplicateBlock.ql
vendored
5
cpp/ql/src/external/DuplicateBlock.ql
vendored
@@ -4,6 +4,11 @@
|
||||
* @kind problem
|
||||
* @id cpp/duplicate-block
|
||||
* @problem.severity recommendation
|
||||
* @precision medium
|
||||
* @tags testability
|
||||
* maintainability
|
||||
* duplicate-code
|
||||
* non-attributable
|
||||
*/
|
||||
import CodeDuplication
|
||||
|
||||
|
||||
@@ -96,13 +96,19 @@ private predicate exprReleases(Expr e, Expr released, string kind) {
|
||||
) or exists(Function f, int arg |
|
||||
// `e` is a call to a function that releases one of it's parameters,
|
||||
// and `released` is the corresponding argument
|
||||
e.(FunctionCall).getTarget() = f and
|
||||
(
|
||||
e.(FunctionCall).getTarget() = f or
|
||||
e.(FunctionCall).getTarget().(MemberFunction).getAnOverridingFunction+() = f
|
||||
) and
|
||||
e.(FunctionCall).getArgument(arg) = released and
|
||||
exprReleases(_, exprOrDereference(f.getParameter(arg).getAnAccess()), kind)
|
||||
) or exists(Function f, ThisExpr innerThis |
|
||||
// `e` is a call to a method that releases `this`, and `released`
|
||||
// is the object that is called
|
||||
e.(FunctionCall).getTarget() = f and
|
||||
(
|
||||
e.(FunctionCall).getTarget() = f or
|
||||
e.(FunctionCall).getTarget().(MemberFunction).getAnOverridingFunction+() = f
|
||||
) and
|
||||
e.(FunctionCall).getQualifier() = exprOrDereference(released) and
|
||||
innerThis.getEnclosingFunction() = f and
|
||||
exprReleases(_, innerThis, kind)
|
||||
|
||||
@@ -19,7 +19,10 @@ predicate hasPragmaDifferentFile(File f) {
|
||||
exists (PreprocessorLine pl, string s |
|
||||
pl.getFile() = f and
|
||||
pl.getHead().splitAt(" ", 1) = s and /* Zero index is line number, one index is file reference */
|
||||
not ("\"" + f.getAbsolutePath() + "\"" = s))
|
||||
not ("\"" + f.getAbsolutePath() + "\"" = s) and
|
||||
not ("\"" + f.getRelativePath() + "\"" = s) and
|
||||
not ("\"" + f.getBaseName() + "\"" = s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -55,10 +55,18 @@ class Macro extends PreprocessorDirective, @ppd_define {
|
||||
}
|
||||
|
||||
/**
|
||||
* A macro access (macro expansion or other macro access).
|
||||
* A macro access. For example:
|
||||
* ```
|
||||
* #ifdef MACRO1 // this line contains a MacroAccess
|
||||
* int x = MACRO2; // this line contains a MacroAccess
|
||||
* #endif
|
||||
* ```
|
||||
*
|
||||
* See also `MacroInvocation`, which represents only macro accesses
|
||||
* that are expanded (such as in the second line of the example above).
|
||||
*/
|
||||
class MacroAccess extends Locatable, @macroinvocation {
|
||||
/** Gets the macro being invoked. */
|
||||
/** Gets the macro that is being accessed. */
|
||||
Macro getMacro() { macroinvocations(underlyingElement(this),unresolveElement(result),_,_) }
|
||||
|
||||
/**
|
||||
@@ -73,7 +81,7 @@ class MacroAccess extends Locatable, @macroinvocation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the location of this macro invocation. For a nested invocation, where
|
||||
* Gets the location of this macro access. For a nested access, where
|
||||
* `exists(this.getParentInvocation())`, this yields a location either inside
|
||||
* a `#define` directive or inside an argument to another macro.
|
||||
*/
|
||||
@@ -126,14 +134,22 @@ class MacroAccess extends Locatable, @macroinvocation {
|
||||
|
||||
override string toString() { result = this.getMacro().getHead() }
|
||||
|
||||
/** Gets the name of the invoked macro. */
|
||||
/** Gets the name of the accessed macro. */
|
||||
string getMacroName() {
|
||||
result = getMacro().getName()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A macro invocation (macro expansion).
|
||||
* A macro invocation (macro access that is expanded). For example:
|
||||
* ```
|
||||
* #ifdef MACRO1
|
||||
* int x = MACRO2; // this line contains a MacroInvocation
|
||||
* #endif
|
||||
* ```
|
||||
*
|
||||
* See also `MacroAccess`, which also represents macro accesses where the macro
|
||||
* is checked but not expanded (such as in the first line of the example above).
|
||||
*/
|
||||
class MacroInvocation extends MacroAccess {
|
||||
MacroInvocation() {
|
||||
@@ -174,7 +190,7 @@ class MacroInvocation extends MacroAccess {
|
||||
/**
|
||||
* Gets the top-level expression associated with this macro invocation,
|
||||
* if any. Note that this predicate will fail if the top-level expanded
|
||||
* element is a statement rather than an expression.
|
||||
* element is not an expression (for example if it is a statement).
|
||||
*/
|
||||
Expr getExpr() {
|
||||
result = getAnExpandedElement() and
|
||||
@@ -185,7 +201,7 @@ class MacroInvocation extends MacroAccess {
|
||||
/**
|
||||
* Gets the top-level statement associated with this macro invocation, if
|
||||
* any. Note that this predicate will fail if the top-level expanded
|
||||
* element is an expression rather than a statement.
|
||||
* element is not a statement (for example if it is an expression).
|
||||
*/
|
||||
Stmt getStmt() {
|
||||
result = getAnExpandedElement() and
|
||||
|
||||
@@ -34,11 +34,5 @@ private predicate readsEnvironment(Expr read, string sourceDescription) {
|
||||
read = call and
|
||||
call.getTarget().hasGlobalName(name) and
|
||||
(name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and
|
||||
sourceDescription = name) or
|
||||
exists(MessageExpr getObjectKey, MessageExpr getEnviron |
|
||||
read = getObjectKey and
|
||||
getObjectKey.getTarget().getQualifiedName().matches("NSDictionary%::-objectForKey:") and
|
||||
getObjectKey.getQualifier() = getEnviron and
|
||||
getEnviron.getTarget().getQualifiedName().matches("NSProcessInfo%:-environment") and
|
||||
sourceDescription = "NSProcessInfo")
|
||||
sourceDescription = name)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,23 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
|
||||
import Cached
|
||||
private cached module Cached {
|
||||
// The base case of `reachable` is factored out for performance. If it's
|
||||
// written in-line in `reachable`, the compiler inserts a `n instanceof
|
||||
// ControlFlowNode` check because the `not ... and not ...` case doesn't
|
||||
// otherwise bind `n`. The problem is that this check is inserted at the
|
||||
// outermost level of this predicate, so it covers all cases including the
|
||||
// recursive case. The optimizer doesn't eliminate the check even though it's
|
||||
// redundant, and having the check leads to needless extra computation and a
|
||||
// risk of bad join orders.
|
||||
private predicate reachableBaseCase(ControlFlowNode n) {
|
||||
exists(Function f | f.getEntryPoint() = n)
|
||||
or
|
||||
// Okay to use successors_extended directly here
|
||||
(not successors_extended(_,n) and not successors_extended(n,_))
|
||||
or
|
||||
n instanceof Handler
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the control-flow node `n` is reachable, meaning that either
|
||||
* it is an entry point, or there exists a path in the control-flow
|
||||
@@ -88,14 +105,9 @@ private cached module Cached {
|
||||
cached
|
||||
predicate reachable(ControlFlowNode n)
|
||||
{
|
||||
exists(Function f | f.getEntryPoint() = n)
|
||||
or
|
||||
// Okay to use successors_extended directly here
|
||||
(not successors_extended(_,n) and not successors_extended(n,_))
|
||||
reachableBaseCase(n)
|
||||
or
|
||||
reachable(n.getAPredecessor())
|
||||
or
|
||||
n instanceof Handler
|
||||
}
|
||||
|
||||
/** Holds if `condition` always evaluates to a nonzero value. */
|
||||
|
||||
@@ -28,6 +28,13 @@ predicate functionEntry(ControlFlowNode entry) {
|
||||
and not hasMultiScopeNode(function))
|
||||
}
|
||||
|
||||
/** Holds if `exit` is the exit node of a function. */
|
||||
predicate functionExit(ControlFlowNode exit) {
|
||||
exists (Function function |
|
||||
function = exit
|
||||
and not hasMultiScopeNode(function))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dest` is an immediate successor of `src` in the control-flow graph.
|
||||
*/
|
||||
@@ -35,12 +42,25 @@ private predicate nodeSucc(ControlFlowNode src, ControlFlowNode dest) {
|
||||
src.getASuccessor() = dest
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `pred` is an immediate predecessor of `src` in the control-flow graph.
|
||||
*/
|
||||
private predicate nodePred(ControlFlowNode src, ControlFlowNode pred) {
|
||||
src.getAPredecessor() = pred
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is an immediate dominator of `node` in the control-flow
|
||||
* graph.
|
||||
*/
|
||||
predicate iDominates(ControlFlowNode dominator, ControlFlowNode node) = idominance(functionEntry/1,nodeSucc/2)(_, dominator, node)
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow
|
||||
* graph.
|
||||
*/
|
||||
predicate iPostDominates(ControlFlowNode postDominator, ControlFlowNode node) = idominance(functionExit/1,nodePred/2)(_, postDominator, node)
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is a strict dominator of `node` in the control-flow
|
||||
* graph. Being strict means that `dominator != node`.
|
||||
@@ -49,6 +69,14 @@ predicate strictlyDominates(ControlFlowNode dominator, ControlFlowNode node) {
|
||||
iDominates+(dominator, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is a strict post-dominator of `node` in the control-flow
|
||||
* graph. Being strict means that `postDominator != node`.
|
||||
*/
|
||||
predicate strictlyPostDominates(ControlFlowNode postDominator, ControlFlowNode node) {
|
||||
iPostDominates+(postDominator, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is a dominator of `node` in the control-flow graph. This
|
||||
* is reflexive.
|
||||
@@ -57,6 +85,14 @@ predicate dominates(ControlFlowNode dominator, ControlFlowNode node) {
|
||||
strictlyDominates(dominator, node) or dominator = node
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is a post-dominator of `node` in the control-flow graph. This
|
||||
* is reflexive.
|
||||
*/
|
||||
predicate postDominates(ControlFlowNode postDominator, ControlFlowNode node) {
|
||||
strictlyPostDominates(postDominator, node) or postDominator = node
|
||||
}
|
||||
|
||||
/*
|
||||
* Dominance predicates for basic blocks.
|
||||
*/
|
||||
@@ -67,14 +103,42 @@ predicate dominates(ControlFlowNode dominator, ControlFlowNode node) {
|
||||
*/
|
||||
predicate bbIDominates(BasicBlock dom, BasicBlock node) = idominance(functionEntry/1, bb_successor/2)(_, dom, node)
|
||||
|
||||
/**
|
||||
* Holds if `pred` is a predecessor of `succ` in the control-flow graph of
|
||||
* basic blocks.
|
||||
*/
|
||||
private predicate bb_predecessor(BasicBlock succ, BasicBlock pred) {
|
||||
bb_successor(pred, succ)
|
||||
}
|
||||
|
||||
/** Holds if `exit` is an `ExitBasicBlock`. */
|
||||
private predicate bb_exit(ExitBasicBlock exit) {
|
||||
any()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is an immediate post-dominator of `node` in the control-flow
|
||||
* graph of basic blocks.
|
||||
*/
|
||||
predicate bbIPostDominates(BasicBlock pDom, BasicBlock node) = idominance(bb_exit/1, bb_predecessor/2)(_, pDom, node)
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is a strict dominator of `node` in the control-flow
|
||||
* graph of basic blocks. Being strict means that `dominator != node`.
|
||||
*/
|
||||
pragma[nomagic] // magic prevents fastTC
|
||||
predicate bbStrictlyDominates(BasicBlock dominator, BasicBlock node) {
|
||||
bbIDominates+(dominator, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is a strict post-dominator of `node` in the control-flow
|
||||
* graph of basic blocks. Being strict means that `postDominator != node`.
|
||||
*/
|
||||
pragma[nomagic] // magic prevents fastTC
|
||||
predicate bbStrictlyPostDominates(BasicBlock postDominator, BasicBlock node) {
|
||||
bbIPostDominates+(postDominator, node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `dominator` is a dominator of `node` in the control-flow graph of
|
||||
@@ -83,3 +147,11 @@ predicate bbStrictlyDominates(BasicBlock dominator, BasicBlock node) {
|
||||
predicate bbDominates(BasicBlock dominator, BasicBlock node) {
|
||||
bbStrictlyDominates(dominator, node) or dominator = node
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `postDominator` is a post-dominator of `node` in the control-flow graph of
|
||||
* basic blocks. This is reflexive.
|
||||
*/
|
||||
predicate bbPostDominates(BasicBlock postDominator, BasicBlock node) {
|
||||
bbStrictlyPostDominates(postDominator, node) or postDominator = node
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.IR
|
||||
|
||||
/**
|
||||
* Holds if `block` consists of an `UnreachedInstruction`.
|
||||
*
|
||||
* We avoiding reporting an unreached block as being controlled by a guard. The unreached block
|
||||
* has the AST for the `Function` itself, which tends to confuse mapping between the AST `BasicBlock`
|
||||
* and the `IRBlock`.
|
||||
*/
|
||||
private predicate isUnreachedBlock(IRBlock block) {
|
||||
block.getFirstInstruction() instanceof UnreachedInstruction
|
||||
}
|
||||
|
||||
/**
|
||||
* A Boolean condition in the AST that guards one or more basic blocks. This includes
|
||||
* operands of logical operators but not switch statements.
|
||||
@@ -215,7 +226,8 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(IRBlock irb |
|
||||
forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and
|
||||
irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled
|
||||
irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -301,6 +313,7 @@ class IRGuardCondition extends Instruction {
|
||||
* `&&` and `||`. See the detailed explanation on predicate `controls`.
|
||||
*/
|
||||
private predicate controlsBlock(IRBlock controlled, boolean testIsTrue) {
|
||||
not isUnreachedBlock(controlled) and
|
||||
exists(IRBlock thisblock
|
||||
| thisblock.getAnInstruction() = this
|
||||
| exists(IRBlock succ, ConditionalBranchInstruction branch
|
||||
|
||||
@@ -67,13 +67,28 @@ class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr {
|
||||
*/
|
||||
class ConditionalExpr extends Operation, @conditionalexpr {
|
||||
/** Gets the condition of this conditional expression. */
|
||||
Expr getCondition() { this.hasChild(result,0) }
|
||||
Expr getCondition() {
|
||||
expr_cond_guard(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/** Gets the 'then' expression of this conditional expression. */
|
||||
Expr getThen() { this.hasChild(result,1) }
|
||||
Expr getThen() {
|
||||
if this.isTwoOperand()
|
||||
then result = this.getCondition()
|
||||
else expr_cond_true(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/** Gets the 'else' expression of this conditional expression. */
|
||||
Expr getElse() { this.hasChild(result,2) }
|
||||
Expr getElse() {
|
||||
expr_cond_false(underlyingElement(this), unresolveElement(result))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this expression used the two operand form `guard ? : false`.
|
||||
*/
|
||||
predicate isTwoOperand() {
|
||||
expr_cond_two_operand(underlyingElement(this))
|
||||
}
|
||||
|
||||
override string getOperator() { result = "?" }
|
||||
|
||||
|
||||
@@ -3,7 +3,18 @@ import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
* sequence.
|
||||
*
|
||||
* This class does not contain any members that query the predecessor or successor edges of the
|
||||
* block. This allows different classes that extend `IRBlockBase` to expose different subsets of
|
||||
* edges (e.g. ignoring unreachable edges).
|
||||
*
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
final string toString() {
|
||||
result = getFirstInstruction(this).toString()
|
||||
}
|
||||
@@ -59,7 +70,14 @@ class IRBlock extends TIRBlock {
|
||||
final Function getFunction() {
|
||||
result = getFirstInstruction(this).getFunction()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block with additional information about its predecessor and successor edges. Each edge
|
||||
* corresponds to the control flow between the last instruction of one block and the first
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
final IRBlock getASuccessor() {
|
||||
blockSuccessor(this, result)
|
||||
}
|
||||
|
||||
@@ -25,15 +25,7 @@ cached private module Cached {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
UnreachedTag(OldInstruction oldInstruction, EdgeKind kind) {
|
||||
// We need an `Unreached` instruction for the destination of any edge whose predecessor
|
||||
// instruction is reachable, but whose successor block is not. This should occur only for
|
||||
// infeasible edges.
|
||||
exists(OldIR::Instruction succInstruction |
|
||||
succInstruction = oldInstruction.getSuccessor(kind) and
|
||||
not succInstruction instanceof OldInstruction
|
||||
)
|
||||
}
|
||||
UnreachedTag()
|
||||
|
||||
cached class InstructionTagType extends TInstructionTag {
|
||||
cached final string toString() {
|
||||
@@ -133,11 +125,12 @@ cached private module Cached {
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldInstruction oldInstruction, EdgeKind kind |
|
||||
oldInstruction.getFunction() = func and
|
||||
tag = UnreachedTag(oldInstruction, kind) and
|
||||
exists(OldInstruction oldInstruction |
|
||||
func = oldInstruction.getFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _) and
|
||||
tag = UnreachedTag() and
|
||||
opcode instanceof Opcode::Unreached and
|
||||
ast = oldInstruction.getSuccessor(kind).getAST() and
|
||||
ast = func and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
)
|
||||
@@ -213,7 +206,7 @@ cached private module Cached {
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,
|
||||
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
|
||||
hasPhiNode(vvar, phiBlock) and
|
||||
predBlock = phiBlock.getAPredecessor() and
|
||||
predBlock = phiBlock.getAFeasiblePredecessor() and
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
newPredecessorBlock = getNewBlock(predBlock) and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
@@ -266,13 +259,22 @@ cached private module Cached {
|
||||
result = getChiInstruction(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
|
||||
result.getTag() = UnreachedTag() and
|
||||
result.getFunction() = instruction.getFunction()
|
||||
)
|
||||
else (
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
) or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChiInstruction(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
) or
|
||||
result.getTag() = UnreachedTag(getOldInstruction(instruction), kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -380,7 +382,7 @@ cached private module Cached {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
variableLiveOnEntryToBlock(vvar, block.getASuccessor())
|
||||
variableLiveOnEntryToBlock(vvar, block.getAFeasibleSuccessor())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,7 +476,7 @@ cached private module Cached {
|
||||
useRank) or
|
||||
(
|
||||
definitionReachesEndOfBlock(vvar, defBlock, defRank,
|
||||
useBlock.getAPredecessor()) and
|
||||
useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
)
|
||||
@@ -518,9 +520,9 @@ cached private module CachedForDebugging {
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
|
||||
) or
|
||||
exists(OldInstruction oldInstr, EdgeKind kind |
|
||||
instr.getTag() = UnreachedTag(oldInstr, kind) and
|
||||
result = "Unreached(" + oldInstr.getUniqueId() + ":" + kind.toString() + ")"
|
||||
(
|
||||
instr.getTag() = UnreachedTag() and
|
||||
result = "Unreached"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,18 @@ import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
* sequence.
|
||||
*
|
||||
* This class does not contain any members that query the predecessor or successor edges of the
|
||||
* block. This allows different classes that extend `IRBlockBase` to expose different subsets of
|
||||
* edges (e.g. ignoring unreachable edges).
|
||||
*
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
final string toString() {
|
||||
result = getFirstInstruction(this).toString()
|
||||
}
|
||||
@@ -59,7 +70,14 @@ class IRBlock extends TIRBlock {
|
||||
final Function getFunction() {
|
||||
result = getFirstInstruction(this).getFunction()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block with additional information about its predecessor and successor edges. Each edge
|
||||
* corresponds to the control flow between the last instruction of one block and the first
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
final IRBlock getASuccessor() {
|
||||
blockSuccessor(this, result)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
private import DominanceInternal
|
||||
private import ReachableBlockInternal
|
||||
private import Dominance
|
||||
import IR
|
||||
|
||||
private class DominancePropertyProvider extends IRPropertyProvider {
|
||||
override string getBlockProperty(IRBlock block, string key) {
|
||||
exists(IRBlock dominator |
|
||||
blockImmediatelyDominates(dominator, block) and
|
||||
key = "ImmediateDominator" and
|
||||
result = "Block " + dominator.getDisplayIndex().toString()
|
||||
) or
|
||||
(
|
||||
key = "DominanceFrontier" and
|
||||
result = strictconcat(IRBlock frontierBlock |
|
||||
frontierBlock = getDominanceFrontier(block) |
|
||||
frontierBlock.getDisplayIndex().toString(), ", " order by frontierBlock.getDisplayIndex()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,9 @@ private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
private import ConstantAnalysis
|
||||
|
||||
predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
exists(ConditionalBranchInstruction instr, int conditionValue |
|
||||
instr = block.getLastInstruction() and
|
||||
conditionValue = getValue(getConstantValue(instr.getCondition())) and
|
||||
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
exists(int conditionValue |
|
||||
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
|
||||
if conditionValue = 0 then
|
||||
kind instanceof TrueEdge
|
||||
else
|
||||
@@ -14,29 +13,44 @@ predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
)
|
||||
}
|
||||
|
||||
IRBlock getAFeasiblePredecessor(IRBlock successor) {
|
||||
predicate isInfeasibleEdge(IRBlockBase block, EdgeKind kind) {
|
||||
isInfeasibleInstructionSuccessor(block.getLastInstruction(), kind)
|
||||
}
|
||||
|
||||
private IRBlock getAFeasiblePredecessorBlock(IRBlock successor) {
|
||||
exists(EdgeKind kind |
|
||||
result.getSuccessor(kind) = successor and
|
||||
not isInfeasibleEdge(result, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBlockReachable(IRBlock block) {
|
||||
private predicate isBlockReachable(IRBlock block) {
|
||||
exists(FunctionIR f |
|
||||
getAFeasiblePredecessor*(block) = f.getEntryBlock()
|
||||
getAFeasiblePredecessorBlock*(block) = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isInstructionReachable(Instruction instr) {
|
||||
isBlockReachable(instr.getBlock())
|
||||
}
|
||||
|
||||
class ReachableBlock extends IRBlock {
|
||||
/**
|
||||
* An IR block that is reachable from the entry block of the function, considering only feasible
|
||||
* edges.
|
||||
*/
|
||||
class ReachableBlock extends IRBlockBase {
|
||||
ReachableBlock() {
|
||||
isBlockReachable(this)
|
||||
}
|
||||
|
||||
final ReachableBlock getAFeasiblePredecessor() {
|
||||
result = getAFeasiblePredecessorBlock(this)
|
||||
}
|
||||
|
||||
final ReachableBlock getAFeasibleSuccessor() {
|
||||
this = getAFeasiblePredecessorBlock(result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock
|
||||
@@ -51,6 +65,6 @@ module Graph {
|
||||
}
|
||||
|
||||
predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) {
|
||||
succ = pred.getASuccessor()
|
||||
succ = pred.getAFeasibleSuccessor()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,18 @@ import Instruction
|
||||
import semmle.code.cpp.ir.implementation.EdgeKind
|
||||
private import Cached
|
||||
|
||||
class IRBlock extends TIRBlock {
|
||||
/**
|
||||
* A basic block in the IR. A basic block consists of a sequence of `Instructions` with the only
|
||||
* incoming edges at the beginning of the sequence and the only outgoing edges at the end of the
|
||||
* sequence.
|
||||
*
|
||||
* This class does not contain any members that query the predecessor or successor edges of the
|
||||
* block. This allows different classes that extend `IRBlockBase` to expose different subsets of
|
||||
* edges (e.g. ignoring unreachable edges).
|
||||
*
|
||||
* Most consumers should use the class `IRBlock`.
|
||||
*/
|
||||
class IRBlockBase extends TIRBlock {
|
||||
final string toString() {
|
||||
result = getFirstInstruction(this).toString()
|
||||
}
|
||||
@@ -59,7 +70,14 @@ class IRBlock extends TIRBlock {
|
||||
final Function getFunction() {
|
||||
result = getFirstInstruction(this).getFunction()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A basic block with additional information about its predecessor and successor edges. Each edge
|
||||
* corresponds to the control flow between the last instruction of one block and the first
|
||||
* instruction of another block.
|
||||
*/
|
||||
class IRBlock extends IRBlockBase {
|
||||
final IRBlock getASuccessor() {
|
||||
blockSuccessor(this, result)
|
||||
}
|
||||
|
||||
@@ -25,15 +25,7 @@ cached private module Cached {
|
||||
not oldInstruction instanceof OldIR::PhiInstruction and
|
||||
hasChiNode(_, oldInstruction)
|
||||
} or
|
||||
UnreachedTag(OldInstruction oldInstruction, EdgeKind kind) {
|
||||
// We need an `Unreached` instruction for the destination of any edge whose predecessor
|
||||
// instruction is reachable, but whose successor block is not. This should occur only for
|
||||
// infeasible edges.
|
||||
exists(OldIR::Instruction succInstruction |
|
||||
succInstruction = oldInstruction.getSuccessor(kind) and
|
||||
not succInstruction instanceof OldInstruction
|
||||
)
|
||||
}
|
||||
UnreachedTag()
|
||||
|
||||
cached class InstructionTagType extends TInstructionTag {
|
||||
cached final string toString() {
|
||||
@@ -133,11 +125,12 @@ cached private module Cached {
|
||||
resultType = vvar.getType() and
|
||||
isGLValue = false
|
||||
) or
|
||||
exists(OldInstruction oldInstruction, EdgeKind kind |
|
||||
oldInstruction.getFunction() = func and
|
||||
tag = UnreachedTag(oldInstruction, kind) and
|
||||
exists(OldInstruction oldInstruction |
|
||||
func = oldInstruction.getFunction() and
|
||||
Reachability::isInfeasibleInstructionSuccessor(oldInstruction, _) and
|
||||
tag = UnreachedTag() and
|
||||
opcode instanceof Opcode::Unreached and
|
||||
ast = oldInstruction.getSuccessor(kind).getAST() and
|
||||
ast = func and
|
||||
resultType instanceof VoidType and
|
||||
isGLValue = false
|
||||
)
|
||||
@@ -213,7 +206,7 @@ cached private module Cached {
|
||||
exists(Alias::VirtualVariable vvar, OldBlock phiBlock,
|
||||
OldBlock defBlock, int defRank, int defIndex, OldBlock predBlock |
|
||||
hasPhiNode(vvar, phiBlock) and
|
||||
predBlock = phiBlock.getAPredecessor() and
|
||||
predBlock = phiBlock.getAFeasiblePredecessor() and
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
newPredecessorBlock = getNewBlock(predBlock) and
|
||||
hasDefinitionAtRank(vvar, defBlock, defRank, defIndex) and
|
||||
@@ -266,13 +259,22 @@ cached private module Cached {
|
||||
result = getChiInstruction(getOldInstruction(instruction)) and
|
||||
kind instanceof GotoEdge
|
||||
else (
|
||||
result = getNewInstruction(getOldInstruction(instruction).getSuccessor(kind))
|
||||
or
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
if Reachability::isInfeasibleInstructionSuccessor(oldInstruction, kind) then (
|
||||
result.getTag() = UnreachedTag() and
|
||||
result.getFunction() = instruction.getFunction()
|
||||
)
|
||||
else (
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
)
|
||||
)
|
||||
) or
|
||||
exists(OldInstruction oldInstruction |
|
||||
instruction = getChiInstruction(oldInstruction) and
|
||||
result = getNewInstruction(oldInstruction.getSuccessor(kind))
|
||||
) or
|
||||
result.getTag() = UnreachedTag(getOldInstruction(instruction), kind)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -380,7 +382,7 @@ cached private module Cached {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate variableLiveOnExitFromBlock(Alias::VirtualVariable vvar, OldBlock block) {
|
||||
variableLiveOnEntryToBlock(vvar, block.getASuccessor())
|
||||
variableLiveOnEntryToBlock(vvar, block.getAFeasibleSuccessor())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,7 +476,7 @@ cached private module Cached {
|
||||
useRank) or
|
||||
(
|
||||
definitionReachesEndOfBlock(vvar, defBlock, defRank,
|
||||
useBlock.getAPredecessor()) and
|
||||
useBlock.getAFeasiblePredecessor()) and
|
||||
not definitionReachesUseWithinBlock(vvar, useBlock, _, useBlock, useRank)
|
||||
)
|
||||
)
|
||||
@@ -518,9 +520,9 @@ cached private module CachedForDebugging {
|
||||
instr.getTag() = PhiTag(vvar, phiBlock) and
|
||||
result = "Phi Block(" + phiBlock.getUniqueId() + "): " + vvar.getUniqueId()
|
||||
) or
|
||||
exists(OldInstruction oldInstr, EdgeKind kind |
|
||||
instr.getTag() = UnreachedTag(oldInstr, kind) and
|
||||
result = "Unreached(" + oldInstr.getUniqueId() + ":" + kind.toString() + ")"
|
||||
(
|
||||
instr.getTag() = UnreachedTag() and
|
||||
result = "Unreached"
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
private import DominanceInternal
|
||||
private import ReachableBlockInternal
|
||||
private import Dominance
|
||||
import IR
|
||||
|
||||
private class DominancePropertyProvider extends IRPropertyProvider {
|
||||
override string getBlockProperty(IRBlock block, string key) {
|
||||
exists(IRBlock dominator |
|
||||
blockImmediatelyDominates(dominator, block) and
|
||||
key = "ImmediateDominator" and
|
||||
result = "Block " + dominator.getDisplayIndex().toString()
|
||||
) or
|
||||
(
|
||||
key = "DominanceFrontier" and
|
||||
result = strictconcat(IRBlock frontierBlock |
|
||||
frontierBlock = getDominanceFrontier(block) |
|
||||
frontierBlock.getDisplayIndex().toString(), ", " order by frontierBlock.getDisplayIndex()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,9 @@ private import semmle.code.cpp.ir.internal.IntegerConstant
|
||||
private import IR
|
||||
private import ConstantAnalysis
|
||||
|
||||
predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
exists(ConditionalBranchInstruction instr, int conditionValue |
|
||||
instr = block.getLastInstruction() and
|
||||
conditionValue = getValue(getConstantValue(instr.getCondition())) and
|
||||
predicate isInfeasibleInstructionSuccessor(Instruction instr, EdgeKind kind) {
|
||||
exists(int conditionValue |
|
||||
conditionValue = getValue(getConstantValue(instr.(ConditionalBranchInstruction).getCondition())) and
|
||||
if conditionValue = 0 then
|
||||
kind instanceof TrueEdge
|
||||
else
|
||||
@@ -14,29 +13,44 @@ predicate isInfeasibleEdge(IRBlock block, EdgeKind kind) {
|
||||
)
|
||||
}
|
||||
|
||||
IRBlock getAFeasiblePredecessor(IRBlock successor) {
|
||||
predicate isInfeasibleEdge(IRBlockBase block, EdgeKind kind) {
|
||||
isInfeasibleInstructionSuccessor(block.getLastInstruction(), kind)
|
||||
}
|
||||
|
||||
private IRBlock getAFeasiblePredecessorBlock(IRBlock successor) {
|
||||
exists(EdgeKind kind |
|
||||
result.getSuccessor(kind) = successor and
|
||||
not isInfeasibleEdge(result, kind)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBlockReachable(IRBlock block) {
|
||||
private predicate isBlockReachable(IRBlock block) {
|
||||
exists(FunctionIR f |
|
||||
getAFeasiblePredecessor*(block) = f.getEntryBlock()
|
||||
getAFeasiblePredecessorBlock*(block) = f.getEntryBlock()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isInstructionReachable(Instruction instr) {
|
||||
isBlockReachable(instr.getBlock())
|
||||
}
|
||||
|
||||
class ReachableBlock extends IRBlock {
|
||||
/**
|
||||
* An IR block that is reachable from the entry block of the function, considering only feasible
|
||||
* edges.
|
||||
*/
|
||||
class ReachableBlock extends IRBlockBase {
|
||||
ReachableBlock() {
|
||||
isBlockReachable(this)
|
||||
}
|
||||
|
||||
final ReachableBlock getAFeasiblePredecessor() {
|
||||
result = getAFeasiblePredecessorBlock(this)
|
||||
}
|
||||
|
||||
final ReachableBlock getAFeasibleSuccessor() {
|
||||
this = getAFeasiblePredecessorBlock(result)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that is contained in a reachable block.
|
||||
*/
|
||||
class ReachableInstruction extends Instruction {
|
||||
ReachableInstruction() {
|
||||
this.getBlock() instanceof ReachableBlock
|
||||
@@ -51,6 +65,6 @@ module Graph {
|
||||
}
|
||||
|
||||
predicate blockSuccessor(ReachableBlock pred, ReachableBlock succ) {
|
||||
succ = pred.getASuccessor()
|
||||
succ = pred.getAFeasibleSuccessor()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,17 +159,6 @@ predicate shellCommandPreface(string cmd, string flag) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An array element. This supports multiple kinds of array syntax.
|
||||
*/
|
||||
private predicate arrayElement(Expr arrayLit, int idx, Expr element) {
|
||||
exists (ArrayLiteral lit | lit = arrayLit |
|
||||
lit.getElement(idx) = element)
|
||||
or exists (MessageExpr arrayWithObjects | arrayWithObjects = arrayLit |
|
||||
arrayWithObjects.getStaticTarget().getQualifiedName().matches("NSArray%::+arrayWithObjects:") and
|
||||
arrayWithObjects.getArgument(idx) = element)
|
||||
}
|
||||
|
||||
/**
|
||||
* A command that is used as a command, or component of a command,
|
||||
* that will be executed by a general-purpose command interpreter
|
||||
@@ -203,18 +192,5 @@ predicate shellCommand(Expr command, string callChain) {
|
||||
and arrayInitializer.getChild(idx) = command
|
||||
and shellCommandPreface(commandInterpreter.getValue(), flag.getValue())
|
||||
and idx > 1)
|
||||
|
||||
// Creation of NSTask
|
||||
or exists(
|
||||
MessageExpr launchedTaskCall, TextLiteral commandInterpreter,
|
||||
Expr arrayLiteral, TextLiteral flag
|
||||
|
|
||||
launchedTaskCall.getStaticTarget().getQualifiedName().matches("NSTask%::+launchedTaskWithLaunchPath:arguments:")
|
||||
and commandInterpreter = launchedTaskCall.getArgument(0)
|
||||
and arrayLiteral = launchedTaskCall.getArgument(1)
|
||||
and arrayElement(arrayLiteral, 0, flag)
|
||||
and arrayElement(arrayLiteral, 1, command)
|
||||
and shellCommandPreface(commandInterpreter.getValue(), flag.getValue())
|
||||
and callChain = "NSTask")
|
||||
}
|
||||
|
||||
|
||||
@@ -35,25 +35,3 @@ class SensitiveCall extends SensitiveExpr {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SensitivePropAccess extends SensitiveExpr {
|
||||
SensitivePropAccess() {
|
||||
exists (PropertyAccess acc, string name |
|
||||
acc = this and
|
||||
name = acc.getProperty().getName().toLowerCase() and
|
||||
name.matches(suspicious()) and
|
||||
not name.matches(nonSuspicious()))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A read from the value of a text widget.
|
||||
*/
|
||||
class SensitiveTextRead extends SensitiveExpr {
|
||||
SensitiveTextRead() {
|
||||
exists (PropertyAccess facc |
|
||||
facc = this and
|
||||
facc.getReceiver() instanceof SensitiveExpr and
|
||||
facc.getProperty().getName() = "text")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,21 +238,12 @@ predicate insideFunctionValueMoveTo(Element src, Element dest)
|
||||
returnArgument(c.getTarget(), sourceArg)
|
||||
and src = c.getArgument(sourceArg)
|
||||
and dest = c)
|
||||
or exists (MessageExpr send |
|
||||
methodReturningAnyArgument(send.getStaticTarget())
|
||||
and not send instanceof FormattingFunctionCall
|
||||
and src = send.getAnArgument()
|
||||
and dest = send)
|
||||
or exists(FormattingFunctionCall formattingSend, int arg, FormatLiteral format, string argFormat |
|
||||
dest = formattingSend
|
||||
and formattingSend.getArgument(arg) = src
|
||||
and format = formattingSend.getFormat()
|
||||
and format.getConversionChar(arg - formattingSend.getTarget().getNumberOfParameters()) = argFormat
|
||||
and (argFormat = "s" or argFormat = "S" or argFormat = "@"))
|
||||
or exists (ExprMessageExpr send |
|
||||
methodReturningReceiver(send.getStaticTarget())
|
||||
and src = send.getReceiver()
|
||||
and dest = send)
|
||||
// Expressions computed from tainted data are also tainted
|
||||
or (exists (FunctionCall call | dest = call and isPureFunction(call.getTarget().getName()) |
|
||||
call.getAnArgument() = src
|
||||
@@ -457,60 +448,6 @@ private predicate returnArgument(Function f, int sourceArg)
|
||||
or (f.hasGlobalName("gethostbyaddr") and sourceArg = 0)
|
||||
}
|
||||
|
||||
/** A method where if any argument is tainted, the return value should be, too */
|
||||
private predicate methodReturningAnyArgument(MemberFunction method) {
|
||||
method.getQualifiedName().matches("NS%Array%::+array%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-arrayBy%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-componentsJoinedByString:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-init%") or
|
||||
method.getQualifiedName().matches("NS%Data%::+dataWith%") or
|
||||
method.getQualifiedName().matches("NS%Data%::-initWith%") or
|
||||
method.getQualifiedName().matches("NS%String%::+pathWithComponents:") or
|
||||
method.getQualifiedName().matches("NS%String%::+stringWith%") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCString:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCStringNoCopy:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCharacters:length:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithCharactersNoCopy:length:freeWhenDone:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithFormat:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithFormat:arguments:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-initWithUTF8String:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByAppendingFormat:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByAppendingString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByPaddingToLength:withString:startingAtIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringByReplacing%") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringsByAppendingPaths:")
|
||||
}
|
||||
|
||||
/** A method where if the receiver is tainted, the return value should be, too */
|
||||
private predicate methodReturningReceiver(MemberFunction method) {
|
||||
method.getQualifiedName().matches("NS%Array%::-arrayBy%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-componentsJoinedByString:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-firstObject") or
|
||||
method.getQualifiedName().matches("NS%Array%::-lastObject") or
|
||||
method.getQualifiedName().matches("NS%Array%::-objectAt%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-pathsMatchingExtensions:") or
|
||||
method.getQualifiedName().matches("NS%Array%::-sortedArray%") or
|
||||
method.getQualifiedName().matches("NS%Array%::-subarrayWithRange:") or
|
||||
method.getQualifiedName().matches("NS%Data%::-bytes") or
|
||||
method.getQualifiedName().matches("NS%Data%::-subdataWithRange:") or
|
||||
method.getQualifiedName().matches("NS%String%::-capitalizedString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-componentsSeparatedByCharactersInSet:") or
|
||||
method.getQualifiedName().matches("NS%String%::-componentsSeparatedByString:") or
|
||||
method.getQualifiedName().matches("NS%String%::-cStringUsingEncoding:") or
|
||||
method.getQualifiedName().matches("NS%String%::-dataUsingEncoding:%") or
|
||||
method.getQualifiedName().matches("NS%String%::-lowercaseString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-pathComponents") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringBy%") or
|
||||
method.getQualifiedName().matches("NS%String%::-stringsByAppendingPaths:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringFromIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringToIndex:") or
|
||||
method.getQualifiedName().matches("NS%String%::-substringWithRange:") or
|
||||
method.getQualifiedName().matches("NS%String%::-uppercaseString%") or
|
||||
method.getQualifiedName().matches("NS%String%::-UTF8String")
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve potential target function(s) for `call`.
|
||||
*
|
||||
|
||||
@@ -1171,6 +1171,41 @@ expr_deallocator(
|
||||
int form: int ref
|
||||
);
|
||||
|
||||
/**
|
||||
* Holds if the `@conditionalexpr` is of the two operand form
|
||||
* `guard ? : false`.
|
||||
*/
|
||||
expr_cond_two_operand(
|
||||
unique int cond: @conditionalexpr ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The guard of `@conditionalexpr` `guard ? true : false`
|
||||
*/
|
||||
expr_cond_guard(
|
||||
unique int cond: @conditionalexpr ref,
|
||||
int guard: @expr ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The expression used when the guard of `@conditionalexpr`
|
||||
* `guard ? true : false` holds. For the two operand form
|
||||
* `guard ?: false` consider using `expr_cond_guard` instead.
|
||||
*/
|
||||
expr_cond_true(
|
||||
unique int cond: @conditionalexpr ref,
|
||||
int true: @expr ref
|
||||
);
|
||||
|
||||
/**
|
||||
* The expression used when the guard of `@conditionalexpr`
|
||||
* `guard ? true : false` does not hold.
|
||||
*/
|
||||
expr_cond_false(
|
||||
unique int cond: @conditionalexpr ref,
|
||||
int false: @expr ref
|
||||
);
|
||||
|
||||
// the second field is a string representation of the value
|
||||
// the third field is the actual text in the source or the same as the second field
|
||||
values(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -886,6 +886,9 @@ VacuousDestructorCall.cpp:
|
||||
# 4| 0: (vacuous destructor call)
|
||||
# 4| Type = void
|
||||
# 4| ValueCategory = prvalue
|
||||
# 4| 0: y
|
||||
# 4| Type = int *
|
||||
# 4| ValueCategory = prvalue(load)
|
||||
# 5| 2: return ...
|
||||
# 7| Vacuous(int) -> void
|
||||
# 7| params:
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
| ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
| ODASA-5692.cpp:14:15:16:3 | { ... } |
|
||||
| ODASA-5692.cpp:14:15:16:3 | { ... } |
|
||||
| exceptions.cpp:44:19:46:5 | { ... } |
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
| ODASA-5692.cpp:11:10:11:14 | p#0 | ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
| ODASA-5692.cpp:11:10:11:14 | p#0 | ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
| exceptions.cpp:28:20:28:20 | e | exceptions.cpp:28:23:30:9 | { ... } |
|
||||
| exceptions.cpp:32:16:32:16 | e | exceptions.cpp:32:19:34:5 | { ... } |
|
||||
| exceptions.cpp:35:16:35:16 | e | exceptions.cpp:35:19:37:5 | { ... } |
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getBlock | ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getBlock | ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getParameter | ODASA-5692.cpp:11:10:11:14 | p#0 |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getParameter | ODASA-5692.cpp:11:10:11:14 | p#0 |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getTryStmt | ODASA-5692.cpp:9:3:10:3 | try { ... } |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getTryStmt | ODASA-5692.cpp:9:3:10:3 | try { ... } |
|
||||
| ODASA-5692.cpp:11:18:13:3 | <handler> | getTryStmt.getACatchClause() | ODASA-5692.cpp:11:18:13:3 | { ... } |
|
||||
|
||||
@@ -137,7 +137,6 @@ astGuardsControl
|
||||
| test.c:26:11:26:15 | ... > ... | false | 42 | 44 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 45 | 45 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 45 | 47 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 48 | 55 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 51 | 53 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 56 | 58 |
|
||||
| test.c:26:11:26:15 | ... > ... | false | 58 | 58 |
|
||||
@@ -150,7 +149,6 @@ astGuardsControl
|
||||
| test.c:34:16:34:21 | ... < ... | false | 42 | 44 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 45 | 45 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 45 | 47 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 48 | 55 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 51 | 53 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 56 | 58 |
|
||||
| test.c:34:16:34:21 | ... < ... | false | 58 | 58 |
|
||||
@@ -161,14 +159,11 @@ astGuardsControl
|
||||
| test.c:42:16:42:21 | ... < ... | true | 42 | 44 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 45 | 45 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 48 | 55 |
|
||||
| test.c:42:16:42:21 | ... < ... | true | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | false | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 45 | 47 |
|
||||
| test.c:44:12:44:16 | ... > ... | true | 48 | 55 |
|
||||
| test.c:45:16:45:20 | ... > ... | false | 48 | 55 |
|
||||
| test.c:45:16:45:20 | ... > ... | true | 45 | 47 |
|
||||
| test.c:58:9:58:14 | ... == ... | false | 58 | 58 |
|
||||
| test.c:58:9:58:14 | ... == ... | false | 62 | 62 |
|
||||
@@ -200,11 +195,13 @@ astGuardsControl
|
||||
| test.c:109:19:109:23 | ... < ... | false | 113 | 113 |
|
||||
| test.c:126:7:126:7 | 1 | true | 126 | 126 |
|
||||
| test.c:126:7:126:7 | 1 | true | 126 | 128 |
|
||||
| test.c:126:7:126:7 | 1 | true | 131 | 131 |
|
||||
| test.c:126:7:126:7 | 1 | true | 131 | 132 |
|
||||
| test.c:126:7:126:7 | 1 | true | 134 | 123 |
|
||||
| test.c:126:7:126:28 | ... && ... | true | 126 | 128 |
|
||||
| test.c:126:12:126:26 | call to test3_condition | true | 126 | 128 |
|
||||
| test.c:131:7:131:7 | b | true | 131 | 132 |
|
||||
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
|
||||
| test.c:137:7:137:7 | 0 | true | 137 | 138 |
|
||||
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
|
||||
| test.c:146:8:146:8 | x | false | 146 | 147 |
|
||||
| test.c:152:10:152:10 | x | true | 151 | 152 |
|
||||
@@ -241,7 +238,6 @@ astGuardsEnsure
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 42 | 44 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 45 | 45 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 45 | 47 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 48 | 55 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 51 | 53 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 56 | 58 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:11:26:11 | x | < | test.c:26:15:26:15 | 0 | 1 | 58 | 58 |
|
||||
@@ -257,7 +253,6 @@ astGuardsEnsure
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 42 | 44 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 45 | 45 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 45 | 47 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 48 | 55 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 51 | 53 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 56 | 58 |
|
||||
| test.c:26:11:26:15 | ... > ... | test.c:26:15:26:15 | 0 | >= | test.c:26:11:26:11 | x | 0 | 58 | 58 |
|
||||
@@ -270,7 +265,6 @@ astGuardsEnsure
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 42 | 44 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 45 | 45 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 45 | 47 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 48 | 55 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 51 | 53 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 56 | 58 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:16:34:16 | j | >= | test.c:34:20:34:21 | 10 | 0 | 58 | 58 |
|
||||
@@ -282,7 +276,6 @@ astGuardsEnsure
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 42 | 44 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 45 | 45 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 45 | 47 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 48 | 55 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 51 | 53 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 56 | 58 |
|
||||
| test.c:34:16:34:21 | ... < ... | test.c:34:20:34:21 | 10 | < | test.c:34:16:34:16 | j | 1 | 58 | 58 |
|
||||
@@ -293,28 +286,22 @@ astGuardsEnsure
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 42 | 44 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 48 | 55 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:16:42:16 | j | < | test.c:42:20:42:21 | 10 | 0 | 51 | 53 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 42 | 42 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 42 | 44 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 45 | 47 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 48 | 55 |
|
||||
| test.c:42:16:42:21 | ... < ... | test.c:42:20:42:21 | 10 | >= | test.c:42:16:42:16 | j | 1 | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | test.c:44:16:44:16 | 0 | 1 | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | < | test.c:44:16:44:16 | 0 | 1 | 51 | 53 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 45 | 47 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:12:44:12 | z | >= | test.c:44:16:44:16 | 0 | 1 | 48 | 55 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 45 | 47 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | < | test.c:44:12:44:12 | z | 0 | 48 | 55 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | >= | test.c:44:12:44:12 | z | 0 | 42 | 42 |
|
||||
| test.c:44:12:44:16 | ... > ... | test.c:44:16:44:16 | 0 | >= | test.c:44:12:44:12 | z | 0 | 51 | 53 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | < | test.c:45:20:45:20 | 0 | 1 | 48 | 55 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:16:45:16 | y | >= | test.c:45:20:45:20 | 0 | 1 | 45 | 47 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:20:45:20 | 0 | < | test.c:45:16:45:16 | y | 0 | 45 | 47 |
|
||||
| test.c:45:16:45:20 | ... > ... | test.c:45:20:45:20 | 0 | >= | test.c:45:16:45:16 | y | 0 | 48 | 55 |
|
||||
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | test.c:58:14:58:14 | 0 | 0 | 58 | 58 |
|
||||
| test.c:58:9:58:14 | ... == ... | test.c:58:9:58:9 | x | != | test.c:58:14:58:14 | 0 | 0 | 62 | 62 |
|
||||
| test.c:58:9:58:14 | ... == ... | test.c:58:14:58:14 | 0 | != | test.c:58:9:58:9 | x | 0 | 58 | 58 |
|
||||
@@ -501,7 +488,6 @@ irGuardsControl
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 43 | 43 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 45 | 45 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 46 | 46 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 49 | 49 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 52 | 52 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 56 | 56 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | false | 58 | 58 |
|
||||
@@ -514,7 +500,6 @@ irGuardsControl
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 43 | 43 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 45 | 45 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 46 | 46 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 49 | 49 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 52 | 52 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 56 | 56 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | false | 58 | 58 |
|
||||
@@ -524,13 +509,10 @@ irGuardsControl
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 46 | 46 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 49 | 49 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | true | 52 | 52 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | false | 52 | 52 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 45 | 45 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 46 | 46 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | true | 49 | 49 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | false | 49 | 49 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | true | 46 | 46 |
|
||||
| test.c:58:9:58:14 | CompareEQ: ... == ... | false | 58 | 58 |
|
||||
| test.c:58:9:58:14 | CompareEQ: ... == ... | false | 62 | 62 |
|
||||
@@ -560,10 +542,12 @@ irGuardsControl
|
||||
| test.c:109:19:109:23 | CompareLT: ... < ... | false | 113 | 113 |
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 126 | 126 |
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 127 | 127 |
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 131 | 131 |
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 132 | 132 |
|
||||
| test.c:126:7:126:7 | Constant: 1 | true | 134 | 134 |
|
||||
| test.c:126:12:126:26 | Call: call to test3_condition | true | 127 | 127 |
|
||||
| test.c:131:7:131:7 | Load: b | true | 132 | 132 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | false | 142 | 142 |
|
||||
| test.c:137:7:137:7 | Constant: 0 | true | 138 | 138 |
|
||||
| test.c:146:8:146:8 | Load: x | false | 147 | 147 |
|
||||
| test.c:152:10:152:10 | Load: x | true | 152 | 152 |
|
||||
| test.c:152:15:152:15 | Load: y | true | 152 | 152 |
|
||||
@@ -593,7 +577,6 @@ irGuardsEnsure
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 43 | 43 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 45 | 45 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 46 | 46 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 49 | 49 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 52 | 52 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 56 | 56 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:11:26:11 | Load: x | < | test.c:26:15:26:15 | Constant: 0 | 1 | 58 | 58 |
|
||||
@@ -610,7 +593,6 @@ irGuardsEnsure
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 43 | 43 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 45 | 45 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 46 | 46 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 49 | 49 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 52 | 52 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 56 | 56 |
|
||||
| test.c:26:11:26:15 | CompareGT: ... > ... | test.c:26:15:26:15 | Constant: 0 | >= | test.c:26:11:26:11 | Load: x | 0 | 58 | 58 |
|
||||
@@ -623,7 +605,6 @@ irGuardsEnsure
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 43 | 43 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 45 | 45 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 46 | 46 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 49 | 49 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 52 | 52 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 56 | 56 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:16:34:16 | Load: j | >= | test.c:34:20:34:21 | Constant: 10 | 0 | 58 | 58 |
|
||||
@@ -635,7 +616,6 @@ irGuardsEnsure
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 43 | 43 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 45 | 45 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 46 | 46 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 49 | 49 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 52 | 52 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 56 | 56 |
|
||||
| test.c:34:16:34:21 | CompareLT: ... < ... | test.c:34:20:34:21 | Constant: 10 | < | test.c:34:16:34:16 | Load: j | 1 | 58 | 58 |
|
||||
@@ -645,25 +625,19 @@ irGuardsEnsure
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 46 | 46 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 49 | 49 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:16:42:16 | Load: j | < | test.c:42:20:42:21 | Constant: 10 | 0 | 52 | 52 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 43 | 43 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 45 | 45 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 46 | 46 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 49 | 49 |
|
||||
| test.c:42:16:42:21 | CompareLT: ... < ... | test.c:42:20:42:21 | Constant: 10 | >= | test.c:42:16:42:16 | Load: j | 1 | 52 | 52 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | < | test.c:44:16:44:16 | Constant: 0 | 1 | 52 | 52 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 46 | 46 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:12:44:12 | Load: z | >= | test.c:44:16:44:16 | Constant: 0 | 1 | 49 | 49 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 45 | 45 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 46 | 46 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | < | test.c:44:12:44:12 | Load: z | 0 | 49 | 49 |
|
||||
| test.c:44:12:44:16 | CompareGT: ... > ... | test.c:44:16:44:16 | Constant: 0 | >= | test.c:44:12:44:12 | Load: z | 0 | 52 | 52 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:16:45:16 | Load: y | < | test.c:45:20:45:20 | Constant: (long)... | 1 | 49 | 49 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:16:45:16 | Load: y | >= | test.c:45:20:45:20 | Constant: (long)... | 1 | 46 | 46 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:20:45:20 | Constant: (long)... | < | test.c:45:16:45:16 | Load: y | 0 | 46 | 46 |
|
||||
| test.c:45:16:45:20 | CompareGT: ... > ... | test.c:45:20:45:20 | Constant: (long)... | >= | test.c:45:16:45:16 | Load: y | 0 | 49 | 49 |
|
||||
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:9:58:9 | Load: x | != | test.c:58:14:58:14 | Constant: 0 | 0 | 58 | 58 |
|
||||
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:9:58:9 | Load: x | != | test.c:58:14:58:14 | Constant: 0 | 0 | 62 | 62 |
|
||||
| test.c:58:9:58:14 | CompareEQ: ... == ... | test.c:58:14:58:14 | Constant: 0 | != | test.c:58:9:58:9 | Load: x | 0 | 58 | 58 |
|
||||
|
||||
@@ -140,7 +140,6 @@
|
||||
| test | f_do_while | 34 | 8 | test.c:34:1:34:1 | return ... | f_do_while |
|
||||
| test | f_if_quest2 | 14 | 1 | test.c:14:32:18:1 | { ... } | if (...) ... |
|
||||
| test | f_if_quest2 | 14 | 12 | test.c:14:6:14:16 | f_if_quest2 | <none> |
|
||||
| test | f_if_quest2 | 15 | 1 | test.c:15:9:15:9 | x | <none> |
|
||||
| test | f_if_quest2 | 15 | 2 | test.c:15:5:17:5 | if (...) ... | ... ? ... : ... |
|
||||
| test | f_if_quest2 | 15 | 3 | test.c:15:9:15:14 | ... ? ... : ... | x |
|
||||
| test | f_if_quest2 | 15 | 4 | test.c:15:9:15:9 | x | <false> y |
|
||||
|
||||
@@ -47,7 +47,7 @@ int lambdas(int captured) {
|
||||
auto f1 = [&] { captured++; }; // capture has location "file://:0:0:0:0"
|
||||
f1();
|
||||
auto f2 = [&captured] { captured++; };
|
||||
f1();
|
||||
f2();
|
||||
return captured;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
| addressOf.cpp:31:23:31:23 | i | addressOf.cpp:38:18:38:30 | ... + ... | addressOf.cpp:40:15:40:15 | i |
|
||||
| addressOf.cpp:40:8:40:11 | iref | addressOf.cpp:40:15:40:15 | i | addressOf.cpp:42:19:42:22 | iref |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:48:3:48:4 | f1 |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:47:13:47:31 | [...](...){...} | addressOf.cpp:50:3:50:4 | f1 |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:49:13:49:39 | [...](...){...} | addressOf.cpp:50:3:50:4 | f2 |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:56:13:56:28 | {...} | addressOf.cpp:57:19:57:19 | a |
|
||||
| addressOf.cpp:56:7:56:7 | a | addressOf.cpp:57:18:57:45 | ... + ... | addressOf.cpp:58:18:58:18 | a |
|
||||
| indirect_use.cpp:20:10:20:10 | p | indirect_use.cpp:20:14:20:15 | ip | indirect_use.cpp:21:17:21:17 | p |
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| addressOf.cpp:42:19:42:22 | iref | non-const address |
|
||||
| addressOf.cpp:48:3:48:4 | f1 | |
|
||||
| addressOf.cpp:49:15:49:22 | captured | non-const address |
|
||||
| addressOf.cpp:50:3:50:4 | f1 | |
|
||||
| addressOf.cpp:50:3:50:4 | f2 | |
|
||||
| addressOf.cpp:51:10:51:17 | captured | |
|
||||
| addressOf.cpp:56:16:56:16 | i | |
|
||||
| addressOf.cpp:56:19:56:19 | i | |
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
| addressOf.cpp:46:17:46:24 | captured | addressOf.cpp:51:10:51:17 | captured |
|
||||
| addressOf.cpp:46:17:46:24 | captured | file://:0:0:0:0 | captured |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:48:3:48:4 | f1 |
|
||||
| addressOf.cpp:47:8:47:9 | f1 | addressOf.cpp:50:3:50:4 | f1 |
|
||||
| addressOf.cpp:49:8:49:9 | f2 | addressOf.cpp:50:3:50:4 | f2 |
|
||||
| addressOf.cpp:55:17:55:17 | i | addressOf.cpp:56:16:56:16 | i |
|
||||
| addressOf.cpp:55:17:55:17 | i | addressOf.cpp:56:19:56:19 | i |
|
||||
| addressOf.cpp:55:17:55:17 | i | addressOf.cpp:56:24:56:24 | i |
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user