Compare commits

...

663 Commits

Author SHA1 Message Date
Henry Mercer
6ae028ebb3 Expose invoke nodes for external API sinks 2021-03-05 21:35:07 +00:00
yoff
7fef1a8817 Merge pull request #5069 from tausbn/python-api-graphs
Python: Add support for API graphs
2021-02-05 13:17:09 +01:00
Taus Brock-Nannestad
78cb53449d Python: Slight cleanup of Cached::call
Makes it more similar to the other functions in this module.
2021-02-05 12:47:26 +01:00
Taus
6c8dfb253d Python: Use flowsTo instead of hasLocalSource
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-02-05 12:42:41 +01:00
Tamás Vajk
d7505e41db Merge pull request #5091 from tamasvajk/feature/cleanup-nullable
C#: Fix nullable warnings and some code quality issues
2021-02-05 12:07:42 +01:00
Jonas Jensen
6e5d56cbcb Merge pull request #5097 from geoffw0/qldoceg11
C++: QLDoc Improvements
2021-02-05 12:00:35 +01:00
Shati Patel
474ddc9bc8 Merge pull request #5090 from RasmusWL/docs-fix-direct-query-link
Docs: Use /blob/ instead of /tree/ for direct query link
2021-02-05 10:50:40 +00:00
Jonas Jensen
c945ece80d Merge pull request #5100 from MathiasVP/fix-changenote-unsigned-difference-expression-compared-zero
C++: Add query author and link to original PR in change-note
2021-02-05 11:21:48 +01:00
Geoffrey White
55b0dbd7b8 C++: Autoformat. 2021-02-05 10:02:31 +00:00
Taus
a66743192e Python: Fix typo in docs
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-02-05 10:58:47 +01:00
Mathias Vorreiter Pedersen
a416a089b4 Update cpp/change-notes/2020-02-04-unsigned-difference-expression-compared-zero.md
Co-authored-by: Jonas Jensen <jbj@github.com>
2021-02-05 09:48:54 +01:00
Tamás Vajk
87ba9d55b6 Merge pull request #4687 from tamasvajk/feature/csharp9-records
C#: Extract record declarations
2021-02-05 08:56:24 +01:00
Robert Marsh
649bd03db6 Merge pull request #5101 from NateD-MSFT/patch-1
Add KeGetCurrentProcessorNumberEx to CWE-457 whitelist
2021-02-04 16:59:07 -08:00
NateD-MSFT
9470a99092 Add KeGetCurrentProcessorNumberEx to CQE-457 whitelist
Windows driver developers may call KeGetCurrentProcessorNumberEx in their driver.  This function optionally may initialize a provided structure, but this initialization always occurs.  The return value is the current processor being run on.  As such, this query incorrectly marks calls to KeGetCurrentProcessorNumberEx that initialize a structure that is later used as risky, even though in reality the initialization always succeeds.

See https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-kegetcurrentprocessornumberex
2021-02-04 13:32:09 -08:00
Tamas Vajk
83f0fad014 Fix expected test AST 2021-02-04 21:08:01 +01:00
Tamas Vajk
f555c0642e Add change note 2021-02-04 21:08:01 +01:00
Tamas Vajk
f0b0845f9f Add 'record' QL class 2021-02-04 21:08:01 +01:00
Tamas Vajk
9ffc38f5b1 Fix deterministic ordering of class members in PrintAst 2021-02-04 21:08:01 +01:00
Tamas Vajk
a6fd7a3203 C#: Extract record declarations 2021-02-04 21:08:01 +01:00
Mathias Vorreiter Pedersen
993abd4499 C++: Add query author and link to original PR in change-note. 2021-02-04 20:23:27 +01:00
Taus
f0d5a91d59 Merge pull request #5093 from RasmusWL/fix-query-names-with-dunder
Python: Fix query names with dunder (__)
2021-02-04 18:47:45 +01:00
Taus Brock-Nannestad
d035937083 Python: Add change note 2021-02-04 18:43:44 +01:00
Taus Brock-Nannestad
a505eb6922 Python: Adhere to QLDoc style guide 2021-02-04 18:34:06 +01:00
Taus Brock-Nannestad
3c7d9c3c4b Python: Fix typo 2021-02-04 18:33:50 +01:00
Geoffrey White
2160edc789 C++: Clean up bits I didn't finish. 2021-02-04 17:16:45 +00:00
Geoffrey White
1f928c2910 CPP: Examples Element.qll. 2021-02-04 17:08:29 +00:00
Geoffrey White
8ae01789b1 CPP: Examples Specifier.qll. 2021-02-04 17:08:29 +00:00
Geoffrey White
500097ca76 CPP: Examples Preprocessor.qll. 2021-02-04 17:08:29 +00:00
Geoffrey White
4b9532c6f7 CPP: Examples Namespace.qll. 2021-02-04 17:08:29 +00:00
Taus Brock-Nannestad
f6e1ea5b2a Python: Fix missing global variable source nodes
In lieu of removing the offending flow (which would likely have
consequences for a lot of other tests), I opted to simply _include_
the relevant nodes directly.
2021-02-04 18:07:13 +01:00
Taus Brock-Nannestad
2524f23a46 Python: Add more test cases
There is now a bit of redundancy in the tests, but I thought it useful
to actually include some of the cases called out explicitly in the
documentation, so as to make it easy to see that the code actually
does what we expect (in these cases, anyway).
2021-02-04 18:05:33 +01:00
Taus Brock-Nannestad
aa7e9f0b56 Python: Add big explanatory comment about prefixes. 2021-02-04 18:03:34 +01:00
Geoffrey White
69c7c83bc2 Merge pull request #5094 from MathiasVP/promote-UnsignedDifferenceExpressionComparedZero
Promote cpp/unsigned-difference-expression-compared-zero out of experimental
2021-02-04 16:54:45 +00:00
Mathias Vorreiter Pedersen
cf0e464ab9 Merge branch 'promote-UnsignedDifferenceExpressionComparedZero' of github.com:MathiasVP/ql into promote-UnsignedDifferenceExpressionComparedZero 2021-02-04 17:24:59 +01:00
Mathias Vorreiter Pedersen
6a97d02247 C++: Address review comments. 2021-02-04 17:24:14 +01:00
Mathias Vorreiter Pedersen
161e5679a7 Apply suggestions from code review
Co-authored-by: hubwriter <hubwriter@github.com>
2021-02-04 16:47:45 +01:00
Taus Brock-Nannestad
305bfaba2d Python: Fix imports/2 2021-02-04 16:46:22 +01:00
Mathias Vorreiter Pedersen
d9d82fc56a C++: Update change-notes 2021-02-04 16:24:56 +01:00
Geoffrey White
7c54512859 Merge pull request #5010 from ihsinme/ihsinme-patch-220
CPP: Add query for CWE-570 detect and handle memory allocation errors.
2021-02-04 15:17:28 +00:00
Mathias Vorreiter Pedersen
707f532e10 C++: Fix bad join-order using a poor man's unbind operator. 2021-02-04 16:11:34 +01:00
Mathias Vorreiter Pedersen
fd596ebbbb C++: Move cpp/unsigned-difference-expression-compared-zero out of experimental. 2021-02-04 16:10:34 +01:00
Mathias Vorreiter Pedersen
c1c9f963b9 C++: Fix qhelp in cpp/unsigned-difference-expression-compared-zero. 2021-02-04 16:10:30 +01:00
Taus Brock-Nannestad
07ffa9f1ae Python: More documentation 2021-02-04 15:59:00 +01:00
Taus Brock-Nannestad
e54c925b70 Python: Greatly simplify imports/2 predicate 2021-02-04 15:58:15 +01:00
Rasmus Wriedt Larsen
b94658fd52 Python: Highlight that __slots__ query is only for Python 2 in qhelp
Since I was already editing this file, it was easy to just add this extra bit of
info.
2021-02-04 15:54:37 +01:00
Rasmus Wriedt Larsen
23d9e2646a Python: Fix name of class in example of __slots__ qhelp 2021-02-04 15:54:10 +01:00
Rasmus Wriedt Larsen
dcb185b659 Python: Fix trailing whitespace in a single qhelp file
Since I edited already, why not get this little bonus? :D
2021-02-04 15:53:23 +01:00
Rasmus Wriedt Larsen
32be53bf72 Python: Fix missing <code> in qhelp file 2021-02-04 15:53:04 +01:00
Rasmus Wriedt Larsen
3fe715abb6 Python: Fix query names that inclde __ (dunder)
Without backticks, the text UNDERSCORE UNDERSCORE eq UNDERSCORE UNDERSCORE would
be considered to make things bold in our markdown output, making the query info
look strange.

Example https://codeql.github.com/codeql-query-help/python/py-slots-in-old-style-class/
2021-02-04 15:49:37 +01:00
Anders Schack-Mulligen
35e620a19c Merge pull request #4854 from luchua-bc/java/insecure-ldap-auth
Java: Insecure LDAP authentication
2021-02-04 14:56:38 +01:00
Tamas Vajk
ce27831b76 C#: Fix nullable warnings and some code quality issues 2021-02-04 14:43:51 +01:00
Rasmus Wriedt Larsen
4af7bc8090 Docs: Use /blob/ instead of /tree/ for direct query link
It doesn't have a huge impact, since there is a working redirect in place, but
still more correct to use /blob/ :)

For example,

https://github.com/github/codeql/tree/main/python/ql/src/Security/CWE-094/CodeInjection.ql

redirects to

https://github.com/github/codeql/blob/main/python/ql/src/Security/CWE-094/CodeInjection.ql
2021-02-04 14:30:56 +01:00
Mathias Vorreiter Pedersen
d3d56fb0af Merge pull request #5011 from ihsinme/ihsinme-patch-221
CPP: add query for CWE-788 Access of memory location after the end of a buffer using strlen.
2021-02-04 14:25:27 +01:00
Mathias Vorreiter Pedersen
9b39163411 Merge pull request #5076 from MathiasVP/improve-UnsignedDifferenceExpressionComparedZero
C++: Improve cpp/unsigned-difference-expression-compared-zero
2021-02-04 14:05:30 +01:00
ihsinme
43045c1f03 Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-02-04 15:47:16 +03:00
ihsinme
a43167faf7 Update WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp 2021-02-04 15:44:28 +03:00
ihsinme
2131f35801 Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-02-04 15:41:40 +03:00
Mathias Vorreiter Pedersen
b55921a391 Update cpp/ql/src/experimental/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2021-02-04 13:25:02 +01:00
Taus Brock-Nannestad
d01d7eea82 Python: Add documentation from DataFlowUtil::importNode 2021-02-04 13:08:19 +01:00
Julian Tibble
a666a692f9 Merge pull request #5086 from github/update-codeql-workflow
Update CodeQL workflow
2021-02-04 12:02:53 +00:00
Taus
634041d2d7 Merge pull request #5047 from yoff/python-dataflow-unpacking-unifying-experiments
Python: dataflow, unify iterated unpacking
2021-02-04 12:57:43 +01:00
Taus
bc448fe067 Merge pull request #5088 from RasmusWL/fix-small-typo
Python: Fix small typo in test-output
2021-02-04 12:56:56 +01:00
Geoffrey White
d41ea6c799 Merge pull request #5081 from MathiasVP/indirection-in-dataflow-models
C++: Add more indirection flow in dataflow models
2021-02-04 11:55:34 +00:00
Julian Tibble
121ffbbfa8 Restrict triggers for CodeQL workflow
Analysing all branches on both 'push' and 'pull request' events causes
duplicate analysis. It is only necessary to analyse the _target_
branches of pull requests on push.
2021-02-04 11:49:15 +00:00
Julian Tibble
ecfad6b5c7 Update CodeQL workflow
Bring the CodeQL workflow up to date with the latest recommended
configuration, which analyses the merge commit of pull requests (not the
head of the PR branch).
2021-02-04 11:45:15 +00:00
Taus
4627799c93 Python: Fix more typos
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-02-04 12:41:17 +01:00
Taus
e5ec1e105c Python: Fix typos in test files
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-02-04 12:18:07 +01:00
Rasmus Wriedt Larsen
ac0f2d37db Python: Fix small typo in test-output
Spotted by yoff in https://github.com/github/codeql/pull/5069#discussion_r570063207
2021-02-04 12:11:20 +01:00
Mathias Vorreiter Pedersen
55615586ee C++: Address review comments. 2021-02-04 11:30:44 +01:00
Tamás Vajk
26288ad391 Merge pull request #5082 from tamasvajk/feature/initial-db
C#: Add initial DB scheme
2021-02-04 11:23:42 +01:00
Tamás Vajk
ca992f2d3c Merge pull request #5005 from tamasvajk/feature/follow-line
C#: Follow line directives when getting element location
2021-02-04 11:22:55 +01:00
Mathias Vorreiter Pedersen
47ab9ba81b C++: emplace and emplace_back takes its arguments by universal references, so they should also specify flow as indirections. 2021-02-04 11:16:27 +01:00
Tamás Vajk
1fd244923b Merge pull request #5052 from tamasvajk/feature/fnptr-df
C#: Add data flow 'getARuntimeTarget' predicate to 'FunctionPointerCall'
2021-02-04 08:51:03 +01:00
Tamas Vajk
543f5916c4 Fix expected test AST 2021-02-04 08:49:19 +01:00
Tamas Vajk
88d1539d43 Fix file read error log message 2021-02-04 08:42:39 +01:00
Tamas Vajk
7068a265a6 Fix XML comment processing 2021-02-04 08:42:39 +01:00
Tamas Vajk
d3244fe298 Add new .stats file 2021-02-04 08:42:39 +01:00
Tamas Vajk
dbe656fe6a Add DB upgrade folder for preprocessor directives 2021-02-04 08:42:39 +01:00
Tamas Vajk
fd09883bfe Add change notes for preprocessor directives 2021-02-04 08:42:39 +01:00
Tamas Vajk
899e52a68a Adjust getMappedLocation to not include line directives 2021-02-04 08:42:39 +01:00
Tamas Vajk
a1d227dbbb C#: Follow line directives when getting element location 2021-02-04 08:42:39 +01:00
Tamas Vajk
967765342e Assign preprocessor directives to compilation + make compilation cached 2021-02-04 08:42:39 +01:00
Tamas Vajk
1ab4af275d Rework if/elif/else/endif extraction 2021-02-04 08:42:39 +01:00
Tamas Vajk
72547b89e6 Rework endregion extraction 2021-02-04 08:42:39 +01:00
Tamas Vajk
a5dec5b4aa C#: Limit ancestor traversal for 'if' and 'elif' lookup 2021-02-04 08:42:38 +01:00
Tamas Vajk
2b7cc15757 Introduce base class for branching and conditional directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
e450b61464 Fix code review findings in directives base class 2021-02-04 08:42:38 +01:00
Tamas Vajk
60b23dc505 Fix code review findings in 'endregion' directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
6ef8e51bcf Fix code review findings in 'line' directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
f7832adfb8 Fix code review findings in 'nullable' directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
567516471c Fix code review findings in 'define' directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
bd64dda4c3 Fix code review findings in pragma warning directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
3900698b41 Add doc comments for preprocessor directive base class 2021-02-04 08:42:38 +01:00
Tamas Vajk
a896e1522d Extract active flag from directives, fix missing assembly location 2021-02-04 08:42:38 +01:00
Tamas Vajk
41fbce0ad0 Extract #if directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
a5d18f9b68 Extract region directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
fe0a494bab Extract line directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
4bb8b6c992 Extract nullable directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
15c611e22f Extract warning and error directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
3740aba4a8 Extract undef directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
9b405144ff Extract define directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
94bf3467b7 Extract pragma checksum directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
8b9c6712d1 Extract pragma warning directives 2021-02-04 08:42:38 +01:00
Tamas Vajk
40186db768 Rename CommentPopulator 2021-02-04 08:42:38 +01:00
Tamas Vajk
48d24b2264 Get line comments from trivia lines 2021-02-04 08:42:38 +01:00
Tamas Vajk
046a37b834 Simplify element access extraction 2021-02-04 08:42:38 +01:00
Tamas Vajk
c3ef6841d0 Add tests for trivia types 2021-02-04 08:42:38 +01:00
Tamas Vajk
3be229f097 C#: Separate visitors to dedicated files, rename and reorganize comment extraction related classes 2021-02-04 08:42:38 +01:00
Taus Brock-Nannestad
5974af661e Python: Update test file
Makes the `a.b.c.d` test more sensible.

Also adds a test that shows a case where we're currently _not_ getting
the right flow.
2021-02-03 22:43:21 +01:00
Taus Brock-Nannestad
ba98b08001 Python: Further elaboration of use/3 2021-02-03 22:31:33 +01:00
Taus Brock-Nannestad
ebfb1faf77 Python: Autoformat 2021-02-03 22:26:46 +01:00
Rasmus Lerchedahl Petersen
a7ca065411 Python: Fix ForTarget 2021-02-03 22:14:15 +01:00
yoff
b5633625b3 Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-02-03 21:56:03 +01:00
Tamas Vajk
cccca879d9 C#: Add initial DB scheme 2021-02-03 21:52:00 +01:00
Taus
56515c5708 Python: Improve documentation for moduleImport
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-02-03 21:29:15 +01:00
Tom Hvitved
cf860f1dac Merge pull request #5071 from hvitved/csharp/ssa/uncertain-reads
C#: Move uncertain-read logic into shared SSA implementation
2021-02-03 20:27:45 +01:00
Taus Brock-Nannestad
05f290f734 Python: Better explanation in use/3 2021-02-03 19:52:40 +01:00
Taus Brock-Nannestad
c5d6792c1e Python: Make toString abstract 2021-02-03 19:52:40 +01:00
Taus Brock-Nannestad
6ce160c51c Python: Use call instead of invocation 2021-02-03 19:52:40 +01:00
luchua-bc
724c3e00e0 Update help file 2021-02-03 16:45:15 +00:00
Taus Brock-Nannestad
3fafb47b16 Python: Fix global flow
A slightly odd fix, but still morally okay, I think. The main issue
here was that global variables have their first occurrence in an inner
scope inside a so-called "scope entry definition", that then
subsequently flows to the first use of this variable. This meant that
that first use was _not_ a `LocalSourceNode` (since _something_ flowed
into it), and this blocked `trackUseNode` from type-tracking to it (as
it expects all nodes to be `LocalSourceNode`s).

The answer, then, is to say that a `LocalSourceNode` is simply one
that doesn't have flow to it from _any `CfgNode`_ (through one or more
steps). This disregards the flow from the scope entry definition, as
that is flow from an `EssaNode`.

Additionally, it makes sense to exclude `ModuleVariableNode`s. These
should never be considered local sources, since they always have flow
from (at least) the place where the corresponding global variable is
introduced.
2021-02-03 16:41:22 +01:00
Mathias Vorreiter Pedersen
8cf8b704c5 C++: Add more indirection flow in dataflow models. Also revert the additions to DataFlowUtil added in #5035 as they can add too much flow. 2021-02-03 16:16:48 +01:00
Anders Schack-Mulligen
40d02e7e32 Merge pull request #4926 from luchua-bc/java/insufficient-key-size
Java: Query to detect weak encryption: insufficient key size
2021-02-03 15:16:10 +01:00
Anders Schack-Mulligen
0df7e9fa4e Merge pull request #4989 from lcartey/lcartey/spring-inheritence-improvements
Java: Track taint through Spring Java bean getters on super types
2021-02-03 15:06:03 +01:00
Jonas Jensen
e3bdebf7a0 Merge pull request #5077 from jbj/revert-nested-fields
C++: Revert #4784
2021-02-03 14:07:28 +01:00
luchua-bc
2ace10fcdf Use PostUpdateNode for wrapper method calls 2021-02-03 12:21:31 +00:00
Tom Hvitved
a45c415c5b Merge pull request #5067 from hvitved/csharp/cfg/patterns
C#: Adjust CFG for `{Recursive,Positional,Property}PatternExpr`
2021-02-03 12:09:39 +01:00
Mathias Vorreiter Pedersen
691a316460 C++: Add tests to cpp/unsigned-difference-expression-compared-zero and remove a couple of classes of FPs. 2021-02-03 11:10:57 +01:00
Jonas Jensen
064568c36d Revert "Merge pull request #4784 from MathiasVP/mathiasvp/reverse-read-take-3"
This reverts commit 1b3d69d617, reversing
changes made to 527c41520e.
2021-02-03 08:49:37 +01:00
CodeQL CI
653c900d62 Merge pull request #4987 from erik-krogh/defensiveFunctions
Approved by esbena
2021-02-02 14:47:23 -08:00
Erik Krogh Kristensen
c51e951d1e add change note 2021-02-02 22:51:03 +01:00
CodeQL CI
209fe8d7e5 Merge pull request #5049 from erik-krogh/singleQuote
Approved by esbena
2021-02-02 13:48:42 -08:00
Taus Brock-Nannestad
e4c3544a3f Python: Add support for from foo.bar import baz
This turned out to be fairly simple. Given an import such as
```python
from foo.bar.baz import quux
```
we create an API-graph node for each valid dotted prefix of
`foo.bar.baz`, i.e. `foo`, `foo.bar`, and `foo.bar.baz`. For these, we
then insert nodes in the API graph, such that `foo` steps to `foo.bar`
along an edge labeled `bar`, etc.

Finally, we only allow undotted names to hang off of the API-graph
root. Thus, `foo` will have a `moduleImport` edge off of the root, and
a `getMember` edge for `bar` (which in turn has a `getMember` edge for
`baz`).

Relative imports are explicitly ignored.

Finally, this commit also adds inline tests for a variety of ways of
importing modules, including a copy of the "import-helper" tests (with
a few modifications to allow a single annotation per line, as these
get rather long quickly!).
2021-02-02 21:59:33 +01:00
luchua-bc
3151aeff48 Enhance the query 2021-02-02 18:26:29 +00:00
Geoffrey White
047cd2b706 Merge pull request #5074 from MathiasVP/strnextc-model-implementation
C++: Implement a model for _strnextc and its variants
2021-02-02 16:45:16 +00:00
luchua-bc
5e3b6fa341 Update qldoc 2021-02-02 16:20:39 +00:00
Mathias Vorreiter Pedersen
ff58d5a7c0 C++: Address review comments. 2021-02-02 17:06:38 +01:00
Mathias Vorreiter Pedersen
9e75a4be34 C++: Implement a model for _strnextc and its variants. 2021-02-02 16:42:39 +01:00
Mathias Vorreiter Pedersen
98d73bf474 Merge pull request #5072 from MathiasVP/strcrement-model-implementation
C++: Implement model for _strinc and related functions
2021-02-02 16:22:13 +01:00
Mathias Vorreiter Pedersen
07a20752bc Fix spelling in qldoc.
Co-authored-by: Cornelius Riemenschneider <criemen@github.com>
2021-02-02 15:51:40 +01:00
luchua-bc
50be54385a Update qldoc 2021-02-02 14:49:50 +00:00
Jonas Jensen
aa9ab41e30 Merge pull request #5059 from geoffw0/mswprintf
C++: Exclude custom vprintf implementations from primitiveVariadicFormatter.
2021-02-02 15:13:25 +01:00
Geoffrey White
708d3870ee C++: Actually it's more appropriate to remove the implementation of vswprintf. 2021-02-02 13:42:27 +00:00
Tamas Vajk
64f0dfb174 Fix code review findings 2021-02-02 14:21:26 +01:00
Geoffrey White
4e904dd87d C++: Repair the test. 2021-02-02 13:08:46 +00:00
Mathias Vorreiter Pedersen
b54f74a68a C++: Implement model for _strinc and related functions. 2021-02-02 12:20:02 +01:00
Mathias Vorreiter Pedersen
5db1984315 Merge pull request #5070 from MathiasVP/strsep-model-implementation
C++: Add strsep model implementation.
2021-02-02 12:00:26 +01:00
Geoffrey White
eed2aee17d C++: Effect on tests. 2021-02-02 10:59:14 +00:00
Geoffrey White
9f50f67e6d Merge pull request #5065 from MathiasVP/scanf-model
C++: Add sscanf and fscanf models
2021-02-02 10:30:19 +00:00
Tom Hvitved
b19fd7bb72 C#: Only cache TDefinition in the shared SSA implementation 2021-02-02 10:52:03 +01:00
Mathias Vorreiter Pedersen
0db54e08b8 C++: Address review comments. 2021-02-02 10:48:07 +01:00
Tom Hvitved
74fd2c1c38 C#: Move uncertain-read logic into shared SSA implementation 2021-02-02 10:43:13 +01:00
CodeQL CI
4fdbda3543 Merge pull request #5056 from erik-krogh/react
Approved by asgerf
2021-02-02 01:40:08 -08:00
Mathias Vorreiter Pedersen
6e71c68f33 C++: Add strsep model implementation. 2021-02-02 10:29:23 +01:00
Tom Hvitved
1ffa15ea96 C#: Update expected test output 2021-02-02 08:52:28 +01:00
Tom Hvitved
8abc37fba3 Merge pull request #5051 from hvitved/csharp/ssa/caching
C#: Reduce caching in `SsaImplCommon.qll`
2021-02-02 08:35:03 +01:00
Erik Krogh Kristensen
ca435763b0 separate message for double and single quotes 2021-02-01 23:54:12 +01:00
Taus Brock-Nannestad
cd7b013a0c Python: Add missing documentation 2021-02-01 18:57:25 +01:00
CodeQL CI
749dfe4358 Merge pull request #5068 from Marcono1234/patch-1
Approved by shati-patel
2021-02-01 08:47:55 -08:00
yoff
b92af8bcec Merge pull request #5042 from RasmusWL/django-more-view-classes
Python: Add full-path modeling of Django more view classes
2021-02-01 17:33:29 +01:00
Marcono1234
fa469587c1 Remove duplicate word in language specification 2021-02-01 17:32:53 +01:00
yoff
c0511ca9f9 Merge pull request #5053 from github/python-add-essavariable-locations
Python: Add locations for ESSA variables
2021-02-01 17:31:25 +01:00
Tamás Vajk
700a2dbb93 Merge pull request #5063 from tamasvajk/feature/remove-indexerproperty-ast
C#: Report IndexerProperty as Property in the PrintAST query
2021-02-01 17:25:25 +01:00
Mathias Vorreiter Pedersen
be9908df87 C++: Fix copy/paste error. 2021-02-01 16:45:07 +01:00
yoff
384d0212b1 Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
Co-authored-by: Taus <tausbn@github.com>
2021-02-01 16:41:43 +01:00
Mathias Vorreiter Pedersen
71e1218ad5 Merge pull request #5061 from MathiasVP/more-memcpy-memset-strcpy-strcat-models
C++: Add more memcpy, memset, strcat and strcpy models
2021-02-01 16:25:01 +01:00
Mathias Vorreiter Pedersen
9db19613d6 C++: Reuse logic from commons/Scanf. 2021-02-01 16:10:28 +01:00
Taus Brock-Nannestad
fc01e5607f Python: Use getLocation directly on EssaNode 2021-02-01 14:55:18 +01:00
Taus Brock-Nannestad
b8194bd1f8 Python: Add support for API graphs
Currently only supports the "use" side of things.

For the most part, this follows the corresponding implementation for
JavaScript. Major differences include:

- No `MkImportUse` nodes -- we just move directly from
  `MkModuleImport` to its uses.

- Paths are no longer labelled by s-expressions, but rather by a
string that mirrors how you would access it in QL. This makes it very
easy to see how to access an API component -- simply look at its
`toString`!

