Compare commits

..

415 Commits

Author SHA1 Message Date
Max Schaefer
aa6b89dc34 Merge pull request #723 from Semmle/qlucie/master
Master-to-next merge
2019-01-07 07:59:54 +00:00
Pavel Avgustinov
42cf76027a Merge branch 'cs/assembly-labels' of https://github.com/calumgrant/ql into HEAD 2019-01-04 18:23:49 +00:00
calum
651d207d0d C#: Fix assembly labels. 2019-01-04 16:19:43 +00:00
Max Schaefer
b4f400fb23 Merge remote-tracking branch 'upstream/next' into qlucie/master 2019-01-04 10:35:57 +00:00
semmle-qlci
6b27dcabc5 Merge pull request #704 from asger-semmle/ts-binary-exprs
Approved by esben-semmle
2019-01-04 08:37:41 +00:00
Jonas Jensen
79e246f961 Merge pull request #722 from geoffw0/doc-macroinv
CPP: Improve qldoc for MacroAccess and MacroInvocation.
2019-01-04 08:40:37 +01:00
Jonas Jensen
8b06b311a0 Merge pull request #668 from ian-semmle/condexpr
C++: Follow changes in how conditional expressions are represented in the database
2019-01-04 07:20:49 +01:00
Ian Lynagh
187fdf67b0 C++: Rename twoOperand to isTwoOperand 2019-01-03 21:09:49 +00:00
Ian Lynagh
98e8858dc6 C++: Accept test changes 2019-01-03 21:09:49 +00:00
Ian Lynagh
283eb51db8 C++: Update stats after adding expr_cond* tables 2019-01-03 21:09:49 +00:00
Ian Lynagh
dc3d87f2fc C++: Add tables for ConditionalExprs 2019-01-03 21:09:49 +00:00
yh-semmle
0e0ff565d5 Merge pull request #686 from aschackmull/java/rm-metrics-queries-xml
Java: Remove `Metrics/queries.xml`
2019-01-03 13:36:17 -05:00
yh-semmle
2d151f71cf Merge pull request #701 from aschackmull/java/override-annot
Java: Add missing override annotations.
2019-01-03 13:34:27 -05:00
semmle-qlci
c0868bcb9e Merge pull request #708 from hvitved/csharp/ssa-read-splitting
Approved by calumgrant
2019-01-03 17:59:55 +00:00
Tom Hvitved
54520003f8 Merge pull request #590 from calumgrant/cs/metadata-handles2
C#: Extract the metadata handle
2019-01-03 18:49:24 +01:00
semmle-qlci
8174fb51ae Merge pull request #705 from asger-semmle/loop-index-concurrent-modification
Approved by mc-semmle, xiemaisi
2019-01-03 17:06:12 +00:00
semmle-qlci
6b459de95f Merge pull request #717 from xiemaisi/js/fix-incorrect-suffix-check-performance
Approved by asger-semmle
2019-01-03 17:04:10 +00:00
semmle-qlci
6c768263d2 Merge pull request #716 from xiemaisi/js/cosmetics
Approved by esben-semmle
2019-01-03 16:11:50 +00:00
semmle-qlci
9b8bf96a6f Merge pull request #718 from xiemaisi/js/ambiguous-id-attr-alert-loc
Approved by asger-semmle
2019-01-03 16:10:57 +00:00
Geoffrey White
114740c148 Merge pull request #721 from jbj/reachable-factor-base-case
C++: Factor out `reachable` base case
2019-01-03 15:56:10 +00:00
Geoffrey White
787febae6e CPP: Improve qldoc for MacroAccess and MacroInvocation. 2019-01-03 15:16:47 +00:00
Asger F
f24313a215 JS: address doc review 2019-01-03 10:49:36 +00:00
Jonas Jensen
b17fb86961 C++: Factor out reachable base case 2019-01-03 11:20:18 +01:00
Max Schaefer
0a2df6c00d JavaScript: Highlight id attribute (not entire element) in AmbiguousIdAttribute. 2019-01-02 11:44:02 +00:00
Asger F
bc59e65222 JS: update suite file 2019-01-02 11:42:47 +00:00
Asger F
9f22da4557 JS: rename query to "Loop iteration skipped due to shifting" 2019-01-02 11:34:06 +00:00
Asger F
8c3b44a525 JS: address comments 2019-01-02 11:12:52 +00:00
Max Schaefer
a9844b2eda JavaScript: Fix performance regression in IncorrectSuffixCheck. 2019-01-02 10:23:16 +00:00
Tom Hvitved
4348de3120 Merge pull request #714 from calumgrant/cs/event-accessors
C#: Fix extraction error when Event accessors are ordinary methods
2019-01-02 10:25:15 +01:00
Tom Hvitved
2427f0ada9 C#: Remove redundant cast 2019-01-02 10:09:24 +01:00
Tom Hvitved
5879e58741 C#: Account for CFG splitting in AssignableDefinition::getAFirstRead() and AssignableRead::getANextRead() 2019-01-02 09:50:13 +01:00
Tom Hvitved
f06a20f666 C#: Add SSA tests with CFG splitting 2019-01-02 09:48:04 +01:00
calum
0fe0544769 C#: Fix extraction error when Event accessors are ordinary methods. 2018-12-31 14:20:47 +00:00
calum
6267946768 C#: Revert breaking change 2018-12-21 14:39:01 +00:00
calumgrant
1b11abfec7 Merge pull request #709 from hvitved/csharp/autoformat/tests
C#: Autoformat QL tests
2018-12-21 11:12:31 +00:00
Tom Hvitved
5478155155 Merge pull request #615 from calumgrant/cs/extractor-caching
C# extractor: Improve performance by changing the caching
2018-12-21 09:36:43 +01:00
Jonas Jensen
d566141273 Merge pull request #694 from dave-bartolomeo/dave/BetterUnreached
C++: Remove infeasible edges to reachable blocks
2018-12-21 07:36:51 +00:00
calum
d73b28efe4 C#: Address review comments.
Add more tests for duplicated entities, and fix some duplicated entities.
    Update the TupleTypes output - some extraneous results gone so it's probably better.
2018-12-20 20:23:12 +00:00
Tom Hvitved
af38a2b9c5 Merge branch 'master' into csharp/autoformat/tests 2018-12-20 20:59:10 +01:00
Dave Bartolomeo
a7cb2d6d7c C++: Ignore Unreached blocks in IR Guards 2018-12-20 11:57:25 -08:00
calumgrant
a6003533a4 Merge pull request #692 from hvitved/csharp/maybe-null-as-expression
C#: Consider `as` expressions as maybe-`null` in `cs/dereferenced-value-may-be-null`
2018-12-20 18:49:33 +00:00
calumgrant
7dd263b413 Merge pull request #689 from hvitved/csharp/remove-get-url
C#: Remove `getUrl()` predicates
2018-12-20 18:49:15 +00:00
calum
f5cfd93d8d C#: Use pattern matching. 2018-12-20 14:38:49 +00:00
Tom Hvitved
33fcbc958d C#: Consider as expressions as maybe-null in cs/dereferenced-value-may-be-null 2018-12-20 14:54:48 +01:00
Tom Hvitved
ccda1c8d3d C#: Add nullness test using an as expression 2018-12-20 14:54:48 +01:00
Tom Hvitved
c66f67dfac C#: Address review comment 2018-12-20 14:49:56 +01:00
calum
d687dd9deb C#: Address review comments. Replace GetHashValue() with MetadataTokens.GetToken().
C#: Make path IDs consistent.
2018-12-20 13:02:25 +00:00
calumgrant
1710f8db7c Merge pull request #661 from hvitved/csharp/maybe-null-path-query
C#: Make `cs/dereferenced-value-may-be-null` a path query
2018-12-20 12:30:07 +00:00
Tom Hvitved
231465143d C#: Autoformat QL tests 2018-12-20 10:19:59 +01:00
Tom Hvitved
546d750045 C#: Reintroduce getURL()
It turns out that we still need `getURL()` to account for cases where there is no
`getLocation()`. Not having `getURL()` for entities without a `getLocation()` results
in a `file://0:0:0:0` URL, which is not rendered in QL4E, unlike a `""` URL.
2018-12-19 20:47:33 +01:00
Tom Hvitved
b2500a0c26 Merge branch 'master' into csharp/maybe-null-path-query 2018-12-19 20:22:19 +01:00
semmle-qlci
83ccddff7a Merge pull request #707 from hvitved/csharp/bounded-fast-tc
Approved by calumgrant
2018-12-19 19:20:42 +00:00
calum
efe2fb502e C#: Convert libraries to use matchesHandle instead of getLabel. 2018-12-19 15:22:53 +00:00
calum
2acde22f43 C#: Add QL and tests for handles. 2018-12-19 15:22:53 +00:00
calum
0ee209e6a4 C#: Update db stats. 2018-12-19 15:22:53 +00:00
calum
fb8895bdc7 C#: Extract metadata handle information. 2018-12-19 15:22:53 +00:00
Esben Sparre Andreasen
c57f8a6d6e Merge pull request #691 from asger-semmle/sendfile-root
JS: Recognize 'root' option in Express res.sendFile
2018-12-19 16:06:15 +01:00
semmle-qlci
495a1fcf3b Merge pull request #698 from asger-semmle/remove-cookie-as-source
Approved by esben-semmle
2018-12-19 15:05:44 +00:00
semmle-qlci
b11b714152 Merge pull request #696 from esben-semmle/js/host-request-forgery
Approved by asger-semmle
2018-12-19 15:04:08 +00:00
Tom Hvitved
10627738d0 C#: Introduce Ssa::Definition::getElement() and AssignableDefinition::getElement() 2018-12-19 14:56:56 +01:00
calumgrant
e15481a622 Merge pull request #702 from hvitved/csharp/remove-deprecated
C#: Remove deprecated predicates
2018-12-19 12:10:49 +00:00
Asger F
ce18aca62b JS: update expected output 2018-12-19 11:30:46 +00:00
Asger F
60ae3e58b8 JS: update change note 2018-12-19 11:26:37 +00:00
Asger F
78334af354 JS: remove cookie source; rely on persistent flow steps instead 2018-12-19 11:23:51 +00:00
calum
6a54a6d3e5 C#: Fix changed unit tests. 2018-12-19 11:03:05 +00:00
Asger F
9440aab3d0 TS: add change note 2018-12-19 10:42:02 +00:00
calum
93ce34ad58 C#: Add a new object->entity cache. 2018-12-19 10:40:07 +00:00
calum
88734f1f8a C#: Fix label conflicts.
C#: Remove unnecessary code from Property.
2018-12-19 10:40:07 +00:00
calum
a7cdf528dd C#: Improve performance by mapping directly from entities to labels. 2018-12-19 10:40:06 +00:00
Asger F
a91599e7fd TS: bump extractor version string 2018-12-19 10:37:27 +00:00
Tom Hvitved
e5cbac5c13 C#: Replace a use of boundedFastTC with fastTC 2018-12-19 11:37:22 +01:00
Asger F
f9da1dc03e JS: add change note 2018-12-19 10:25:49 +00:00
Asger F
0e40717358 JS: recognize res.sendfile root option 2018-12-19 10:25:15 +00:00
Asger F
f84301e476 JS: add tests with res.sendFile root option 2018-12-19 10:25:15 +00:00
Asger F
f9d7f8ba11 JS: fix links in qhelp 2018-12-19 10:10:56 +00:00
semmle-qlci
595634126f Merge pull request #706 from asger-semmle/jquery-location-sink
Approved by esben-semmle
2018-12-18 21:14:08 +00:00
Asger F
f57454951b JS: move <ul> outside of <p> element 2018-12-18 14:15:12 +00:00
Asger F
1246de466a JS: add change note 2018-12-18 13:58:03 +00:00
Asger F
7f538e82c0 JS: add test case for non-whitelisted use of location 2018-12-18 13:55:05 +00:00
Asger F
02978c97f1 JS: whitelist $(location) in simple cases 2018-12-18 13:11:42 +00:00
Asger F
c17eca90a1 JS: add test case for $(location) 2018-12-18 13:06:12 +00:00
calumgrant
b051b7546d Merge pull request #638 from hvitved/csharp/split-dominance-performance
C#: Speedup `Assertions::strictlyDominates()` and `ControlFlowElement::controlsBlock()`
2018-12-18 13:05:36 +00:00
ian-semmle
d2d119eb75 Merge pull request #700 from jbj/mergeback-20181217
Mergeback master -> next
2018-12-18 12:18:54 +00:00
Tom Hvitved
edf1df1577 C#: Remove tests for deprecated predicates 2018-12-18 10:43:12 +01:00
semmle-qlci
c37d655fe8 Merge pull request #697 from esben-semmle/js/fix-heuristics-compilation-time
Approved by asger-semmle
2018-12-18 09:07:36 +00:00
semmle-qlci
7fd1d64d97 Merge pull request #699 from esben-semmle/js/add-lastIndexOf
Approved by asger-semmle
2018-12-18 09:07:17 +00:00
Dave Bartolomeo
63a2670fcd C++: Don't have ReachableBlock extends IRBlock 2018-12-17 13:10:53 -08:00
Dave Bartolomeo
fda8605aae C++: One Unreached per function 2018-12-17 11:03:15 -08:00
Asger F
e1c25c81f6 JS: add change note 2018-12-17 16:34:35 +00:00
Asger F
2044f5fe89 TS: reorganize convertBinaryExpression and create AssignmentExpression when appropriate 2018-12-17 16:23:46 +00:00
Asger F
cc0961a988 TS: translate logical operators correctly 2018-12-17 15:41:15 +00:00
Asger F
d595f20cb1 JS: add to correctness-more suite 2018-12-17 15:29:10 +00:00
Tom Hvitved
d9ae5933d4 C#: Remove deprecated predicates 2018-12-17 16:20:41 +01:00
Asger F
280382e91e JS: whitelist if array access at another index is seen 2018-12-17 15:19:26 +00:00
Tom Hvitved
e14259126e Merge pull request #658 from calumgrant/cs/extractor/for-is
C#: Fix extraction bug for variable declarations in for condition
2018-12-17 16:16:00 +01:00
Anders Schack-Mulligen
d3f6362ba2 Java: Add missing override annotations. 2018-12-17 15:40:46 +01:00
Tom Hvitved
e822510d6b C#: Fix typo 2018-12-17 15:33:05 +01:00
calumgrant
6648c8414f Merge pull request #680 from hvitved/csharp/data-flow-performance-tweaks
C#: Minor data flow performance tweaks
2018-12-17 14:25:51 +00:00
calumgrant
dbd0c7e80a Merge pull request #674 from hvitved/csharp/cache-get-label
C#: Cache `NamedElement::getLabel()`
2018-12-17 14:24:01 +00:00
calumgrant
f50d0e373a Merge pull request #642 from hvitved/csharp/extractor/nullness-refactorings
C#: nullness related extractor refactorings
2018-12-17 14:16:51 +00:00
Asger F
5040d3e26c JS: add query for loop index bug 2018-12-17 13:35:44 +00:00
Jonas Jensen
5ac5aa0c2a Merge remote-tracking branch 'upstream/master' into mergeback-20181217 2018-12-17 13:42:45 +01:00
Esben Sparre Andreasen
4a631b42d4 JS: use .lastIndexOf in js/incomplete-url-substring-sanitization 2018-12-17 13:22:31 +01:00
Asger F
7adf1d9958 Merge pull request #631 from esben-semmle/js/bad-url-regexing
JS: add query: js/incomplete-url-regexp
2018-12-17 11:53:22 +00:00
Tom Hvitved
5f269b2d87 Merge branch 'master' into cs/extractor/for-is 2018-12-17 11:14:50 +01:00
Esben Sparre Andreasen
50cba92f5f JS: remove slow test Security/heuristics/AdditionalCommandInjections 2018-12-17 10:58:46 +01:00
Tom Hvitved
ada0115d6a C#: Remove getUrl() predicates
As described on https://lgtm.com/help/ql/locations#providing-location-information,
there is no need to provide a `getUrl()` predicate, when there is a `getLocation()`
predicate. Not only is it redundant, but it can also be slow because of string
construction.
2018-12-17 10:52:24 +01:00
Esben Sparre Andreasen
3cd62234d4 JS: change notes for js/request-forgery improvements 2018-12-17 10:33:39 +01:00
Esben Sparre Andreasen
c6b4e29b93 JS: add "host" as a sink for js/request-forgery 2018-12-17 10:32:30 +01:00
Esben Sparre Andreasen
60fe0176ed JS: add ClientRequest::getHost 2018-12-17 10:32:30 +01:00
Esben Sparre Andreasen
3a5962aa34 JS: minor fixups in ClientRequests.qll 2018-12-17 10:32:30 +01:00
Anders Schack-Mulligen
01f58758f1 Merge pull request #693 from sb-semmle/remove-duplicate-predicate
Remove a duplicated predicate.
2018-12-17 08:47:33 +00:00
Dave Bartolomeo
56bb9dcde0 C++: Remove infeasible edges to reachable blocks
The existing unreachable IR removal code only retargeted an infeasible edge to an `Unreached` instruction if the successor of the edge was an unreachable block. This is too conservative, because it doesn't remove an infeasible edge that targets a block that is still reachable via other paths. The trivial example of this is `do { } while (false);`, where the back edge is infeasible, but the body block is still reachable from the loop entry.