This PR also extends `LocalSourceNode` to support looking up attribute
references and invocations of such nodes. This was again based on the
JavaScript equivalent (though without specific classes for
`InvokeNode` and the like, it's a bit more awkward to use).
2021-02-01 14:38:59 +01:00
CodeQL CI
2de230ea75 Merge pull request #5062 from esbena/js/test-for-html-concat-obfuscation
Approved by erik-krogh
2021-02-01 05:29:50 -08:00
Tom Hvitved
249e431e87 C#: Adjust CFG for {Recursive,Positional,Property}PatternExpr 2021-02-01 13:52:18 +01:00
Tamas Vajk
7d62e33feb C#: Rework function pointer/delegate call DF 2021-02-01 13:40:03 +01:00
Mathias Vorreiter Pedersen
27b41c2016 C++: Address review comments. 2021-02-01 13:32:46 +01:00
Mathias Vorreiter Pedersen
c747914ef2 C++: Add sscanf and fscanf model implementations. 2021-02-01 12:54:59 +01:00
Taus
b8b42eaea3 Merge pull request #5064 from RasmusWL/fix-missing-override
Python: Add missing override annotation
2021-02-01 12:37:38 +01:00
Mathias Vorreiter Pedersen
61125b4bf2 C++: Address review comments. 2021-02-01 12:15:57 +01:00
Taus
3179546b8c Merge pull request #5058 from yoff/python-add-consistency-checks-to-all-dataflow-test-folders
Python: Add consistency checks to all data-flow test folders
2021-02-01 11:41:31 +01:00
Rasmus Wriedt Larsen
4ef9a6cf2a Python: Add missing override annotation 2021-02-01 11:28:41 +01:00
Rasmus Wriedt Larsen
4b6a59a126 Python: Apply code-review suggestion
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-02-01 11:12:32 +01:00
Esben Sparre Andreasen
9678534f25 JS: add tests for some syntactic XSS vector obfuscations 2021-02-01 10:20:23 +01:00
Tamas Vajk
1b6cb340d3 C#: Report IndexerProperty as Property in the PrintAST query 2021-02-01 10:08:51 +01:00
Erik Krogh Kristensen
aae69c6537 update expected output 2021-02-01 09:33:52 +01:00
Tamás Vajk
aa35fcafeb Merge pull request #5018 from tamasvajk/feature/csharp9-binary-pattern-cfg
C#: Extract 'and' and 'or' patterns
2021-02-01 09:17:52 +01:00
Rasmus Lerchedahl Petersen
27fd46b855 Python: Update test expectation 2021-02-01 08:55:20 +01:00
Rasmus Lerchedahl Petersen
6730396ad6 Python: Remove tests from non-test directory 2021-02-01 08:52:00 +01:00
Mathias Vorreiter Pedersen
6c3f44bba8 C++: Add more memcpy, memset, strcat and strcpy models. Also refine which strcpy functions can live in the std namespace. 2021-02-01 08:44:10 +01:00
ihsinme
2b946aee5a Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-01-31 15:21:54 +03:00
ihsinme
b7df18b97e Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql 2021-01-31 15:16:40 +03:00
Geoffrey White
064d89735b Merge pull request #5046 from MathiasVP/model-more-pure-functions
C++: Model more pure functions
2021-01-29 22:05:48 +00:00
Geoffrey White
03922aa1f5 C++: Exclude custom vprintf implementations. 2021-01-29 21:20:36 +00:00
Rasmus Lerchedahl Petersen
f6fa1276a6 Python: Add consistency checks
to all data-flow test floders
2021-01-29 21:28:43 +01:00
Rasmus Lerchedahl Petersen
05a138694d Python: Fix crashing test 2021-01-29 21:12:44 +01:00
Rasmus Lerchedahl Petersen
7f1affa122 Python: UnpackingAssignment -> IterableUnpacking 2021-01-29 17:44:53 +01:00
Rasmus Lerchedahl Petersen
182d435dc6 Python: Replace comprehension read-step by for
read-step. Add a version targetting sequence nodes.
2021-01-29 17:31:59 +01:00
Tamas Vajk
7e9913a8a7 Fix failing pattern tests 2021-01-29 17:25:44 +01:00
Tamas Vajk
a9c51e7300 Fix missing pattern matching completions 2021-01-29 15:16:30 +01:00
CodeQL CI
c9537f2639 Merge pull request #5029 from asgerf/js/silence-angular-template-fps
Approved by erik-krogh
2021-01-29 06:06:37 -08:00
Taus Brock-Nannestad
817a142abc Python: Add getLocation to EssaVariable.
This may be a slightly "bogus" location to provide for ESSA variables,
but it can be useful for debugging. For instance, where previously you
might just see

```
SSA variable x | ...
SSA variable x | ...
SSA variable x | ...
SSA variable x | ...
SSA variable x | ...
SSA variable x | ...
```

where each instance of `SSA variable x` was just a bare string, now
each occurrence will tell you (via its location) _where_ this variable
is being (re)defined.
2021-01-29 14:45:12 +01:00
Taus
cb195a0dc4 Merge pull request #4752 from yoff/python-dataflow-unpacking-assignment
Python: Dataflow, unpacking assignment
2021-01-29 14:15:28 +01:00
Taus
be5b7bb4c4 Merge pull request #5022 from yoff/python-split-lambdas
Python: Callable for lambdas
2021-01-29 14:12:26 +01:00
Mathias Vorreiter Pedersen
92a5a2a06a C++: Solve merge conflicts by merging the two test.c test files. 2021-01-29 13:34:19 +01:00
Mathias Vorreiter Pedersen
d5f1c19152 Merge branch 'main' into ihsinme-patch-221 2021-01-29 13:05:07 +01:00
Erik Krogh Kristensen
c9ec983cd8 add js/client-side-unvalidated-url-redirection test for script tags inside react code 2021-01-29 12:50:43 +01:00
Erik Krogh Kristensen
39591687ba add js/code-injection sink for script tags in React 2021-01-29 12:50:17 +01:00
Luke Cartey
76c9b6466e Reformat TaintTrackingUtil.qll with more recent CodeQL CLI 2021-01-29 11:27:30 +00:00
Tamas Vajk
91152d3a65 Add additional tests to delegate call data flow 2021-01-29 12:02:11 +01:00
Tamas Vajk
191962f64c C#: Add data flow 'getARuntimeTarget' predicate to 'FunctionPointerCall' 2021-01-29 12:01:38 +01:00
Tom Hvitved
bf5851f1c2 C#: Reduce caching in SsaImplCommon.qll 2021-01-29 11:42:52 +01:00
ihsinme
bdbf5a4fae Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2021-01-29 13:41:45 +03:00
Tom Hvitved
1a507ff497 C#: Remove Cached module from SsaImplCommon.qll 2021-01-29 10:52:42 +01:00
Geoffrey White
50f2557dd2 Merge pull request #5043 from MathiasVP/uniform-treatment-of-params-and-qualifiers-in-model-dataflow
C++: Uniform treatment of parameters and qualifiers in model dataflow
2021-01-29 09:48:07 +00:00
Erik Krogh Kristensen
3f1e81533c support html attribute concatenations with single quotes 2021-01-29 10:37:37 +01:00
ihsinme
c8eeb5f73e Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-01-29 11:51:15 +03:00
Mathias Vorreiter Pedersen
339c4c6ce0 C++: Model more pure functions. 2021-01-28 19:37:53 +01:00
Geoffrey White
7d9ebaf9d8 Merge pull request #5040 from MathiasVP/strset-and-strtok-models
C++: Strset and strtok model implementations
2021-01-28 18:34:06 +00:00
Geoffrey White
768be9ec2c Merge pull request #5041 from ihsinme/ihsinme-patch-198
CPP: Improve cpp/memory-leak-on-failed-call-to-realloc
2021-01-28 18:29:24 +00:00
Mathias Vorreiter Pedersen
23eb4d2009 C++: Fix isParameterDeref typo. 2021-01-28 18:29:30 +01:00
Mathias Vorreiter Pedersen
75aa1e8a3b C++: Respond to review comments. 2021-01-28 16:39:11 +01:00
Geoffrey White
02d60a26eb Merge pull request #5037 from github/igfoo/decltype
C++: decltypes may have multiple expressions
2021-01-28 14:44:53 +00:00
Shati Patel
1c56c30eba Merge pull request #5028 from shati-patel/docs/update-footer
Docs: Update copyright date in footer
2021-01-28 13:11:43 +00:00
Tom Hvitved
59d87e2570 Merge pull request #4557 from hvitved/csharp/dataflow/parameters
C#: Simpler data-flow modelling of parameters
2021-01-28 14:02:42 +01:00
ihsinme
f94a7fc2f0 Update MemoryLeakOnFailedCallToRealloc.ql 2021-01-28 15:47:38 +03:00
Mathias Vorreiter Pedersen
5a420f2bae C++: Use the new predicates for uniform treatment of parameters and qualifiers in model dataflow. 2021-01-28 13:33:08 +01:00
ihsinme
8ed28157e1 Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected 2021-01-28 15:28:52 +03:00
ihsinme
f65ec97ac2 Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/test.c to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/test.c 2021-01-28 15:28:34 +03:00
ihsinme
8880b38b1f Rename cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref to cpp/ql/test/experimental/query-tests/Security/CWE/CWE-788/semmle/tests/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.qlref 2021-01-28 15:28:15 +03:00
Rasmus Wriedt Larsen
b6007cf324 Merge pull request #5023 from yoff/python-unify-synthetic-post-update-nodes
Python: Only generate one post-update node, even if there are multiple reasons for doing so.
2021-01-28 13:11:50 +01:00
Rasmus Wriedt Larsen
173012578e Python: Add missing type-tracking step for django.views
Easy to overlook, and will onyl be caught by tests if they use `import
parent.thing` and not `from parent import thing`
2021-01-28 12:10:42 +01:00
Rasmus Wriedt Larsen
54725ccbb9 Python: Support full-path import of Django View class
requestHandler still MISSING :(
2021-01-28 12:10:40 +01:00
Rasmus Wriedt Larsen
61d69f2cc8 Python: Add test for full-path import of Django View class 2021-01-28 12:10:39 +01:00
ihsinme
2b4296feb1 Update MemoryLeakOnFailedCallToRealloc.ql 2021-01-28 13:38:26 +03:00
ihsinme
cf565970e3 Merge pull request #1 from github/main
update fork
2021-01-28 13:26:11 +03:00
yoff
1068edeb28 Merge pull request #5038 from RasmusWL/import-fix
Python: Fix too many results from DataFlow::importNode
2021-01-28 11:25:17 +01:00
Mathias Vorreiter Pedersen
2c70106d2d Merge pull request #5009 from ihsinme/ihsinme-patch-219
CPP: add query for CWE-788 Access of memory location after the end of a buffer using strncat.
2021-01-28 11:10:30 +01:00
Anders Schack-Mulligen
bbdd7c9b57 Merge pull request #4963 from joefarebrother/guava-collections
Java: Add flow steps for Guava collection utilities
2021-01-28 11:01:03 +01:00
Mathias Vorreiter Pedersen
7affbfc6cb C++: Add tests. 2021-01-28 10:57:39 +01:00
Mathias Vorreiter Pedersen
6255662114 C++: Add two new model implementation classes. 2021-01-28 10:57:30 +01:00
Tom Hvitved
e6f81bcf0b C#: Update expected test output 2021-01-28 10:34:50 +01:00
Tom Hvitved
6ee5cdf2b2 C#: Simpler data-flow modelling of parameters 2021-01-28 10:34:47 +01:00
Jonas Jensen
69ce24d4b8 Merge pull request #5035 from MathiasVP/implied-deref-flow
C++: Implied dataflow models
2021-01-28 09:35:58 +01:00
Tom Hvitved
65ea01e145 Merge pull request #4999 from hvitved/csharp/dataflow/phi-input
C#: Adjust flow into phi nodes
2021-01-28 09:07:01 +01:00
luchua-bc
ab7d257569 Add more cases and change EC to 256 bits 2021-01-28 04:06:27 +00:00
luchua-bc
2ac7b4bab4 Update qldoc 2021-01-28 04:06:27 +00:00
luchua-bc
058f3af4b2 Refactor the hasShortSymmetricKey method 2021-01-28 04:06:27 +00:00
luchua-bc
cbaee937d0 Optimize the query 2021-01-28 04:06:27 +00:00
luchua-bc
cfc950f803 Query for weak encryption: Insufficient key size 2021-01-28 03:25:15 +00:00
luchua-bc
6a93099b64 Simplify the query and update qldoc 2021-01-28 03:02:53 +00:00
Rasmus Lerchedahl Petersen
0e0b18c214 Python: Adjust comment based on review. 2021-01-28 01:09:03 +01:00
Robert Marsh
0addce5be4 Merge pull request #5036 from MathiasVP/memcpy-models
C++: Model aliasing of memcpy-like functions and include more functions
2021-01-27 14:38:08 -08:00
Rasmus Lerchedahl Petersen
ae2c122159 Python: Small refactor
- align synthetic pre-update nodes with synthetic post -update nodes
- move the classes into the modules
- rename modules after the new main class (eliding "needs")
2021-01-27 23:15:50 +01:00
Mathias Vorreiter Pedersen
24f76f9a17 C++: Accept test changes. 2021-01-27 21:57:12 +01:00
Rasmus Lerchedahl Petersen
2120868939 Python: format 2021-01-27 19:48:01 +01:00
yoff
2c5da85e3b Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll
Co-authored-by: Taus <tausbn@github.com>
2021-01-27 19:43:40 +01:00
Rasmus Wriedt Larsen
5646af56dd Python: Fix too many results from DataFlow::importNode 2021-01-27 19:11:55 +01:00
Rasmus Wriedt Larsen
0d42e546a0 Python: Add deep import chain to import-helper tests 2021-01-27 19:09:09 +01:00
Rasmus Wriedt Larsen
44bb41e84b Python: Add extra type-tracking test for "long" import chain
While trying to debug an other problem related to full import of django view, I
stumbled upon this oddity. (yikes)
2021-01-27 19:06:51 +01:00
Mathias Vorreiter Pedersen
c90dc62cc4 C++: Autoformat. 2021-01-27 18:57:09 +01:00
Mathias Vorreiter Pedersen
aec18e7123 C++: Add mempcpy to MemcpyFunction model class. 2021-01-27 18:12:32 +01:00
Mathias Vorreiter Pedersen
5aff5c3254 C++: Add AliasFunction model to MemcpyFunction. 2021-01-27 18:12:02 +01:00
Mathias Vorreiter Pedersen
066f83630d C++: bcopy can never be in the std namespace. 2021-01-27 18:07:14 +01:00
Ian Lynagh
3880b48736 C++: Add an upgrade script 2021-01-27 16:31:56 +00:00
Tamas Vajk
ca5e3b4489 Add new .stats file 2021-01-27 17:18:50 +01:00
Ian Lynagh
307bef0ec3 C++: decltypes may have multiple expressions 2021-01-27 16:06:42 +00:00
Mathias Vorreiter Pedersen
52e2a69db9 C++: Accept test changes. 2021-01-27 16:56:37 +01:00
Mathias Vorreiter Pedersen
32b5c7fe06 C++: Model implied dataflow 2021-01-27 16:53:21 +01:00
Tamas Vajk
034d0a7b10 Add DB upgrade folder for binary patterns 2021-01-27 16:47:15 +01:00
Tamas Vajk
552e11de19 Fix change note date 2021-01-27 16:42:03 +01:00
Tamas Vajk
669e207600 Fix sign analysis expected file 2021-01-27 16:40:56 +01:00
Geoffrey White
a4d7bfbb2b Merge pull request #5031 from MathiasVP/remove-linear-scan-of-functions-2
C++: Remove more linear scans
2021-01-27 14:29:27 +00:00
Tamas Vajk
d1cc2cc999 Remove code duplication 2021-01-27 13:52:12 +01:00
Tamas Vajk
5157236999 Fix doc comments 2021-01-27 13:49:13 +01:00
ihsinme
bdfdcbd673 Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-01-27 15:48:18 +03:00
Tamas Vajk
10518744cf C#: Remove expressions inside attributes from CFG 2021-01-27 13:20:06 +01:00
Mathias Vorreiter Pedersen
c61dec1dff C++: Remove more linear scans. 2021-01-27 13:17:47 +01:00
ihsinme
16d058f498 Update WrongInDetectingAndHandlingMemoryAllocationErrors.ql 2021-01-27 15:06:57 +03:00
ihsinme
5d163b4c15 Update WrongInDetectingAndHandlingMemoryAllocationErrors.qhelp 2021-01-27 15:05:58 +03:00
ihsinme
25de82c78c Apply suggestions from code review
Co-authored-by: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
2021-01-27 15:05:01 +03:00
ihsinme
bec0064396 Update test.cpp 2021-01-27 14:54:47 +03:00
CodeQL CI
6d952bda27 Merge pull request #5020 from asgerf/js/getaqlclass-test
Approved by esbena
2021-01-27 03:48:57 -08:00
ihsinme
8737c1442b Update WrongInDetectingAndHandlingMemoryAllocationErrors.cpp 2021-01-27 14:48:23 +03:00
CodeQL CI
bb423828de Merge pull request #5025 from asgerf/js/slow-xml-parent-upgrade-script
Approved by erik-krogh
2021-01-27 03:27:43 -08:00
yoff
f2241e04e5 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-01-27 12:15:35 +01:00
Geoffrey White
988c1bc044 Merge pull request #5026 from MathiasVP/remove-linear-scan-of-functions
C++: Remove linear scan of functions table
2021-01-27 11:15:02 +00:00
ihsinme
19b7d46099 Update test.c 2021-01-27 14:06:53 +03:00
Shati Patel
4ba9d10b9a Docs: Update copyright date in footer 2021-01-27 11:03:46 +00:00
Asger Feldthaus
1637b72092 JS: Ignore Angular templates in a few non-security queries 2021-01-27 11:02:19 +00:00
Tamas Vajk
e24e5b13f5 C#: Improve CFG to handle 'and' and 'or' patterns 2021-01-27 11:52:59 +01:00
Mathias Vorreiter Pedersen
3604557e62 C++: Remove linear scan in isSVariant. 2021-01-27 11:47:45 +01:00
Tamas Vajk
4685fc0a32 C#: Extract binary patterns 2021-01-27 11:27:52 +01:00
ihsinme
68eba11dbf Update AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql 2021-01-27 13:16:56 +03:00
ihsinme
aebf7bdff4 Update test.c 2021-01-27 13:12:48 +03:00
Asger Feldthaus
5a89fa3f67 JS: Fix performance issue in upgrade script 2021-01-27 10:10:37 +00:00
ihsinme
885d26805f Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.expected 2021-01-27 12:47:51 +03:00
ihsinme
9a85b761a1 Update test.c 2021-01-27 12:46:10 +03:00
Tom Hvitved
39977e9a43 Merge pull request #4724 from hvitved/csharp/cfg/not-pattern
C#: Implement CFG for `not` patterns
2021-01-27 10:12:31 +01:00
Anders Schack-Mulligen
0381190a30 Merge pull request #5021 from hmakholm/qlpack-test
Add "tests" fields to test qlpacks
2021-01-27 09:23:35 +01:00
Tom Hvitved
214505c4dc Merge pull request #5016 from hvitved/csharp/exception-dispatch-info
C#: Teach CFG about `ExceptionDispatchInfo::Throw`
2021-01-27 08:36:51 +01:00
Rasmus Lerchedahl Petersen
5d62a56ed8 Python: Remove debug function 2021-01-27 08:24:11 +01:00
Rasmus Lerchedahl Petersen
d18c1602cd Python: autoformat 2021-01-27 01:25:38 +01:00
Rasmus Lerchedahl Petersen
d29fdda779 Python: Only generate one post-update node,
even if there are multiple reasons for doing so.
Solves `uniqueNodeToString` inconsistencies
(and probably saves quite a lot of nodes).
2021-01-27 01:20:51 +01:00
ihsinme
5d5cd4fde5 Update AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql 2021-01-27 00:10:04 +03:00
ihsinme
f074564dc1 Apply suggestions from code review
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-27 00:00:18 +03:00
ihsinme
636fe73f40 Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql 2021-01-26 23:52:18 +03:00
ihsinme
fc9d219057 Update AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql 2021-01-26 23:50:54 +03:00
ihsinme
de0bbc8826 Apply suggestions from code review
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-26 23:47:07 +03:00
Rasmus Lerchedahl Petersen
9b13834d28 Python: small refactor 2021-01-26 21:17:59 +01:00
Rasmus Lerchedahl Petersen
d3e0e84c37 Python: Separate callable for lambdas
Since lambdas are split, but their children are not,
we use the Function as the callable.
2021-01-26 21:17:59 +01:00
Rasmus Lerchedahl Petersen
4526a1dd2f Python: test for split lambda 2021-01-26 21:17:59 +01:00
yoff
cd85cf1645 Update python/ql/src/semmle/python/dataflow/new/internal/DataFlowPrivate.qll 2021-01-26 19:16:54 +01:00
yoff
500ea12224 Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-01-26 19:14:46 +01:00
Henning Makholm
54f00de3e0 Add "tests" fields to test qlpacks
This will allow `codeql resolve tests --ignore-dubious-cases`
(and thus the VSCode extension) to recognize all `.ql` files in those
packs as test cases, even if they don't have accompanying `.expected`
files.

CLI versions prior to 2.1.0 will choke on this, but it's almost 10
months since that came out.
2021-01-26 18:15:22 +01:00
Mathias Vorreiter Pedersen
04a3c3d29c Merge pull request #4953 from ihsinme/ihsinme-patch-207
CPP: Add query for CWE-14 compiler removal of code to clear buffers.
2021-01-26 18:13:18 +01:00
Mathias Vorreiter Pedersen
416aa49d99 C++: Capitalize alert message. 2021-01-26 17:24:03 +01:00
Asger Feldthaus
c69a051292 JS: Add test that depends on getAQlClass 2021-01-26 15:16:27 +00:00
Mathias Vorreiter Pedersen
aec0e9808b Merge pull request #5017 from rvermeulen/patch-2
C++: Correct pointer to data member example
2021-01-26 14:56:57 +01:00
Rasmus Wriedt Larsen
902bade5ae Merge pull request #5015 from yoff/python-add-missing-postupdate-nodes
Python: add missing postupdate nodes
2021-01-26 14:39:29 +01:00
Remco Vermeulen
1834403148 Replace HTTP entity
The code formatting operator correctly translate to HTTP entities.
2021-01-26 14:14:42 +01:00
Remco Vermeulen
8c09032d1d Correct access specifier
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-26 13:23:43 +01:00
Remco Vermeulen
932ee968e0 Correct pointer to data member example
The class `PointerToMemberType` is preceded by an example that doesn't define the variable `c` used to access a data member.
2021-01-26 13:08:28 +01:00
CodeQL CI
76e1e4d668 Merge pull request #4712 from asgerf/js/api-graph-tweaks
Approved by max-schaefer
2021-01-26 04:04:05 -08:00
Taus
4c0f54f5d3 Merge pull request #5007 from yoff/python-disregard-comp-args 2021-01-26 12:53:33 +01:00
Rasmus Lerchedahl Petersen
e253855999 Python: Add comment about reverse reads. 2021-01-26 12:11:21 +01:00
CodeQL CI
0be0929693 Merge pull request #4958 from asgerf/js/angular2
Approved by erik-krogh
2021-01-26 02:53:33 -08:00
Rasmus Lerchedahl Petersen
e44f1813fa Python: Add TODO comment 2021-01-26 11:29:14 +01:00
Tamás Vajk
e4ed050c87 Merge pull request #4970 from tamasvajk/feature/extraction-errors
C#: Fix extraction errors
2021-01-26 11:28:39 +01:00
Rasmus Lerchedahl Petersen
2c58643fd1 Python: Test for parameters without nodes. 2021-01-26 11:28:31 +01:00
Tamás Vajk
3ece8c3a01 Merge pull request #4835 from tamasvajk/feature/cil-fnptr
C#: Extract function pointer types from CIL
2021-01-26 11:28:02 +01:00
Asger Feldthaus
e6d9cd1905 JS: Add clause to getReturn/getInstance 2021-01-26 10:14:12 +00:00
CodeQL CI
c1726ed868 Merge pull request #5014 from RasmusWL/typetracking-test-track-self
Approved by tausbn
2021-01-26 02:10:52 -08:00
Asger Feldthaus
d59ccb7687 JS: Remove unhelpful mat-table load step 2021-01-26 09:27:48 +00:00
Asger Feldthaus
89225e222c JS: Remove confusing comment 2021-01-26 09:25:12 +00:00
Tom Hvitved
71d25c1f8b C#: Fix join-orders in ControlFlowTree::last() 2021-01-26 09:58:01 +01:00
Rasmus Lerchedahl Petersen
7b9ca7171a Python: update test expectations 2021-01-26 09:47:48 +01:00
Rasmus Lerchedahl Petersen
dacc21d0b5 Python: update test expectation 2021-01-26 09:45:41 +01:00
Tom Hvitved
cd8155c201 C#: Teach CFG about ExceptionDispatchInfo::Throw 2021-01-26 09:16:53 +01:00
Tom Hvitved
07a96c3596 C#: Add CFG tests for ExceptionDispatchInfo::Throw 2021-01-26 09:01:06 +01:00
yoff
09bb3001d6 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-01-25 21:58:20 +01:00
yoff
7ba0939239 Merge pull request #4995 from RasmusWL/tornado-model-http-sinks
Python: model HTTP sink in Tornado
2021-01-25 21:53:44 +01:00
Rasmus Wriedt Larsen
91caa13f48 Merge pull request #5004 from github/erik-krogh/ignore-venv
add .venv/ to .gitignore
2021-01-25 18:06:28 +01:00
Joe Farebrother
d69ecde5c1 Java: Add additional flow steps for guava collection methods and more unit tests 2021-01-25 16:37:40 +00:00
Joe Farebrother
7e11d8ed07 Java: Add modelling for guava Sets 2021-01-25 16:37:40 +00:00
Joe Farebrother
d1427fcd93 Java: Add modelling for Guava's collection classes 2021-01-25 16:37:40 +00:00
Rasmus Lerchedahl Petersen
96b7f75905 Python: add postupdate nodes for kwargs
drops remaining reverse read failures on saltstack.
2021-01-25 17:34:49 +01:00
Rasmus Wriedt Larsen
a8186be2fa Python: Add test of type-tracking self in methods 2021-01-25 17:20:11 +01:00
Rasmus Lerchedahl Petersen
ad39bfb2ff Python: Add postupdate nodes for subscripts.
This drops reverse read inconsistencies on saltstack from 14909 to 1353.
2021-01-25 17:01:25 +01:00
Rasmus Lerchedahl Petersen
361bee851a Python: Tests inspired by reverse read check 2021-01-25 17:01:25 +01:00
Rasmus Lerchedahl Petersen
4ff2c6d85a Python: fix test expectation
probably a copy-paste error..
2021-01-25 16:49:51 +01:00
Tom Hvitved
7c9a6064cf C#: Get rid of ReadKind 2021-01-25 16:20:14 +01:00
CodeQL CI
4601eb9c7c Merge pull request #4706 from max-schaefer/issue-247
Approved by asgerf
2021-01-25 07:11:35 -08:00
Tom Hvitved
6ffeaf8c2a C#: Adjust flow into phi nodes 2021-01-25 15:44:37 +01:00
Tom Hvitved
38b0f743cb C#: Add test that illustrates problem with flow through phi nodes 2021-01-25 14:20:27 +01:00
Tom Hvitved
36ad6b3432 Merge pull request #5001 from hvitved/csharp/ssa/read-kind
C#: Remove `ReadKind` from the shared SSA library
2021-01-25 14:11:54 +01:00
Tom Hvitved
221aebc833 C#: Fix bug in AssignOperationWithExpandedAssignment::last 2021-01-25 14:01:31 +01:00
alexet
355edcb136 Csharp: Reduce BDD usage. 2021-01-25 13:52:17 +01:00
Tom Hvitved
0543e34812 C#: Address review comment 2021-01-25 13:52:17 +01:00
Tom Hvitved
e0c7f32282 C#: Add relational pattern CFG test 2021-01-25 13:52:17 +01:00
Tom Hvitved
063733ad52 C#: Implement CFG for not patterns 2021-01-25 13:52:17 +01:00
Tom Hvitved
ab85b2c2d2 C#: Add is not null guards test 2021-01-25 13:52:17 +01:00
Tom Hvitved
0080357153 C#: Add unary pattern CFG tests 2021-01-25 13:52:17 +01:00
Erik Krogh Kristensen
0ba610f7db Merge pull request #5013 from erik-krogh/asmWhitespace
JS: remove benign result for js/whitespace-contradicts-precedence related to " | 0" expressions
2021-01-25 13:29:07 +01:00
Tom Hvitved
e7b43e50b6 C#: Remove ReadKind from the shared SSA library 2021-01-25 12:09:34 +01:00
Tamas Vajk
eac69c1674 Add DB upgrade folder for CIL fnptr support 2021-01-25 11:34:47 +01:00
Tamas Vajk
b434a0f395 Add change notes 2021-01-25 11:27:13 +01:00
Tom Hvitved
1c84455a6d Merge pull request #5003 from hvitved/csharp/remove-getaqlclass
C#: Remove uses of `getAQlClass()`
2021-01-25 10:57:04 +01:00
Erik Krogh Kristensen
d86705fe7a remove benign result for js/whitespace-contradicts-precedence related to " | 0" expressions 2021-01-25 10:43:39 +01:00
Jonas Jensen
1b3d69d617 Merge pull request #4784 from MathiasVP/mathiasvp/reverse-read-take-3
C++: Support longer access paths in IR field flow
2021-01-25 10:36:03 +01:00
Tom Hvitved
c235462f7d C++: Sync IRType.qll 2021-01-25 09:43:57 +01:00
ihsinme
b899229298 Add files via upload 2021-01-25 00:33:54 +03:00
ihsinme
9ae503a5a8 Add files via upload 2021-01-25 00:30:35 +03:00
ihsinme
20e19ec467 Add files via upload 2021-01-25 00:09:55 +03:00
ihsinme
9071ba2f99 Add files via upload 2021-01-25 00:06:19 +03:00
ihsinme
fcd532522d Add files via upload 2021-01-24 22:36:42 +03:00
ihsinme
20d1b24e9c Add files via upload 2021-01-24 22:35:11 +03:00
Rasmus Lerchedahl Petersen
89e56707c3 Python: Omit all unresolved parameter nodes.
Drops the results further to 139.
2021-01-24 16:16:07 +01:00
Rasmus Lerchedahl Petersen
baf0917524 On saltstack this drops the number of consistency errors
of type uniqueEnclosingCallable from 4026 to 614.
2021-01-24 15:30:59 +01:00
Rasmus Lerchedahl Petersen
0d20a4cb4a Python: Simplify modelling 2021-01-22 19:40:34 +01:00
Rasmus Lerchedahl Petersen
f948ef8f27 Merge branch 'main' of github.com:github/codeql into python-dataflow-unpacking-assignment 2021-01-22 16:26:48 +01:00
CodeQL CI
527c41520e Merge pull request #4951 from esbena/js/reintroduce-server-crash
Approved by erik-krogh
2021-01-22 06:37:50 -08:00
Tom Hvitved
6fc14976cf C#: Remove uses of getAQlClass() 2021-01-22 15:00:45 +01:00
Erik Krogh Kristensen
b3497191b1 add .venv/ to .gitignore 2021-01-22 14:44:18 +01:00
Mathias Vorreiter Pedersen
87b738d48c Merge pull request #5002 from MathiasVP/fix-PrivateCleartextWrite-format
C++: Fix path-problem format in cpp/private-cleartext-write
2021-01-22 14:28:03 +01:00
Mathias Vorreiter Pedersen
b4f9b1590d C++: Restore lost result on git/git. We lost the result in a00bd7ae02 because the added check for type T to type T* conversion didn't handle const qualifiers. 2021-01-22 14:20:18 +01:00
Esben Sparre Andreasen
3f3962f7a9 Update javascript/ql/src/Security/CWE-730/examples/server-crash.GOOD-B.js
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-01-22 14:03:21 +01:00
Mathias Vorreiter Pedersen
682b246441 C++: Fix path-problem format. 2021-01-22 13:40:44 +01:00
Esben Sparre Andreasen
718f6eb3fd JS: update and prettify examples 2021-01-22 13:17:38 +01:00
Asger Feldthaus
b36593a76b JS: Fix broken link tag 2021-01-22 10:11:16 +00:00
Asger Feldthaus
0ffa720d3b JS: Capitalize other enum constants 2021-01-22 09:48:11 +00:00
Asger Feldthaus
c257f6617f JS: Capitalize enum members in ScopeKind and TopLevelKind 2021-01-22 09:33:25 +00:00
Mathias Vorreiter Pedersen
7bc461aeb2 Merge pull request #4990 from geoffw0/cpp401b
C++: Further improvements to experimental query cpp/memory-leak-on-failed-call-to-realloc
2021-01-22 09:51:10 +01:00
CodeQL CI
0e059cea56 Merge pull request #5000 from erik-krogh/redosOnlyNonMin
Approved by esbena
2021-01-21 15:29:03 -08:00
Erik Krogh Kristensen
11f35a5193 Update javascript/ql/src/semmle/javascript/security/performance/ReDoSUtil.qll
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2021-01-21 23:11:50 +01:00
Erik Krogh Kristensen
62746bbbac skip analyzing regular expressions in minified files for ReDoS 2021-01-21 22:31:42 +01:00
CodeQL CI
d0b70d15f0 Merge pull request #4996 from esbena/js/nodejs-client-request-event-emitter
Approved by erik-krogh
2021-01-21 12:37:00 -08:00
Esben Sparre Andreasen
cb25f2ab20 JS: add docstring with source examples 2021-01-21 20:46:34 +01:00
CodeQL CI
b83c949109 Merge pull request #4986 from erik-krogh/logInf
Approved by esbena
2021-01-21 06:02:50 -08:00
Asger Feldthaus
c29014f122 JS: Autoformat 2021-01-21 13:55:21 +00:00
ihsinme
9c53e39394 Update CompilerRemovalOfCodeToClearBuffers.ql 2021-01-21 16:52:00 +03:00
Esben Sparre Andreasen
1c100bbbc2 JS: recognize event emitters in nodejs client requests 2021-01-21 14:14:00 +01:00
Rasmus Wriedt Larsen
ee2d18afd8 Merge pull request #4665 from yoff/python-dataflow-modernize-tests
Python: Add new-style tests
2021-01-21 13:35:39 +01:00
Rasmus Wriedt Larsen
b55817a5b2 Python: Model HTTP responses in tornado
This is quite a simpel model, but ends up matching what we were able to do with
points-to.

I think this modeling excercise really shows that we need a bit of a different
way to model HTTP responses... but I'm not going to try to fix that in this PR.
2021-01-21 13:26:31 +01:00
Rasmus Wriedt Larsen
ac77a8b8a8 Python: Add proper HTTP response tests for Tornado 2021-01-21 13:22:31 +01:00
Asger Feldthaus
2f58683f2d JS: Remove PipeCallExpr 2021-01-21 12:12:17 +00:00
Asger Feldthaus
1d1149f4cd JS: Test and QLDoc for RxJS model 2021-01-21 12:08:22 +00:00
Rasmus Lerchedahl Petersen
e786be06ae Python: Fix broken references 2021-01-21 12:40:35 +01:00
Asger Feldthaus
144d04f3ce JS: Add test exposing source location of attribute after line break 2021-01-21 11:25:39 +00:00
Asger Feldthaus
7c6704a63f JS: Shift line numbers in test case 2021-01-21 11:09:36 +00:00
Asger F
34280f90b0 Update QLDoc for getATemplateArgument
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-01-21 10:51:46 +00:00
Erik Krogh Kristensen
a9a901d1e2 add change note 2021-01-21 11:08:39 +01:00
Erik Krogh Kristensen
dafec3ceaa rename to AnalyzedCompoundNumericAssignExpr 2021-01-21 11:06:46 +01:00
Rasmus Lerchedahl Petersen
88db8f562d Python: Elaborate comments for steps 2021-01-21 10:55:59 +01:00
Tom Hvitved
bc41c26354 Merge pull request #4959 from hvitved/csharp/ssa/split
C#: Split up SSA implementation
2021-01-21 10:52:49 +01:00
Rasmus Lerchedahl Petersen
bc1b50788a Python: Small refactor 2021-01-21 10:44:58 +01:00
Rasmus Lerchedahl Petersen
19918e2e57 Python: Have Node-postfix consistently 2021-01-21 10:43:15 +01:00
CodeQL CI
30015ee995 Merge pull request #4942 from esbena/js/reintroduce-resource-exhaustion
Approved by erik-krogh
2021-01-21 01:21:33 -08:00
CodeQL CI
9cfbe6feb7 Merge pull request #4980 from erik-krogh/defaultExport
Approved by esbena
2021-01-21 00:55:15 -08:00
Esben Sparre Andreasen
b90dd89746 JS: move js/resource-exhaustion to experimental 2021-01-21 09:09:01 +01:00
Esben Sparre Andreasen
5a6e692807 add js/server-crash to the security suite 2021-01-21 08:43:13 +01:00
Esben Sparre Andreasen
9e3cc3b1b2 JS: add qhelp and changenotes for js/server-crash 2021-01-21 08:43:13 +01:00
Tamas Vajk
eb8a52ba8d Add new .stats file 2021-01-20 21:21:03 +01:00
Rasmus Lerchedahl Petersen
419449fb8a Python: default value for argN 2021-01-20 20:33:04 +01:00
Rasmus Lerchedahl Petersen
2409a7899b Python: Remove func tag in some situations.
Also make ArgumentNode public
2021-01-20 20:18:40 +01:00
Erik Krogh Kristensen
a44aefa6c9 add test for top-level closure modules - and simplify 2021-01-20 19:47:32 +01:00
Rasmus Lerchedahl Petersen
7a5d553dd2 Merge branch 'main' of github.com:github/codeql into python-dataflow-unpacking-assignment 2021-01-20 19:27:34 +01:00
Geoffrey White
d5d8b48218 C++: More accurate solution using Guards library. 2021-01-20 17:15:42 +00:00
Mathias Vorreiter Pedersen
3877f03a46 Merge pull request #4979 from geoffw0/cpp401
C++: Improvements to experimental query cpp/memory-leak-on-failed-call-to-realloc
2021-01-20 18:10:13 +01:00
Luke Cartey
5c6f5b7b33 Java: Track taint through Spring Java bean getters on super types 2021-01-20 16:53:03 +00:00
yoff
e072864948 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-01-20 17:38:34 +01:00
Geoffrey White
439fe41b0a C++: Add a couple more test cases. 2021-01-20 15:33:32 +00:00
yoff
3fc085ff38 Update python/ql/test/experimental/dataflow/TestUtil/RoutingTest.qll
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-01-20 16:11:40 +01:00
yoff
d0663e5c3a Merge pull request #4971 from RasmusWL/avoid-double-route-setup-django
Python: Avoid duplicated route-setup in django
2021-01-20 16:10:33 +01:00
Erik Krogh Kristensen
bf518f1c90 flag less overly general functions with js/unneeded-defensive-code 2021-01-20 15:48:12 +01:00
Mathias Vorreiter Pedersen
b0e255eb16 C++: Encapsulate skipSkippableInstructions in a module. 2021-01-20 15:45:37 +01:00
Tamas Vajk
ab8dc27b26 Add missing 'bindingset' 2021-01-20 15:44:05 +01:00
Tamas Vajk
727412b26b Store by-ref type annotation in trap and add tests 2021-01-20 15:44:05 +01:00
Tamas Vajk
2804f5cba9 Add by-ref, and fix pinned CIL extraction 2021-01-20 15:44:05 +01:00
Tamas Vajk
f99bf5755c Merge parameter extraction between methods and function pointers 2021-01-20 15:44:05 +01:00
Tamas Vajk
f986c15200 Add QL classes for CIL function pointers, and add test 2021-01-20 15:44:05 +01:00
Tamas Vajk
0c213d0926 C#: Extract function pointer types from CIL 2021-01-20 15:44:05 +01:00
Mathias Vorreiter Pedersen
f12ebe88e6 Revert "C++: Replace SkippableInstruction with local flow steps."
This reverts commit 258d04178f. This
change caused a ~20% performance regression.
2021-01-20 15:43:24 +01:00
Tamás Vajk
5fa0dd719c Merge pull request #4619 from tamasvajk/feature/csharp9-function-pointer
C#: Extract function pointers
2021-01-20 15:42:58 +01:00
Rasmus Wriedt Larsen
9a397b6faf Python: Apply code-review suggestion
Co-authored-by: yoff <lerchedahl@gmail.com>
2021-01-20 15:28:20 +01:00
Erik Krogh Kristensen
2e024c3c61 fix that type inference assumed every compound-assignment have type number 2021-01-20 15:26:39 +01:00
ihsinme
4c9de4574a Update CompilerRemovalOfCodeToClearBuffers.ql 2021-01-20 16:24:43 +03:00
CodeQL CI
2f459d9a72 Merge pull request #4977 from RasmusWL/missing-flask-class-view-handler-changenote
Approved by yoff
2021-01-20 02:38:30 -08:00
Tamas Vajk
70c302ffbe Add DB upgrade folder for function pointer 2021-01-20 11:20:55 +01:00
Shati Patel
bf0febd9d2 Merge pull request #4982 from github/update-sphix-readme
Update reference to new CodeQL site
2021-01-20 09:00:38 +00:00
Anders Schack-Mulligen
9b2f69ca94 Merge pull request #4978 from github/yo-h/struts-xml-change-note
Java: add change note for `struts.xml` extraction
2021-01-20 08:59:45 +01:00
Felicity Chapman
e96f942269 Update reference to new CodeQL site 2021-01-19 22:38:12 +00:00
Erik Krogh Kristensen
fbfbe70deb add support for unnamed/default exports in PackageExports.qll 2021-01-19 22:40:45 +01:00
Rasmus Lerchedahl Petersen
5a652ab3aa Python: Add missing test cases 2021-01-19 20:19:45 +01:00
Rasmus Lerchedahl Petersen
23d3343bfb Merge branch 'main' of github.com:github/codeql into python-dataflow-modernize-tests 2021-01-19 18:24:52 +01:00
Rasmus Lerchedahl Petersen
8e126603b3 Python: Remember that old style tests still needs
updated expectations.
2021-01-19 18:21:27 +01:00
Rasmus Lerchedahl Petersen
ae38bbe03b Python: Fearlessly adding another test
in the middle of the file.
2021-01-19 18:19:11 +01:00
Rasmus Lerchedahl Petersen
69913c053e Python: relative line numbers in
MISSING-annotations
2021-01-19 18:10:22 +01:00
Geoffrey White
d2dd19a293 C++: It turns out __assert_fail is special (see DefaultOptions.qll) so we don't need a body here. And the body was wrong. 2021-01-19 16:56:19 +00:00
Geoffrey White
fe4ae7e975 C++: General solution for functions that may exit. 2021-01-19 16:56:19 +00:00
Geoffrey White
8fa3ffe125 C++: Add a few more test cases that we don't recognize as OK. 2021-01-19 16:56:19 +00:00
CodeQL CI
bdfb81064d Merge pull request #4969 from asgerf/js/angular-dom-santizier-from-core
Approved by erik-krogh
2021-01-19 08:45:15 -08:00
Erik Krogh Kristensen
2a8a2832e2 Merge pull request #4946 from erik-krogh/libRedos
JS: Add library input as source for `js/polynomial-redos`
2021-01-19 17:30:20 +01:00
Tamas Vajk
d34992d36c Add .stats file 2021-01-19 17:26:31 +01:00
Tamas Vajk
35b955f694 Update change note date 2021-01-19 17:26:31 +01:00
Tamas Vajk
f7a0c98cb3 Code quality improvement 2021-01-19 17:26:31 +01:00
Tamas Vajk
613bf6dca6 Fix failing test 2021-01-19 17:26:31 +01:00
Tamas Vajk
1d9b3ec8b4 Allow annotating fnptr return types 2021-01-19 17:26:31 +01:00
Tamas Vajk
348fe8f2fc Address PR review comments 2021-01-19 17:26:31 +01:00
Tamas Vajk
a9986ca72d Fix expected printed AST 2021-01-19 17:26:31 +01:00
Tamas Vajk
fd27bde4b5 Add function pointer conversion tests 2021-01-19 17:26:31 +01:00
Tamas Vajk
15e88471be Adjust 'Cast.getTargetType()' to return the expression type instead of the type access type 2021-01-19 17:26:31 +01:00
Tamas Vajk
a11d852054 Fix address of unary operator extraction 2021-01-19 17:26:31 +01:00
Tamas Vajk
183926d9fd C#: Add QL classes for function pointer type/invocation, tests 2021-01-19 17:26:31 +01:00
Tamas Vajk
876123315d C#: Extract function pointers 2021-01-19 17:26:31 +01:00
Rasmus Lerchedahl Petersen
77da4b0106 Python: Remove absolute line numbers
- Use relative line numbers in flow test
- Elide line numbers in routing test (new concept)
2021-01-19 17:05:42 +01:00
yo-h
91fa12b1be Java: add change note for struts.xml extraction 2021-01-19 10:19:18 -05:00
Rasmus Wriedt Larsen
830f8bfef6 Python: Add change-note for Flask class based view handlers
For https://github.com/github/codeql/pull/4944
2021-01-19 15:09:04 +01:00
Jonas Jensen
24947f27b4 Merge pull request #4750 from geoffw0/modelclasses
C++: Model classes in StdString.qll.
2021-01-19 12:51:30 +01:00
CodeQL CI
fbab8f8539 Merge pull request #4972 from Marcono1234/marcono1234/qldoc-link-fixes
Approved by shati-patel
2021-01-19 03:07:41 -08:00
Shati Patel
47470e08c3 Add QLDoc link, suggested by @Marcono1234 2021-01-19 10:54:17 +00:00
Geoffrey White
cff56350e0 C++: Fix getClassAndName parameter name. 2021-01-19 10:34:25 +00:00
Tamás Vajk
e2af176727 Merge pull request #4974 from tamasvajk/feature/cleanup-db
C#: Remove leftover DB upgrade folder
2021-01-19 11:30:07 +01:00
Tom Hvitved
0674881ffd C#: Do not rely on BasicBlock member predicates from SsaImplSpecific 2021-01-19 10:52:50 +01:00
Tom Hvitved
2a8060102d C#: Split up SSA implementation 2021-01-19 10:52:50 +01:00
Tamás Vajk
b228b7d17b Merge pull request #4975 from tamasvajk/feature/fix-build-error
C#: Fix build error in RelationalPattern
2021-01-19 10:10:53 +01:00
Tamas Vajk
be7d458dc6 C#: Fix build error in RelationalPattern 2021-01-19 09:49:51 +01:00
Geoffrey White
b4a5346dc3 C++: It turns out .getTemplate() is not necessary. 2021-01-19 08:46:53 +00:00
Geoffrey White
f8a1fb1c35 C++: Apply the new pattern where it doesn't matter for performance as well, for consistency. 2021-01-19 08:46:53 +00:00
Geoffrey White
bfef1a200e C++: Apply the new pattern in other parts of StdString.qll where it matters. 2021-01-19 08:46:53 +00:00
Geoffrey White
b8e6ad8922 C++: Introduce new predicate for better performance in models. 2021-01-19 08:46:52 +00:00
Geoffrey White
a5632b272e C++: Fix performance issue in hasTaintFlow / hasDataFlow. 2021-01-19 08:46:52 +00:00
Tamas Vajk
6cafb281b5 C#: Remove leftover DB upgrade folder 2021-01-19 09:45:34 +01:00
Tamás Vajk
b775eb4cf7 Merge pull request #4789 from tamasvajk/feature/csharp9-relational-pattern2
C#: Relational patterns
2021-01-19 09:38:57 +01:00
Tom Hvitved
25095f919e Merge pull request #4962 from hvitved/csharp/nullability-extraction
C#: Improved extraction of type nullability
2021-01-19 09:34:38 +01:00
Rasmus Lerchedahl Petersen
42fa3bdb81 Python: Only consider the closest SOURCE
(in use-use flow) a source
2021-01-19 09:13:17 +01:00
Esben Sparre Andreasen
3015dcd310 JS: reformulate js/server-crash. Support promises and shorter paths. 2021-01-19 09:08:52 +01:00
Anders Schack-Mulligen
b620e02000 Merge pull request #4973 from Marcono1234/patch-1
Add ArrayInit.getSize(), improve documentation
2021-01-19 09:06:45 +01:00
Anders Schack-Mulligen
dde8d320f3 Apply suggestions from code review
Minor qldoc fixes.
2021-01-19 08:24:24 +01:00
Rasmus Lerchedahl Petersen
bd3de23c6e Python: Remove some unhelpful store steps 2021-01-19 00:05:10 +01:00
Marcono1234
703336a77f Add ArrayInit.getSize(), improve documentation 2021-01-18 16:44:53 +01:00
Marcono1234
e9aa63b670 Fix broken links to QLDoc specification 2021-01-18 16:18:45 +01:00
Rasmus Wriedt Larsen
8e5557eca3 Python: Avoid duplicated route-setup in django
When using `django.conf.urls.url` with Django 2+
2021-01-18 16:18:29 +01:00
Tamas Vajk
d05d4e22ad C#: Fix namespace extraction of NoMetadataHandleType 2021-01-18 16:14:37 +01:00
Tamas Vajk
1b285ee792 C#: Hardcode well-known underlying enum types 2021-01-18 16:14:37 +01:00
Rasmus Lerchedahl Petersen
bfc6660795 Python: Remember to update test expectations 2021-01-18 15:00:06 +01:00
Erik Krogh Kristensen
01900d7ca2 remove false positive due to "\n" not being in the relevant relation 2021-01-18 14:47:29 +01:00
Asger Feldthaus
deca7f3cd6 JS: Add change note 2021-01-18 13:46:43 +00:00
CodeQL CI
fc2fe6cccb Merge pull request #4928 from esbena/js/rewrite-multi-sanitization
Approved by asgerf
2021-01-18 05:11:42 -08:00
Asger Feldthaus
fbb5d14263 JS: Update angular test output 2021-01-18 12:19:09 +00:00
Asger Feldthaus
bb6bd9168e JS: Update HTML TRAP tests output 2021-01-18 12:19:09 +00:00
Asger Feldthaus
2a7b4487f1 JS: More auto format 2021-01-18 12:19:09 +00:00
Asger Feldthaus
d8c9dba990 JS: Autoformat 2021-01-18 12:19:09 +00:00
Asger Feldthaus
5f4016be76 JS: Cache Import.getImportedModule 2021-01-18 12:19:09 +00:00
Asger Feldthaus
c5f2c04f16 JS: Add upgrade script 2021-01-18 12:19:09 +00:00
Asger Feldthaus
1b4a4ea2fa JS: Bump extractor version string 2021-01-18 12:19:09 +00:00
Asger Feldthaus
44c5d36e83 JS: Simple RxJS model 2021-01-18 12:19:09 +00:00
Asger Feldthaus
00cd0644f0 JS: Implement getAResponseDataNode 2021-01-18 12:19:09 +00:00
Asger Feldthaus
2f3cef177b JS: More steps in Angular2 model 2021-01-18 12:19:09 +00:00
Asger Feldthaus
c8901b62f5 JS: Add test for $any step 2021-01-18 12:19:08 +00:00
Asger Feldthaus
2ba98da107 JS: Only extract local vars in TemplateTopLevel
Angular template expressions cannot refer to global variables, any
unqualified identifier is a reference to a property provided by the
component.

We extract them as implicitly declared local variables which the
QL model can then connect with data flow steps.
2021-01-18 12:19:08 +00:00
Asger Feldthaus
faad466aa8 JS: Add ScopeKind enum 2021-01-18 12:19:08 +00:00
Asger Feldthaus
07cfceee19 JS: TRAP test for angular templates 2021-01-18 12:19:08 +00:00
Asger Feldthaus
3c0867125b JS: Remove FP in TargetBlank 2021-01-18 12:19:08 +00:00
Asger Feldthaus
97f7cb4dc1 JS: Track location information using SourceMaps 2021-01-18 12:19:08 +00:00
Asger Feldthaus
898d22d2f4 JS: Simplify HTML element access 2021-01-18 12:19:08 +00:00
Asger Feldthaus
f24af58a60 JS: Extract mapping from HTML node to parent Expression 2021-01-18 12:19:08 +00:00
Asger Feldthaus
3b666a5646 JS: Extract mapping from TopLevel to parent HTML node 2021-01-18 12:19:08 +00:00
Asger Feldthaus
8848ee2d10 JS: Extract HTML from inline templates 2021-01-18 12:19:08 +00:00
Asger Feldthaus
6bf9345258 JS: Add test for class with locally-unused field 2021-01-18 12:19:08 +00:00
Asger Feldthaus
cc952bd2a4 JS: Reorganize test a bit 2021-01-18 12:19:08 +00:00
Asger Feldthaus
1ab36dc81f JS: Flow through *ngFor loops 2021-01-18 12:19:08 +00:00
Asger Feldthaus
29dd8470d5 JS: Fix offset of *ngFor snippet 2021-01-18 12:18:27 +00:00
Asger Feldthaus
0da207a5f9 JS: Update test with pipes 2021-01-18 12:18:27 +00:00
Asger Feldthaus
d80313be4f JS: Model pipe classes 2021-01-18 12:18:27 +00:00
Asger Feldthaus
debb5691a1 JS: Make PipeRefExpr a SourceNode 2021-01-18 12:18:27 +00:00
Asger Feldthaus
fcb8124376 JS: Expose data flow node for field declaration 2021-01-18 12:18:26 +00:00
Asger Feldthaus
9ee893c9c1 JS: Add data flow steps in Angular2 model 2021-01-18 12:16:13 +00:00
Asger Feldthaus
77fcf3d8a2 JS: Support postfix "!" operator in templates 2021-01-18 12:16:13 +00:00
Asger Feldthaus
c08ba1416d JS: Add new SourceType for angular templates 2021-01-18 12:16:13 +00:00
Asger Feldthaus
b1d45a6773 JS: Mark angular pipe refs as incomplete 2021-01-18 12:16:13 +00:00
Asger Feldthaus
4b5a861ee6 JS: Add TopLevelKind enum 2021-01-18 12:16:13 +00:00
Asger Feldthaus
9b99f56d44 JS: isAngularTemplateAttributeName 2021-01-18 12:16:13 +00:00
Asger Feldthaus
ed27c8b13f JS: Add test and fix bug in pipe parser 2021-01-18 12:16:13 +00:00
Asger Feldthaus
16a2a60b9a JS: Add AngularPipeRef 2021-01-18 12:16:13 +00:00
Asger Feldthaus
928a382ad5 JS: Add parser for angular expressions 2021-01-18 12:16:13 +00:00
Asger Feldthaus
3db6069372 JS: Add test for new sink 2021-01-18 10:55:34 +00:00
Asger Feldthaus
2752b4ba64 JS: Shift line numbers in test 2021-01-18 10:54:39 +00:00
Asger Feldthaus
ff1d0cc4c7 JS: Recognize DomSanitizer from @angular/core 2021-01-18 10:54:27 +00:00
Rasmus Lerchedahl Petersen
66426bf0cc Python: Add tests for iterable unpacking
in for-iterations and comprehensions.
2021-01-18 09:36:13 +01:00
Tamas Vajk
8400a3862b Add DB upgrade folder 2021-01-18 09:19:27 +01:00
Tamas Vajk
ce58514453 Change release note date 2021-01-18 09:19:27 +01:00
Tamas Vajk
c0b31cbfe7 Add new stats file 2021-01-18 09:19:27 +01:00
Tamas Vajk
f235a28295 C# Add relational patterns extraction 2021-01-18 09:19:27 +01:00
Rasmus Lerchedahl Petersen
175e43d6f2 Python: Slight refactor 2021-01-18 09:12:05 +01:00
Rasmus Lerchedahl Petersen
5f189a7e43 Python: Address reviews 2021-01-15 20:18:37 +01:00
Mathias Vorreiter Pedersen
dcbae8b22b Fix code tag. 2021-01-15 19:47:09 +01:00
yoff
1edad03622 Apply suggestions from code review
Co-authored-by: Rasmus Wriedt Larsen <rasmuswriedtlarsen@gmail.com>
2021-01-15 18:50:04 +01:00
Erik Krogh Kristensen
401e516654 update expected output, and update PackageExports test 2021-01-15 17:40:47 +01:00
Erik Krogh Kristensen
26783b6ab0 make getTopmostPackageJSON public again, and update PackageExports test 2021-01-15 16:05:49 +01:00
Tom Hvitved
9a9a57716c C#: Improved extraction of type nullability 2021-01-15 16:01:14 +01:00
Asger Feldthaus
5fa3b17956 JS: Tolerate Angular-specific HTML attribute names 2021-01-15 14:51:10 +00:00
Asger Feldthaus
f33630aab6 JS: Reformat HTMLExtractor 2021-01-15 14:51:10 +00:00
yoff
48910d0597 Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-01-15 14:02:27 +01:00
Erik Krogh Kristensen
1506ac09e5 limit the number of characters produced by getAThreewayIntersect 2021-01-15 13:54:16 +01:00
Erik Krogh Kristensen
0117a0fac1 specialize the getAValueExportedBy predicate to only topmost package.jsons 2021-01-15 13:54:16 +01:00
Erik Krogh Kristensen
0c9d46a7f9 changes based on review
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2021-01-15 13:54:05 +01:00
luchua-bc
32c54628f8 Drop fieldName from the function for runtime evaluation 2021-01-15 12:33:00 +00:00
luchua-bc
e5a703e49c Revamp the query 2021-01-15 04:05:11 +00:00
Geoffrey White
15089c4117 Merge branch 'main' into modelclasses 2021-01-14 15:57:02 +00:00
Geoffrey White
7012bc05a2 C++: Simplification. 2021-01-14 15:21:26 +00:00
Geoffrey White
54bd36def2 C++: Correct QLDoc comments. 2021-01-14 15:20:29 +00:00
Geoffrey White
13d0efe96d C++: Change to more natural expressions without use of weird predicates or 'any'. The classes for string objects now match instantiations directly rather than the template. 2021-01-14 15:02:51 +00:00
ihsinme
805352945e Update CompilerRemovalOfCodeToClearBuffers.ql 2021-01-14 17:27:58 +03:00
ihsinme
10ab1d9b54 Update CompilerRemovalOfCodeToClearBuffers.ql 2021-01-14 17:24:49 +03:00
ihsinme
cd0d2a5692 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:21:19 +03:00
ihsinme
7f5e5fcb99 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:19:57 +03:00
ihsinme
3e715ff52d Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.qhelp
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:19:23 +03:00
ihsinme
0d0ea0c5e1 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:17:56 +03:00
ihsinme
4ba4de3d41 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:17:08 +03:00
ihsinme
76b768f7e0 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:16:53 +03:00
ihsinme
4631658e5e Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:16:37 +03:00
ihsinme
9e3b288f33 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.c
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:16:21 +03:00
ihsinme
b26a90e1e6 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:15:58 +03:00
ihsinme
1c4610c722 Update cpp/ql/src/experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-01-14 17:15:36 +03:00
Erik Krogh Kristensen
c106b09d49 change-note 2021-01-14 14:17:32 +01:00
Erik Krogh Kristensen
c5595f4cbd improve alert message for js/polynomial-redos 2021-01-14 13:48:26 +01:00
Erik Krogh Kristensen
86e33d9d79 select the shortest possible reason 2021-01-14 13:38:37 +01:00
Erik Krogh Kristensen
03d8aeb7b6 refactor PolynomialBackTrackingTerm, to allow getting the pump string and the prefix-message 2021-01-14 13:35:32 +01:00
Erik Krogh Kristensen
a520a51d42 highlight the use of the regular expression, instead of the sink for user input 2021-01-14 11:22:20 +01:00
Erik Krogh Kristensen
e8ea720650 adjust description to not mention user-provided values 2021-01-14 10:36:10 +01:00
Rasmus Lerchedahl Petersen
dfdfd3c2b7 Python: FIx flow 2021-01-14 01:19:58 +01:00
Rasmus Lerchedahl Petersen
6dc0d691ac Python: Final(?!) fix of annotations 2021-01-14 01:06:10 +01:00
Rasmus Lerchedahl Petersen
e3199fbbe2 Python: Fix inconsostencies to fix flow
(and fix annotations again)
2021-01-14 00:09:18 +01:00
Rasmus Lerchedahl Petersen
36a4a5081e Python: big refactor and fix tests
Make sure tests are valid
Fix wrong test annotations
Big refactor to make code readable
Big comment to explain code
2021-01-13 18:33:08 +01:00
Esben Sparre Andreasen
1bc7d68a50 Update javascript/ql/test/query-tests/Security/CWE-730/server-crash.js
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-01-13 14:49:42 +01:00
Esben Sparre Andreasen
12b985be87 Update javascript/ql/src/Security/CWE-730/ServerCrash.ql
Co-authored-by: Erik Krogh Kristensen <erik-krogh@github.com>
2021-01-13 14:49:29 +01:00
ihsinme
3ad45f28c9 Add files via upload 2021-01-13 14:18:54 +03:00
ihsinme
4cee67da75 Add files via upload 2021-01-13 14:17:21 +03:00
Erik Krogh Kristensen
d71adff079 dont sanitize global replacements where the regexp is a char class 2021-01-13 10:12:12 +01:00
Rasmus Lerchedahl Petersen
b2d95e617d Python: Test interaction between nesting,
iteration, and conversion
2021-01-13 09:02:56 +01:00
Rasmus Lerchedahl Petersen
b10cf78e17 Python: start handling iterated unpacking 2021-01-13 08:40:47 +01:00
luchua-bc
babe744a30 Add SECURITY_PROTOCOL check 2021-01-13 03:49:08 +00:00
Esben Sparre Andreasen
d591c519a8 JS: reformulate js/server-crash as a path problem 2021-01-13 00:08:28 +01:00
Rasmus Lerchedahl Petersen
4ee2f49f38 Python: model conversion during unpacking 2021-01-12 22:19:31 +01:00
Rasmus Lerchedahl Petersen
d8d8b45c6a Python: add test annotations 2021-01-12 22:03:49 +01:00
Erik Krogh Kristensen
0a17b04650 refactor copy-pasted code into getAnLibraryInputParameter 2021-01-12 20:21:37 +01:00
Erik Krogh Kristensen
eaee5c2d87 add library input as source for js/polynomial-redos 2021-01-12 20:21:33 +01:00
Esben Sparre Andreasen
3c9c79a550 JS: remove flow labels from js/resource-exhaustion 2021-01-12 13:20:20 +01:00
Esben Sparre Andreasen
5965035c09 JS: add query js/resource-exhaustion 2021-01-12 13:20:20 +01:00
Rasmus Lerchedahl Petersen
a1ab5cc2b8 Python: start support for nested unpacking 2021-01-12 13:09:12 +01:00
Rasmus Lerchedahl Petersen
9c08467828 Python: add tests for conversion during unpacking 2021-01-12 12:46:51 +01:00
Rasmus Lerchedahl Petersen
4d9f5be2bc Python: Add more unpacking tests 2021-01-12 12:30:03 +01:00
Mathias Vorreiter Pedersen
84f1b11448 Merge branch 'main' into mathiasvp/reverse-read-take-3 2021-01-12 10:37:32 +01:00
Esben Sparre Andreasen
847687974f JS: only select non-nullable terms in the broken sanitizer 2021-01-12 08:50:19 +01:00
Esben Sparre Andreasen
40cfbab335 JS: address review feedback 2021-01-12 08:49:08 +01:00
Max Schaefer
f40b406a2d JavaScript: Address review comments. 2021-01-11 13:53:47 +00:00
Max Schaefer
c9132ca6f8 JavaScript: Refactor trackUseNode to avoid bad join order. 2021-01-11 13:53:47 +00:00
Max Schaefer
7a229d9381 JavaScript: Simplify NoSQL framework modelling. 2021-01-11 13:53:47 +00:00
Max Schaefer
b3ab6efd1d JavaScript: Remove a bindingset annotation. 2021-01-11 13:53:47 +00:00
Max Schaefer
3853da0969 JavaScript: Teach API-graphs about bound arguments. 2021-01-11 13:53:46 +00:00
Max Schaefer
ecab17a626 JavaScript: Teach API graphs to handle promisify.
Following a suggestion by Asger, we track use nodes through calls to `promisify`. When we see a call to a promisified function, we introduce a new synthetic API-graph node representing the callback argument synthesised by the promisification, and track the result of the call to an `await` (or other promise resolution), which is then considered to be a use of the first parameter of the synthetic callback (the zeroth parameter being an error code, which we do not model yet).
2021-01-11 13:53:46 +00:00
Esben Sparre Andreasen
2dbd762bd9 JS: reintroduce reverted js/server-crash
This reverts commit 0a8d15ccc4.
2021-01-11 14:13:41 +01:00
Esben Sparre Andreasen
580a24e982 JS: rewrite js/incomplete-multi-character-sanitization 2021-01-11 11:26:45 +01:00
Mathias Vorreiter Pedersen
46393c33ef C++: Fix bad join orders introduced in previous commit. 2021-01-11 09:19:58 +01:00
Mathias Vorreiter Pedersen
a00bd7ae02 C++: Respond to review comments. 2021-01-08 19:47:02 +01:00
Geoffrey White
7f0209f72e Merge branch 'main' into modelclasses 2021-01-08 17:11:25 +00:00
Mathias Vorreiter Pedersen
7b003678a9 Merge branch 'main' into mathiasvp/reverse-read-take-3 2021-01-07 11:56:18 +01:00
luchua-bc
c069a5b4c6 Factor private host regex into the networking library and enhance the query 2021-01-04 14:51:32 +00:00
Mathias Vorreiter Pedersen
258d04178f C++: Replace SkippableInstruction with local flow steps. 2020-12-30 13:39:24 +01:00
Mathias Vorreiter Pedersen
6545d0b53a C++: Move conflation check into each disjunct. 2020-12-22 16:56:30 +01:00
Mathias Vorreiter Pedersen
d2d8377e88 Update cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
Co-authored-by: Jonas Jensen <jbj@github.com>
2020-12-22 16:34:53 +01:00
Mathias Vorreiter Pedersen
b95cf94824 Update cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
Co-authored-by: Jonas Jensen <jbj@github.com>
2020-12-22 15:57:34 +01:00
Mathias Vorreiter Pedersen
ec35e0d518 C++: Respond to review comments. 2020-12-22 15:22:33 +01:00
Mathias Vorreiter Pedersen
77aa9615c0 C++: Accept test changes in paths. 2020-12-22 09:14:55 +01:00
Mathias Vorreiter Pedersen
fd8034cd8c C++: Add store step out of read side effects when we don't have a model for the callee. This brings back the lost result on boost. 2020-12-22 09:14:55 +01:00
Mathias Vorreiter Pedersen
a8b4fb6fd0 C++: Add qldoc (and remove predicate that wasn't needed). 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
72a80e3722 C++: Accept test changes. 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
145ab17f6b Fix a bad join-order caused by the optimizer not seeing that
`Node.getEnclosingCallable` is functional. This is fixed in the same way
as in Java's DataFlowUtil: We make create a non-virtual dispatching
`getEnclosingCallableImpl`, and implement `getEnclosingCallable` as a
wrapper that uses the `unique` aggregate to tell the compiler that there
is exactly 1 result.

Tuple numbers from an arbitrarily chosen iteration of
DataFlowImpl3::Stage4::fwdFlow0#fffff.

Before:
4569      ~5%        {5} r24 = SCAN DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS I OUTPUT I.<0>, I.<4> 'config', I.<1>, I.<2>, I.<3>
2876      ~1%        {5} r25 = JOIN r24 WITH DataFlowImpl3::LocalFlowBigStep::localFlowEntry#ff AS R ON FIRST 2 OUTPUT r24.<2> 'cc', r24.<0>, r24.<3> 'argAp', r24.<4>, r24.<1> 'config'
409404537 ~0%        {6} r26 = JOIN r25 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#ff AS R ON FIRST 1 OUTPUT r25.<1>, R.<1>, r25.<0> 'cc', r25.<2> 'argAp', r25.<3>, r25.<4> 'config'
2876      ~0%        {6} r27 = JOIN r26 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 2 OUTPUT r26.<0>, true, r26.<5> 'config', r26.<2> 'cc', r26.<3> 'argAp', r26.<4>
79821     ~1781%     {5} r28 = JOIN r27 WITH DataFlowImpl3::Stage4::localStep#ffbfff_0241#join_rhs AS R ON FIRST 3 OUTPUT r27.<3> 'cc', r27.<4> 'argAp', r27.<2> 'config', r27.<5> 'ap', R.<3> 'node'
2876      ~0%        {5} r29 = JOIN r26 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 2 OUTPUT r26.<4>, r26.<0>, r26.<2> 'cc', r26.<3> 'argAp', r26.<5> 'config'
0         ~0%        {5} r30 = JOIN r29 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r29.<1>, false, r29.<4> 'config', r29.<2> 'cc', r29.<3> 'argAp'
0         ~0%        {5} r31 = JOIN r30 WITH DataFlowImpl3::Stage4::localStep#ffbfff_02413#join_rhs AS R ON FIRST 3 OUTPUT r30.<3> 'cc', r30.<4> 'argAp', r30.<2> 'config', R.<4> 'ap', R.<3> 'node'
4569      ~157%      {6} r32 = JOIN DataFlowImpl3::Stage4::fwdFlow0#fffff#join_rhs AS L WITH DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS R CARTESIAN PRODUCT OUTPUT R.<3>, L.<0> 'ap', L.<1> 'cc', L.<2> 'argAp', R.<0>, R.<4> 'config'
0         ~0%        {5} r33 = JOIN r32 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r32.<4>, r32.<5> 'config', r32.<1> 'ap', r32.<2> 'cc', r32.<3> 'argAp'
0         ~0%        {5} r34 = JOIN r33 WITH DataFlowImpl3::additionalJumpStep#fff_021#join_rhs AS R ON FIRST 2 OUTPUT R.<2> 'node', r33.<2> 'ap', r33.<3> 'cc', r33.<4> 'argAp', r33.<1> 'config'
0         ~0%        {5} r35 = JOIN r34 WITH DataFlowUtil::TIRDataFlowNode#f@staged_ext AS R ON FIRST 1 OUTPUT r34.<0> 'node', r34.<1> 'ap', r34.<2> 'cc', r34.<3> 'argAp', r34.<4> 'config'
0         ~0%        {6} r36 = JOIN r35 WITH project#DataFlowImpl3::Stage3::revFlow#fffff#12 AS R ON FIRST 1 OUTPUT r35.<1> 'ap', r35.<2> 'cc', r35.<3> 'argAp', r35.<4> 'config', r35.<0> 'node', R.<1>

After:
4569     ~0%        {5} r24 = SCAN DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS I OUTPUT I.<0>, I.<4> 'config', I.<1>, I.<2>, I.<3>
2876     ~0%        {5} r25 = JOIN r24 WITH DataFlowImpl3::LocalFlowBigStep::localFlowEntry#ff AS R ON FIRST 2 OUTPUT r24.<0>, r24.<2> 'cc', r24.<3> 'argAp', r24.<4>, r24.<1> 'config'
2876     ~0%        {6} r26 = JOIN r25 WITH DataFlowUtil::Node::getEnclosingCallable_dispred#ff AS R ON FIRST 1 OUTPUT r25.<1> 'cc', R.<1>, r25.<0>, r25.<2> 'argAp', r25.<3>, r25.<4> 'config'
2876     ~0%        {6} r27 = JOIN r26 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#fb AS R ON FIRST 2 OUTPUT r26.<2>, true, r26.<5> 'config', r26.<0> 'cc', r26.<3> 'argAp', r26.<4>
79821    ~1862%     {5} r28 = JOIN r27 WITH DataFlowImpl3::Stage4::localStep#ffbfff_0241#join_rhs AS R ON FIRST 3 OUTPUT r27.<3> 'cc', r27.<4> 'argAp', r27.<2> 'config', r27.<5> 'ap', R.<3> 'node'
2876     ~0%        {5} r29 = JOIN r26 WITH DataFlowImplCommon::getLocalCallContext#cpe#12#fb AS R ON FIRST 2 OUTPUT r26.<4>, r26.<2>, r26.<0> 'cc', r26.<3> 'argAp', r26.<5> 'config'
0        ~0%        {5} r30 = JOIN r29 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r29.<1>, false, r29.<4> 'config', r29.<2> 'cc', r29.<3> 'argAp'
0        ~0%        {5} r31 = JOIN r30 WITH DataFlowImpl3::Stage4::localStep#ffbfff_02413#join_rhs AS R ON FIRST 3 OUTPUT r30.<3> 'cc', r30.<4> 'argAp', r30.<2> 'config', R.<4> 'ap', R.<3> 'node'
4569     ~148%      {6} r32 = JOIN DataFlowImpl3::Stage4::fwdFlow0#fffff#join_rhs AS L WITH DataFlowImpl3::Stage4::fwdFlow#fffff#prev_delta AS R CARTESIAN PRODUCT OUTPUT R.<3>, L.<0> 'ap', L.<1> 'cc', L.<2> 'argAp', R.<0>, R.<4> 'config'
0        ~0%        {5} r33 = JOIN r32 WITH DataFlowImpl3::TNil#ff_1#join_rhs AS R ON FIRST 1 OUTPUT r32.<4>, r32.<5> 'config', r32.<1> 'ap', r32.<2> 'cc', r32.<3> 'argAp'
0        ~0%        {5} r34 = JOIN r33 WITH DataFlowImpl3::additionalJumpStep#fff_021#join_rhs AS R ON FIRST 2 OUTPUT R.<2> 'node', r33.<2> 'ap', r33.<3> 'cc', r33.<4> 'argAp', r33.<1> 'config'
0        ~0%        {5} r35 = JOIN r34 WITH DataFlowUtil::TIRDataFlowNode#f@staged_ext AS R ON FIRST 1 OUTPUT r34.<0> 'node', r34.<1> 'ap', r34.<2> 'cc', r34.<3> 'argAp', r34.<4> 'config'
0        ~0%        {6} r36 = JOIN r35 WITH project#DataFlowImpl3::Stage3::revFlow#fffff#12 AS R ON FIRST 1 OUTPUT r35.<1> 'ap', r35.<2> 'cc', r35.<3> 'argAp', r35.<4> 'config', r35.<0> 'node', R.<1>
2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
f5a2603cc1 C++: Add store steps that target the new partial definitions. 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
7a2b69feed C++: Add partial definition class backed by an IPA. 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
2930128421 C++: Implement read steps using ReadNodes. 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
91debe8669 C++: Add ReadNodes and implement local flow steps into them. 2020-12-22 09:14:54 +01:00
Mathias Vorreiter Pedersen
ba4da72b9e C++: Add examples that require longer access paths 2020-12-22 09:14:53 +01:00
luchua-bc
4ec78d04f8 Insecure LDAP authentication 2020-12-21 00:15:15 +00:00
Geoffrey White
79f32b0e26 C++: Autoformat. 2020-12-01 10:51:51 +00:00
Rasmus Lerchedahl Petersen
289b9e62f9 Python: Add read step for unpacking assignment 2020-11-30 15:30:14 +01:00
Rasmus Lerchedahl Petersen
f345e55951 Python: Adjust test expectations 2020-11-30 14:21:30 +01:00
Rasmus Lerchedahl Petersen
673ff901fb Python: Test for unpacking assignment 2020-11-30 14:18:22 +01:00
Geoffrey White
905b04a6fb C++: Model classes in StdString.qll. 2020-11-27 19:12:01 +00:00
Asger Feldthaus
432a59185f Merge branch 'js/api-graph-tweaks' of github.com:asgerf/codeql into js/api-graph-tweaks 2020-11-24 14:32:28 +00:00
Asger Feldthaus
cf12b65c80 JS: Autoformat 2020-11-24 14:32:20 +00:00
Rasmus Lerchedahl Petersen
80dcb8da4a Python: annotate missing flow 2020-11-24 11:55:28 +01:00
Rasmus Lerchedahl Petersen
737f4dff09 Python: update test annotations 2020-11-24 10:57:57 +01:00
Rasmus Lerchedahl Petersen
da805f8242 Merge remote-tracking branch 'upstream/main' into python-dataflow-modernize-tests 2020-11-24 10:56:22 +01:00
Rasmus Lerchedahl Petersen
a19304a4a0 Python: Factor out prettyPrinter and update tests 2020-11-24 02:17:38 +01:00
Asger F
ac6d4aac9d Apply suggestions from code review
Co-authored-by: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2020-11-23 21:20:38 +00:00
Asger Feldthaus
d3412bb0ec JS: Fix typo in NoSQL model 2020-11-23 21:19:17 +00:00
Asger Feldthaus
85f0a627c4 JS: Autoformat 2020-11-23 16:17:22 +00:00
Asger Feldthaus
c146e044ca JS: Update NoSQL model 2020-11-23 16:17:00 +00:00
Asger Feldthaus
b6b8a55b37 JS: Add test case 2020-11-23 16:16:50 +00:00
Asger Feldthaus
ac00e02855 JS: Add API::Node.getAValueReachingRhs 2020-11-23 15:37:08 +00:00
Asger Feldthaus
3b5ff73862 JS: Introduce API::InvokeNode to simplify reasoning about calls 2020-11-23 15:36:32 +00:00
Rasmus Lerchedahl Petersen
dc91406ff0 Python: make .expected empty
still need to annotate missing results
2020-11-13 09:22:57 +01:00
Rasmus Lerchedahl Petersen
e468d49b19 Python: routing tests 3-7 and some annotations 2020-11-12 23:07:01 +01:00
Rasmus Lerchedahl Petersen
4fe2576b9a Python: start modernizing routing tests 2020-11-12 22:43:34 +01:00
Rasmus Lerchedahl Petersen
823ed447df Python: Add new-style tests
should perhaps move `LocalFlowStepTest` and `MaximalFlowStep` into where
 they are referenced (they did not seem too reusable after all).
Should also add argument tests in the same way.
2020-11-12 21:57:29 +01:00
737 changed files with 97564 additions and 15845 deletions

View File

@@ -2,7 +2,13 @@ name: "Code scanning - action"
on:
push:
branches:
- main
- 'rc/*'
pull_request:
branches:
- main
- 'rc/*'
schedule:
- cron: '0 9 * * 1'
@@ -14,16 +20,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1

3
.gitignore vendored
View File

@@ -17,6 +17,9 @@
# Byte-compiled python files
*.pyc
# python virtual environment folder
.venv/
# It's useful (though not required) to be able to unpack codeql in the ql checkout itself
/codeql/

View File

@@ -0,0 +1,2 @@
lgtm
* A new query (`cpp/unsigned-difference-expression-compared-zero`) is run but not yet displayed on LGTM. The query finds unsigned subtractions used in relational comparisons with the value 0. This query was originally submitted as an experimental query by @ihsinme in https://github.com/github/codeql/pull/4745.

View File

@@ -10,6 +10,7 @@
+ semmlecode-cpp-queries/Likely Bugs/Underspecified Functions/MistypedFunctionArguments.ql: /Correctness/Dangerous Conversions
+ semmlecode-cpp-queries/Security/CWE/CWE-253/HResultBooleanConversion.ql: /Correctness/Dangerous Conversions
+ semmlecode-cpp-queries/Likely Bugs/OO/UnsafeUseOfThis.ql: /Correctness/Dangerous Conversions
+ semmlecode-cpp-queries/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql: /Correctness/Dangerous Conversions
# Consistent Use
+ semmlecode-cpp-queries/Critical/ReturnValueIgnored.ql: /Correctness/Consistent Use
+ semmlecode-cpp-queries/Likely Bugs/InconsistentCheckReturnNull.ql: /Correctness/Consistent Use

View File

@@ -0,0 +1,5 @@
unsigned limit = get_limit();
unsigned total = 0;
while (limit - total > 0) { // wrong: if `total` is greater than `limit` this will underflow and continue executing the loop.
total += get_data();
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
This rule finds relational comparisons between the result of an unsigned subtraction and the value <code>0</code>.
Such comparisons are likely to be wrong as the value of an unsigned subtraction can never be negative. So the
relational comparison ends up checking whether the result of the subtraction is equal to <code>0</code>.
This is probably not what the programmer intended.
</p>
</overview>
<recommendation>
<p>If a relational comparison is intended, consider casting the result of the subtraction to a signed type.
If the intention was to test for equality, consider replacing the relational comparison with an equality test.
</p>
</recommendation>
<example>
<sample src="UnsignedDifferenceExpressionComparedZero.c" />
</example>
<references>
<li>SEI CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules">INT02-C. Understand integer conversion rules</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,49 @@
/**
* @name Unsigned difference expression compared to zero
* @description A subtraction with an unsigned result can never be negative. Using such an expression in a relational comparison with `0` is likely to be wrong.
* @kind problem
* @id cpp/unsigned-difference-expression-compared-zero
* @problem.severity warning
* @precision medium
* @tags security
* correctness
* external/cwe/cwe-191
*/
import cpp
import semmle.code.cpp.commons.Exclusions
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.controlflow.Guards
/** Holds if `sub` is guarded by a condition which ensures that `left >= right`. */
pragma[noinline]
predicate isGuarded(SubExpr sub, Expr left, Expr right) {
exists(GuardCondition guard |
guard.controls(sub.getBasicBlock(), true) and
guard.ensuresLt(left, right, 0, sub.getBasicBlock(), false)
)
}
/** Holds if `sub` will never be negative. */
predicate nonNegative(SubExpr sub) {
not exprMightOverflowNegatively(sub.getFullyConverted())
or
// The subtraction is guarded by a check of the form `left >= right`.
exists(GVN left, GVN right |
// This is basically a poor man's version of a directional unbind operator.
strictcount([left, globalValueNumber(sub.getLeftOperand())]) = 1 and
strictcount([right, globalValueNumber(sub.getRightOperand())]) = 1 and
isGuarded(sub, left.getAnExpr(), right.getAnExpr())
)
}
from RelationalOperation ro, SubExpr sub
where
not isFromMacroDefinition(ro) and
not isFromMacroDefinition(sub) and
ro.getLesserOperand().getValue().toInt() = 0 and
ro.getGreaterOperand() = sub and
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned() and
not nonNegative(sub)
select ro, "Unsigned subtraction can never be negative."

View File

@@ -353,7 +353,9 @@ class InitializationFunction extends Function {
// Destination range is zeroed out on failure, assuming first two parameters are valid
"memcpy_s",
// This zeroes the memory unconditionally
"SeCreateAccessState"
"SeCreateAccessState",
// Argument initialization is optional, but always succeeds
"KeGetCurrentProcessorNumberEx"
]
)
}

View File

@@ -0,0 +1,35 @@
// BAD: the memset call will probably be removed.
void getPassword(void) {
char pwd[64];
if (GetPassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
memset(pwd, 0, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
memset_s(pwd, 0, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
SecureZeroMemory(pwd, sizeof(pwd));
}
// GOOD: in this case the memset will not be removed.
void getPassword(void) {
char pwd[64];
if (retrievePassword(pwd, sizeof(pwd))) {
/* Checking of password, secure operations, etc. */
}
#pragma optimize("", off)
memset(pwd, 0, sizeof(pwd));
#pragma optimize("", on)
}

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Compiler optimization will exclude the cleaning of private information.
Using the <code>memset</code> function to clear private data in a variable that has no subsequent use is potentially dangerous, since the compiler can remove the call.
For some compilers, optimization is also possible when using calls to free memory after the <code>memset</code> function.</p>
<p>It is possible to miss detection of vulnerabilities if used to clear fields of structures or parts of a buffer.</p>
</overview>
<recommendation>
<p>We recommend to use the <code>RtlSecureZeroMemory</code> or <code>memset_s</code> functions, or compilation flags that exclude optimization of <code>memset</code> calls (e.g. -fno-builtin-memset).</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of the <code>memset</code> function.</p>
<sample src="CompilerRemovalOfCodeToClearBuffers.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC06-C.+Beware+of+compiler+optimizations">MSC06-C. Beware of compiler optimizations</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,127 @@
/**
* @name Compiler Removal Of Code To Clear Buffers
* @description Using <code>memset</code> the function to clear private data in a variable that has no subsequent use
* is potentially dangerous because the compiler can remove the call.
* @kind problem
* @id cpp/compiler-removal-of-code-to-clear-buffers
* @problem.severity warning
* @precision medium
* @tags security
* external/cwe/cwe-14
*/
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.dataflow.StackAddress
/**
* A call to `memset` of the form `memset(ptr, value, num)`, for some local variable `ptr`.
*/
class CompilerRemovaMemset extends FunctionCall {
CompilerRemovaMemset() {
this.getTarget().hasGlobalOrStdName("memset") and
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
(
source.asExpr() = exp
or
// handle the case where exp is defined by an address being passed into some function.
source.asDefiningArgument() = exp
) and
exp.getLocation().getEndLine() < this.getArgument(0).getLocation().getStartLine() and
sink.asExpr() = this.getArgument(0)
)
}
predicate isExistsAllocForThisVariable() {
exists(AllocationExpr alloc, Variable v |
alloc = v.getAnAssignedValue() and
this.getArgument(0) = v.getAnAccess() and
alloc.getASuccessor+() = this
)
or
not stackPointerFlowsToUse(this.getArgument(0), _, _, _)
}
predicate isExistsFreeForThisVariable() {
exists(DeallocationExpr free, Variable v |
this.getArgument(0) = v.getAnAccess() and
free.getFreedExpr() = v.getAnAccess() and
this.getASuccessor+() = free
)
}
predicate isExistsCallWithThisVariableExcludingDeallocationCalls() {
exists(FunctionCall fc, Variable v |
not fc instanceof DeallocationExpr and
this.getArgument(0) = v.getAnAccess() and
fc.getAnArgument() = v.getAnAccess() and
this.getASuccessor+() = fc
)
}
predicate isVariableUseAfterMemsetExcludingCalls() {
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
source.asExpr() = isv.getAnAccess() and
exp.getLocation().getStartLine() > this.getArgument(2).getLocation().getEndLine() and
not exp.getParent() instanceof FunctionCall and
sink.asExpr() = exp
)
}
predicate isVariableUseBoundWithArgumentFunction() {
exists(DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, Parameter p, Expr exp |
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
this.getEnclosingFunction().getAParameter() = p and
exp.getAChild*() = p.getAnAccess() and
source.asExpr() = exp and
sink.asExpr() = isv.getAnAccess()
)
}
predicate isVariableUseBoundWithGlobalVariable() {
exists(
DataFlow::Node source, DataFlow::Node sink, LocalVariable isv, GlobalVariable gv, Expr exp
|
DataFlow::localFlow(source, sink) and
this.getArgument(0) = isv.getAnAccess() and
exp.getAChild*() = gv.getAnAccess() and
source.asExpr() = exp and
sink.asExpr() = isv.getAnAccess()
)
}
predicate isExistsCompilationFlagsBlockingRemoval() {
exists(Compilation c |
c.getAFileCompiled() = this.getFile() and
c.getAnArgument() = "-fno-builtin-memset"
)
}
predicate isUseVCCompilation() {
exists(Compilation c |
c.getAFileCompiled() = this.getFile() and
(
c.getArgument(2).matches("%gcc%") or
c.getArgument(2).matches("%g++%") or
c.getArgument(2).matches("%clang%") or
c.getArgument(2) = "--force-recompute"
)
)
}
}
from CompilerRemovaMemset fc
where
not (fc.isExistsAllocForThisVariable() and not fc.isExistsFreeForThisVariable()) and
not (fc.isExistsFreeForThisVariable() and not fc.isUseVCCompilation()) and
not fc.isVariableUseAfterMemsetExcludingCalls() and
not fc.isExistsCallWithThisVariableExcludingDeallocationCalls() and
not fc.isVariableUseBoundWithArgumentFunction() and
not fc.isVariableUseBoundWithGlobalVariable() and
not fc.isExistsCompilationFlagsBlockingRemoval()
select fc.getArgument(0), "This variable will not be cleared."

View File

@@ -1,11 +0,0 @@
unsigned long sizeArray;
// BAD: let's consider several values, taking ULONG_MAX =18446744073709551615
// sizeArray = 60; (sizeArray - 10) = 50; true
// sizeArray = 10; (sizeArray - 10) = 0; false
// sizeArray = 1; (sizeArray - 10) = 18446744073709551607; true
// sizeArray = 0; (sizeArray - 10) = 18446744073709551606; true
if (sizeArray - 10 > 0)
// GOOD: Prevent overflow by checking the input
if (sizeArray > 10)

View File

@@ -1,33 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The code compares the unsigned difference with zero.
It is highly probable that the condition is wrong if the difference expression has the unsigned type.
The condition holds in all the cases when difference is not equal to zero.
It means that we may use condition not equal. But the programmer probably wanted to compare the difference of elements.</p>
<p>False positives include code in which the first difference element is always greater than or equal to the second.
For comparison, ">" such conditions are equivalent to "! =", And are recommended for replacement.
For comparison "> =", the conditions are always true and are recommended to be excluded.</p>
</overview>
<recommendation>
<p>Use a simple comparison of two elements, instead of comparing their difference to zero.</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of comparison.</p>
<sample src="UnsignedDifferenceExpressionComparedZero.c" />
</example>
<references>
<li>CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules">INT02-C. Understand integer conversion rules</a>.
</li>
</references>
</qhelp>

View File

@@ -1,23 +0,0 @@
/**
* @name Unsigned difference expression compared to zero
* @description It is highly probable that the condition is wrong if the difference expression has the unsigned type.
* The condition holds in all the cases when difference is not equal to zero. It means that we may use condition not equal.
* But the programmer probably wanted to compare the difference of elements.
* @kind problem
* @id cpp/unsigned-difference-expression-compared-zero
* @problem.severity warning
* @precision medium
* @tags security
* external/cwe/cwe-191
*/
import cpp
import semmle.code.cpp.commons.Exclusions
from RelationalOperation ro, SubExpr sub
where
not isFromMacroDefinition(ro) and
ro.getLesserOperand().getValue().toInt() = 0 and
ro.getGreaterOperand() = sub and
sub.getFullyConverted().getUnspecifiedType().(IntegralType).isUnsigned()
select ro, "Difference in condition is always greater than or equal to zero"

View File

@@ -16,6 +16,6 @@ import DataFlow::PathGraph
from WriteConfig b, DataFlow::PathNode source, DataFlow::PathNode sink
where b.hasFlowPath(source, sink)
select sink.getNode(),
"This write into the external location '" + sink + "' may contain unencrypted data from $@",
source, "this source."
select sink.getNode(), source, sink,
"This write into the external location '" + sink.getNode() +
"' may contain unencrypted data from $@", source, "this source."

View File

@@ -12,6 +12,21 @@
*/
import cpp
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.valuenumbering.HashCons
/**
* A function call that potentially does not return (such as `exit`).
*/
class CallMayNotReturn extends FunctionCall {
CallMayNotReturn() {
// call that is known to not return
not exists(this.(ControlFlowNode).getASuccessor())
or
// call to another function that may not return
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
}
}
/**
* A call to `realloc` of the form `v = realloc(v, size)`, for some variable `v`.
@@ -20,50 +35,27 @@ class ReallocCallLeak extends FunctionCall {
Variable v;
ReallocCallLeak() {
exists(AssignExpr ex, VariableAccess va1, VariableAccess va2 |
this.getTarget().hasName("realloc") and
exists(AssignExpr ex |
this.getTarget().hasGlobalOrStdName("realloc") and
this = ex.getRValue() and
va1 = ex.getLValue() and
va2 = this.getArgument(0) and
va1 = v.getAnAccess() and
va2 = v.getAnAccess()
hashCons(ex.getLValue()) = hashCons(this.getArgument(0)) and
v.getAnAccess() = this.getArgument(0)
)
}
predicate isExistsIfWithExitCall() {
exists(IfStmt ifc |
this.getArgument(0) = v.getAnAccess() and
ifc.getCondition().getAChild*() = v.getAnAccess() and
ifc.getEnclosingFunction() = this.getEnclosingFunction() and
ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and
exists(FunctionCall fc |
fc.getTarget().hasName("exit") and
fc.getEnclosingFunction() = this.getEnclosingFunction() and
(ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc)
)
or
exists(FunctionCall fc, FunctionCall ftmp1, FunctionCall ftmp2 |
ftmp1.getTarget().hasName("exit") and
ftmp2.(ControlFlowNode).getASuccessor*() = ftmp1 and
fc = ftmp2.getEnclosingFunction().getACallToThisFunction() and
fc.getEnclosingFunction() = this.getEnclosingFunction() and
(ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc)
)
)
}
predicate isExistsAssertWithArgumentCall() {
exists(FunctionCall fc |
fc.getTarget().hasName("__assert_fail") and
this.getEnclosingFunction() = fc.getEnclosingFunction() and
fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and
fc.getArgument(0).toString().matches("%" + this.getArgument(0).toString() + "%")
/**
* Holds if failure of this allocation may be handled by termination, for
* example a call to `exit()`.
*/
predicate mayHandleByTermination() {
exists(GuardCondition guard, CallMayNotReturn exit |
this.(ControlFlowNode).getASuccessor*() = guard and
guard.getAChild*() = v.getAnAccess() and
guard.controls(exit.getBasicBlock(), _)
)
}
}
from ReallocCallLeak rcl
where
not rcl.isExistsIfWithExitCall() and
not rcl.isExistsAssertWithArgumentCall()
where not rcl.mayHandleByTermination()
select rcl, "possible loss of original pointer on unsuccessful call realloc"

View File

@@ -0,0 +1,35 @@
// BAD: on memory allocation error, the program terminates.
void badFunction(const int *source, std::size_t length) noexcept {
int * dest = new int[length];
std::memset(dest, 0, length);
// ..
}
// GOOD: memory allocation error will be handled.
void goodFunction(const int *source, std::size_t length) noexcept {
try {
int * dest = new int[length];
} catch(std::bad_alloc) {
// ...
}
std::memset(dest, 0, length);
// ..
}
// BAD: memory allocation error will not be handled.
void badFunction(const int *source, std::size_t length) noexcept {
try {
int * dest = new (std::nothrow) int[length];
} catch(std::bad_alloc) {
// ...
}
std::memset(dest, 0, length);
// ..
}
// GOOD: memory allocation error will be handled.
void goodFunction(const int *source, std::size_t length) noexcept {
int * dest = new (std::nothrow) int[length];
if (!dest) {
return;
}
std::memset(dest, 0, length);
// ..
}

View File

@@ -0,0 +1,27 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>When using the <code>new</code> operator to allocate memory, you need to pay attention to the different ways of detecting errors. <code>::operator new(std::size_t)</code> throws an exception on error, whereas <code>::operator new(std::size_t, const std::nothrow_t &amp;)</code> returns zero on error. The programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p>
</overview>
<recommendation>
<p>Use the correct error detection method corresponding with the memory allocation.</p>
</recommendation>
<example>
<p>The following example demonstrates various approaches to detecting memory allocation errors using the <code>new</code> operator.</p>
<sample src="WrongInDetectingAndHandlingMemoryAllocationErrors.cpp" />
</example>
<references>
<li>
CERT C++ Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM52-CPP.+Detect+and+handle+memory+allocation+errors">MEM52-CPP. Detect and handle memory allocation errors</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,87 @@
/**
* @name Detect And Handle Memory Allocation Errors
* @description --::operator new(std::size_t) throws an exception on error, and ::operator new(std::size_t, const std::nothrow_t &) returns zero on error.
* --the programmer can get confused when check the error that occurs when allocating memory incorrectly.
* @kind problem
* @id cpp/detect-and-handle-memory-allocation-errors
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-570
*/
import cpp
/**
* Lookup if condition compare with 0
*/
class IfCompareWithZero extends IfStmt {
IfCompareWithZero() {
this.getCondition().(EQExpr).getAChild().getValue() = "0"
or
this.getCondition().(NEExpr).getAChild().getValue() = "0" and
this.hasElse()
or
this.getCondition().(NEExpr).getAChild().getValue() = "0" and
this.getThen().getAChild*() instanceof ReturnStmt
}
}
/**
* lookup for calls to `operator new`, with incorrect error handling.
*/
class WrongCheckErrorOperatorNew extends FunctionCall {
Expr exp;
WrongCheckErrorOperatorNew() {
this = exp.(NewOrNewArrayExpr).getAChild().(FunctionCall) and
(
this.getTarget().hasGlobalOrStdName("operator new")
or
this.getTarget().hasGlobalOrStdName("operator new[]")
)
}
/**
* Holds if handler `try ... catch` exists.
*/
predicate isExistsTryCatchBlock() {
exists(TryStmt ts | this.getEnclosingStmt() = ts.getStmt().getAChild*())
}
/**
* Holds if results call `operator new` check in `operator if`.
*/
predicate isExistsIfCondition() {
exists(IfCompareWithZero ifc, AssignExpr aex, Initializer it |
// call `operator new` directly from the condition of `operator if`.
this = ifc.getCondition().getAChild*()
or
// check results call `operator new` with variable appropriation
postDominates(ifc, this) and
aex.getAChild() = exp and
ifc.getCondition().getAChild().(VariableAccess).getTarget() =
aex.getLValue().(VariableAccess).getTarget()
or
// check results call `operator new` with declaration variable
postDominates(ifc, this) and
exp = it.getExpr() and
it.getDeclaration() = ifc.getCondition().getAChild().(VariableAccess).getTarget()
)
}
/**
* Holds if `(std::nothrow)` exists in call `operator new`.
*/
predicate isExistsNothrow() { this.getAChild().toString() = "nothrow" }
}
from WrongCheckErrorOperatorNew op
where
// use call `operator new` with `(std::nothrow)` and checking error using `try ... catch` block and not `operator if`
op.isExistsNothrow() and not op.isExistsIfCondition() and op.isExistsTryCatchBlock()
or
// use call `operator new` without `(std::nothrow)` and checking error using `operator if` and not `try ... catch` block
not op.isExistsNothrow() and not op.isExistsTryCatchBlock() and op.isExistsIfCondition()
select op, "memory allocation error check is incorrect or missing"

View File

@@ -0,0 +1,9 @@
// BAD: if buffer does not have a terminal zero, then access outside the allocated memory is possible.
buffer[strlen(buffer)] = 0;
// GOOD: we will eliminate dangerous behavior if we use a different method of calculating the length.
size_t len;
...
buffer[len] = 0

View File

@@ -0,0 +1,31 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Potentially dangerous use of the strlen function to calculate the length of a string.
The expression <code>buffer[strlen(buffer)] = 0</code> is potentially dangerous, if the variable buffer does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior.
If terminal zero is present, then the specified expression is meaningless.</p>
<p>False positives include heavily nested strlen. This situation is unlikely.</p>
</overview>
<recommendation>
<p>We recommend using another method for calculating the string length</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of the strlen function.</p>
<sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/STR32-C.+Do+not+pass+a+non-null-terminated+character+sequence+to+a+library+function+that+expects+a+string">STR32-C. Do not pass a non-null-terminated character sequence to a library function that expects a string</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,34 @@
/**
* @name Access Of Memory Location After End Of Buffer
* @description The expression `buffer [strlen (buffer)] = 0` is potentially dangerous, if the variable `buffer` does not have a terminal zero, then access beyond the bounds of the allocated memory is possible, which will lead to undefined behavior.
* If terminal zero is present, then the specified expression is meaningless.
* @kind problem
* @id cpp/access-memory-location-after-end-buffer
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-788
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
import semmle.code.cpp.dataflow.DataFlow
from StrlenCall fc, AssignExpr expr, ArrayExpr exprarr
where
exprarr = expr.getLValue() and
expr.getRValue().getValue().toInt() = 0 and
globalValueNumber(exprarr.getArrayOffset()) = globalValueNumber(fc) and
not exists(Expr exptmp |
(
DataFlow::localExprFlow(fc, exptmp) or
exptmp.getAChild*() = fc.getArgument(0).(VariableAccess).getTarget().getAnAccess()
) and
dominates(exptmp, expr) and
postDominates(exptmp, fc) and
not exptmp.getEnclosingStmt() = fc.getEnclosingStmt() and
not exptmp.getEnclosingStmt() = expr.getEnclosingStmt()
) and
globalValueNumber(fc.getArgument(0)) = globalValueNumber(exprarr.getArrayBase())
select expr, "potential unsafe or redundant assignment."

View File

@@ -0,0 +1,4 @@
strncat(dest, source, sizeof(dest) - strlen(dest)); // BAD: writes a zero byte past the `dest` buffer.
strncat(dest, source, sizeof(dest) - strlen(dest) -1); // GOOD: Reserves space for the zero byte.

View File

@@ -0,0 +1,32 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>The standard library function <code>strncat(dest, source, count)</code> appends the <code>source</code> string to the <code>dest</code> string. <code>count</code> specifies the maximum number of characters to append and must be less than the remaining space in the target buffer. Calls of the form <code> strncat (dest, source, sizeof (dest) - strlen (dest)) </code> set the third argument to one more than possible. So when the <code>dest</code> is full, the expression <code> sizeof (dest) - strlen (dest) </code> will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the <code>dest</code> buffer.</p>
</overview>
<recommendation>
<p>We recommend subtracting one from the third argument. For example, replace <code>strncat(dest, source, sizeof(dest)-strlen(dest))</code> with <code>strncat(dest, source, sizeof(dest)-strlen(dest)-1)</code>.</p>
</recommendation>
<example>
<p>The following example demonstrates an erroneous and corrected use of the <code>strncat</code> function.</p>
<sample src="AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.c" />
</example>
<references>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/STR31-C.+Guarantee+that+storage+for+strings+has+sufficient+space+for+character+data+and+the+null+terminator">STR31-C. Guarantee that storage for strings has sufficient space for character data and the null terminator</a>.
</li>
<li>
CERT C Coding Standard:
<a href="https://wiki.sei.cmu.edu/confluence/display/c/ARR30-C.+Do+not+form+or+use+out-of-bounds+pointers+or+array+subscripts">ARR30-C. Do not form or use out-of-bounds pointers or array subscripts</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,64 @@
/**
* @name Access Of Memory Location After The End Of A Buffer Using Strncat
* @description Calls of the form `strncat(dest, source, sizeof (dest) - strlen (dest))` set the third argument to one more than possible. So when `dest` is full, the expression `sizeof(dest) - strlen (dest)` will be equal to one, and not zero as the programmer might think. Making a call of this type may result in a zero byte being written just outside the `dest` buffer.
* @kind problem
* @id cpp/access-memory-location-after-end-buffer
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-788
*/
import cpp
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* A call to `strncat` of the form `strncat(buff, str, someExpr - strlen(buf))`, for some expression `someExpr` equal to `sizeof(buff)`.
*/
class WrongCallStrncat extends FunctionCall {
Expr leftsomeExpr;
WrongCallStrncat() {
this.getTarget().hasGlobalOrStdName("strncat") and
// the expression of the first argument in `strncat` and `strnlen` is identical
globalValueNumber(this.getArgument(0)) =
globalValueNumber(this.getArgument(2).(SubExpr).getRightOperand().(StrlenCall).getStringExpr()) and
// using a string constant often speaks of manually calculating the length of the required buffer.
(
not this.getArgument(1) instanceof StringLiteral and
not this.getArgument(1) instanceof CharLiteral
) and
// for use in predicates
leftsomeExpr = this.getArgument(2).(SubExpr).getLeftOperand()
}
/**
* Holds if the left side of the expression `someExpr` equal to `sizeof(buf)`.
*/
predicate isExpressionEqualSizeof() {
// the left side of the expression `someExpr` is `sizeof(buf)`.
globalValueNumber(this.getArgument(0)) =
globalValueNumber(leftsomeExpr.(SizeofExprOperator).getExprOperand())
or
// value of the left side of the expression `someExpr` equal `sizeof(buf)` value, and `buf` is array.
leftsomeExpr.getValue().toInt() = this.getArgument(0).getType().getSize()
}
/**
* Holds if the left side of the expression `someExpr` equal to variable containing the length of the memory allocated for the buffer.
*/
predicate isVariableEqualValueSizegBuffer() {
// the left side of expression `someExpr` is the variable that was used in the function of allocating memory for the buffer`.
exists(AllocationExpr alc |
leftsomeExpr.(VariableAccess).getTarget() =
alc.(FunctionCall).getArgument(0).(VariableAccess).getTarget()
)
}
}
from WrongCallStrncat sc
where
sc.isExpressionEqualSizeof() or
sc.isVariableEqualValueSizegBuffer()
select sc, "if the used buffer is full, writing out of the buffer is possible"

View File

@@ -50,5 +50,5 @@ class CStyleComment extends Comment {
* ```
*/
class CppStyleComment extends Comment {
CppStyleComment() { this.getContents().prefix(2) = "//" }
CppStyleComment() { this.getContents().matches("//%") }
}

View File

@@ -270,7 +270,12 @@ private predicate isFromUninstantiatedTemplateRec(Element e, Element template) {
}
/**
* A C++11 `static_assert` or C11 `_Static_assert` construct.
* A C++11 `static_assert` or C11 `_Static_assert` construct. For example each
* line in the following example contains a static assert:
* ```
* static_assert(sizeof(MyStruct) <= 4096);
* static_assert(sizeof(MyStruct) <= 4096, "MyStruct is too big!");
* ```
*/
class StaticAssert extends Locatable, @static_assert {
override string toString() { result = "static_assert(..., \"" + getMessage() + "\")" }

View File

@@ -334,6 +334,18 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
)
}
/**
* Gets the class of which this function, called `memberName`, is a member.
*
* Prefer to use `getDeclaringType()` or `getName()` directly if you do not
* need to reason about both.
*/
pragma[nomagic]
Class getClassAndName(string memberName) {
this.hasName(memberName) and
this.getDeclaringType() = result
}
/**
* Implements `ControlFlowNode.getControlFlowScope`. The `Function` is
* used to represent the exit node of the control flow graph, so it is

View File

@@ -7,8 +7,21 @@ import semmle.code.cpp.Type
import semmle.code.cpp.metrics.MetricNamespace
/**
* A C++ namespace.
* A C++ namespace. For example the (single) namespace `A` in the following
* code:
* ```
* namespace A
* {
* // ...
* }
*
* // ...
*
* namespace A
* {
* // ...
* }
* ```
* Note that namespaces are somewhat nebulous entities, as they do not in
* general have a single well-defined location in the source code. The
* related notion of a `NamespaceDeclarationEntry` is rather more concrete,
@@ -96,10 +109,22 @@ class Namespace extends NameQualifyingElement, @namespace {
}
/**
* A declaration of (part of) a C++ namespace.
* A declaration of (part of) a C++ namespace. This corresponds to a single
* `namespace N { ... }` occurrence in the source code. For example the two
* mentions of `A` in the following code:
* ```
* namespace A
* {
* // ...
* }
*
* This corresponds to a single `namespace N { ... }` occurrence in the
* source code.
* // ...
*
* namespace A
* {
* // ...
* }
* ```
*/
class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
/**
@@ -143,8 +168,9 @@ class UsingEntry extends Locatable, @using {
/**
* A C++ `using` declaration. For example:
*
* `using std::string;`
* ```
* using std::string;
* ```
*/
class UsingDeclarationEntry extends UsingEntry {
UsingDeclarationEntry() {
@@ -162,8 +188,9 @@ class UsingDeclarationEntry extends UsingEntry {
/**
* A C++ `using` directive. For example:
*
* `using namespace std;`
* ```
* using namespace std;
* ```
*/
class UsingDirectiveEntry extends UsingEntry {
UsingDirectiveEntry() {

View File

@@ -2,9 +2,14 @@ import semmle.code.cpp.Location
import semmle.code.cpp.Element
/**
* A C/C++ preprocessor directive.
*
* For example: `#ifdef`, `#line`, or `#pragma`.
* A C/C++ preprocessor directive. For example each of the following lines of
* code contains a `PreprocessorDirective`:
* ```
* #pragma once
* #ifdef MYDEFINE
* #include "myfile.h"
* #line 1 "source.c"
* ```
*/
class PreprocessorDirective extends Locatable, @preprocdirect {
override string toString() { result = "Preprocessor directive" }
@@ -98,9 +103,9 @@ class PreprocessorBranchDirective extends PreprocessorDirective, TPreprocessorBr
* A C/C++ preprocessor branching directive: `#if`, `#ifdef`, `#ifndef`, or
* `#elif`.
*
* A branching directive can have its condition evaluated at compile-time,
* and as a result, the preprocessor will either take the branch, or not
* take the branch.
* A branching directive has a condition and that condition may be evaluated
* at compile-time. As a result, the preprocessor will either take the
* branch, or not take the branch.
*
* However, there are also situations in which a branch's condition isn't
* evaluated. The obvious case of this is when the directive is contained
@@ -136,8 +141,13 @@ class PreprocessorBranch extends PreprocessorBranchDirective, @ppd_branch {
}
/**
* A C/C++ preprocessor `#if` directive.
*
* A C/C++ preprocessor `#if` directive. For example there is a
* `PreprocessorIf` on the first line of the following code:
* ```
* #if defined(MYDEFINE)
* // ...
* #endif
* ```
* For the related notion of a directive which causes branching (which
* includes `#if`, plus also `#ifdef`, `#ifndef`, and `#elif`), see
* `PreprocessorBranch`.
@@ -147,8 +157,13 @@ class PreprocessorIf extends PreprocessorBranch, @ppd_if {
}
/**
* A C/C++ preprocessor `#ifdef` directive.
*
* A C/C++ preprocessor `#ifdef` directive. For example there is a
* `PreprocessorIfdef` on the first line of the following code:
* ```
* #ifdef MYDEFINE
* // ...
* #endif
* ```
* The syntax `#ifdef X` is shorthand for `#if defined(X)`.
*/
class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
@@ -158,8 +173,13 @@ class PreprocessorIfdef extends PreprocessorBranch, @ppd_ifdef {
}
/**
* A C/C++ preprocessor `#ifndef` directive.
*
* A C/C++ preprocessor `#ifndef` directive. For example there is a
* `PreprocessorIfndef` on the first line of the following code:
* ```
* #ifndef MYDEFINE
* // ...
* #endif
* ```
* The syntax `#ifndef X` is shorthand for `#if !defined(X)`.
*/
class PreprocessorIfndef extends PreprocessorBranch, @ppd_ifndef {
@@ -167,42 +187,80 @@ class PreprocessorIfndef extends PreprocessorBranch, @ppd_ifndef {
}
/**
* A C/C++ preprocessor `#else` directive.
* A C/C++ preprocessor `#else` directive. For example there is a
* `PreprocessorElse` on the fifth line of the following code:
* ```
* #ifdef MYDEFINE1
* // ...
* #elif MYDEFINE2
* // ...
* #else
* // ...
* #endif
* ```
*/
class PreprocessorElse extends PreprocessorBranchDirective, @ppd_else {
override string toString() { result = "#else" }
}
/**
* A C/C++ preprocessor `#elif` directive.
* A C/C++ preprocessor `#elif` directive. For example there is a
* `PreprocessorElif` on the third line of the following code:
* ```
* #ifdef MYDEFINE1
* // ...
* #elif MYDEFINE2
* // ...
* #else
* // ...
* #endif
* ```
*/
class PreprocessorElif extends PreprocessorBranch, @ppd_elif {
override string toString() { result = "#elif " + this.getHead() }
}
/**
* A C/C++ preprocessor `#endif` directive.
* A C/C++ preprocessor `#endif` directive. For example there is a
* `PreprocessorEndif` on the third line of the following code:
* ```
* #ifdef MYDEFINE
* // ...
* #endif
* ```
*/
class PreprocessorEndif extends PreprocessorBranchDirective, @ppd_endif {
override string toString() { result = "#endif" }
}
/**
* A C/C++ preprocessor `#warning` directive.
* A C/C++ preprocessor `#warning` directive. For example:
* ```
* #warning "This configuration is not supported."
* ```
*/
class PreprocessorWarning extends PreprocessorDirective, @ppd_warning {
override string toString() { result = "#warning " + this.getHead() }
}
/**
* A C/C++ preprocessor `#error` directive.
* A C/C++ preprocessor `#error` directive. For example:
* ```
* #error "This configuration is not implemented."
* ```
*/
class PreprocessorError extends PreprocessorDirective, @ppd_error {
override string toString() { result = "#error " + this.getHead() }
}
/**
* A C/C++ preprocessor `#undef` directive.
* A C/C++ preprocessor `#undef` directive. For example there is a
* `PreprocessorUndef` on the second line of the following code:
* ```
* #ifdef MYMACRO
* #undef MYMACRO
* #endif
* ```
*/
class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
override string toString() { result = "#undef " + this.getHead() }
@@ -214,7 +272,10 @@ class PreprocessorUndef extends PreprocessorDirective, @ppd_undef {
}
/**
* A C/C++ preprocessor `#pragma` directive.
* A C/C++ preprocessor `#pragma` directive. For example:
* ```
* #pragma once
* ```
*/
class PreprocessorPragma extends PreprocessorDirective, @ppd_pragma {
override string toString() {
@@ -223,7 +284,10 @@ class PreprocessorPragma extends PreprocessorDirective, @ppd_pragma {
}
/**
* A C/C++ preprocessor `#line` directive.
* A C/C++ preprocessor `#line` directive. For example:
* ```
* #line 1 "source.c"
* ```
*/
class PreprocessorLine extends PreprocessorDirective, @ppd_line {
override string toString() { result = "#line " + this.getHead() }

View File

@@ -171,8 +171,11 @@ class StdAttribute extends Attribute, @stdattribute {
}
/**
* An attribute introduced by Microsoft's `__declspec(name)` syntax, for
* example: `__declspec(dllimport)`.
* An attribute introduced by Microsoft's `__declspec(name)` syntax. For
* example the attribute on the following declaration:
* ```
* __declspec(dllimport) void myFunction();
* ```
*/
class Declspec extends Attribute, @declspec { }
@@ -186,8 +189,13 @@ class MicrosoftAttribute extends Attribute, @msattribute {
}
/**
* A C++11 `alignas` construct.
*
* A C++11 `alignas` construct. For example the attribute in the following
* code:
* ```
* struct alignas(16) MyStruct {
* int x;
* };
* ```
* Though it doesn't use the attribute syntax, `alignas(...)` is presented
* as an `Attribute` for consistency with the `[[align(...)]]` attribute.
*/
@@ -197,7 +205,11 @@ class AlignAs extends Attribute, @alignas {
/**
* A GNU `format` attribute of the form `__attribute__((format(archetype, format-index, first-arg)))`
* that declares a function to accept a `printf` style format string.
* that declares a function to accept a `printf` style format string. For example the attribute
* on the following declaration:
* ```
* int myPrintf(const char *format, ...) __attribute__((format(printf, 1, 2)));
* ```
*/
class FormatAttribute extends GnuAttribute {
FormatAttribute() { getName() = "format" }
@@ -242,7 +254,11 @@ class FormatAttribute extends GnuAttribute {
}
/**
* An argument to an `Attribute`.
* An argument to an `Attribute`. For example the argument "dllimport" on the
* attribute in the following code:
* ```
* __declspec(dllimport) void myFunction();
* ```
*/
class AttributeArgument extends Element, @attribute_arg {
/**

View File

@@ -274,7 +274,7 @@ class Type extends Locatable, @type {
/**
* Gets this type with any typedefs resolved. For example, given
* `typedef C T`, this would resolve `const T&amp;` to `const C&amp;`.
* `typedef C T`, this would resolve `const T&` to `const C&`.
* Note that this will only work if the resolved type actually appears
* on its own elsewhere in the program.
*/
@@ -1544,9 +1544,9 @@ class FunctionPointerIshType extends DerivedType {
/**
* A C++ pointer to data member. See 15.5.
* ```
* class C { int m; };
* class C { public: int m; };
* int C::* p = &C::m; // pointer to data member m of class C
* class C *;
* class C c;
* int val = c.*p; // access data member
* ```
*/

View File

@@ -50,7 +50,10 @@ predicate primitiveVariadicFormatter(
then formatParamIndex = f.getNumberOfParameters() - 3
else formatParamIndex = f.getNumberOfParameters() - 2
) and
if type = "" then outputParamIndex = -1 else outputParamIndex = 0 // Conveniently, these buffer parameters are all at index 0.
(
if type = "" then outputParamIndex = -1 else outputParamIndex = 0 // Conveniently, these buffer parameters are all at index 0.
) and
not exists(f.getBlock()) // exclude functions with an implementation in the snapshot as they may not be standard implementations.
}
private predicate callsVariadicFormatter(

View File

@@ -92,7 +92,9 @@ class Snscanf extends ScanfFunction {
this instanceof TopLevelFunction and
(
hasName("_snscanf") or // _snscanf(src, max_amount, format, args...)
hasName("_snwscanf") // _snwscanf(src, max_amount, format, args...)
hasName("_snwscanf") or // _snwscanf(src, max_amount, format, args...)
hasName("_snscanf_l") or // _snscanf_l(src, max_amount, format, locale, args...)
hasName("_snwscanf_l") // _snwscanf_l(src, max_amount, format, locale, args...)
// note that the max_amount is not a limit on the output length, it's an input length
// limit used with non null-terminated strings.
)
@@ -101,6 +103,12 @@ class Snscanf extends ScanfFunction {
override int getInputParameterIndex() { result = 0 }
override int getFormatParameterIndex() { result = 2 }
/**
* Gets the position at which the maximum number of characters in the
* input string is specified.
*/
int getInputLengthParameterIndex() { result = 1 }
}
/**

View File

@@ -87,7 +87,7 @@ abstract class MutexType extends Type {
private Function mustlockCandidate() {
exists(string name | name = result.getName() |
name = "lock" or
name.suffix(name.length() - 10) = "mutex_lock"
name.matches("%mutex\\_lock")
)
}
@@ -97,7 +97,7 @@ private Function mustlockCandidate() {
private Function trylockCandidate() {
exists(string name | name = result.getName() |
name = "try_lock" or
name.suffix(name.length() - 13) = "mutex_trylock"
name.matches("%mutex\\_trylock")
)
}
@@ -107,7 +107,7 @@ private Function trylockCandidate() {
private Function unlockCandidate() {
exists(string name | name = result.getName() |
name = "unlock" or
name.suffix(name.length() - 12) = "mutex_unlock"
name.matches("%mutex\\_unlock")
)
}

View File

@@ -716,21 +716,15 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
iTo = call
or
exists(int index, WriteSideEffectInstruction outNode |
modelOut.isParameterDeref(index) and
modelOut.isParameterDerefOrQualifierObject(index) and
iTo = outNode and
outNode = getSideEffectFor(call, index)
)
or
exists(WriteSideEffectInstruction outNode |
modelOut.isQualifierObject() and
iTo = outNode and
outNode = getSideEffectFor(call, -1)
)
) and
(
exists(int index |
modelIn.isParameter(index) and
opFrom = call.getPositionalArgumentOperand(index)
modelIn.isParameterOrQualifierAddress(index) and
opFrom = call.getArgumentOperand(index)
)
or
exists(int index, ReadSideEffectInstruction read |
@@ -739,9 +733,6 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
opFrom = read.getSideEffectOperand()
)
or
modelIn.isQualifierAddress() and
opFrom = call.getThisArgumentOperand()
or
exists(ReadSideEffectInstruction read |
modelIn.isQualifierObject() and
read = getSideEffectFor(call, -1) and

View File

@@ -341,7 +341,7 @@ module IRTypeConsistency {
query predicate multipleIRTypes(Language::LanguageType type, string message) {
strictcount(type.getIRType()) > 1 and
message =
"`LanguageType` " + type.getAQlClass() + " has multiple `IRType`s: " +
"`LanguageType` " + type + " has multiple `IRType`s: " +
concat(type.getIRType().toString(), ", ")
}

View File

@@ -15,6 +15,10 @@ private import implementations.Strcat
private import implementations.Strcpy
private import implementations.Strdup
private import implementations.Strftime
private import implementations.Strtok
private import implementations.Strset
private import implementations.Strcrement
private import implementations.Strnextc
private import implementations.StdContainer
private import implementations.StdPair
private import implementations.StdMap
@@ -23,3 +27,4 @@ private import implementations.StdString
private import implementations.Swap
private import implementations.GetDelim
private import implementations.SmartPointer
private import implementations.Sscanf

View File

@@ -32,5 +32,7 @@ private class IdentityFunction extends DataFlowFunction, SideEffectFunction, Ali
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// These functions simply return the argument value.
input.isParameter(0) and output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
}
}

View File

@@ -109,6 +109,8 @@ private class IteratorCrementOperator extends Operator, DataFlowFunction {
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input = iteratorInput and
output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
}
}
@@ -159,6 +161,8 @@ private class IteratorAssignArithmeticOperator extends Operator, DataFlowFunctio
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and
output.isReturnValue()
or
input.isParameterDeref(0) and output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -201,6 +205,9 @@ private class IteratorCrementMemberOperator extends MemberFunction, DataFlowFunc
or
input.isReturnValueDeref() and
output.isQualifierObject()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -6,6 +6,7 @@
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint
@@ -13,32 +14,35 @@ import semmle.code.cpp.models.interfaces.Taint
* The standard functions `memcpy`, `memmove` and `bcopy`; and the gcc variant
* `__builtin___memcpy_chk`.
*/
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction {
private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction,
AliasFunction {
MemcpyFunction() {
// memcpy(dest, src, num)
// memmove(dest, src, num)
// memmove(dest, src, num, remaining)
this.hasName(["memcpy", "memmove", "__builtin___memcpy_chk"])
this.hasGlobalOrStdName(["memcpy", "memmove"])
or
// bcopy(src, dest, num)
this.hasGlobalOrStdName("bcopy")
// mempcpy(dest, src, num)
// memccpy(dest, src, c, n)
this.hasGlobalName(["bcopy", mempcpy(), "memccpy", "__builtin___memcpy_chk"])
}
/**
* Gets the index of the parameter that is the source buffer for the copy.
*/
int getParamSrc() { if this.hasGlobalOrStdName("bcopy") then result = 0 else result = 1 }
int getParamSrc() { if this.hasGlobalName("bcopy") then result = 0 else result = 1 }
/**
* Gets the index of the parameter that is the destination buffer for the
* copy.
*/
int getParamDest() { if this.hasGlobalOrStdName("bcopy") then result = 1 else result = 0 }
int getParamDest() { if this.hasGlobalName("bcopy") then result = 1 else result = 0 }
/**
* Gets the index of the parameter that is the size of the copy (in bytes).
*/
int getParamSize() { result = 2 }
int getParamSize() { if this.hasGlobalName("memccpy") then result = 3 else result = 2 }
override predicate hasArrayInput(int bufParam) { bufParam = getParamSrc() }
@@ -68,7 +72,10 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = getParamDest() and buffer = true and mustWrite = true
i = getParamDest() and
buffer = true and
// memccpy only writes until a given character `c` is found
(if this.hasGlobalName("memccpy") then mustWrite = false else mustWrite = true)
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
@@ -82,4 +89,21 @@ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffect
i = getParamSrc()
)
}
override predicate parameterNeverEscapes(int index) {
index = getParamSrc()
or
this.hasGlobalName("bcopy") and index = getParamDest()
}
override predicate parameterEscapesOnlyViaReturn(int index) {
not this.hasGlobalName("bcopy") and index = getParamDest()
}
override predicate parameterIsAlwaysReturned(int index) {
not this.hasGlobalName(["bcopy", mempcpy(), "memccpy"]) and
index = getParamDest()
}
}
private string mempcpy() { result = ["mempcpy", "wmempcpy"] }

View File

@@ -15,8 +15,9 @@ import semmle.code.cpp.models.interfaces.SideEffect
private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction {
MemsetFunction() {
hasGlobalName(["memset", "wmemset", "bzero", "__builtin_memset", "__builtin_memset_chk"]) or
hasQualifiedName("std", ["memset", "wmemset"])
this.hasGlobalOrStdName(["memset", "wmemset"])
or
this.hasGlobalName([bzero(), "__builtin_memset", "__builtin_memset_chk"])
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
@@ -28,17 +29,17 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
bufParam = 0 and
(if hasGlobalName("bzero") then countParam = 1 else countParam = 2)
(if hasGlobalName(bzero()) then countParam = 1 else countParam = 2)
}
override predicate parameterNeverEscapes(int index) { hasGlobalName("bzero") and index = 0 }
override predicate parameterNeverEscapes(int index) { hasGlobalName(bzero()) and index = 0 }
override predicate parameterEscapesOnlyViaReturn(int index) {
not hasGlobalName("bzero") and index = 0
not hasGlobalName(bzero()) and index = 0
}
override predicate parameterIsAlwaysReturned(int index) {
not hasGlobalName("bzero") and index = 0
not hasGlobalName(bzero()) and index = 0
}
override predicate hasOnlySpecificReadSideEffects() { any() }
@@ -51,6 +52,8 @@ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunct
override ParameterIndex getParameterSizeIndex(ParameterIndex i) {
i = 0 and
if hasGlobalName("bzero") then result = 1 else result = 2
if hasGlobalName(bzero()) then result = 1 else result = 2
}
}
private string bzero() { result = ["bzero", "explicit_bzero"] }

View File

@@ -8,9 +8,8 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
SideEffectFunction {
PureStrFunction() {
hasGlobalOrStdName([
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
"strtol", "strtoll", "strtoq", "strtoul"
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr()
])
}
@@ -24,11 +23,16 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(ParameterIndex i |
input.isParameter(i) and
exists(getParameter(i))
or
input.isParameterDeref(i) and
getParameter(i).getUnspecifiedType() instanceof PointerType
(
input.isParameter(i) and
exists(getParameter(i))
or
input.isParameterDeref(i) and
getParameter(i).getUnspecifiedType() instanceof PointerType
) and
// Functions that end with _l also take a locale argument (always as the last argument),
// and we don't want taint from those arguments.
(not this.getName().matches("%\\_l") or exists(getParameter(i + 1)))
) and
(
output.isReturnValueDeref() and
@@ -60,6 +64,31 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
}
}
private string atoi() { result = ["atof", "atoi", "atol", "atoll"] }
private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] }
private string strlwr() {
result = ["_strlwr", "_wcslwr", "_mbslwr", "_strlwr_l", "_wcslwr_l", "_mbslwr_l"]
}
private string strupr() {
result = ["_strupr", "_wcsupr", "_mbsupr", "_strupr_l", "_wcsupr_l", "_mbsupr_l"]
}
private string strrev() { result = ["_strrev", "_wcsrev", "_mbsrev", "_mbsrev_l"] }
private string strcmp() {
// NOTE: `strcoll` doesn't satisfy _all_ the definitions of purity: its behavior depends on
// `LC_COLLATE` (which is set by `setlocale`). Not sure this behavior worth including in the model, so
// for now we interpret the function as being pure.
result =
[
"strcmp", "strcspn", "strncmp", "strcoll", "strverscmp", "_mbsnbcmp", "_mbsnbcmp_l",
"_stricmp"
]
}
/** String standard `strlen` function, and related functions for computing string lengths. */
private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction {
StrLenFunction() {
@@ -114,7 +143,12 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
/** Pure raw-memory functions. */
private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
SideEffectFunction {
PureMemFunction() { hasGlobalOrStdName(["memchr", "memrchr", "rawmemchr", "memcmp", "memmem"]) }
PureMemFunction() {
hasGlobalOrStdName([
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"
]) or
this.hasGlobalName("memfrob")
}
override predicate hasArrayInput(int bufParam) {
getParameter(bufParam).getUnspecifiedType() instanceof PointerType
@@ -122,11 +156,15 @@ private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunctio
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(ParameterIndex i |
input.isParameter(i) and
exists(getParameter(i))
or
input.isParameterDeref(i) and
getParameter(i).getUnspecifiedType() instanceof PointerType
(
input.isParameter(i) and
exists(getParameter(i))
or
input.isParameterDeref(i) and
getParameter(i).getUnspecifiedType() instanceof PointerType
) and
// `memfrob` should not have taint from the size argument.
(not this.hasGlobalName("memfrob") or i = 0)
) and
(
output.isReturnValueDeref() and

View File

@@ -0,0 +1,72 @@
/**
* Provides implementation classes modeling `sscanf`, `fscanf` and various similar
* functions. See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.commons.Scanf
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function `sscanf`, `fscanf` and its assorted variants
*/
private class SscanfModel extends ArrayFunction, TaintFunction, AliasFunction, SideEffectFunction {
SscanfModel() { this instanceof Sscanf or this instanceof Fscanf or this instanceof Snscanf }
override predicate hasArrayWithNullTerminator(int bufParam) {
bufParam = this.(ScanfFunction).getFormatParameterIndex()
or
not this instanceof Fscanf and
bufParam = this.(ScanfFunction).getInputParameterIndex()
}
override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) }
private int getLengthParameterIndex() { result = this.(Snscanf).getInputLengthParameterIndex() }
private int getLocaleParameterIndex() {
this.getName().matches("%\\_l") and
(
if exists(getLengthParameterIndex())
then result = getLengthParameterIndex() + 2
else result = 2
)
}
private int getArgsStartPosition() { result = this.getNumberOfParameters() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(this.(ScanfFunction).getInputParameterIndex()) and
output.isParameterDeref(any(int i | i >= getArgsStartPosition()))
}
override predicate parameterNeverEscapes(int index) {
index = [0 .. max(getACallToThisFunction().getNumberOfArguments())]
}
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i >= getArgsStartPosition() and
buffer = true and
mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
buffer = true and
i =
[
this.(ScanfFunction).getInputParameterIndex(),
this.(ScanfFunction).getFormatParameterIndex(), getLocaleParameterIndex()
]
}
}

View File

@@ -193,7 +193,7 @@ class StdVectorEmplace extends TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter except the position iterator to qualifier and return value
// (here we assume taint flow from any constructor parameter to the constructed object)
input.isParameter([1 .. getNumberOfParameters() - 1]) and
input.isParameterDeref([1 .. getNumberOfParameters() - 1]) and
(
output.isQualifierObject() or
output.isReturnValue()
@@ -210,7 +210,7 @@ class StdVectorEmplaceBack extends TaintFunction {
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from any parameter to qualifier
// (here we assume taint flow from any constructor parameter to the constructed object)
input.isParameter([0 .. getNumberOfParameters() - 1]) and
input.isParameterDeref([0 .. getNumberOfParameters() - 1]) and
output.isQualifierObject()
}
}

View File

@@ -9,9 +9,9 @@ import semmle.code.cpp.models.interfaces.Iterator
import semmle.code.cpp.models.interfaces.DataFlow
/**
* The `std::basic_string` template class.
* The `std::basic_string` template class instantiations.
*/
private class StdBasicString extends TemplateClass {
private class StdBasicString extends ClassTemplateInstantiation {
StdBasicString() { this.hasQualifiedName("std", "basic_string") }
}
@@ -24,7 +24,7 @@ private class StdBasicString extends TemplateClass {
* ```
*/
private class StdStringConstructor extends Constructor, TaintFunction {
StdStringConstructor() { this.getDeclaringType().hasQualifiedName("std", "basic_string") }
StdStringConstructor() { this.getDeclaringType() instanceof StdBasicString }
/**
* Gets the index of a parameter to this function that is a string (or
@@ -69,7 +69,7 @@ private class StdStringConstructor extends Constructor, TaintFunction {
* The `std::string` function `c_str`.
*/
private class StdStringCStr extends TaintFunction {
StdStringCStr() { this.hasQualifiedName("std", "basic_string", "c_str") }
StdStringCStr() { this.getClassAndName("c_str") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
@@ -82,7 +82,7 @@ private class StdStringCStr extends TaintFunction {
* The `std::string` function `data`.
*/
private class StdStringData extends TaintFunction {
StdStringData() { this.hasQualifiedName("std", "basic_string", "data") }
StdStringData() { this.getClassAndName("data") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from string itself (qualifier) to return value
@@ -100,7 +100,7 @@ private class StdStringData extends TaintFunction {
* The `std::string` function `push_back`.
*/
private class StdStringPush extends TaintFunction {
StdStringPush() { this.hasQualifiedName("std", "basic_string", "push_back") }
StdStringPush() { this.getClassAndName("push_back") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from parameter to qualifier
@@ -113,7 +113,7 @@ private class StdStringPush extends TaintFunction {
* The `std::string` functions `front` and `back`.
*/
private class StdStringFrontBack extends TaintFunction {
StdStringFrontBack() { this.hasQualifiedName("std", "basic_string", ["front", "back"]) }
StdStringFrontBack() { this.getClassAndName(["front", "back"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from object to returned reference
@@ -123,12 +123,12 @@ private class StdStringFrontBack extends TaintFunction {
}
/**
* The `std::string` function `operator+`.
* The (non-member) `std::string` function `operator+`.
*/
private class StdStringPlus extends TaintFunction {
StdStringPlus() {
this.hasQualifiedName("std", "operator+") and
this.getUnspecifiedType() = any(StdBasicString s).getAnInstantiation()
this.getUnspecifiedType() instanceof StdBasicString
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -148,7 +148,7 @@ private class StdStringPlus extends TaintFunction {
*/
private class StdStringAppend extends TaintFunction {
StdStringAppend() {
this.hasQualifiedName("std", "basic_string", ["operator+=", "append", "insert", "replace"])
this.getClassAndName(["operator+=", "append", "insert", "replace"]) instanceof StdBasicString
}
/**
@@ -190,7 +190,7 @@ private class StdStringAppend extends TaintFunction {
* The standard function `std::string.assign`.
*/
private class StdStringAssign extends TaintFunction {
StdStringAssign() { this.hasQualifiedName("std", "basic_string", "assign") }
StdStringAssign() { this.getClassAndName("assign") instanceof StdBasicString }
/**
* Gets the index of a parameter to this function that is a string (or
@@ -230,7 +230,7 @@ private class StdStringAssign extends TaintFunction {
* The standard function `std::string.copy`.
*/
private class StdStringCopy extends TaintFunction {
StdStringCopy() { this.hasQualifiedName("std", "basic_string", "copy") }
StdStringCopy() { this.getClassAndName("copy") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// copy(dest, num, pos)
@@ -243,7 +243,7 @@ private class StdStringCopy extends TaintFunction {
* The standard function `std::string.substr`.
*/
private class StdStringSubstr extends TaintFunction {
StdStringSubstr() { this.hasQualifiedName("std", "basic_string", "substr") }
StdStringSubstr() { this.getClassAndName("substr") instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// substr(pos, num)
@@ -252,11 +252,18 @@ private class StdStringSubstr extends TaintFunction {
}
}
/**
* The `std::basic_stringstream` template class instantiations.
*/
private class StdBasicStringStream extends ClassTemplateInstantiation {
StdBasicStringStream() { this.hasQualifiedName("std", "basic_stringstream") }
}
/**
* The `std::string` functions `at` and `operator[]`.
*/
private class StdStringAt extends TaintFunction {
StdStringAt() { this.hasQualifiedName("std", "basic_string", ["at", "operator[]"]) }
StdStringAt() { this.getClassAndName(["at", "operator[]"]) instanceof StdBasicString }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to referenced return value
@@ -270,9 +277,9 @@ private class StdStringAt extends TaintFunction {
}
/**
* The `std::basic_istream` template class.
* The `std::basic_istream` template class instantiations.
*/
private class StdBasicIStream extends TemplateClass {
private class StdBasicIStream extends ClassTemplateInstantiation {
StdBasicIStream() { this.hasQualifiedName("std", "basic_istream") }
}
@@ -280,12 +287,15 @@ private class StdBasicIStream extends TemplateClass {
* The `std::istream` function `operator>>` (defined as a member function).
*/
private class StdIStreamIn extends DataFlowFunction, TaintFunction {
StdIStreamIn() { this.hasQualifiedName("std", "basic_istream", "operator>>") }
StdIStreamIn() { this.getClassAndName("operator>>") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -305,14 +315,16 @@ private class StdIStreamIn extends DataFlowFunction, TaintFunction {
private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
StdIStreamInNonMember() {
this.hasQualifiedName("std", "operator>>") and
this.getUnspecifiedType().(ReferenceType).getBaseType() =
any(StdBasicIStream s).getAnInstantiation()
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicIStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter to return value
input.isParameter(0) and
output.isReturnValue()
or
input.isParameterDeref(0) and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -331,7 +343,7 @@ private class StdIStreamInNonMember extends DataFlowFunction, TaintFunction {
*/
private class StdIStreamGet extends TaintFunction {
StdIStreamGet() {
this.hasQualifiedName("std", "basic_istream", ["get", "peek"]) and
this.getClassAndName(["get", "peek"]) instanceof StdBasicIStream and
this.getNumberOfParameters() = 0
}
@@ -347,7 +359,7 @@ private class StdIStreamGet extends TaintFunction {
*/
private class StdIStreamRead extends DataFlowFunction, TaintFunction {
StdIStreamRead() {
this.hasQualifiedName("std", "basic_istream", ["get", "read"]) and
this.getClassAndName(["get", "read"]) instanceof StdBasicIStream and
this.getNumberOfParameters() > 0
}
@@ -355,6 +367,9 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -372,7 +387,7 @@ private class StdIStreamRead extends DataFlowFunction, TaintFunction {
* The `std::istream` function `readsome`.
*/
private class StdIStreamReadSome extends TaintFunction {
StdIStreamReadSome() { this.hasQualifiedName("std", "basic_istream", "readsome") }
StdIStreamReadSome() { this.getClassAndName("readsome") instanceof StdBasicIStream }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to first parameter
@@ -385,12 +400,15 @@ private class StdIStreamReadSome extends TaintFunction {
* The `std::istream` function `putback`.
*/
private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
StdIStreamPutBack() { this.hasQualifiedName("std", "basic_istream", "putback") }
StdIStreamPutBack() { this.getClassAndName("putback") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -418,12 +436,15 @@ private class StdIStreamPutBack extends DataFlowFunction, TaintFunction {
* The `std::istream` function `getline`.
*/
private class StdIStreamGetLine extends DataFlowFunction, TaintFunction {
StdIStreamGetLine() { this.hasQualifiedName("std", "basic_istream", "getline") }
StdIStreamGetLine() { this.getClassAndName("getline") instanceof StdBasicIStream }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -447,6 +468,9 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
// flow from first parameter to return value
input.isParameter(0) and
output.isReturnValue()
or
input.isParameterDeref(0) and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -461,9 +485,9 @@ private class StdGetLine extends DataFlowFunction, TaintFunction {
}
/**
* The `std::basic_ostream` template class.
* The `std::basic_ostream` template class instantiations.
*/
private class StdBasicOStream extends TemplateClass {
private class StdBasicOStream extends ClassTemplateInstantiation {
StdBasicOStream() { this.hasQualifiedName("std", "basic_ostream") }
}
@@ -472,12 +496,17 @@ private class StdBasicOStream extends TemplateClass {
* `put` and `write`.
*/
private class StdOStreamOut extends DataFlowFunction, TaintFunction {
StdOStreamOut() { this.hasQualifiedName("std", "basic_ostream", ["operator<<", "put", "write"]) }
StdOStreamOut() {
this.getClassAndName(["operator<<", "put", "write"]) instanceof StdBasicOStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -507,14 +536,16 @@ private class StdOStreamOut extends DataFlowFunction, TaintFunction {
private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
StdOStreamOutNonMember() {
this.hasQualifiedName("std", "operator<<") and
this.getUnspecifiedType().(ReferenceType).getBaseType() =
any(StdBasicOStream s).getAnInstantiation()
this.getUnspecifiedType().(ReferenceType).getBaseType() instanceof StdBasicOStream
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// flow from first parameter to return value
input.isParameter(0) and
output.isReturnValue()
or
input.isParameterDeref(0) and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -537,9 +568,7 @@ private class StdOStreamOutNonMember extends DataFlowFunction, TaintFunction {
* input parameter.
*/
private class StdStringStreamConstructor extends Constructor, TaintFunction {
StdStringStreamConstructor() {
this.getDeclaringType().hasQualifiedName("std", "basic_stringstream")
}
StdStringStreamConstructor() { this.getDeclaringType() instanceof StdBasicStringStream }
/**
* Gets the index of a parameter to this function that is a string.
@@ -563,7 +592,7 @@ private class StdStringStreamConstructor extends Constructor, TaintFunction {
* The `std::stringstream` function `str`.
*/
private class StdStringStreamStr extends TaintFunction {
StdStringStreamStr() { this.hasQualifiedName("std", "basic_stringstream", "str") }
StdStringStreamStr() { this.getClassAndName("str") instanceof StdBasicStringStream }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// flow from qualifier to return value (if any)
@@ -576,21 +605,33 @@ private class StdStringStreamStr extends TaintFunction {
}
}
/**
* The `std::basic_ios` template class instantiations.
*/
private class StdBasicIOS extends ClassTemplateInstantiation {
StdBasicIOS() { this.hasQualifiedName("std", "basic_ios") }
}
/**
* A `std::` stream function that does not require a model, except that it
* returns a reference to `*this` and thus could be used in a chain.
*/
private class StdStreamFunction extends DataFlowFunction, TaintFunction {
StdStreamFunction() {
this.hasQualifiedName("std", "basic_istream", ["ignore", "unget", "seekg"]) or
this.hasQualifiedName("std", "basic_ostream", ["seekp", "flush"]) or
this.hasQualifiedName("std", "basic_ios", "copyfmt")
this.getClassAndName(["ignore", "unget", "seekg"]) instanceof StdBasicIStream
or
this.getClassAndName(["seekp", "flush"]) instanceof StdBasicOStream
or
this.getClassAndName("copyfmt") instanceof StdBasicIOS
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// returns reference to `*this`
input.isQualifierAddress() and
output.isReturnValue()
or
input.isQualifierObject() and
output.isReturnValueDeref()
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {

View File

@@ -13,16 +13,20 @@ import semmle.code.cpp.models.interfaces.SideEffect
*/
class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, SideEffectFunction {
StrcatFunction() {
getName() =
[
this.hasGlobalOrStdName([
"strcat", // strcat(dst, src)
"strncat", // strncat(dst, src, max_amount)
"wcscat", // wcscat(dst, src)
"wcsncat" // wcsncat(dst, src, max_amount)
])
or
this.hasGlobalName([
"_mbscat", // _mbscat(dst, src)
"wcsncat", // wcsncat(dst, src, max_amount)
"_mbsncat", // _mbsncat(dst, src, max_amount)
"_mbsncat_l" // _mbsncat_l(dst, src, max_amount, locale)
]
"_mbsncat_l", // _mbsncat_l(dst, src, max_amount, locale)
"_mbsnbcat", // _mbsnbcat(dest, src, count)
"_mbsnbcat_l" // _mbsnbcat_l(dest, src, count, locale)
])
}
/**
@@ -50,7 +54,7 @@ class StrcatFunction extends TaintFunction, DataFlowFunction, ArrayFunction, Sid
input.isParameter(2) and
output.isParameterDeref(0)
or
getName() = "_mbsncat_l" and
getName() = ["_mbsncat_l", "_mbsnbcat_l"] and
input.isParameter(3) and
output.isParameterDeref(0)
or

View File

@@ -13,25 +13,36 @@ import semmle.code.cpp.models.interfaces.SideEffect
*/
class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, SideEffectFunction {
StrcpyFunction() {
getName() =
[
this.hasGlobalOrStdName([
"strcpy", // strcpy(dst, src)
"wcscpy", // wcscpy(dst, src)
"_mbscpy", // _mbscpy(dst, src)
"strncpy", // strncpy(dst, src, max_amount)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"wcsncpy", // wcsncpy(dst, src, max_amount)
"strxfrm", // strxfrm(dest, src, max_amount)
"wcsxfrm" // wcsxfrm(dest, src, max_amount)
])
or
this.hasGlobalName([
"_mbscpy", // _mbscpy(dst, src)
"_strncpy_l", // _strncpy_l(dst, src, max_amount, locale)
"_wcsncpy_l", // _wcsncpy_l(dst, src, max_amount, locale)
"_mbsncpy", // _mbsncpy(dst, src, max_amount)
"_mbsncpy_l"
] // _mbsncpy_l(dst, src, max_amount, locale)
"_mbsncpy_l", // _mbsncpy_l(dst, src, max_amount, locale)
"_strxfrm_l", // _strxfrm_l(dest, src, max_amount, locale)
"wcsxfrm_l", // _strxfrm_l(dest, src, max_amount, locale)
"_mbsnbcpy", // _mbsnbcpy(dest, src, max_amount)
"stpcpy", // stpcpy(dest, src)
"stpncpy" // stpcpy(dest, src, max_amount)
])
or
getName() =
[
"strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s", // wcscpy_s(dst, max_amount, src)
"_mbscpy_s"
] and // _mbscpy_s(dst, max_amount, src)
(
this.hasGlobalOrStdName([
"strcpy_s", // strcpy_s(dst, max_amount, src)
"wcscpy_s" // wcscpy_s(dst, max_amount, src)
])
or
this.hasGlobalName("_mbscpy_s") // _mbscpy_s(dst, max_amount, src)
) and
// exclude the 2-parameter template versions
// that find the size of a fixed size destination buffer.
getNumberOfParameters() = 3
@@ -40,9 +51,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
/**
* Holds if this is one of the `strcpy_s` variants.
*/
private predicate isSVariant() {
exists(string name | name = getName() | name.suffix(name.length() - 2) = "_s")
}
private predicate isSVariant() { getName().matches("%\\_s") }
/**
* Gets the index of the parameter that is the maximum size of the copy (in characters).
@@ -50,10 +59,10 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction, Sid
int getParamSize() {
if isSVariant()
then result = 1
else
if exists(getName().indexOf("ncpy"))
then result = 2
else none()
else (
getName().matches(["%ncpy%", "%nbcpy%", "%xfrm%"]) and
result = 2
)
}
/**

View File

@@ -0,0 +1,49 @@
/**
* Provides implementation classes modeling `_strinc`, `_strdec` and their variants.
* See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The function `_strinc`, `_strdec` and their variants.
*/
private class Strcrement extends ArrayFunction, TaintFunction, SideEffectFunction {
Strcrement() {
this.hasGlobalName([
"_strinc", // _strinc(source, locale)
"_wcsinc", // _strinc(source, locale)
"_mbsinc", // _strinc(source)
"_mbsinc_l", // _strinc(source, locale)
"_strdec", // _strdec(start, source)
"_wcsdec", // _wcsdec(start, source)
"_mbsdec", // _mbsdec(start, source)
"_mbsdec_l" // _mbsdec_l(start, source, locale)
])
}
override predicate hasArrayWithNullTerminator(int bufParam) {
// Match all parameters that are not locales.
this.getParameter(bufParam).getUnspecifiedType() instanceof PointerType
}
override predicate hasArrayInput(int bufParam) { hasArrayWithNullTerminator(bufParam) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
exists(int index | hasArrayInput(index) |
input.isParameter(index) and output.isReturnValue()
or
input.isParameterDeref(index) and output.isReturnValueDeref()
)
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
hasArrayInput(i) and buffer = true
}
}

View File

@@ -0,0 +1,38 @@
/**
* Provides implementation classes modeling `strnextc` and various similar functions.
* See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The function `strnextc` and its variants.
*/
private class Strnextc extends TaintFunction, ArrayFunction, AliasFunction, SideEffectFunction {
Strnextc() { this.hasGlobalName(["_strnextc", "_wcsnextc", "_mbsnextc", "_mbsnextc_l"]) }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameterDeref(0) and output.isReturnValue()
}
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
override predicate parameterNeverEscapes(int index) { index = 0 }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = true
}
}

View File

@@ -0,0 +1,62 @@
/**
* Provides implementation classes modeling `strset` and various similar
* functions. See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function `strset` and its assorted variants
*/
private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction,
SideEffectFunction {
StrsetFunction() {
hasGlobalName([
"strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l",
"_mbsnbset", "_mbsnbset_l", "_strnset", "_strnset_l", "_wcsnset", "_wcsnset_l", "_mbsnset",
"_mbsnset_l"
])
}
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// flow from the character that overrides the string
input.isParameter(1) and
(
output.isReturnValueDeref()
or
output.isParameterDeref(0)
)
or
// flow from the input string to the output string
input.isParameter(0) and
output.isReturnValue()
}
override predicate parameterNeverEscapes(int index) { none() }
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and buffer = true and mustWrite = true
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = true
}
}

View File

@@ -0,0 +1,88 @@
/**
* Provides implementation classes modeling `strtok` and various similar
* functions. See `semmle.code.cpp.models.Models` for usage information.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.ArrayFunction
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.SideEffect
import semmle.code.cpp.models.interfaces.Taint
/**
* The standard function `strtok` and its assorted variants
*/
private class Strtok extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
Strtok() {
this.hasGlobalOrStdName("strtok") or
this.hasGlobalName(["strtok_r", "_strtok_l", "wcstok", "_wcstok_l", "_mbstok", "_mbstok_l"])
}
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = [0, 1] }
override predicate hasArrayInput(int bufParam) { bufParam = [0, 1] }
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
override predicate parameterNeverEscapes(int index) { index = 1 }
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReturnValue()
}
override predicate hasOnlySpecificReadSideEffects() { none() }
override predicate hasOnlySpecificWriteSideEffects() { none() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and buffer = true and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = [0, 1] and buffer = true
}
}
/**
* The function `strtok` is a variant of `strtok` that takes a `char**` parameter instead of
* a `char*` as the first parameter.
*/
private class Strsep extends ArrayFunction, AliasFunction, TaintFunction, SideEffectFunction {
Strsep() { this.hasGlobalName("strsep") }
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 1 }
override predicate hasArrayInput(int bufParam) { bufParam = 1 }
override predicate parameterNeverEscapes(int index) { index = [0, 1] }
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
override predicate parameterIsAlwaysReturned(int index) { none() }
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// NOTE: What we really want here is: (input.isParameterDerefDeref(0) or input.isParameterDeref(1))
// as the first conjunct.
input.isParameterDeref([0, 1]) and
(output.isReturnValue() or output.isReturnValueDeref())
}
override predicate hasOnlySpecificReadSideEffects() { any() }
override predicate hasOnlySpecificWriteSideEffects() { any() }
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
i = 0 and buffer = false and mustWrite = false
}
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
i = 0 and buffer = false
or
i = 1 and buffer = true
}
}

View File

@@ -24,5 +24,6 @@ abstract class DataFlowFunction extends Function {
* represented by `input` to the return value or buffer represented by
* `output`
*/
pragma[nomagic]
abstract predicate hasDataFlow(FunctionInput input, FunctionOutput output);
}

View File

@@ -108,6 +108,16 @@ class FunctionInput extends TFunctionInput {
*/
predicate isQualifierAddress() { none() }
/**
* Holds if `i >= 0` and `isParameter(i)` holds for this value, or
* if `i = -1` and `isQualifierAddress()` holds for this value.
*/
final predicate isParameterOrQualifierAddress(ParameterIndex i) {
i >= 0 and this.isParameter(i)
or
i = -1 and this.isQualifierAddress()
}
/**
* Holds if this is the input value pointed to by the return value of a
* function, if the function returns a pointer, or the input value referred
@@ -134,7 +144,7 @@ class FunctionInput extends TFunctionInput {
predicate isReturnValueDeref() { none() }
/**
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this is value, or
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this value, or
* if `i = -1` and `isQualifierObject()` holds for this value.
*/
final predicate isParameterDerefOrQualifierObject(ParameterIndex i) {

View File

@@ -28,5 +28,6 @@ abstract class TaintFunction extends Function {
* Holds if data passed into the argument, qualifier, or buffer represented by
* `input` influences the return value or buffer represented by `output`
*/
pragma[nomagic]
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);
}

View File

@@ -691,8 +691,28 @@ typedefbase(
int type_id: @type ref
);
/**
* An instance of the C++11 `decltype` operator. For example:
* ```
* int a;
* decltype(1+a) b;
* ```
* Here `expr` is `1+a`.
*
* Sometimes an additional pair of parentheses around the expression
* would change the semantics of this decltype, e.g.
* ```
* struct A { double x; };
* const A* a = new A();
* decltype( a->x ); // type is double
* decltype((a->x)); // type is const double&
* ```
* (Please consult the C++11 standard for more details).
* `parentheses_would_change_meaning` is `true` iff that is the case.
*/
#keyset[id, expr]
decltypes(
unique int id: @decltype,
int id: @decltype,
int expr: @expr ref,
int base_type: @type ref,
boolean parentheses_would_change_meaning: boolean ref

View File

@@ -0,0 +1,3 @@
| test.c:13:9:13:13 | buff1 | This variable will not be cleared. |
| test.c:35:9:35:13 | buff1 | This variable will not be cleared. |
| test.c:43:9:43:13 | buff1 | This variable will not be cleared. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-14/CompilerRemovalOfCodeToClearBuffers.ql

View File

@@ -0,0 +1,201 @@
struct buffers
{
unsigned char buff1[50];
unsigned char *buff2;
} globalBuff1,*globalBuff2;
unsigned char * globalBuff;
void badFunc0_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
}
void nobadFunc0_0(){
unsigned char buff1[12];
memset(buff1,12,12);
}
void nobadFunc0_1(){
unsigned char buff1[12];
int i;
memset(buff1,12,12);
for(i=0;i<12;i++)
buff1[i]=13;
free(buff1);
}
void nobadFunc1_0(){
unsigned char * buff1;
buff1 = (unsigned char *) malloc(12);
memset(buff1,12,12);
}
void badFunc1_0(){
unsigned char * buff1;
buff1 = (unsigned char *) malloc(12);
memset(buff1,12,12);
free(buff1);
}
void badFunc1_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
free(buff1);
}
void nobadFunc2_0_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(buff1);
}
void nobadFunc2_0_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(buff1+3);
}
void nobadFunc2_0_2(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(*buff1);
}
void nobadFunc2_0_3(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
printf(*(buff1+3));
}
unsigned char * nobadFunc2_0_4(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return buff1;
}
unsigned char * nobadFunc2_0_5(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return buff1+3;
}
unsigned char nobadFunc2_0_6(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return *buff1;
}
unsigned char nobadFunc2_0_7(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
return *(buff1+3);
}
void nobadFunc2_1_0(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
if(*buff1==0)
printf("123123");
}
void nobadFunc2_1_1(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
if(*(buff1+3)==0)
printf("123123");
}
void nobadFunc2_1_2(){
unsigned char buff1[12];
int i;
for(i=0;i<12;i++)
buff1[i]=13;
memset(buff1,12,12);
buff1[2]=5;
}
void nobadFunc3_0(unsigned char * buffAll){
unsigned char * buff1 = buffAll;
memset(buff1,12,12);
}
void nobadFunc3_1(unsigned char * buffAll){
unsigned char * buff1 = buffAll+3;
memset(buff1,12,12);
}
void nobadFunc3_2(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff1;
memset(buff1,12,12);
}
void nobadFunc3_3(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff2;
memset(buff1,12,12);
}
void nobadFunc3_4(struct buffers buffAll){
unsigned char * buff1 = buffAll.buff2+3;
memset(buff1,12,12);
}
void nobadFunc3_5(struct buffers * buffAll){
unsigned char * buff1 = buffAll->buff1;
memset(buff1,12,12);
}
void nobadFunc3_6(struct buffers *buffAll){
unsigned char * buff1 = buffAll->buff2;
memset(buff1,12,12);
}
void nobadFunc4(){
unsigned char * buff1 = globalBuff;
memset(buff1,12,12);
}
void nobadFunc4_0(){
unsigned char * buff1 = globalBuff;
memset(buff1,12,12);
}
void nobadFunc4_1(){
unsigned char * buff1 = globalBuff+3;
memset(buff1,12,12);
}
void nobadFunc4_2(){
unsigned char * buff1 = globalBuff1.buff1;
memset(buff1,12,12);
}
void nobadFunc4_3(){
unsigned char * buff1 = globalBuff1.buff2;
memset(buff1,12,12);
}
void nobadFunc4_4(){
unsigned char * buff1 = globalBuff1.buff2+3;
memset(buff1,12,12);
}
void nobadFunc4_5(){
unsigned char * buff1 = globalBuff2->buff1;
memset(buff1,12,12);
}
void nobadFunc4_6(){
unsigned char * buff1 = globalBuff2->buff2;
memset(buff1,12,12);
}

View File

@@ -13,9 +13,9 @@ nodes
| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode |
| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode |
#select
| test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
| test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
| test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. |
| test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. |
| test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. |
| test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. |
| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:57:9:57:18 | theZipcode | this source. |
| test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@ | test.cpp:74:24:74:30 | medical | this source. |
| test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@ | test.cpp:77:16:77:22 | medical | this source. |
| test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@ | test.cpp:81:22:81:28 | medical | this source. |
| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:96:37:96:46 | theZipcode | this source. |
| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@ | test.cpp:99:42:99:51 | theZipcode | this source. |

View File

@@ -2,3 +2,7 @@
| test.c:63:29:63:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:139:29:139:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:186:29:186:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:282:29:282:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:299:26:299:32 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:328:29:328:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |
| test.c:342:29:342:35 | call to realloc | possible loss of original pointer on unsuccessful call realloc |

View File

@@ -2,7 +2,7 @@
#define NULL ((void*)0)
#define assert(x) if (!(x)) __assert_fail(#x,__FILE__,__LINE__)
void __assert_fail(const char *assertion, const char *file, int line) { }
void __assert_fail(const char *assertion, const char *file, int line);
void aFakeFailed_1(int file, int line)
{
@@ -272,3 +272,75 @@ unsigned char * noBadResize_2_7(unsigned char * buffer,size_t currentSize,size_t
myASSERT_2(buffer);
return buffer;
}
unsigned char *goodResize_3_1(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: this way we will exclude possible memory leak [FALSE POSITIVE]
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
if (buffer == NULL)
{
free(tmp);
return NULL;
}
}
return buffer;
}
unsigned char *goodResize_3_2(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: this way we will exclude possible memory leak [FALSE POSITIVE]
unsigned char *tmp = buffer;
if (currentSize < newSize)
{
tmp = (unsigned char *)realloc(tmp, newSize);
if (tmp != 0)
{
buffer = tmp;
}
}
return buffer;
}
void abort(void);
unsigned char *noBadResize_4_1(unsigned char *buffer, size_t currentSize, size_t newSize)
{
// GOOD: program to end
if (currentSize < newSize)
{
if (buffer = (unsigned char *)realloc(buffer, newSize))
abort();
}
return buffer;
}
unsigned char * badResize_5_2(unsigned char *buffer, size_t currentSize, size_t newSize, int cond)
{
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
}
if (cond)
{
abort(); // irrelevant
}
return buffer;
}
unsigned char * badResize_5_1(unsigned char *buffer, size_t currentSize, size_t newSize, int cond)
{
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
if (currentSize < newSize)
{
buffer = (unsigned char *)realloc(buffer, newSize);
assert(cond); // irrelevant
}
return buffer;
}

View File

@@ -0,0 +1,5 @@
| test.cpp:30:15:30:26 | call to operator new[] | memory allocation error check is incorrect or missing |
| test.cpp:38:9:38:20 | call to operator new[] | memory allocation error check is incorrect or missing |
| test.cpp:50:13:50:38 | call to operator new[] | memory allocation error check is incorrect or missing |
| test.cpp:51:22:51:47 | call to operator new[] | memory allocation error check is incorrect or missing |
| test.cpp:53:18:53:43 | call to operator new[] | memory allocation error check is incorrect or missing |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql

View File

@@ -0,0 +1,97 @@
#define NULL ((void*)0)
class exception {};
namespace std{
struct nothrow_t {};
typedef unsigned long size_t;
class bad_alloc{
const char* what() const throw();
};
extern const std::nothrow_t nothrow;
}
using namespace std;
void* operator new(std::size_t _Size);
void* operator new[](std::size_t _Size);
void* operator new( std::size_t count, const std::nothrow_t& tag );
void* operator new[]( std::size_t count, const std::nothrow_t& tag );
void badNew_0_0()
{
while (true) {
new int[100]; // BAD [NOT DETECTED]
if(!(new int[100])) // BAD [NOT DETECTED]
return;
}
}
void badNew_0_1()
{
int * i = new int[100]; // BAD
if(i == 0)
return;
if(!i)
return;
if(i == NULL)
return;
int * j;
j = new int[100]; // BAD
if(j == 0)
return;
if(!j)
return;
if(j == NULL)
return;
}
void badNew_1_0()
{
try {
while (true) {
new(std::nothrow) int[100]; // BAD
int* p = new(std::nothrow) int[100]; // BAD
int* p1;
p1 = new(std::nothrow) int[100]; // BAD
}
} catch (const exception &){//const std::bad_alloc& e) {
// std::cout << e.what() << '\n';
}
}
void badNew_1_1()
{
while (true) {
int* p = new(std::nothrow) int[100]; // BAD [NOT DETECTED]
new(std::nothrow) int[100]; // BAD [NOT DETECTED]
}
}
void goodNew_0_0()
{
try {
while (true) {
new int[100]; // GOOD
}
} catch (const exception &){//const std::bad_alloc& e) {
// std::cout << e.what() << '\n';
}
}
void goodNew_1_0()
{
while (true) {
int* p = new(std::nothrow) int[100]; // GOOD
if (p == nullptr) {
// std::cout << "Allocation returned nullptr\n";
break;
}
int* p1;
p1 = new(std::nothrow) int[100]; // GOOD
if (p1 == nullptr) {
// std::cout << "Allocation returned nullptr\n";
break;
}
if (new(std::nothrow) int[100] == nullptr) { // GOOD
// std::cout << "Allocation returned nullptr\n";
break;
}
}
}

View File

@@ -0,0 +1,9 @@
| test.c:42:3:42:24 | ... = ... | potential unsafe or redundant assignment. |
| test.c:43:3:43:40 | ... = ... | potential unsafe or redundant assignment. |
| test.c:44:3:44:40 | ... = ... | potential unsafe or redundant assignment. |
| test.c:45:3:45:44 | ... = ... | potential unsafe or redundant assignment. |
| test.c:46:3:46:44 | ... = ... | potential unsafe or redundant assignment. |
| test.c:47:3:47:48 | ... = ... | potential unsafe or redundant assignment. |
| test.c:48:3:48:48 | ... = ... | potential unsafe or redundant assignment. |
| test.c:49:3:49:50 | ... = ... | potential unsafe or redundant assignment. |
| test.c:50:3:50:50 | ... = ... | potential unsafe or redundant assignment. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql

View File

@@ -0,0 +1,3 @@
| test.c:4:3:4:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
| test.c:11:3:11:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |
| test.c:19:3:19:9 | call to strncat | if the used buffer is full, writing out of the buffer is possible |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrncat.ql

View File

@@ -0,0 +1,73 @@
void workFunction_0(char *s) {
char buf[80];
strncat(buf, s, sizeof(buf)-strlen(buf)-1); // GOOD
strncat(buf, s, sizeof(buf)-strlen(buf)); // BAD
strncat(buf, "fix", sizeof(buf)-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_1(char *s) {
#define MAX_SIZE 80
char buf[MAX_SIZE];
strncat(buf, s, MAX_SIZE-strlen(buf)-1); // GOOD
strncat(buf, s, MAX_SIZE-strlen(buf)); // BAD
strncat(buf, "fix", MAX_SIZE-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_2_0(char *s) {
char * buf;
int len=80;
buf = (char *) malloc(len);
strncat(buf, s, len-strlen(buf)-1); // GOOD
strncat(buf, s, len-strlen(buf)); // BAD
strncat(buf, "fix", len-strlen(buf)); // BAD [NOT DETECTED]
}
void workFunction_2_1(char *s) {
char * buf;
int len=80;
buf = (char *) malloc(len+1);
strncat(buf, s, len-strlen(buf)-1); // GOOD
strncat(buf, s, len-strlen(buf)); // GOOD
}
struct buffers
{
unsigned char buff1[50];
unsigned char *buff2;
} globalBuff1,*globalBuff2,globalBuff1_c,*globalBuff2_c;
void badFunc0(){
unsigned char buff1[12];
struct buffers buffAll;
struct buffers * buffAll1;
buff1[strlen(buff1)]=0; // BAD
buffAll.buff1[strlen(buffAll.buff1)]=0; // BAD
buffAll.buff2[strlen(buffAll.buff2)]=0; // BAD
buffAll1->buff1[strlen(buffAll1->buff1)]=0; // BAD
buffAll1->buff2[strlen(buffAll1->buff2)]=0; // BAD
globalBuff1.buff1[strlen(globalBuff1.buff1)]=0; // BAD
globalBuff1.buff2[strlen(globalBuff1.buff2)]=0; // BAD
globalBuff2->buff1[strlen(globalBuff2->buff1)]=0; // BAD
globalBuff2->buff2[strlen(globalBuff2->buff2)]=0; // BAD
}
void noBadFunc0(){
unsigned char buff1[12],buff1_c[12];
struct buffers buffAll,buffAll_c;
struct buffers * buffAll1,*buffAll1_c;
buff1[strlen(buff1_c)]=0; // GOOD
buffAll.buff1[strlen(buffAll_c.buff1)]=0; // GOOD
buffAll.buff2[strlen(buffAll.buff1)]=0; // GOOD
buffAll1->buff1[strlen(buffAll1_c->buff1)]=0; // GOOD
buffAll1->buff2[strlen(buffAll1->buff1)]=0; // GOOD
globalBuff1.buff1[strlen(globalBuff1_c.buff1)]=0; // GOOD
globalBuff1.buff2[strlen(globalBuff1.buff1)]=0; // GOOD
globalBuff2->buff1[strlen(globalBuff2_c->buff1)]=0; // GOOD
globalBuff2->buff2[strlen(globalBuff2->buff1)]=0; // GOOD
}
void goodFunc0(){
unsigned char buffer[12];
int i;
for(i = 0; i < 6; i++)
buffer[i] = 'A';
buffer[i]=0;
}

View File

@@ -123,7 +123,7 @@ void test1()
{
int i = 0;
sink(sscanf(string::source(), "%i", &i));
sink(i); // $ MISSING: ast,ir
sink(i); // $ ast,ir
}
{
char buffer[256] = {0};
@@ -133,7 +133,7 @@ void test1()
{
char buffer[256] = {0};
sink(sscanf(string::source(), "%s", &buffer));
sink(buffer); // $ MISSING: ast,ir
sink(buffer); // $ ast,ir
}
}

View File

@@ -378,23 +378,27 @@
| format.cpp:114:37:114:50 | call to source | format.cpp:114:18:114:23 | ref arg buffer | TAINT |
| format.cpp:119:10:119:11 | 0 | format.cpp:120:29:120:29 | i | |
| format.cpp:119:10:119:11 | 0 | format.cpp:121:8:121:8 | i | |
| format.cpp:120:15:120:19 | 123 | format.cpp:120:28:120:29 | ref arg & ... | TAINT |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:120:29:120:29 | i [inner post update] | |
| format.cpp:120:28:120:29 | ref arg & ... | format.cpp:121:8:121:8 | i | |
| format.cpp:120:29:120:29 | i | format.cpp:120:28:120:29 | & ... | |
| format.cpp:124:10:124:11 | 0 | format.cpp:125:40:125:40 | i | |
| format.cpp:124:10:124:11 | 0 | format.cpp:126:8:126:8 | i | |
| format.cpp:125:15:125:28 | call to source | format.cpp:125:39:125:40 | ref arg & ... | TAINT |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:125:40:125:40 | i [inner post update] | |
| format.cpp:125:39:125:40 | ref arg & ... | format.cpp:126:8:126:8 | i | |
| format.cpp:125:40:125:40 | i | format.cpp:125:39:125:40 | & ... | |
| format.cpp:129:21:129:24 | {...} | format.cpp:130:32:130:37 | buffer | |
| format.cpp:129:21:129:24 | {...} | format.cpp:131:8:131:13 | buffer | |
| format.cpp:129:23:129:23 | 0 | format.cpp:129:21:129:24 | {...} | TAINT |
| format.cpp:130:15:130:22 | Hello. | format.cpp:130:31:130:37 | ref arg & ... | TAINT |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:130:32:130:37 | buffer [inner post update] | |
| format.cpp:130:31:130:37 | ref arg & ... | format.cpp:131:8:131:13 | buffer | |
| format.cpp:130:32:130:37 | buffer | format.cpp:130:31:130:37 | & ... | |
| format.cpp:134:21:134:24 | {...} | format.cpp:135:40:135:45 | buffer | |
| format.cpp:134:21:134:24 | {...} | format.cpp:136:8:136:13 | buffer | |
| format.cpp:134:23:134:23 | 0 | format.cpp:134:21:134:24 | {...} | TAINT |
| format.cpp:135:15:135:28 | call to source | format.cpp:135:39:135:45 | ref arg & ... | TAINT |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:135:40:135:45 | buffer [inner post update] | |
| format.cpp:135:39:135:45 | ref arg & ... | format.cpp:136:8:136:13 | buffer | |
| format.cpp:135:40:135:45 | buffer | format.cpp:135:39:135:45 | & ... | |
@@ -5861,6 +5865,183 @@
| taint.cpp:483:18:483:19 | ref arg & ... | taint.cpp:483:19:483:19 | n [inner post update] | |
| taint.cpp:483:19:483:19 | n | taint.cpp:483:18:483:19 | & ... | |
| taint.cpp:483:28:483:34 | source1 | taint.cpp:483:11:483:15 | ref arg & ... | TAINT |
| taint.cpp:492:24:492:29 | source | taint.cpp:494:27:494:32 | source | |
| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:494:35:494:39 | delim | |
| taint.cpp:493:22:493:29 | ,.-;:_ | taint.cpp:496:7:496:11 | delim | |
| taint.cpp:494:20:494:25 | call to strtok | taint.cpp:495:7:495:15 | tokenized | |
| taint.cpp:494:27:494:32 | source | taint.cpp:494:20:494:25 | call to strtok | TAINT |
| taint.cpp:503:26:503:28 | ptr | taint.cpp:504:10:504:12 | ptr | |
| taint.cpp:503:26:503:28 | ptr | taint.cpp:505:7:505:9 | ptr | |
| taint.cpp:503:26:503:28 | ptr | taint.cpp:506:8:506:10 | ptr | |
| taint.cpp:503:36:503:41 | source | taint.cpp:504:15:504:20 | source | |
| taint.cpp:504:10:504:12 | ptr | taint.cpp:504:2:504:8 | call to _strset | |
| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:505:7:505:9 | ptr | |
| taint.cpp:504:10:504:12 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | |
| taint.cpp:504:15:504:20 | source | taint.cpp:504:2:504:8 | call to _strset | TAINT |
| taint.cpp:504:15:504:20 | source | taint.cpp:504:10:504:12 | ref arg ptr | |
| taint.cpp:505:7:505:9 | ref arg ptr | taint.cpp:506:8:506:10 | ptr | |
| taint.cpp:506:8:506:10 | ptr | taint.cpp:506:7:506:10 | * ... | TAINT |
| taint.cpp:509:26:509:31 | source | taint.cpp:510:10:510:15 | source | |
| taint.cpp:509:26:509:31 | source | taint.cpp:511:7:511:12 | source | |
| taint.cpp:510:10:510:15 | ref arg source | taint.cpp:511:7:511:12 | source | |
| taint.cpp:510:10:510:15 | source | taint.cpp:510:2:510:8 | call to _strset | |
| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:2:510:8 | call to _strset | TAINT |
| taint.cpp:510:18:510:18 | 0 | taint.cpp:510:10:510:15 | ref arg source | |
| taint.cpp:518:24:518:29 | source | taint.cpp:520:14:520:19 | source | |
| taint.cpp:519:6:519:6 | x | taint.cpp:520:11:520:11 | x | |
| taint.cpp:519:6:519:6 | x | taint.cpp:521:7:521:7 | x | |
| taint.cpp:520:10:520:11 | & ... | taint.cpp:520:2:520:8 | call to mempcpy | |
| taint.cpp:520:10:520:11 | ref arg & ... | taint.cpp:520:11:520:11 | x [inner post update] | |
| taint.cpp:520:10:520:11 | ref arg & ... | taint.cpp:521:7:521:7 | x | |
| taint.cpp:520:11:520:11 | x | taint.cpp:520:10:520:11 | & ... | |
| taint.cpp:520:14:520:19 | source | taint.cpp:520:2:520:8 | call to mempcpy | TAINT |
| taint.cpp:520:14:520:19 | source | taint.cpp:520:10:520:11 | ref arg & ... | TAINT |
| taint.cpp:528:24:528:29 | source | taint.cpp:530:16:530:21 | source | |
| taint.cpp:529:6:529:9 | dest | taint.cpp:530:10:530:13 | dest | |
| taint.cpp:529:6:529:9 | dest | taint.cpp:530:35:530:38 | dest | |
| taint.cpp:529:6:529:9 | dest | taint.cpp:531:7:531:10 | dest | |
| taint.cpp:530:10:530:13 | dest | taint.cpp:530:2:530:8 | call to memccpy | |
| taint.cpp:530:10:530:13 | ref arg dest | taint.cpp:531:7:531:10 | dest | |
| taint.cpp:530:16:530:21 | source | taint.cpp:530:2:530:8 | call to memccpy | TAINT |
| taint.cpp:530:16:530:21 | source | taint.cpp:530:10:530:13 | ref arg dest | TAINT |
| taint.cpp:538:24:538:28 | dest1 | taint.cpp:539:9:539:13 | dest1 | |
| taint.cpp:538:24:538:28 | dest1 | taint.cpp:540:7:540:11 | dest1 | |
| taint.cpp:538:37:538:41 | dest2 | taint.cpp:542:9:542:13 | dest2 | |
| taint.cpp:538:37:538:41 | dest2 | taint.cpp:543:7:543:11 | dest2 | |
| taint.cpp:538:50:538:54 | clean | taint.cpp:542:16:542:20 | clean | |
| taint.cpp:538:63:538:68 | source | taint.cpp:539:16:539:21 | source | |
| taint.cpp:539:9:539:13 | dest1 | taint.cpp:539:2:539:7 | call to strcat | |
| taint.cpp:539:9:539:13 | dest1 | taint.cpp:539:9:539:13 | ref arg dest1 | TAINT |
| taint.cpp:539:9:539:13 | ref arg dest1 | taint.cpp:540:7:540:11 | dest1 | |
| taint.cpp:539:16:539:21 | source | taint.cpp:539:9:539:13 | ref arg dest1 | TAINT |
| taint.cpp:542:9:542:13 | dest2 | taint.cpp:542:2:542:7 | call to strcat | |
| taint.cpp:542:9:542:13 | dest2 | taint.cpp:542:9:542:13 | ref arg dest2 | TAINT |
| taint.cpp:542:9:542:13 | ref arg dest2 | taint.cpp:543:7:543:11 | dest2 | |
| taint.cpp:542:16:542:20 | clean | taint.cpp:542:9:542:13 | ref arg dest2 | TAINT |
| taint.cpp:550:37:550:41 | dest1 | taint.cpp:552:36:552:40 | dest1 | |
| taint.cpp:550:37:550:41 | dest1 | taint.cpp:553:7:553:11 | dest1 | |
| taint.cpp:550:37:550:41 | dest1 | taint.cpp:554:8:554:12 | dest1 | |
| taint.cpp:550:65:550:67 | ptr | taint.cpp:552:43:552:45 | ptr | |
| taint.cpp:550:65:550:67 | ptr | taint.cpp:558:43:558:45 | ptr | |
| taint.cpp:550:85:550:89 | dest3 | taint.cpp:558:36:558:40 | dest3 | |
| taint.cpp:550:85:550:89 | dest3 | taint.cpp:559:7:559:11 | dest3 | |
| taint.cpp:550:85:550:89 | dest3 | taint.cpp:560:8:560:12 | dest3 | |
| taint.cpp:551:32:551:36 | clean | taint.cpp:558:51:558:55 | clean | |
| taint.cpp:551:49:551:54 | source | taint.cpp:552:51:552:56 | source | |
| taint.cpp:551:61:551:61 | n | taint.cpp:552:48:552:48 | n | |
| taint.cpp:551:61:551:61 | n | taint.cpp:558:48:558:48 | n | |
| taint.cpp:552:25:552:34 | call to _mbsncat_l | taint.cpp:555:7:555:11 | dest2 | |
| taint.cpp:552:25:552:34 | call to _mbsncat_l | taint.cpp:556:8:556:12 | dest2 | |
| taint.cpp:552:36:552:40 | dest1 | taint.cpp:552:25:552:34 | call to _mbsncat_l | |
| taint.cpp:552:36:552:40 | dest1 | taint.cpp:552:36:552:40 | ref arg dest1 | TAINT |
| taint.cpp:552:36:552:40 | ref arg dest1 | taint.cpp:553:7:553:11 | dest1 | |
| taint.cpp:552:36:552:40 | ref arg dest1 | taint.cpp:554:8:554:12 | dest1 | |
| taint.cpp:552:43:552:45 | ptr | taint.cpp:552:36:552:40 | ref arg dest1 | TAINT |
| taint.cpp:552:48:552:48 | n | taint.cpp:552:36:552:40 | ref arg dest1 | TAINT |
| taint.cpp:552:51:552:56 | source | taint.cpp:552:36:552:40 | ref arg dest1 | TAINT |
| taint.cpp:553:7:553:11 | ref arg dest1 | taint.cpp:554:8:554:12 | dest1 | |
| taint.cpp:554:8:554:12 | dest1 | taint.cpp:554:7:554:12 | * ... | TAINT |
| taint.cpp:555:7:555:11 | ref arg dest2 | taint.cpp:556:8:556:12 | dest2 | |
| taint.cpp:556:8:556:12 | dest2 | taint.cpp:556:7:556:12 | * ... | TAINT |
| taint.cpp:558:25:558:34 | call to _mbsncat_l | taint.cpp:561:7:561:11 | dest4 | |
| taint.cpp:558:25:558:34 | call to _mbsncat_l | taint.cpp:562:8:562:12 | dest4 | |
| taint.cpp:558:36:558:40 | dest3 | taint.cpp:558:25:558:34 | call to _mbsncat_l | |
| taint.cpp:558:36:558:40 | dest3 | taint.cpp:558:36:558:40 | ref arg dest3 | TAINT |
| taint.cpp:558:36:558:40 | ref arg dest3 | taint.cpp:559:7:559:11 | dest3 | |
| taint.cpp:558:36:558:40 | ref arg dest3 | taint.cpp:560:8:560:12 | dest3 | |
| taint.cpp:558:43:558:45 | ptr | taint.cpp:558:36:558:40 | ref arg dest3 | TAINT |
| taint.cpp:558:48:558:48 | n | taint.cpp:558:36:558:40 | ref arg dest3 | TAINT |
| taint.cpp:558:51:558:55 | clean | taint.cpp:558:36:558:40 | ref arg dest3 | TAINT |
| taint.cpp:559:7:559:11 | ref arg dest3 | taint.cpp:560:8:560:12 | dest3 | |
| taint.cpp:560:8:560:12 | dest3 | taint.cpp:560:7:560:12 | * ... | TAINT |
| taint.cpp:561:7:561:11 | ref arg dest4 | taint.cpp:562:8:562:12 | dest4 | |
| taint.cpp:562:8:562:12 | dest4 | taint.cpp:562:7:562:12 | * ... | TAINT |
| taint.cpp:569:24:569:29 | source | taint.cpp:572:29:572:34 | source | |
| taint.cpp:570:23:570:30 | ,.-;:_ | taint.cpp:572:37:572:41 | delim | |
| taint.cpp:572:9:572:17 | tokenized | taint.cpp:572:9:572:42 | ... = ... | |
| taint.cpp:572:21:572:26 | call to strsep | taint.cpp:572:9:572:42 | ... = ... | |
| taint.cpp:572:21:572:26 | call to strsep | taint.cpp:573:10:573:18 | tokenized | |
| taint.cpp:572:21:572:26 | call to strsep | taint.cpp:574:11:574:19 | tokenized | |
| taint.cpp:572:28:572:34 | & ... | taint.cpp:572:21:572:26 | call to strsep | TAINT |
| taint.cpp:572:28:572:34 | ref arg & ... | taint.cpp:572:29:572:34 | source | |
| taint.cpp:572:28:572:34 | ref arg & ... | taint.cpp:572:29:572:34 | source [inner post update] | |
| taint.cpp:572:29:572:34 | source | taint.cpp:572:21:572:26 | call to strsep | TAINT |
| taint.cpp:572:29:572:34 | source | taint.cpp:572:28:572:34 | & ... | |
| taint.cpp:572:37:572:41 | delim | taint.cpp:572:21:572:26 | call to strsep | TAINT |
| taint.cpp:573:10:573:18 | ref arg tokenized | taint.cpp:574:11:574:19 | tokenized | |
| taint.cpp:574:11:574:19 | tokenized | taint.cpp:574:10:574:19 | * ... | TAINT |
| taint.cpp:584:25:584:30 | source | taint.cpp:585:18:585:23 | source | |
| taint.cpp:584:39:584:43 | clean | taint.cpp:589:18:589:22 | clean | |
| taint.cpp:584:82:584:87 | locale | taint.cpp:585:26:585:31 | locale | |
| taint.cpp:584:82:584:87 | locale | taint.cpp:589:25:589:30 | locale | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:585:2:585:32 | ... = ... | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:586:7:586:11 | dest1 | |
| taint.cpp:585:10:585:16 | call to _strinc | taint.cpp:587:8:587:12 | dest1 | |
| taint.cpp:585:18:585:23 | source | taint.cpp:585:10:585:16 | call to _strinc | TAINT |
| taint.cpp:585:26:585:31 | locale | taint.cpp:585:10:585:16 | call to _strinc | TAINT |
| taint.cpp:585:26:585:31 | ref arg locale | taint.cpp:589:25:589:30 | locale | |
| taint.cpp:586:7:586:11 | ref arg dest1 | taint.cpp:587:8:587:12 | dest1 | |
| taint.cpp:587:8:587:12 | dest1 | taint.cpp:587:7:587:12 | * ... | TAINT |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:589:2:589:31 | ... = ... | |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:590:7:590:11 | dest2 | |
| taint.cpp:589:10:589:16 | call to _strinc | taint.cpp:591:8:591:12 | dest2 | |
| taint.cpp:589:18:589:22 | clean | taint.cpp:589:10:589:16 | call to _strinc | TAINT |
| taint.cpp:589:25:589:30 | locale | taint.cpp:589:10:589:16 | call to _strinc | TAINT |
| taint.cpp:590:7:590:11 | ref arg dest2 | taint.cpp:591:8:591:12 | dest2 | |
| taint.cpp:591:8:591:12 | dest2 | taint.cpp:591:7:591:12 | * ... | TAINT |
| taint.cpp:594:34:594:48 | source_unsigned | taint.cpp:595:26:595:40 | source_unsigned | |
| taint.cpp:594:57:594:62 | source | taint.cpp:599:40:599:45 | source | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:595:2:595:41 | ... = ... | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:596:7:596:19 | dest_unsigned | |
| taint.cpp:595:18:595:24 | call to _mbsinc | taint.cpp:597:8:597:20 | dest_unsigned | |
| taint.cpp:595:26:595:40 | source_unsigned | taint.cpp:595:18:595:24 | call to _mbsinc | TAINT |
| taint.cpp:596:7:596:19 | ref arg dest_unsigned | taint.cpp:597:8:597:20 | dest_unsigned | |
| taint.cpp:597:8:597:20 | dest_unsigned | taint.cpp:597:7:597:20 | * ... | TAINT |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:599:2:599:46 | ... = ... | |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:600:7:600:10 | dest | |
| taint.cpp:599:16:599:22 | call to _mbsinc | taint.cpp:601:8:601:11 | dest | |
| taint.cpp:599:40:599:45 | source | taint.cpp:599:16:599:22 | call to _mbsinc | TAINT |
| taint.cpp:600:7:600:10 | ref arg dest | taint.cpp:601:8:601:11 | dest | |
| taint.cpp:601:8:601:11 | dest | taint.cpp:601:7:601:11 | * ... | TAINT |
| taint.cpp:604:40:604:45 | source | taint.cpp:605:18:605:23 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:605:31:605:36 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:611:25:611:30 | source | |
| taint.cpp:604:40:604:45 | source | taint.cpp:616:18:616:23 | source | |
| taint.cpp:604:63:604:67 | clean | taint.cpp:611:18:611:22 | clean | |
| taint.cpp:604:63:604:67 | clean | taint.cpp:616:26:616:30 | clean | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:605:2:605:37 | ... = ... | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:606:7:606:11 | dest1 | |
| taint.cpp:605:10:605:16 | call to _strdec | taint.cpp:607:8:607:12 | dest1 | |
| taint.cpp:605:18:605:23 | source | taint.cpp:605:18:605:28 | ... + ... | TAINT |
| taint.cpp:605:18:605:28 | ... + ... | taint.cpp:605:10:605:16 | call to _strdec | TAINT |
| taint.cpp:605:27:605:28 | 12 | taint.cpp:605:18:605:28 | ... + ... | TAINT |
| taint.cpp:605:31:605:36 | source | taint.cpp:605:10:605:16 | call to _strdec | TAINT |
| taint.cpp:606:7:606:11 | ref arg dest1 | taint.cpp:607:8:607:12 | dest1 | |
| taint.cpp:607:8:607:12 | dest1 | taint.cpp:607:7:607:12 | * ... | TAINT |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:611:2:611:31 | ... = ... | |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:612:7:612:11 | dest2 | |
| taint.cpp:611:10:611:16 | call to _strdec | taint.cpp:613:8:613:12 | dest2 | |
| taint.cpp:611:18:611:22 | clean | taint.cpp:611:10:611:16 | call to _strdec | TAINT |
| taint.cpp:611:25:611:30 | source | taint.cpp:611:10:611:16 | call to _strdec | TAINT |
| taint.cpp:612:7:612:11 | ref arg dest2 | taint.cpp:613:8:613:12 | dest2 | |
| taint.cpp:613:8:613:12 | dest2 | taint.cpp:613:7:613:12 | * ... | TAINT |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:616:2:616:31 | ... = ... | |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:617:7:617:11 | dest3 | |
| taint.cpp:616:10:616:16 | call to _strdec | taint.cpp:618:8:618:12 | dest3 | |
| taint.cpp:616:18:616:23 | source | taint.cpp:616:10:616:16 | call to _strdec | TAINT |
| taint.cpp:616:26:616:30 | clean | taint.cpp:616:10:616:16 | call to _strdec | TAINT |
| taint.cpp:617:7:617:11 | ref arg dest3 | taint.cpp:618:8:618:12 | dest3 | |
| taint.cpp:618:8:618:12 | dest3 | taint.cpp:618:7:618:12 | * ... | TAINT |
| taint.cpp:625:33:625:38 | source | taint.cpp:628:17:628:22 | source | |
| taint.cpp:628:7:628:15 | call to _strnextc | taint.cpp:628:3:628:25 | ... = ... | |
| taint.cpp:628:7:628:15 | call to _strnextc | taint.cpp:629:8:629:8 | c | |
| taint.cpp:628:7:628:15 | call to _strnextc | taint.cpp:630:10:630:10 | c | |
| taint.cpp:628:17:628:22 | source | taint.cpp:628:17:628:24 | ... ++ | |
| taint.cpp:628:17:628:24 | ... ++ | taint.cpp:628:7:628:15 | call to _strnextc | TAINT |
| taint.cpp:628:17:628:24 | ... ++ | taint.cpp:628:17:628:22 | source | TAINT |
| taint.cpp:631:6:631:14 | call to _strnextc | taint.cpp:631:2:631:18 | ... = ... | |
| taint.cpp:631:6:631:14 | call to _strnextc | taint.cpp:632:7:632:7 | c | |
| taint.cpp:631:16:631:17 | | taint.cpp:631:6:631:14 | call to _strnextc | TAINT |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

View File

@@ -38,13 +38,13 @@ public:
void test_typedefs(int_iterator_by_typedefs source1) {
sink(*source1); // $ ast,ir
sink(*(source1++)); // $ ast MISSING: ir
sink(*(source1++)); // $ ast,ir
sink(*(++source1)); // $ ast MISSING: ir
}
void test_trait(int_iterator_by_trait source1) {
sink(*source1); // $ ast,ir
sink(*(source1++)); // $ ast MISSING: ir
sink(*(source1++)); // $ ast,ir
sink(*(++source1)); // $ ast MISSING: ir
}

View File

@@ -415,10 +415,10 @@ void test_string_iterators() {
sink(*i9); // $ ast,ir
i10 = i2;
sink(*(i10++)); // $ ast MISSING: ir
sink(*(i10++)); // $ ast,ir
sink(i10); // $ ast,ir
i11 = i2;
sink(*(i11--)); // $ ast MISSING: ir
sink(*(i11--)); // $ ast,ir
sink(i11); // $ ast,ir
}
}

View File

@@ -75,7 +75,7 @@ void test_stringstream_int(int source)
sink(ss1 << 1234);
sink(ss2 << source); // $ ast MISSING: ir
sink(ss1 >> v1);
sink(ss2 >> v2); // $ ast MISSING: ir
sink(ss2 >> v2); // $ ast,ir
sink(ss1);
sink(ss2); // $ ast,ir
@@ -143,27 +143,27 @@ void test_stringstream_in()
sink(ss2 << source()); // $ ast,ir
sink(ss1 >> s1);
sink(ss2 >> s2); // $ ast MISSING: ir
sink(ss2 >> s3 >> s4); // $ ast MISSING: ir
sink(ss2 >> s2); // $ ast,ir
sink(ss2 >> s3 >> s4); // $ ast,ir
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ ast,ir
sink(s4); // $ ast MISSING: ir
sink(s4); // $ ast,ir
sink(ss1 >> b1);
sink(ss2 >> b2); // $ ast MISSING: ir
sink(ss2 >> b3 >> b4); // $ ast MISSING: ir
sink(ss2 >> b2); // $ ast,ir
sink(ss2 >> b3 >> b4); // $ ast,ir
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ ast,ir
sink(b4); // $ ast MISSING: ir
sink(b4); // $ ast,ir
sink(ss1.read(b5, 100));
sink(ss2.read(b6, 100)); // $ ast MISSING: ir
sink(ss2.read(b6, 100)); // $ ast,ir
sink(ss1.readsome(b7, 100));
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
sink(ss1.get(b9, 100));
sink(ss2.get(b10, 100)); // $ ast MISSING: ir
sink(ss2.get(b10, 100)); // $ ast,ir
sink(b5);
sink(b6); // $ ast,ir
sink(b7);
@@ -176,7 +176,7 @@ void test_stringstream_in()
sink(c3 = ss1.peek());
sink(c4 = ss2.peek()); // $ ast,ir
sink(ss1.get(c5));
sink(ss2.get(c6)); // $ ast MISSING: ir
sink(ss2.get(c6)); // $ ast,ir
sink(c1);
sink(c2); // $ ast,ir
sink(c3);
@@ -212,44 +212,44 @@ void test_getline()
std::string s1, s2, s3, s4, s5, s6, s7, s8;
sink(ss1.getline(b1, 1000));
sink(ss2.getline(b2, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b3, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b2, 1000)); // $ ast,ir
sink(ss2.getline(b3, 1000)); // $ ast,ir
sink(ss1.getline(b3, 1000));
sink(b1);
sink(b2); // $ ast,ir
sink(b3); // $ SPURIOUS: ast,ir
sink(ss1.getline(b4, 1000, ' '));
sink(ss2.getline(b5, 1000, ' ')); // $ ast MISSING: ir
sink(ss2.getline(b6, 1000, ' ')); // $ ast MISSING: ir
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
sink(ss2.getline(b6, 1000, ' ')); // $ ast,ir
sink(ss1.getline(b6, 1000, ' '));
sink(b4);
sink(b5); // $ ast,ir
sink(b6); // $ SPURIOUS: ast,ir
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast MISSING: ir
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
sink(b7); // $ ast,ir
sink(b8); // $ ast MISSING: ir
sink(getline(ss1, s1));
sink(getline(ss2, s2)); // $ ast MISSING: ir
sink(getline(ss2, s3)); // $ ast MISSING: ir
sink(getline(ss2, s2)); // $ ast,ir
sink(getline(ss2, s3)); // $ ast,ir
sink(getline(ss1, s3));
sink(s1);
sink(s2); // $ ast,ir
sink(s3); // $ SPURIOUS: ast,ir
sink(getline(ss1, s4, ' '));
sink(getline(ss2, s5, ' ')); // $ ast MISSING: ir
sink(getline(ss2, s6, ' ')); // $ ast MISSING: ir
sink(getline(ss2, s5, ' ')); // $ ast,ir
sink(getline(ss2, s6, ' ')); // $ ast,ir
sink(getline(ss1, s6, ' '));
sink(s4);
sink(s5); // $ ast,ir
sink(s6); // $ SPURIOUS: ast,ir
sink(getline(getline(ss2, s7), s8)); // $ ast MISSING: ir
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
sink(s7); // $ ast,ir
sink(s8); // $ ast MISSING: ir
sink(s8); // $ ast,ir
}
void test_chaining()
@@ -259,7 +259,7 @@ void test_chaining()
char b1[1000] = {0};
char b2[1000] = {0};
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast MISSING: ir
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast,ir
sink(b1); // $ ast,ir
sink(b2); // $ ast MISSING: ir

View File

@@ -484,3 +484,150 @@ void test_getdelim(FILE* source1) {
sink(line); // $ ir,ast
}
// --- strtok ---
char *strtok(char *str, const char *delim);
void test_strtok(char *source) {
const char* delim = ",.-;:_";
char* tokenized = strtok(source, delim);
sink(tokenized); // $ ast,ir
sink(delim);
}
// --- strset ---
char *_strset(char *str, int c);
void test_strset_1(char* ptr, char source) {
_strset(ptr, source);
sink(ptr); // $ SPURIOUS: ast,ir
sink(*ptr); // $ ast,ir
}
void test_strset_2(char* source) {
_strset(source, 0);
sink(source); // $ ast,ir
}
// --- mempcpy ---
void *mempcpy(void *dest, const void *src, size_t n);
void test_mempcpy(int *source) {
int x;
mempcpy(&x, source, sizeof(int));
sink(x); // $ ast=518:24 MISSING: ir SPURIOUS: ast=519:6
}
// --- memccpy ---
void *memccpy(void *dest, const void *src, int c, size_t n);
void test_memccpy(int *source) {
int dest[16];
memccpy(dest, source, 42, sizeof(dest));
sink(dest); // $ ast=528:24 MISSING: ir SPURIOUS: ast=529:6
}
// --- strcat and related functions ---
char* strcat (char*, const char*);
void test_strcat(char* dest1, char* dest2, char* clean, char* source) {
strcat(dest1, source);
sink(dest1); // $ ast,ir
strcat(dest2, clean);
sink(dest2);
}
typedef void* _locale_t;
unsigned char *_mbsncat_l(unsigned char *, const unsigned char *, int, _locale_t);
void test__mbsncat_l(unsigned char* dest1, unsigned const char* ptr, unsigned char* dest3,
_locale_t clean, _locale_t source, int n) {
unsigned char* dest2 = _mbsncat_l(dest1, ptr, n, source);
sink(dest1); // $ SPURIOUS: ast,ir
sink(*dest1); // $ ast,ir
sink(dest2); // $ SPURIOUS: ir
sink(*dest2); // $ ir
unsigned char* dest4 = _mbsncat_l(dest3, ptr, n, clean);
sink(dest3);
sink(*dest3);
sink(dest4);
sink(*dest4);
}
// --- strsep ---
char *strsep(char**, const char *);
void test_strsep(char *source) {
const char* delim = ",.-;:_";
char* tokenized;
while(tokenized = strsep(&source, delim)) {
sink(tokenized); // $ ast,ir
sink(*tokenized); // $ ast,ir
}
}
// --- _strinc and related functions ---
char* _strinc(const char*, _locale_t);
unsigned char* _mbsinc(const unsigned char*);
unsigned char *_strdec(const unsigned char*, const unsigned char*);
void test__strinc(char* source, char* clean, char* dest1, char* dest2, _locale_t locale) {
dest1 = _strinc(source, locale);
sink(dest1); // $ ast,ir
sink(*dest1); // $ ast,ir
dest2 = _strinc(clean, locale);
sink(dest2);
sink(*dest2);
}
void test__mbsinc(unsigned char* source_unsigned, char* source, unsigned char* dest_unsigned, char* dest) {
dest_unsigned = _mbsinc(source_unsigned);
sink(dest_unsigned); // $ ast,ir
sink(*dest_unsigned); // $ ast,ir
dest = (char*)_mbsinc((unsigned char*)source);
sink(dest); // $ ast,ir
sink(*dest); // $ ast,ir
}
void test__strdec(const unsigned char* source, unsigned char* clean, unsigned char* dest1, unsigned char* dest2, unsigned char* dest3) {
dest1 = _strdec(source + 12, source);
sink(dest1); // $ ast,ir
sink(*dest1); // $ ast,ir
// If `clean` does not precede `source` this technically breaks the precondition of _strdec.
// We would still like to have taint, though.
dest2 = _strdec(clean, source);
sink(dest2); // $ ast,ir
sink(*dest2); // $ ast,ir
// Also breaks the precondition on _strdec.
dest3 = _strdec(source, clean);
sink(dest3); // $ ast,ir
sink(*dest3); // $ ast,ir
}
// --- strnextc ---
unsigned int _strnextc(const char*);
void test__strnextc(const char* source) {
unsigned c = 0;
do {
c = _strnextc(source++);
sink(c); // $ ast,ir
} while(c != '\0');
c = _strnextc("");
sink(c);
}

View File

@@ -491,8 +491,8 @@ void test_vector_emplace() {
std::vector<int> v1(10), v2(10);
v1.emplace_back(source());
sink(v1); // $ ast MISSING: ir
sink(v1); // $ ast,ir
v2.emplace(v2.begin(), source());
sink(v2); // $ ast MISSING: ir
sink(v2); // $ ast,ir
}

View File

@@ -889,10 +889,8 @@ ssa.cpp:
# 207| m207_4(unknown) = Chi : total:m207_2, partial:m207_3
# 207| r207_5(glval<int>) = VariableAddress[x] :
# 207| m207_6(int) = InitializeParameter[x] : &:r207_5
# 207| m207_7(unknown) = Chi : total:m207_4, partial:m207_6
# 208| r208_1(glval<int>) = VariableAddress[y] :
# 208| m208_2(int) = Uninitialized[y] : &:r208_1
# 208| m208_3(unknown) = Chi : total:m207_7, partial:m208_2
# 209| r209_1(glval<unknown>) = FunctionAddress[memcpy] :
# 209| r209_2(glval<int>) = VariableAddress[y] :
# 209| r209_3(int *) = CopyValue : r209_2
@@ -904,15 +902,15 @@ ssa.cpp:
# 209| r209_9(void *) = Call[memcpy] : func:r209_1, 0:r209_4, 1:r209_7, 2:r209_8
# 209| v209_10(void) = ^SizedBufferReadSideEffect[1] : &:r209_7, r209_8, ~m207_6
# 209| m209_11(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r209_4, r209_8
# 209| m209_12(unknown) = Chi : total:m208_3, partial:m209_11
# 209| m209_12(int) = Chi : total:m208_2, partial:m209_11
# 210| r210_1(glval<int>) = VariableAddress[#return] :
# 210| r210_2(glval<int>) = VariableAddress[y] :
# 210| r210_3(int) = Load[y] : &:r210_2, ~m209_12
# 210| r210_3(int) = Load[y] : &:r210_2, m209_12
# 210| m210_4(int) = Store[#return] : &:r210_1, r210_3
# 207| r207_8(glval<int>) = VariableAddress[#return] :
# 207| v207_9(void) = ReturnValue : &:r207_8, m210_4
# 207| v207_10(void) = AliasedUse : m207_3
# 207| v207_11(void) = ExitFunction :
# 207| r207_7(glval<int>) = VariableAddress[#return] :
# 207| v207_8(void) = ReturnValue : &:r207_7, m210_4
# 207| v207_9(void) = AliasedUse : m207_3
# 207| v207_10(void) = ExitFunction :
# 213| void InitArray()
# 213| Block 0
@@ -1104,51 +1102,49 @@ ssa.cpp:
# 247| m247_6(char *) = InitializeParameter[src] : &:r247_5
# 247| r247_7(char *) = Load[src] : &:r247_5, m247_6
# 247| m247_8(unknown) = InitializeIndirection[src] : &:r247_7
# 247| m247_9(unknown) = Chi : total:m247_4, partial:m247_8
# 247| r247_10(glval<int>) = VariableAddress[size] :
# 247| m247_11(int) = InitializeParameter[size] : &:r247_10
# 247| r247_9(glval<int>) = VariableAddress[size] :
# 247| m247_10(int) = InitializeParameter[size] : &:r247_9
# 248| r248_1(glval<char *>) = VariableAddress[dst] :
# 248| r248_2(glval<unknown>) = FunctionAddress[operator new[]] :
# 248| r248_3(glval<int>) = VariableAddress[size] :
# 248| r248_4(int) = Load[size] : &:r248_3, m247_11
# 248| r248_4(int) = Load[size] : &:r248_3, m247_10
# 248| r248_5(unsigned long) = Convert : r248_4
# 248| r248_6(unsigned long) = Constant[1] :
# 248| r248_7(unsigned long) = Mul : r248_5, r248_6
# 248| r248_8(void *) = Call[operator new[]] : func:r248_2, 0:r248_7
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_9
# 248| m248_10(unknown) = Chi : total:m247_9, partial:m248_9
# 248| m248_9(unknown) = ^CallSideEffect : ~m247_4
# 248| m248_10(unknown) = Chi : total:m247_4, partial:m248_9
# 248| m248_11(unknown) = ^InitializeDynamicAllocation : &:r248_8
# 248| m248_12(unknown) = Chi : total:m248_10, partial:m248_11
# 248| r248_13(char *) = Convert : r248_8
# 248| m248_14(char *) = Store[dst] : &:r248_1, r248_13
# 248| r248_12(char *) = Convert : r248_8
# 248| m248_13(char *) = Store[dst] : &:r248_1, r248_12
# 249| r249_1(char) = Constant[97] :
# 249| r249_2(glval<char *>) = VariableAddress[src] :
# 249| r249_3(char *) = Load[src] : &:r249_2, m247_6
# 249| r249_4(glval<char>) = CopyValue : r249_3
# 249| m249_5(char) = Store[?] : &:r249_4, r249_1
# 249| m249_6(unknown) = Chi : total:m248_12, partial:m249_5
# 249| m249_6(unknown) = Chi : total:m247_8, partial:m249_5
# 250| r250_1(glval<unknown>) = FunctionAddress[memcpy] :
# 250| r250_2(glval<char *>) = VariableAddress[dst] :
# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_14
# 250| r250_3(char *) = Load[dst] : &:r250_2, m248_13
# 250| r250_4(void *) = Convert : r250_3
# 250| r250_5(glval<char *>) = VariableAddress[src] :
# 250| r250_6(char *) = Load[src] : &:r250_5, m247_6
# 250| r250_7(void *) = Convert : r250_6
# 250| r250_8(glval<int>) = VariableAddress[size] :
# 250| r250_9(int) = Load[size] : &:r250_8, m247_11
# 250| r250_9(int) = Load[size] : &:r250_8, m247_10
# 250| r250_10(void *) = Call[memcpy] : func:r250_1, 0:r250_4, 1:r250_7, 2:r250_9
# 250| v250_11(void) = ^SizedBufferReadSideEffect[1] : &:r250_7, r250_9, ~m249_6
# 250| m250_12(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r250_4, r250_9
# 250| m250_13(unknown) = Chi : total:m249_6, partial:m250_12
# 250| m250_13(unknown) = Chi : total:m248_11, partial:m250_12
# 251| r251_1(glval<char *>) = VariableAddress[#return] :
# 251| r251_2(glval<char *>) = VariableAddress[dst] :
# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_14
# 251| r251_3(char *) = Load[dst] : &:r251_2, m248_13
# 251| m251_4(char *) = Store[#return] : &:r251_1, r251_3
# 247| v247_12(void) = ReturnIndirection[src] : &:r247_7, ~m250_13
# 247| r247_13(glval<char *>) = VariableAddress[#return] :
# 247| v247_14(void) = ReturnValue : &:r247_13, m251_4
# 247| v247_15(void) = AliasedUse : ~m250_13
# 247| v247_16(void) = ExitFunction :
# 247| v247_11(void) = ReturnIndirection[src] : &:r247_7, m249_6
# 247| r247_12(glval<char *>) = VariableAddress[#return] :
# 247| v247_13(void) = ReturnValue : &:r247_12, m251_4
# 247| v247_14(void) = AliasedUse : ~m248_10
# 247| v247_15(void) = ExitFunction :
# 254| char StringLiteralAliasing2(bool)
# 254| Block 0
@@ -1206,39 +1202,37 @@ ssa.cpp:
# 268| m268_6(void *) = InitializeParameter[s] : &:r268_5
# 268| r268_7(void *) = Load[s] : &:r268_5, m268_6
# 268| m268_8(unknown) = InitializeIndirection[s] : &:r268_7
# 268| m268_9(unknown) = Chi : total:m268_4, partial:m268_8
# 268| r268_10(glval<int>) = VariableAddress[size] :
# 268| m268_11(int) = InitializeParameter[size] : &:r268_10
# 268| r268_9(glval<int>) = VariableAddress[size] :
# 268| m268_10(int) = InitializeParameter[size] : &:r268_9
# 269| r269_1(glval<void *>) = VariableAddress[buf] :
# 269| r269_2(glval<unknown>) = FunctionAddress[malloc] :
# 269| r269_3(glval<int>) = VariableAddress[size] :
# 269| r269_4(int) = Load[size] : &:r269_3, m268_11
# 269| r269_4(int) = Load[size] : &:r269_3, m268_10
# 269| r269_5(void *) = Call[malloc] : func:r269_2, 0:r269_4
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_9
# 269| m269_7(unknown) = Chi : total:m268_9, partial:m269_6
# 269| m269_6(unknown) = ^CallSideEffect : ~m268_4
# 269| m269_7(unknown) = Chi : total:m268_4, partial:m269_6
# 269| m269_8(unknown) = ^InitializeDynamicAllocation : &:r269_5
# 269| m269_9(unknown) = Chi : total:m269_7, partial:m269_8
# 269| m269_10(void *) = Store[buf] : &:r269_1, r269_5
# 269| m269_9(void *) = Store[buf] : &:r269_1, r269_5
# 270| r270_1(glval<unknown>) = FunctionAddress[memcpy] :
# 270| r270_2(glval<void *>) = VariableAddress[buf] :
# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_10
# 270| r270_3(void *) = Load[buf] : &:r270_2, m269_9
# 270| r270_4(glval<void *>) = VariableAddress[s] :
# 270| r270_5(void *) = Load[s] : &:r270_4, m268_6
# 270| r270_6(glval<int>) = VariableAddress[size] :
# 270| r270_7(int) = Load[size] : &:r270_6, m268_11
# 270| r270_7(int) = Load[size] : &:r270_6, m268_10
# 270| r270_8(void *) = Call[memcpy] : func:r270_1, 0:r270_3, 1:r270_5, 2:r270_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m269_7
# 270| v270_9(void) = ^SizedBufferReadSideEffect[1] : &:r270_5, r270_7, ~m268_8
# 270| m270_10(unknown) = ^SizedBufferMustWriteSideEffect[0] : &:r270_3, r270_7
# 270| m270_11(unknown) = Chi : total:m269_9, partial:m270_10
# 270| m270_11(unknown) = Chi : total:m269_8, partial:m270_10
# 271| r271_1(glval<void *>) = VariableAddress[#return] :
# 271| r271_2(glval<void *>) = VariableAddress[buf] :
# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_10
# 271| r271_3(void *) = Load[buf] : &:r271_2, m269_9
# 271| m271_4(void *) = Store[#return] : &:r271_1, r271_3
# 268| v268_12(void) = ReturnIndirection[s] : &:r268_7, ~m270_11
# 268| r268_13(glval<void *>) = VariableAddress[#return] :
# 268| v268_14(void) = ReturnValue : &:r268_13, m271_4
# 268| v268_15(void) = AliasedUse : ~m270_11
# 268| v268_16(void) = ExitFunction :
# 268| v268_11(void) = ReturnIndirection[s] : &:r268_7, m268_8
# 268| r268_12(glval<void *>) = VariableAddress[#return] :
# 268| v268_13(void) = ReturnValue : &:r268_12, m271_4
# 268| v268_14(void) = AliasedUse : ~m269_7
# 268| v268_15(void) = ExitFunction :
# 275| void EscapedButNotConflated(bool, Point, int)
# 275| Block 0

View File

@@ -2,3 +2,4 @@ name: codeql-cpp-tests
version: 0.0.0
libraryPathDependencies: codeql-cpp
extractor: cpp
tests: .

View File

@@ -1,3 +1,3 @@
| printf.cpp:33:31:33:37 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:45:29:45:35 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:52:29:52:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |
| printf.cpp:31:31:31:37 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:43:29:43:35 | test | This argument should be of type 'char *' but is of type 'char16_t *' |
| printf.cpp:50:29:50:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *' |

View File

@@ -1,2 +1,2 @@
| printf.cpp:15:5:15:12 | swprintf | char | char16_t | char16_t |
| printf.cpp:26:5:26:11 | sprintf | char | char16_t | char16_t |
| printf.cpp:13:5:13:12 | swprintf | char | char16_t | char16_t |
| printf.cpp:24:5:24:11 | sprintf | char | char16_t | char16_t |

View File

@@ -8,9 +8,7 @@ typedef void *va_list;
#define va_start(va, other)
#define va_end(args)
int vswprintf(WCHAR *dest, WCHAR *format, va_list args) {
return 0;
}
int vswprintf(WCHAR *dest, WCHAR *format, va_list args);
int swprintf(WCHAR *dest, WCHAR *format, ...) {
va_list args;

View File

@@ -0,0 +1,10 @@
| test.cpp:6:5:6:13 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:10:8:10:24 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:15:9:15:25 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:32:12:32:20 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:39:12:39:20 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:47:5:47:13 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:55:5:55:13 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:62:5:62:13 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:69:5:69:13 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:75:8:75:16 | ... > ... | Unsigned subtraction can never be negative. |

View File

@@ -0,0 +1 @@
Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql

View File

@@ -0,0 +1,77 @@
int getAnInt();
bool cond();
void test(unsigned x, unsigned y, bool unknown) {
if(x - y > 0) { } // BAD
unsigned total = getAnInt();
unsigned limit = getAnInt();
while(limit - total > 0) { // BAD
total += getAnInt();
}
if(total <= limit) {
while(limit - total > 0) { // GOOD [FALSE POSITIVE]
total += getAnInt();
if(total > limit) break;
}
}
if(x >= y) {
bool b = x - y > 0; // GOOD
}
if((int)(x - y) >= 0) { } // GOOD. Maybe an overflow happened, but the result is converted to the "likely intended" result before the comparison
if(unknown) {
y = x & 0xFF;
} else {
y = x;
}
bool b1 = x - y > 0; // GOOD [FALSE POSITIVE]
x = getAnInt();
y = getAnInt();
if(y > x) {
y = x - 1;
}
bool b2 = x - y > 0; // GOOD [FALSE POSITIVE]
int N = getAnInt();
y = x;
while(cond()) {
if(unknown) { y--; }
}
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
x = y;
while(cond()) {
if(unknown) break;
y--;
}
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
y = 0;
for(int i = 0; i < x; ++i) {
if(unknown) { ++y; }
}
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
x = y;
while(cond()) {
if(unknown) { x++; }
}
if(x - y > 0) { } // GOOD [FALSE POSITIVE]
int n = getAnInt();
if (n > x - y) { n = x - y; }
if (n > 0) {
y += n; // NOTE: `n` is at most `x - y` at this point.
if (x - y > 0) {} // GOOD [FALSE POSITIVE]
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
description: Change decltype keysets
compatibility: backwards

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* The `RelationalPatternExpr` and its 4 sub class have been added to support C# 9
relational `<`, `>`, `<=`, and `>=` patterns.

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* Function pointer types (`FunctionPointerType`) and call to function pointers
(`FunctionPointerCall`) are extracted.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Function pointer types (`FunctionPointerType`) are extracted from IL. Also, `pinned` and `by-reference` (`cil_type_annotation`) type extraction is fixed.

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* The `BinaryPatternExpr` class has been added to support C# 9 `and` and `or`
patterns.

View File

@@ -0,0 +1,8 @@
lgtm,codescanning
* The `PreprocessorDirective` class and its base classes have been added to support
preprocessor directives, such as `#if`, `#define`, `#undef`, `#line`, `#region`,
`#warning`, `#error`, `#pragma warning`, `#pragma checksum` and `#nullable`. Furthermore,
`#line` directives are now taken into account when querying the location of any
code construct. Files referenced in preprocessor directives are also included in the
extraction sources. This change is expected to lead to better error reporting locations
in generated code, such as generated code from `.cshtml` files in ASP.NET Core.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Record types (`Record`) are extracted.

View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace Semmle.Extraction.CIL.Entities
{
/// <summary>
/// Types that are passed by reference are not written directly to trap files. Instead, the annotation is stored on
/// the entity.
/// </summary>
internal sealed class ByRefType : Type
{
public ByRefType(Context cx, Type elementType) : base(cx)
{
ElementType = elementType;
}
public override CilTypeKind Kind => throw new NotImplementedException();
public override Namespace? ContainingNamespace => throw new NotImplementedException();
public override Type? ContainingType => throw new NotImplementedException();
public override int ThisTypeParameterCount => throw new NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
public override string Name => $"{ElementType.Name}&";
public Type ElementType { get; }
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
public override void WriteId(TextWriter trapFile, bool inContext)
{
ElementType.WriteId(trapFile, inContext);
trapFile.Write('&');
}
}
}

View File

@@ -8,6 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
ValueOrRefType,
TypeParameter,
Array,
Pointer
Pointer,
FunctionPointer
}
}

View File

@@ -1,5 +1,4 @@
using System;
using Microsoft.CodeAnalysis;
using System.Linq;
using System.Collections.Generic;
using System.IO;

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
@@ -36,12 +37,26 @@ namespace Semmle.Extraction.CIL.Entities
}
var name = type.GetQualifiedName();
if (wellKnownEnums.TryGetValue(name, out var code))
{
cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Debug, $"Using hard coded underlying enum type for {name}");
return code;
}
cx.Cx.Extractor.Logger.Log(Util.Logging.Severity.Info, $"Couldn't get underlying enum type for {name}");
// We can't fall back to Int32, because the type returned here defines how many bytes are read from the
// stream and how those bytes are interpreted.
throw new NotImplementedException();
}
public bool IsSystemType(Type type) => type.GetQualifiedName() == "System.Type";
private static readonly Dictionary<string, PrimitiveTypeCode> wellKnownEnums = new Dictionary<string, PrimitiveTypeCode>
{
{ "System.AttributeTargets", PrimitiveTypeCode.Int32 },
{ "System.ComponentModel.EditorBrowsableState", PrimitiveTypeCode.Int32 }
};
}
}

View File

@@ -121,8 +121,19 @@ namespace Semmle.Extraction.CIL.Entities
for (var l = 0; l < this.locals.Length; ++l)
{
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, localVariableTypes[l]));
yield return this.locals[l];
var t = localVariableTypes[l];
if (t is ByRefType brt)
{
t = brt.ElementType;
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t));
yield return this.locals[l];
yield return Tuples.cil_type_annotation(this.locals[l], TypeAnnotation.Ref);
}
else
{
this.locals[l] = Cx.Populate(new LocalVariable(Cx, Implementation, l, t));
yield return this.locals[l];
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection.Metadata;
namespace Semmle.Extraction.CIL.Entities
{
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
{
private readonly MethodSignature<Type> signature;
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
{
this.signature = signature;
}
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
public override string Name
{
get
{
using var id = new StringWriter();
WriteName(
id.Write,
t => id.Write(t.Name),
signature
);
return id.ToString();
}
}
public override Namespace? ContainingNamespace => Cx.GlobalNamespace;
public override Type? ContainingType => null;
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
public override void WriteId(TextWriter trapFile, bool inContext)
{
WriteName(
trapFile.Write,
t => t.WriteId(trapFile, inContext),
signature
);
}
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
{
write("delegate* ");
write(GetCallingConvention(signature.Header.CallingConvention));
write("<");
foreach (var pt in signature.ParameterTypes)
{
writeType(pt);
write(",");
}
writeType(signature.ReturnType);
write(">");
}
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
{
if (callingConvention == SignatureCallingConvention.Default)
{
return "managed";
}
if (callingConvention == SignatureCallingConvention.Unmanaged)
{
return "unmanaged";
}
return $"unmanaged[{callingConvention}]";
}
public override IEnumerable<IExtractionProduct> Contents
{
get
{
foreach (var c in base.Contents)
{
yield return c;
}
var retType = signature.ReturnType;
if (retType is ModifiedType mt)
{
retType = mt.Unmodified;
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
}
if (retType is ByRefType byRefType)
{
retType = byRefType.ElementType;
yield return Tuples.cil_type_annotation(this, TypeAnnotation.Ref);
}
yield return Tuples.cil_function_pointer_return_type(this, retType);
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
foreach (var p in Method.GetParameterExtractionProducts(signature.ParameterTypes, this, this, Cx, 0))
{
yield return p;
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More