This change retargets all infeasible edges to `Unreached` instructions, regardless of the reachability of the successor block.
2018-12-14 12:13:22 -08:00
Sebastian Bauersfeld
c35fc82218 Remove a duplicated predicate. 2018-12-14 12:59:49 -05:00
Geoffrey White
b8877f1d5f Merge pull request #690 from jbj/prepareQueries-fix-warnings-2
C++: Delete dead code with warnings in it
2018-12-14 14:23:19 +00:00
Tom Hvitved
91e4f7ad83 C#: Make cs/dereferenced-value-may-be-null a path query 2018-12-14 12:07:16 +00:00
Esben Sparre Andreasen
487b8c52c6 JS: fix <p></p> issue 2018-12-14 13:04:10 +01:00
Tom Hvitved
e2f271bddb C#: Add more guard implication steps 2018-12-14 12:03:32 +00:00
Tom Hvitved
078dc7b6c0 C#: Fix false positives in cs/dereferenced-value-may-be-null 2018-12-14 12:03:32 +00:00
Tom Hvitved
287ce4e683 C#: Add more nullness tests 2018-12-14 12:03:32 +00:00
Max Schaefer
5ccad6ffc2 JavaScript: Minor improvements. 2018-12-14 11:56:59 +00:00
Max Schaefer
3e04f53ed2 Merge pull request #688 from adityasharad/merge/master-next-141218
Merge master into next.
2018-12-14 11:48:00 +00:00
Jonas Jensen
23a2bf1756 C++: Delete dead code with warnings in it 2018-12-14 10:59:41 +00:00
Tom Hvitved
654f2ae290 C#: Address review comment 2018-12-14 10:38:34 +00:00
Aditya Sharad
7bc729a7dc Merge master into next. 2018-12-14 10:16:47 +00:00
Tom Hvitved
56b80ae13a C#: Add getALocation() for namespaces and namespace declarations 2018-12-14 10:16:20 +00:00
Esben Sparre Andreasen
bb3e3a541d JS: address doc review comments 2018-12-14 10:24:30 +01:00
semmle-qlci
936094d0b6 Merge pull request #671 from xiemaisi/js/more-unhelpful-magic
Approved by asger-semmle
2018-12-14 08:44:45 +00:00
Max Schaefer
f9106b3bfe Merge pull request #685 from asger-semmle/useless-conditional-as-value
JS: fix FPs in UselessConditional
2018-12-14 08:44:10 +00:00
semmle-qlci
7f21f145e2 Merge pull request #678 from asger-semmle/function-receiver
Approved by xiemaisi
2018-12-14 08:39:04 +00:00
Tom Hvitved
b11d5c5075 Merge pull request #679 from calumgrant/cs/omitted-array-size
C#: Extract stackalloc initializers
2018-12-14 07:48:46 +01:00
Arthur Baars
18eb60b98e Merge pull request #687 from adityasharad/merge/master-next-131218
Merge master into next.
2018-12-13 19:43:58 +01:00
Aditya Sharad
f71e5ac338 Merge master into next. 2018-12-13 17:57:31 +00:00
Anders Schack-Mulligen
7656936cad Java: Remove Metrics/queries.xml 2018-12-13 17:43:26 +00:00
Asger F
f737830f18 JS: fix typo 2018-12-13 15:56:00 +00:00
Asger F
ae4b55de9a JS: fix FPs in UselessConditional 2018-12-13 15:41:41 +00:00
Geoffrey White
b21e832ee2 Merge pull request #683 from jbj/prepareQueries-fix-warnings
C++: Fix all prepareQueries errors and warnings
2018-12-13 15:30:44 +00:00
calum
9fba643fb0 C#: Address review comments. 2018-12-13 13:53:58 +00:00
Arthur Baars
1158708ea4 Merge pull request #684 from adityasharad/merge/1.19-next-131218
Merge rc/1.19 into next.
2018-12-13 14:14:42 +01:00
Aditya Sharad
ce8ca5979b Merge rc/1.19 into next. 2018-12-13 12:23:59 +00:00
calumgrant
16c065274d Merge pull request #666 from hvitved/csharp/useless-upcast-performance
C#: Improve performance of `cs/useless-upcast`
2018-12-13 12:04:12 +00:00
Jonas Jensen
bee2ddaf26 C++: Fix all prepareQueries errors and warnings
With these changes we can run `odasa prepareQueries --check-only
--fail-on-warnings` on the C++ query directory. Two changes were needed:

1. The `Metrics/queries.xml` file had to be deleted. It existed because
   the built distribution has a different file layout, where `Metrics`
   is moved to the top-level query dir `odasa-cpp-metrics`. Since
   internal PR 28230 this file is created as needed as part of the dist
   build process, so it doesn't need to be checked in with the sources.
2. All uses of the `deprecated` and stubbed-out Objective C classes were
   removed.
2018-12-13 11:13:50 +00:00
Asger F
cb349348e7 JS: rename getThisParameter to getReceiver 2018-12-13 10:19:44 +00:00
Max Schaefer
e194021c3b Merge pull request #629 from esben-semmle/js/persistent-read-taint
JS: add persistent storage taint steps
2018-12-13 08:24:42 +00:00
Max Schaefer
969fe6e4f1 Merge pull request #657 from esben-semmle/js/classify-more-files
JS: classify additional files
2018-12-13 08:20:33 +00:00
Max Schaefer
e8c8360ad1 Merge pull request #659 from esben-semmle/js/more-constant-string-usage
JS: replace StringLiteral with ConstantString in two queries
2018-12-13 08:19:22 +00:00
Max Schaefer
f1dcec8369 Merge pull request #667 from asger-semmle/ts-binding-pattern-with-defaults
TS: fix extraction of binding pattern with default
2018-12-13 08:18:22 +00:00
Max Schaefer
54bb9d185f Merge pull request #632 from asger-semmle/pseudo-random-bytes
JS: add crypto.pseudoRandomBytes as source in InsecureRandomness.ql
2018-12-13 08:14:40 +00:00
Max Schaefer
df42707050 Merge pull request #675 from asger-semmle/window.name
JS: Add window.name as remote flow source
2018-12-13 08:13:15 +00:00
Max Schaefer
3f185364f9 Merge pull request #669 from adityasharad/merge/master-next-111218
Merge master into next.
2018-12-13 07:58:58 +00:00
Tom Hvitved
b155a0f5fb C#: Avoid computing CIL strings and non-PDB locations in data flow library
Computing strings and locations for CIL instructions can be quite time consuming.
The CIL `toString()`s are not very helpful in path explanations, and their locations
are only useful when a PDB source file exists. Therefore, produce a simple constant
`toString()`, and restrict locations to those in PDB files.
2018-12-12 21:58:16 +01:00
Tom Hvitved
344466a8c1 C#: Cache DataFlow::Node::getEnclosingCallable() 2018-12-12 21:49:21 +01:00
Aditya Sharad
f92456fcad Merge master into next.
Conflict in `cpp/ql/test/library-tests/sideEffects/functions/sideEffects.expected`,
resolved by accepting test output (combining changes).
2018-12-12 17:26:18 +00:00
Aditya Sharad
41a48078f7 Merge pull request #673 from calumgrant/cs/sync-files
C#: Sync samples and qltest cases
2018-12-12 17:10:00 +00:00
calumgrant
8e546a30b0 Merge pull request #637 from hvitved/csharp/cfg/throwing-callable
C#: Fix a bug in `ThrowingCallable`
2018-12-12 16:58:28 +00:00
calum
2bbd55519b C#: Add tests for C# 7.3 features. 2018-12-12 16:44:55 +00:00
Asger F
635a3cb1ec JS: add FunctionNode.getThisParameter 2018-12-12 16:26:02 +00:00
calum
5596bc8827 C#: Add change note. 2018-12-12 16:16:07 +00:00
Anders Schack-Mulligen
12bc1fc656 Merge pull request #581 from jf205/metadata-guide
Query metadata style guide: add to ql/docs
2018-12-12 12:55:20 +00:00
Asger F
a96c53f9b8 JS: restrict when a variable reference is considered a source 2018-12-12 12:28:26 +00:00
Asger F
14621760bb JS: add window.name as DOM-based remote flow source 2018-12-12 12:22:39 +00:00
Tom Hvitved
74167e478a C#: Cache NamedElement::getLabel() 2018-12-12 13:16:28 +01:00
Tom Hvitved
6918dad1db C#: Refactor localFlowStep()
Using the `forceCachingInSameStage()` trick, we can get rid of the non-cached version
of local flow, while still computing it in the same stage.
2018-12-12 13:14:22 +01:00
Tom Hvitved
1366638f06 C#: Fix whitespaces 2018-12-12 13:13:13 +01:00
calum
3037b2b197 C#: Sync the -Good and -Bad files in the qltest to match the sample. 2018-12-12 11:36:00 +00:00
calum
1df1b0c28e C#: Refactor ArrayCreations to allow stackalloc arrays to have initializers (C# 7.3). 2018-12-12 11:05:34 +00:00
Asger F
aa04e9c77f TS: fix extraction of binding pattern with default 2018-12-12 10:36:30 +00:00
Max Schaefer
faaca21996 JavaScript: Avoid more unhelpful magic. 2018-12-12 08:40:21 +00:00
Max Schaefer
4fc27aaa51 Merge branch 'master' into pseudo-random-bytes 2018-12-12 08:19:57 +00:00
semmle-qlci
06dd5f3616 Merge pull request #656 from xiemaisi/js/unused-local-underscore
Approved by esben-semmle
2018-12-12 08:11:37 +00:00
semmle-qlci
9df5d4b0c2 Merge pull request #660 from esben-semmle/js/angularjs-alert-locations
Approved by xiemaisi
2018-12-12 08:05:19 +00:00
yh-semmle
14488cb62e Merge pull request #652 from aschackmull/java/constant-loop-cond-alert-pos
Java: Change alert location for ConstantLoopCondition.
2018-12-11 21:26:14 -05:00
Esben Sparre Andreasen
fac638ffab JS: improve alert location of js/angular/unused-dependency 2018-12-11 21:47:08 +01:00
Esben Sparre Andreasen
b5bbf990b0 JS: improve alert location of js/angular/repeated-dependency-injection 2018-12-11 21:47:08 +01:00
Esben Sparre Andreasen
5acd1ca26d JS: improve alert location of js/angular/duplicate-dependency 2018-12-11 21:47:08 +01:00
Robert Marsh
98005edd9d Merge pull request #641 from geoffw0/exprnoeffect2
CPP: More tests of isSideEffectFree() / ExprHasNoEffect.ql
2018-12-11 12:17:30 -08:00
Tom Hvitved
7422947e78 C#: Improve performance of cs/useless-upcast 2018-12-11 17:48:04 +01:00
Asger F
a01a9dc5cc JS: add crypto.pseudoRandomBytes as source in InsecureRandomness.ql 2018-12-11 16:06:22 +00:00
Tom Hvitved
9707b34124 Merge pull request #663 from adityasharad/merge/1.19-next-111218
Merge rc/1.19 into next.
2018-12-11 16:06:55 +01:00
Tom Hvitved
e80837681f C#: Refactor LINQ logic
Factor `ClauseCall` out into three classes to make it clear when the fields
`operand` and `declaration` can be `null`.
2018-12-11 16:04:25 +01:00
Aditya Sharad
dde42a5723 Merge rc/1.19 into next. 2018-12-11 14:38:58 +00:00
Esben Sparre Andreasen
376ed7a4d2 JS: generalize js/command-line-injection to handle ConstantString 2018-12-11 13:39:15 +01:00
Esben Sparre Andreasen
a1d92bfa50 JS: generalize js/incomplete-sanitization to handle ConstantString 2018-12-11 13:39:15 +01:00
Esben Sparre Andreasen
1bc73ab592 JS: address review comments 2018-12-11 13:03:17 +01:00
calum
f0fb47cde0 C#: Update change notes. 2018-12-11 10:31:45 +00:00
calum
8d072863df C#: Reorder for statements to ensure variables declared in the condition are declared before they are used. 2018-12-11 10:31:45 +00:00
Esben Sparre Andreasen
7cc6f2f4d8 JS: add test case 2018-12-11 10:17:25 +01:00
Esben Sparre Andreasen
36e36a414e JS: change notes for improve file classification 2018-12-11 10:01:54 +01:00
Esben Sparre Andreasen
73aa223b08 JS: handle additional multi-license file patterns 2018-12-11 09:55:38 +01:00
Max Schaefer
4d186e0edc JavaScript: Teach Unused{Variable,Parameter} to ignore variables with leading underscore. 2018-12-11 08:50:50 +00:00
Esben Sparre Andreasen
edbef289a7 JS: improve whitespace handling for multi-license file recognition 2018-12-11 09:30:10 +01:00
Esben Sparre Andreasen
e016098f86 JS: support purs classification 2018-12-11 09:17:01 +01:00
Esben Sparre Andreasen
3879e57f18 JS: support <meta name="generator"/> classification 2018-12-11 09:12:39 +01:00
Esben Sparre Andreasen
a295dfd2c5 JS: support AutoRest classification 2018-12-11 08:54:19 +01:00
Esben Sparre Andreasen
09e7124bb1 JS: update change notes for renamed query 2018-12-10 22:22:54 +01:00
Esben Sparre Andreasen
ab519d4abf JS: rename query
"Incomplete URL regular expression" -> "Incomplete regular expression for hostnames".
2018-12-10 22:22:54 +01:00
Esben Sparre Andreasen
7c6e28d917 JS: introduce near-empty RegularExpressions.qll 2018-12-10 22:22:54 +01:00
Esben Sparre Andreasen
994fe1bea5 JS: address non-semantic review comments 2018-12-10 22:21:02 +01:00
Esben Sparre Andreasen
d4e4bc6a0b JS: sharpen js/incomplete-url-regexp by not matching .* or .+ 2018-12-10 22:21:02 +01:00
Esben Sparre Andreasen
c65c7e700e JS: change notes for js/incomplete-url-regexp 2018-12-10 22:21:01 +01:00
Esben Sparre Andreasen
52ca696ff4 JS: add query js/incomplete-url-regexp 2018-12-10 22:20:29 +01:00
Esben Sparre Andreasen
6d6379fc09 JS: address review comments 2018-12-10 22:03:52 +01:00
Jonas Jensen
a4b3b1e8c8 Merge pull request #653 from geoffw0/ex-ch-notes
CPP: Additional change notes (for 1.20)
2018-12-10 16:59:12 +01:00
Geoffrey White
709fd6382a CPP: Change note for #562. 2018-12-10 13:51:15 +00:00
Geoffrey White
6b7337d766 CPP: Change note for #540. 2018-12-10 13:42:17 +00:00
Jonas Jensen
1f7383498a Merge pull request #644 from geoffw0/pointerscaling
CPP: Fix type confusion in IncorrectPointerscaling.ql
2018-12-10 14:22:10 +01:00
Anders Schack-Mulligen
bfc7fb7c8a Java: Change alert location for ConstantLoopCondition. 2018-12-10 12:37:11 +00:00
Felicity Chapman
6ef16bb728 Merge pull request #649 from jf205/qhelp-guide
Query help style guide: editorial review
2018-12-10 10:59:48 +00:00
Aditya Sharad
02b58a8319 Merge pull request #625 from adityasharad/merge/1.19-next-051218
Merge rc/1.19 into next.
2018-12-10 10:05:16 +00:00
james
a0d5049132 update links to query pages 2018-12-10 09:33:58 +00:00
james
4bd922e442 address further comments 2018-12-10 09:18:05 +00:00
james
36fe86f730 address felicity's comments 2018-12-10 09:18:05 +00:00
james
59542fc367 mention of qldoc comment requirements 2018-12-10 09:18:05 +00:00
james
934fd9f3d6 address geoffrey's comments and reword tags 2018-12-10 09:18:05 +00:00
james
2ed648d798 metadat-style-guide: address anders' review 2018-12-10 09:18:05 +00:00
james
09d08a7547 metadata-style-guide: update title 2018-12-10 09:18:04 +00:00
james
9560165921 metadata-style-guide: add style guide 2018-12-10 09:18:04 +00:00
james
41f5d65e0c remove hyphen from title and update some links 2018-12-10 09:13:33 +00:00
Nick Rolfe
976aa22fac Merge pull request #646 from ian-semmle/stats
C++: Update stats
2018-12-09 17:59:46 +00:00
yh-semmle
ba4fa0a246 Merge pull request #643 from aschackmull/java/nullguard-isblank
Java: Add org.apache.commons.lang3.StringUtils.isBlank as a nullguard.
2018-12-07 15:31:58 -05:00
Geoffrey White
9857a85817 CPP: Fix similar queries. 2018-12-07 18:43:28 +00:00
Geoffrey White
d3c6d83786 CPP: Change note. 2018-12-07 18:43:27 +00:00
Geoffrey White
0f268cac40 CPP: Fix the issue. 2018-12-07 18:43:27 +00:00
Geoffrey White
02a060fbfa CPP: Add a test. 2018-12-07 18:21:48 +00:00
Ian Lynagh
4f51257e56 C++: Update stats 2018-12-07 16:13:07 +00:00
calumgrant
67d4099e3f Merge pull request #593 from hvitved/csharp/nullness
C#: Rewrite nullness queries
2018-12-07 15:57:27 +00:00
Geoffrey White
91578258f7 Merge pull request #595 from jf205/qhelp-guide
Query help style-guide
2018-12-07 15:38:58 +00:00
Anders Schack-Mulligen
f09eb67af0 Java: Add org.apache.commons.lang3.StringUtils.isBlank as a nullguard. 2018-12-07 16:18:32 +01:00
Tom Hvitved
6411d1c7dd C#: Refactor operator call logic
Refactored to make it clear when `@operator.Symbol as IMethodSymbol` can be `null`.
2018-12-07 15:47:20 +01:00
Tom Hvitved
e05bbb0f10 C#: Fix always-null bug in TRAP writer 2018-12-07 15:46:27 +01:00
Geoffrey White
e7390f3ea5 CPP: Add simple tests of CommaExpr. 2018-12-07 14:29:09 +00:00
Aditya Sharad
fcfab26267 Merge rc/1.19 into next. 2018-12-07 12:31:51 +00:00
Tom Hvitved
664453707a C#: Speedup Assertions::strictlyDominates() and ControlFlowElement::controlsBlock()
Only calculate dominance by explicit recursion for split nodes; all other nodes
can use regular CFG dominance.
2018-12-07 12:03:12 +01:00
Anders Schack-Mulligen
6beb396d93 Merge pull request #634 from yh-semmle/java/field-annotations
Java: account for change to field annotation extraction
2018-12-07 11:29:46 +01:00
Tom Hvitved
2a30dee8df Merge pull request #621 from calumgrant/cs/invalid-key
C#: Fix [INVALID_KEY] error
2018-12-07 11:24:45 +01:00
Tom Hvitved
c887dc89dc C#: Fix a bug in ThrowingCallable
A method such as

```
void M()
{
    throw new Exception();
}
```

was incorrectly not categorized as a `ThrowingCallable`, that is, a callable
that always throws an exception upon invocation.
2018-12-07 10:56:11 +01:00
Geoffrey White
b1e7649d02 CPP: Add functions containing errors to the sideEffects tests. 2018-12-07 09:54:36 +00:00
Tom Hvitved
243af36167 C#: Add more CFG tests with throwing methods 2018-12-07 10:43:45 +01:00
Tom Hvitved
fce805834e C#: Address review comments 2018-12-07 09:40:49 +01:00
yh-semmle
bc78219653 Java: account for change to field annotation extraction 2018-12-06 23:06:14 -05:00
yh-semmle
a709783fe5 Merge pull request #622 from ian-semmle/range_for
C++: Follow range for statement test output changes
2018-12-06 23:05:08 -05:00
semmle-qlci
9e73ed71b9 Merge pull request #623 from esben-semmle/js/incomplete-url-sanitization
Approved by mc-semmle
2018-12-06 20:46:37 +00:00
yh-semmle
c2116f0d91 Merge pull request #560 from aschackmull/java/normalize-parentheses
Java: Normalize parentheses.
2018-12-06 12:38:26 -05:00
Esben Sparre Andreasen
4f53411397 JS: recognize HTTP URLs in js/incomplete-url-sanitization 2018-12-06 15:53:20 +01:00
Esben Sparre Andreasen
56fb63adbc JS: change notes for js/incomplete-url-substring-sanitization 2018-12-06 15:53:20 +01:00
Esben Sparre Andreasen
229eea00dc JS: add query js/incomplete-url-substring-sanitization 2018-12-06 15:53:20 +01:00
semmle-qlci
3397533045 Merge pull request #628 from xiemaisi/js/setUnsafeHTML
Approved by esben-semmle
2018-12-06 13:58:52 +00:00
Esben Sparre Andreasen
bf048e7e49 JS: change notes for persistent storage taint step and cookie models 2018-12-06 14:53:22 +01:00
Esben Sparre Andreasen
45b207c21b JS: introduce models of three cookie libraries 2018-12-06 14:53:22 +01:00
Esben Sparre Andreasen
28b4a78430 JS: introduce DOM::PersistentWebStorage 2018-12-06 14:53:22 +01:00
Jonas Jensen
0a496c1d3d Merge pull request #617 from geoffw0/unusedstatic
CPP: Fix false positives in UnusedStaticVariables.ql
2018-12-06 14:09:52 +01:00
Ian Lynagh
8d655c74ae C++: Follow range for statement test output changes 2018-12-06 11:12:46 +00:00
Esben Sparre Andreasen
7fb752784a JS: introduce persistent read/write pairs as a taint step 2018-12-06 10:36:10 +01:00
Max Schaefer
ef347b3870 JavaScript: Teach Xss query about WinJS HTML injection functions. 2018-12-06 09:13:21 +00:00
Max Schaefer
75842fec1c Merge pull request #627 from samlanning/inconsistentStateExample
JS: Fix syntax error in js/react/inconsistent-state-update example
2018-12-06 08:03:32 +00:00
Sam Lanning
2ea148016c JS: Fix syntax error in js/react/inconsistent-state-update example 2018-12-05 16:44:40 -08:00
Nick Rolfe
d577ee8849 Merge pull request #613 from ian-semmle/catch
C++: Test output changes following CatchAny fix
2018-12-05 16:02:43 +00:00
Ian Lynagh
7d8a8de53d C++: Test output changes following CatchAny fix 2018-12-05 15:35:54 +00:00
calum
919d7cbf01 C#: Fix [INVALID_KEY] errors. 2018-12-05 13:55:55 +00:00
Geoffrey White
f6a87574f0 CPP: Add query ID to change note. 2018-12-05 13:55:46 +00:00
Aditya Sharad
7d3e637eb0 Merge pull request #618 from xiemaisi/js/fix-test-output
JavaScript: Fix expected test output.
2018-12-05 10:15:59 +00:00
Max Schaefer
7ee0ba36af JavaScript: Fix expected test output. 2018-12-05 10:14:25 +00:00
Geoffrey White
d0a0d2300e CPP: Change note. 2018-12-05 10:03:21 +00:00
Geoffrey White
d85f4b540c CPP: Fix false positive. 2018-12-05 10:01:54 +00:00
Geoffrey White
e7f19e97cb CPP: Add a test of UnusedStaticVariable.ql. 2018-12-05 10:01:54 +00:00
Max Schaefer
3c00d4be6d Merge pull request #607 from esben-semmle/js/more-react-methods
JS: model additional React component methods
2018-12-05 08:00:16 +00:00
yh-semmle
00779c518c Merge pull request #611 from aschackmull/java/usessl-fp-fix
Java: Fix FP in `UseSSL.ql`.
2018-12-04 19:31:53 -05:00
Esben Sparre Andreasen
d63d838534 JS: add regression test for ODASA-7506 2018-12-04 22:22:46 +01:00
Arthur Baars
d1cc53cd36 Merge pull request #588 from adityasharad/merge/1.19-next-301118
Merge rc/1.19 into next.
2018-12-04 22:16:37 +01:00
Anders Schack-Mulligen
d3fcfb0957 Java: Fix FP in UseSSL. 2018-12-04 17:44:05 +01:00
semmle-qlci
d05b11f00d Merge pull request #587 from asger-semmle/incorrect-suffix-check
Approved by mc-semmle, xiemaisi
2018-12-04 16:18:42 +00:00
yh-semmle
0ba7633e4d Merge pull request #553 from aschackmull/java/double-checked-locking
Java: Add two double-checked-locking queries.
2018-12-04 10:23:46 -05:00
Tom Hvitved
3bb3de23ce C#: Update change note 2018-12-04 16:08:41 +01:00
james
bdda3ae477 fix typo 2018-12-04 14:01:11 +00:00
Aditya Sharad
3caf4e52a7 Merge rc/1.19 into next. 2018-12-04 12:39:41 +00:00
james
26f030045a address anders' feedback 2018-12-04 11:07:17 +00:00
Asger F
7121a18eba JS: address comments 2018-12-04 10:40:43 +00:00
Esben Sparre Andreasen
b418968efb JS: add change note for improved React model 2018-12-04 10:55:24 +01:00
Esben Sparre Andreasen
679db191f5 JS: move shared conjunct up 2018-12-04 10:55:24 +01:00
Esben Sparre Andreasen
a342fa36c6 JS: support React getSnapshotBeforeUpdate 2018-12-04 10:48:35 +01:00
Esben Sparre Andreasen
67b1487384 JS: support React shouldComponentUpdate 2018-12-04 10:48:35 +01:00
Esben Sparre Andreasen
417dac7ad6 JS: support React getDerivedStateFromProps 2018-12-04 10:48:35 +01:00
Esben Sparre Andreasen
9ff3d2ef1f JS: introduce ReactComponent::getStaticMethod 2018-12-04 10:48:35 +01:00
Esben Sparre Andreasen
0d62191d84 JS: add more React tests 2018-12-04 10:48:35 +01:00
Anders Schack-Mulligen
e836fa7512 Java: Update metadata. 2018-12-04 10:12:56 +01:00
ian-semmle
47e15a6f75 Merge pull request #605 from nickrolfe/agg_init
C++: fix expected test output for improved extraction of aggregate initialisers
2018-12-03 23:30:00 +00:00
Nick Rolfe
a637eb651f C++: fix expected test output for improved extraction of agg. inits. 2018-12-03 16:45:53 +00:00
ian-semmle
a43125c3e0 Merge pull request #591 from nickrolfe/CPP-298
C++: we now process operands for vacuous destructor calls through pointers
2018-12-03 16:42:00 +00:00
Jonas Jensen
b80cf30cee Merge pull request #562 from geoffw0/cpp-308
CPP: Fix FPs for 'Resource not released in destructor' involving virtual method calls
2018-12-03 15:57:11 +01:00
Tom Hvitved
4739a6334e C#: Fix a bug and generalize guards implication logic 2018-12-03 15:33:00 +01:00
semmle-qlci
b58c263fd0 Merge pull request #602 from esben-semmle/js/additional-route-handlers-from-context
Approved by xiemaisi
2018-12-03 14:31:10 +00:00
Geoffrey White
d8c7537557 CPP: * -> + 2018-12-03 13:11:52 +00:00
Geoffrey White
dfbccc4bcf CPP: Additional test cases. 2018-12-03 13:11:52 +00:00
calumgrant
43d14ce011 Merge pull request #586 from hvitved/csharp/cfg/field-split
C#: Handle multiple-field Boolean CFG splitting
2018-12-03 12:52:43 +00:00
Nick Rolfe
fc91ff1a69 C++: we now process operands for vacuous destructor calls thru pointers 2018-12-03 12:16:35 +00:00
Asger F
1130d0c6f9 JS: add comment about arrays 2018-12-03 11:23:02 +00:00
Asger F
374f7ab65d JS: address comments 2018-12-03 11:23:02 +00:00
Asger F
c4d7672ea7 JS: fix typo in method name 2018-12-03 11:23:02 +00:00
Asger F
0462eb4b50 JS: add IncorrectSuffixCheck query 2018-12-03 11:23:02 +00:00
Esben Sparre Andreasen
2cc235d61b Merge pull request #556 from xiemaisi/js/invalid-entity-transcoding
JavaScript: Add new query `InvalidEntityTranscoding`.
2018-12-03 10:31:41 +01:00
Esben Sparre Andreasen
104eafec2f JS: cleanup for all HTTP::RouteHandlerCandidates 2018-12-03 10:13:08 +01:00
Esben Sparre Andreasen
88c69e2c9c JS: change note for tracked Hapi route handlers 2018-12-03 09:24:55 +01:00
Esben Sparre Andreasen
a3bd072590 JS: add Hapi::RouteHandlerCandidate 2018-12-03 09:22:21 +01:00
Esben Sparre Andreasen
fd489271b7 JS: refactor Hapi::RouteSetup 2018-12-03 09:22:21 +01:00
Aditya Sharad
b638961a4f Merge pull request #596 from Semmle/dll-binary
.gitattributes: DLLs are binary
2018-11-30 18:06:13 +00:00
Nick Rolfe
b173752de9 .gitattributes: DLLs are binary 2018-11-30 18:05:02 +00:00
Max Schaefer
52b8a6bb56 Merge branch 'master' into js/invalid-entity-transcoding 2018-11-30 16:49:20 +00:00
Tom Hvitved
d25bd598db C#: Add change note 2018-11-30 17:44:48 +01:00
Tom Hvitved
3b0d1599ad C#: Teach guards library about unique assignments
For example, in

```
void M(object x)
{
    var y = x == null ? 1 : 2;
    if (y == 2)
        x.ToString();
}
```

the guard `y == 2` implies that the guard `x == null` must be false,
as the assignment of `2` to `y` is unique.
2018-11-30 17:43:10 +01:00
Tom Hvitved
ab9aa7d338 C#: Teach guards library about conditional assignments
For example, in

```
void M(object x)
{
    var y = x != null ? "" : null;
    if (y != null)
        x.ToString();
}
```

the guard `y != null` implies that the guard `x != null` must be true.
2018-11-30 17:41:36 +01:00
Tom Hvitved
80144a00c8 C#: Update nullness analyses
Port the SSA-based logic from the Java nullness analyses.
2018-11-30 17:41:31 +01:00
james
bebac21e19 add qhelp style-guide 2018-11-30 16:27:01 +00:00
Aditya Sharad
ec0663e587 Merge pull request #584 from jbj/mergeback-20181130
Mergeback master -> next
2018-11-30 16:15:21 +00:00
Tom Hvitved
d2a431e6f3 C#: Add more nullness tests
Port many of the nullness test from Java, as well as add new tests.
2018-11-30 17:02:05 +01:00
Kevin Backhouse
939db5a7cd Merge pull request #583 from jbj/bbStrictlyDominates-nomagic
C++: pragma[nomagic] on bbStrictlyDominates
2018-11-30 15:12:24 +00:00
calumgrant
1c2dd3e7b9 Merge pull request #570 from hvitved/csharp/ssa/split-to-string
C#: Include CFG splits in `Ssa::Definition::toString()`
2018-11-30 15:04:36 +00:00
Max Schaefer
dfcf767090 Merge pull request #440 from asger-semmle/range-analysis
JS: Range analysis for dead code detection
2018-11-30 15:01:34 +00:00
semmle-qlci
dbeb2dfa0e Merge pull request #585 from xiemaisi/js/join-order-fiddling
Approved by esben-semmle
2018-11-30 14:59:53 +00:00
calumgrant
08f5c2b6a6 Merge pull request #567 from hvitved/csharp/guards-splitting
C#: Account for split SSA definitions in guards library
2018-11-30 14:57:57 +00:00
Jonas Jensen
60076cb734 Merge pull request #532 from geoffw0/query-tags-3
CPP: Query Tags 3 (JPL_C queries)
2018-11-30 15:45:01 +01:00
Jonas Jensen
4712a8f913 C++: pragma[nomagic] on bbStrictlyPostDominates
This predicate was recently added and is likely to get the same problems
as `bbStrictlyDominates` with magic.
2018-11-30 11:37:18 +01:00
Jonas Jensen
ace8fa88f2 C++: pragma[nomagic] on bbStrictlyDominates
I noticed that queries using the data flow library spent significant
time in `#Dominance::bbIDominates#fbPlus`, which is the body of the
`bbStrictlyDominates` predicate. That predicate took 28 seconds to
compute on Wireshark.

The `b` in the predicate name means that magic was applied, and the
application of magic meant that it could not be evaluated with the
built-in `fastTC` HOP but became an explicit recursion instead. Applying
`pragma[nomagic]` to this predicate means that we will always get it
evaluated with `fastTC`, and that takes less than a second in my test
case.
2018-11-30 11:36:11 +01:00
calumgrant
ca72c8ebfe Merge pull request #579 from hvitved/csharp/guards-loop
C#: Fix bug in guards library when the guarded expression is in a loop
2018-11-30 10:27:21 +00:00
Tom Hvitved
05b9519e9a C#: Handle multiple-field Boolean CFG splitting
The internal pre-SSA library was extended on 3e78c2671f
to include fields/properties that are local-scope-like. The CFG splitting logic
uses ranking of SSA definitions to define an (arbitrary) order of splits, but for
fields/properties the implicit entry definition all have the same line and column.
In effect, such SSA definitions incorrectly get the same rank. Adding the name
of the field/property to the lexicographic ordering resolves the issue.
2018-11-30 10:57:34 +01:00
Max Schaefer
10166be535 JavaScript: Add new query DoubleEscaping. 2018-11-30 09:39:00 +00:00
Max Schaefer
3ed40d5da1 Merge branch 'master' into range-analysis 2018-11-30 09:36:40 +00:00
semmle-qlci
1c5322274a Merge pull request #557 from esben-semmle/js/unused-react-variable
Approved by xiemaisi
2018-11-30 09:35:36 +00:00
Max Schaefer
dcad2a3431 JavaScript: Simplify an if condition.
By pulling this out of the condition we can avoid computing its negation for the `else` branch, which could previously lead to quite an enormous pipeline.
2018-11-30 09:32:31 +00:00
Tom Hvitved
610be85c8c C#: Add CFG test for multiple-field Boolean splitting 2018-11-30 10:32:08 +01:00
Jonas Jensen
9babb4366b Merge remote-tracking branch 'upstream/master' into mergeback-20181130 2018-11-30 10:13:33 +01:00
semmle-qlci
adc15cad07 Merge pull request #574 from xiemaisi/js/avoid-materialisation
Approved by esben-semmle
2018-11-30 08:30:14 +00:00
Tom Hvitved
8bd8975795 Merge pull request #568 from calumgrant/cs/index-out-of-bounds
C#: Fix false-positives in cs/index-out-of-bounds
2018-11-29 18:40:05 +01:00
Tom Hvitved
a12a72e90f C#: Fix bug in guards library when the guarded expression is in a loop
Follow-up on 03e69e9945.
2018-11-29 15:53:03 +01:00
Mark Shannon
11ca7b74a3 Merge pull request #572 from geoffw0/deprecate-cpython
CPP: Delete CPython queries
2018-11-29 14:50:06 +00:00
Jonas Jensen
90ad5cfac5 Merge pull request #569 from geoffw0/deprecate-pointsto-debug
CPP: Deprecate the PointsTo debug queries.
2018-11-29 15:28:07 +01:00
calum
6a1ab51d66 C#: Address review comments. 2018-11-29 11:39:10 +00:00
Asger F
d4023fe95a JS: address review 2018-11-29 11:37:38 +00:00
Asger F
b2a82ae598 JS: add 1.20 change note 2018-11-29 11:26:31 +00:00
Asger F
959776b775 JS: add test case 2018-11-29 11:22:15 +00:00
Asger F
d69e584cc2 JS: fix bug in foldedComparisonEdge 2018-11-29 11:22:15 +00:00
Asger F
8fd3a417c2 JS: address comments 2018-11-29 11:22:15 +00:00
Asger F
2c51f86f1b JS: avoid joining on =0 2018-11-29 11:22:14 +00:00
Asger F
6d7ac885ec JS: add to correctness-more suite 2018-11-29 11:22:14 +00:00
Asger F
477be260f3 JS: rename UselessRangeCheck -> UselessComparisonTest 2018-11-29 11:22:14 +00:00
Asger F
2e65f6b660 JS: address some style comments 2018-11-29 11:22:14 +00:00
Asger F
2870209299 JS: fix links in qhelp file 2018-11-29 11:22:14 +00:00
Asger F
76a69f4ff2 JS: address review comments 2018-11-29 11:22:14 +00:00
Asger F
f3020f776e JS: avoid extending self-edges 2018-11-29 11:22:14 +00:00
Asger F
4a367d3fdb JS: more efficient encoding of unary constraints 2018-11-29 11:22:14 +00:00
Asger F
5283c6cd48 JS: only warn about dead code 2018-11-29 11:22:14 +00:00
Asger F
2d6bf0aff3 JS: improve join ordering in extendedEdge 2018-11-29 11:22:14 +00:00
Asger F
84ea4cf1d1 JS: manually reorder extendedEdge and negativeEdge 2018-11-29 11:22:14 +00:00
Asger F
344bec3865 JS: Add UselessRangeCheck.ql 2018-11-29 11:22:14 +00:00
Asger F
d813635f3e JS: Restrict constraint generation to relevant nodes 2018-11-29 11:22:14 +00:00
Asger F
43df9538bf JS: be conservative in presence of NaN comments 2018-11-29 11:22:14 +00:00
Asger F
feb8a8c4fd JS: restrict bias to 30-bit range to avoid overflow 2018-11-29 11:22:14 +00:00
Asger F
20aa4e1f6d JS: handle sharp inequalities directly 2018-11-29 11:22:14 +00:00
Asger F
9d8d953292 JS: perform widening when adding operands of very different magnitude 2018-11-29 11:22:14 +00:00
Asger F
6c53ad80c7 JS: add constant constraints in range analysis 2018-11-29 11:22:13 +00:00
Asger F
064b1099eb JS: range analysis through phi nodes 2018-11-29 11:22:13 +00:00
Asger F
09ca6652fb JS: Support return value of x++ 2018-11-29 11:22:13 +00:00
Asger F
73cbdee691 JS: Compound assignments and update exprs in range analysis 2018-11-29 11:22:13 +00:00
Asger F
a374540c55 JS: Range analysis library 2018-11-29 11:22:13 +00:00
Jonas Jensen
d991fa84b1 Merge pull request #552 from geoffw0/move-security-tests-add
CPP: Add the Semmle security tests.
2018-11-29 10:49:20 +01:00
Geoffrey White
9d95291124 CPP: Delete the CPython queries and libraries. 2018-11-29 09:29:46 +00:00
Geoffrey White
909ff428ac CPP: Deprecate the CPython queries. 2018-11-29 09:28:29 +00:00
Tom Hvitved
ab7a094439 C#: Include CFG splits in Ssa::Definition::toString()
Just like syntax elements can be split in the control flow graph, so can SSA
definitions. To make this clear, and to make debugging easier, this commit
adds the splits as a prefix in the textual representation of SSA definitions.
2018-11-29 10:00:08 +01:00
semmle-qlci
d64067aaae Merge pull request #558 from xiemaisi/js/sanitise-access-paths
Approved by asger-semmle
2018-11-29 08:27:58 +00:00
semmle-qlci
d31c9950f9 Merge pull request #566 from ian-semmle/defuse_test
Approved by dave-bartolomeo
2018-11-28 20:48:14 +00:00
Geoffrey White
d261f1b6d2 CPP: Deprecate the PointsTo tests. 2018-11-28 20:23:33 +00:00
calum
f2d7b6ebe9 C#: Change notes. 2018-11-28 20:21:34 +00:00
Tom Hvitved
3eb163f656 C#: Account for split SSA definitions in guards library
On 03e69e9945, I updated the guards library to account
for control flow graph splitting. However, the logic that relates SSA qualifiers for
the guard and the guarded expression was not updated accordingly.
2018-11-28 20:00:13 +01:00
Tom Hvitved
1a25f0a068 C#: Add test for guard inside a split CFG block 2018-11-28 19:59:05 +01:00
Geoffrey White
1232694340 CPP: Add external/jpl tags. 2018-11-28 18:18:28 +00:00
calum
6c6d7e4fff C#: Fix false-positives in cs/index-out-of-bounds. 2018-11-28 17:42:08 +00:00
Ian Lynagh
6cb6b1c07d C++: Tweak the defuse test
It looks like this is what it was originally intended to do.
2018-11-28 17:11:17 +00:00
Geoffrey White
0eb0bf988e CPP: Fix for virtual method calls. 2018-11-28 14:19:24 +00:00
Esben Sparre Andreasen
f3889e715e JS: simplify isReactImportForJSX to isReactForJSX 2018-11-28 15:06:53 +01:00
Anders Schack-Mulligen
ae44b90456 Java: Normalize parentheses. 2018-11-28 15:01:25 +01:00
Anders Schack-Mulligen
e2dd0ea083 Java: Add 2 double-checked-locking queries. 2018-11-28 13:52:34 +01:00
Max Schaefer
fb78e14db1 JavaScript: Add support for sanitising dynamic property accesses.
This generalises our previous handling of sanitisers operating on property accesses to support dynamic property accesses where the property name is an SSA variable by representing them as access paths.
2018-11-28 12:37:53 +00:00
Esben Sparre Andreasen
72092529d1 JS: add change note for js/unused-local-variable 2018-11-28 13:25:26 +01:00
Esben Sparre Andreasen
f3c90114df JS: add empty 1.20 change note 2018-11-28 13:24:26 +01:00
Esben Sparre Andreasen
54e2215db4 JS: support require in isReactImportForJSX 2018-11-28 13:16:55 +01:00
Esben Sparre Andreasen
737a816e6f JS: refactor isReactImportForJSX 2018-11-28 13:16:55 +01:00
Max Schaefer
9c98aaf4bd JavaScript: Refactor a few predicates to avoid materialisations. 2018-11-28 10:51:29 +00:00
Geoffrey White
7107cec503 CPP: Add test cases. 2018-11-27 17:20:14 +00:00
Arthur Baars
044dcfbf66 Merge pull request #549 from adityasharad/merge/1.19-next-271118
Merge rc/1.19 into next.
2018-11-27 16:54:43 +01:00
Tom Hvitved
41edd61e2e Merge pull request #545 from calumgrant/cs/typemention-constraints
C#: Fix for type mentions of type parameter constraints
2018-11-27 14:25:48 +01:00
Aditya Sharad
5d5bfc215e Merge rc/1.19 into next. 2018-11-27 12:04:46 +00:00
Jonas Jensen
c403bb1cad Merge pull request #541 from kevinbackhouse/CppPostDominators
Add post-dominators
2018-11-27 08:23:43 +01:00
calumgrant
d1f7eef7eb Merge pull request #537 from hvitved/csharp/guards-splitting
C#: Make guards library work with CFG splitting
2018-11-26 18:19:37 +00:00
Geoffrey White
f034abc275 CPP: Add the Semmle security tests. 2018-11-26 17:52:34 +00:00
Max Schaefer
588defd6b6 Merge pull request #519 from esben-semmle/js/nullish-coalescing-extractor-and-ql
JS: nullish coalescing support in extractor and QL
2018-11-26 15:03:23 +00:00
Kevin Backhouse
4877659578 Fix names. 2018-11-26 14:56:35 +00:00
Tom Hvitved
e069041bd5 Merge pull request #431 from calumgrant/cs/extractor/fsharp-core
C#: Fix extraction of method signatures
2018-11-26 15:07:33 +01:00
Jonas Jensen
fcd53ae631 Merge pull request #540 from geoffw0/cpp-296
CPP: Fix false positive from AutoGeneratedFile.qll.
2018-11-26 15:03:21 +01:00
calum
de36151c4a C#: Add regression test and fix for type mentions of type parameter constraints. 2018-11-26 13:51:02 +00:00
semmle-qlci
03fd5498d9 Merge pull request #542 from xiemaisi/js/move-project-file-back-to-code
Approved by esben-semmle
2018-11-26 11:41:39 +00:00
Esben Sparre Andreasen
2d7f09d321 JS(ql): support nullish coalescing operators 2018-11-26 10:31:19 +01:00
Esben Sparre Andreasen
a2a798e59c JS(extractor): support nullish coalescing operators 2018-11-26 09:45:19 +01:00
Max Schaefer
93f4ee8813 JavaScript: Remove Eclipse metadata files for extractor. 2018-11-26 08:24:33 +00:00
Kevin Backhouse
bc752e1a98 Add post-dominators. 2018-11-24 18:23:27 +00:00
Geoffrey White
f338a4f0d6 CPP: Fix false positive from AutoGeneratedFile.qll. 2018-11-23 17:34:18 +00:00
Tom Hvitved
03e69e9945 C#: Make guards library work with CFG splitting 2018-11-23 15:20:33 +01:00
Tom Hvitved
228189db5a C#: Add tests for guards inside split CFG blocks 2018-11-23 15:20:27 +01:00
calum
b67bc7b612 C#: Fix id generation of constructed methods, by avoid id clashes by ensuring that method type parameters are qualified where necessary. Add a qltest. 2018-11-23 12:11:10 +00:00
calum
051dd191ac C#: Change notes. 2018-11-23 12:11:10 +00:00
calum
e00807d66b C#: Fix decoding method type parameters in FSharp.Core. 2018-11-23 12:09:52 +00:00
Geoffrey White
0855543ac4 CPP: Tag the JPL_C LOC-4 queries. 2018-11-23 10:31:37 +00:00
Geoffrey White
e6dddd90b7 CPP: Add a test of FunctionPointerConversions.ql. 2018-11-23 10:31:36 +00:00
Geoffrey White
5d8e34a55f CPP: Add a test of NonConstFunctionPointer.ql. 2018-11-22 17:48:40 +00:00
Geoffrey White
17560cf92e CPP: Tag the JPL_C LOC-3 queries. 2018-11-22 17:48:35 +00:00
Geoffrey White
9cc39ae875 CPP: Tag the JPL_C LOC-2 queries. 2018-11-22 16:31:08 +00:00
Geoffrey White
a47db56a68 CPP: Tag DuplicateBlock.ql. 2018-11-22 16:31:08 +00:00
1330 changed files with 37406 additions and 17619 deletions

1
.gitattributes vendored
View File

@@ -46,3 +46,4 @@
*.jpg -text
*.jpeg -text
*.gif -text
*.dll -text

View File

@@ -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

View 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

View 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

View 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

View 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

View 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.

View File

@@ -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"
]
}

View File

@@ -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"

View File

@@ -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, _))
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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()

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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()

View File

@@ -4,6 +4,8 @@
* @kind problem
* @id cpp/jpl-c/exit-nonterminating-loop
* @problem.severity warning
* @tags correctness
* external/jpl
*/
import cpp

View File

@@ -5,6 +5,8 @@
* @kind problem
* @id cpp/jpl-c/loop-bounds
* @problem.severity warning
* @tags correctness
* external/jpl
*/
import cpp

View File

@@ -4,6 +4,10 @@
* @kind problem
* @id cpp/jpl-c/recursion
* @problem.severity warning
* @tags maintainability
* readability
* testability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/thread-safety
* @problem.severity warning
* @tags correctness
* concurrency
* external/jpl
*/
import cpp

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/avoid-nested-semaphores
* @problem.severity warning
* @tags correctness
* concurrency
* external/jpl
*/
import Semaphores

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/out-of-order-locks
* @problem.severity warning
* @tags correctness
* concurrency
* external/jpl
*/
import Semaphores

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/release-locks-when-acquired
* @problem.severity warning
* @tags correctness
* concurrency
* external/jpl
*/
import Semaphores

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/simple-control-flow-goto
* @problem.severity warning
* @tags maintainability
* readability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,8 @@
* @kind problem
* @id cpp/jpl-c/extern-decls-in-header
* @problem.severity warning
* @tags maintainability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/checking-return-values
* @problem.severity warning
* @tags correctness
* reliability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/no-boolean-side-effects
* @problem.severity warning
* @tags correctness
* readability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/mismatched-ifdefs
* @problem.severity warning
* @tags maintainability
* readability
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -4,6 +4,9 @@
* @kind problem
* @id cpp/jpl-c/function-pointer-conversions
* @problem.severity warning
* @precision low
* @tags correctness
* external/jpl
*/
import cpp

View File

@@ -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

View File

@@ -1 +0,0 @@
<queries language="cpp"/>

View File

@@ -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

View File

@@ -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))),

View File

@@ -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

View File

@@ -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

View File

@@ -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())
}

View File

@@ -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())
}

View File

@@ -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())
}

View File

@@ -4,6 +4,11 @@
* @kind problem
* @id cpp/duplicate-block
* @problem.severity recommendation
* @precision medium
* @tags testability
* maintainability
* duplicate-code
* non-attributable
*/
import CodeDuplication

View File

@@ -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)

View File

@@ -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)
)
}
/**

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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. */

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 = "?" }

View File

@@ -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)
}

View File

@@ -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"
)
}

View File

@@ -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)
}

View File

@@ -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()
)
)
}
}

View File

@@ -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()
}
}

View File

@@ -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)
}

View File

@@ -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"
)
}

View File

@@ -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()
)
)
}
}

View File

@@ -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()
}
}

View File

@@ -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")
}

View File

@@ -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")
}
}

View File

@@ -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`.
*

View File

@@ -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

View File

@@ -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:

View File

@@ -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 | { ... } |

View File

@@ -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 | { ... } |

View File

@@ -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 | { ... } |

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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;
}

View File

@@ -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 |

View File

@@ -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 | |

View File

@@ -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