Compare commits

..

763 Commits

Author SHA1 Message Date
James Fletcher
bb44a76d5e Merge pull request #3138 from jf205/recent-changes
docs: fix links in Python articles (rc/1.23)
2020-03-27 08:17:03 +00:00
Felicity Chapman
1a992ba9ed Merge pull request #3037 from felicitymay/1.23/2209-update-links
Replace remaining links to semmle.com in 'docs' directory
2020-03-10 15:22:48 +00:00
Felicity Chapman
48dcf12760 Replace remaining links to semmle.com in 'docs' directory 2020-03-10 13:22:35 +00:00
Felicity Chapman
62bcc1a512 Merge pull request #2986 from felicitymay/1.23/2210-replace-links-semmle.com
1.23: Update or remove unwanted links
2020-03-05 10:20:35 +00:00
Felicity Chapman
4a415d8ad6 Update or remove unwanted links 2020-03-04 14:18:24 +00:00
Geoffrey White
427b440389 Merge pull request #2918 from jbj/UnsignedGEZero-recursion
C++: Fix performance of UnsignedGEZero.ql
2020-02-26 15:49:03 +00:00
Jonas Jensen
5f6d07dd57 C++: Fix performance of UnsignedGEZero.ql
This query used two fastTC operations that were already somewhat
inefficient on their own but could send the evaluator into an OOM loop
when run in parallel without enough RAM.

The fix is to recurse manually, starting just from the expressions that
are potential candidates for alerts.
2020-02-26 11:32:41 +01:00
Shati Patel
2aed6fb971 Merge pull request #2878 from jf205/monotonic-aggregates-123
QL handbook: updates for rc/1.23
2020-02-19 16:55:11 +00:00
james
fc3d30c10b docs: technical feedback
(cherry picked from commit d5ff8f2b8e)
2020-02-19 16:45:48 +00:00
james
100a603a86 docs: expand handbook entry on monotonic aggregates
(cherry picked from commit b32683fc9f)
2020-02-19 16:45:48 +00:00
Shati Patel
c5d8aac2ce Merge pull request #2876 from jf205/advanced-ql-123
docs: continue reorganizing 'Advanced QL' (rc/1.23)
2020-02-19 16:29:57 +00:00
james
2bc5d11610 docs: delete advanced-ql section 2020-02-19 16:20:09 +00:00
james
1f84722d2f docs: delete constraining-types.rst
(cherry picked from commit 142106bc99)
2020-02-19 16:12:07 +00:00
james
afbb70af47 docs: remove advanced ql topic about determining specific types
(cherry picked from commit 3d90f6fe71)
2020-02-19 16:12:07 +00:00
james
30913c9e7c docs: add info about using getAQlClass()
(cherry picked from commit 3fb3b9b54a)
2020-02-19 16:12:06 +00:00
Shati Patel
bd94e80271 Merge pull request #2809 from jf205/update-rc123
docs: port some more changes onto rc/1.23
2020-02-11 11:26:36 +01:00
James Fletcher
cb94c95115 Merge pull request #2807 from shati-patel/sphinx-blog
Remove link to blog
2020-02-11 09:16:42 +00:00
Arthur Baars
a460d90434 Remove trailing ; in QL language spec
(cherry picked from commit c91815f44d)
2020-02-11 09:13:30 +00:00
Arthur Baars
b56b10b0d9 Fix typos in QL language spec
(cherry picked from commit c431d47481)
2020-02-11 09:13:30 +00:00
James Fletcher
d8f31068d5 Update docs/language/learn-ql/writing-queries/debugging-queries.rst
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
(cherry picked from commit 47f61f3569)
2020-02-11 09:04:45 +00:00
james
f3d2588dae docs: address review comments
(cherry picked from commit 537739c42d)
2020-02-11 09:04:45 +00:00
james
646670708c docs: move abstract classes topic to handbook
(cherry picked from commit 23d1e06aa4)
2020-02-11 09:04:45 +00:00
james
bcf08649ee docs: delete equivalence topic
(cherry picked from commit e8016a2303)
2020-02-11 09:03:59 +00:00
james
8e6e6d356d docs: move folding predicates topic
(cherry picked from commit fe18c18619)
2020-02-11 09:03:59 +00:00
james
2900dced18 docs: add link to module resolution in ql spec
(cherry picked from commit f2320bbe56)
2020-02-11 09:03:58 +00:00
Shati Patel
ce28d0fde7 Remove link to blog 2020-02-10 17:48:44 +00:00
james
2407eb103a docs: fix list
(cherry picked from commit 618a3f91d8)
2020-01-08 16:16:39 +00:00
Rasmus Wriedt Larsen
cdcca630f3 docs: remove extra comma in dataflow articles
(cherry picked from commit e882060839)
2020-01-08 16:16:39 +00:00
Rasmus Wriedt Larsen
24e551905e docs: Fix Python taint tracking links
at some point we moved security/TaintTracking.qll to dataflow/TaintTracking.qll

(cherry picked from commit f44ce7d647)
2020-01-08 16:16:39 +00:00
james
97d3d1fca3 docs: fix ast node link
(cherry picked from commit cff5df0779)
2020-01-08 16:16:39 +00:00
James Fletcher
a974bccd62 Merge pull request #2545 from shati-patel/update-ql4e
Docs: Update mention of "QL for Eclipse"
2019-12-17 12:39:31 +00:00
shati-patel
8143333928 Docs: Update mention of "QL for Eclipse" 2019-12-17 12:33:01 +00:00
James Fletcher
05ad7777cb Merge pull request #2536 from shati-patel/docs/ql4e
Docs: Update references to QL for Eclipse
2019-12-16 14:10:56 +00:00
Shati Patel
1ff5a8e8e2 Docs: Update references to QL for Eclipse 2019-12-16 12:28:39 +00:00
Felicity Chapman
54a7b89b99 Merge pull request #2526 from yo-h/java-change-note-netty
Java: add change note for `java/netty-http-response-splitting`
2019-12-13 08:12:01 +00:00
yo-h
32f146fbca Java: add change note for java/netty-http-response-splitting 2019-12-12 14:31:06 -05:00
Geoffrey White
73446ea610 Merge pull request #2511 from jbj/isInCycle-raw-only
C++: Compute isInCycle only for raw IR
2019-12-12 14:22:00 +00:00
shati-patel
f2d1e534c9 Merge pull request #1914 from jf205/query-debugging
docs: make a start on query debugging topic
2019-12-11 14:31:55 +00:00
James Fletcher
ff4a604119 Update docs/language/learn-ql/writing-queries/debugging-queries.rst
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-12-11 14:29:10 +00:00
James Fletcher
b2db72d336 Apply suggestions from code review
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-12-11 14:13:56 +00:00
James Fletcher
2ce1c2bfee Apply suggestions from code review
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-12-11 12:44:35 +00:00
james
d6202da876 docs: address max's comments 2019-12-11 12:25:35 +00:00
James Fletcher
61576caede Apply suggestions from code review
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-12-11 12:20:38 +00:00
james
d56c02b1b7 docs: start work on debugging queries topic 2019-12-11 10:42:54 +00:00
Jonas Jensen
5a8407749f C#: autoformat fixup 2019-12-11 09:10:23 +01:00
Geoffrey White
5ecfaed6b1 Merge pull request #2510 from jbj/getTempVariable-perf
C++: Fix getTempVariable join order in IR
2019-12-10 16:06:52 +00:00
Jonas Jensen
66876d0f63 C++: Compute isInCycle only for raw IR
On wireshark/wireshark, `isInCycle` ran into a low-memory loop on the
`aliased_ssa` stage. It shouldn't be necessary to detect cycles after
the `raw` stage, so this commit moves cycle detection into the
`Construction` modules and makes it a no-op in `SSAConstruction.qll`.
2019-12-10 16:03:39 +01:00
Jonas Jensen
7c151644f5 C++: Fix getTempVariable join order in IR
This join order seems to have broken so it took forever on
wireshark/wireshark.
2019-12-10 13:43:36 +01:00
Geoffrey White
1c2f36930d Merge pull request #2504 from jbj/1.23-legacy-suites
C++: Add new queries in 1.23 to legacy suites
2019-12-09 16:02:42 +00:00
Jonas Jensen
9bbebfc01f C++: Add new queries to C suite too 2019-12-09 17:00:33 +01:00
Jonas Jensen
ff7b6e2ce7 C++: Add new queries in 1.23 to legacy suites
I didn't add `JapaneseEraDate.ql` since it's not displayed on LGTM by
default.
2019-12-09 15:36:51 +01:00
shati-patel
bc2e15c133 Merge pull request #2503 from jf205/support-notes
CodeQL support docs: remove some full stops
2019-12-09 12:32:16 +00:00
james
07f35e8b58 docs: remove some full stops 2019-12-09 12:26:53 +00:00
James Fletcher
61d4a87aa4 Merge pull request #2499 from felicitymay/1.23/update-supported-versions
Update supported versions for 1.23 release
2019-12-09 12:23:59 +00:00
Tom Hvitved
c562d6757c Merge pull request #2500 from shati-patel/typo
Fix typos
2019-12-09 13:06:39 +01:00
Shati Patel
f40b1b570c Fix typo 2019-12-06 15:56:01 +00:00
Felicity Chapman
e59d65e67f Update supported versions for 1.23 release 2019-12-06 15:41:18 +00:00
Luke Cartey
b940f3e637 Merge pull request #2461 from jf205/codeql-172
CodeQL training: update QL4E links and provide database instructions
2019-12-06 11:15:49 +00:00
shati-patel
ad2da41af8 Merge pull request #2493 from jf205/deprecate-cobol
Learning CodeQL docs: add COBOL notes and remove links (rc/1.23)
2019-12-04 16:46:51 +00:00
james
40920b162c docs: delete link to query console 2019-12-04 16:36:44 +00:00
james
ad32d9140b docs: increase trainig project version number 2019-12-04 16:36:44 +00:00
james
fe3a908317 docs: add cobol notes 2019-12-04 16:36:44 +00:00
Calum Grant
db30947e54 Merge pull request #2490 from felicitymay/1.23/SD-4095-finalize-change-notes-csharp
1.23/sd 4095 finalize change notes csharp
2019-12-03 17:38:09 +00:00
Dave Bartolomeo
48e92e2399 Merge pull request #2481 from calumgrant/cs/fix-ir-types
C#: Fix some IR types that didn't compile.
2019-12-02 09:42:33 -08:00
Calum Grant
c05263ca98 C#: Fix some IR types that didn't compile. 2019-12-02 13:27:58 +00:00
Jonas Jensen
4494d61e56 Merge pull request #2473 from aschackmull/java/field-flow-rev-read
Java/C++/C#: Bugfix for field flow through reverse read.
2019-11-29 14:45:12 +01:00
semmle-qlci
a40ad9f276 Merge pull request #2456 from felicitymay/1.23/SD-4095-finalize-change-notes-js
Approved by erik-krogh, max-schaefer
2019-11-29 08:59:29 +00:00
Anders Schack-Mulligen
333d0a69d2 Java/C++/C#: Bugfix for field flow through reverse read. 2019-11-29 09:38:24 +01:00
semmle-qlci
d59ea3d53c Merge pull request #2466 from esbena/js/fix-mjs-check
Approved by asgerf
2019-11-28 13:37:43 +00:00
Esben Sparre Andreasen
4e0dfce427 JS: cache charpred for NodeJS::Require 2019-11-28 08:10:25 +01:00
Esben Sparre Andreasen
d909653a6b JS: simplify charpred for NodeJS::Require 2019-11-28 08:10:25 +01:00
james
931cc73d1e docs: add brief instructions for using databases in VS Code 2019-11-27 15:05:50 +00:00
james
24857e5616 docs: update or remove other uses of QL4E 2019-11-27 15:05:08 +00:00
Felicity Chapman
4070992273 Fix sort order 2019-11-27 12:38:39 +00:00
Felicity Chapman
587dd54a3c Minor text changes 2019-11-27 12:38:38 +00:00
james
3782d1b6e4 docs: update links on opening slide 2019-11-27 12:28:57 +00:00
Felicity Chapman
eaf68e86e0 Merge pull request #2443 from tausbn/python-finalise-change-notes
Python: Update change note for 1.23.
2019-11-27 11:51:04 +00:00
Taus Brock-Nannestad
b503cdb9d4 Python: Final change note fixes.
- `false positives` becomes `false positive results`
- Items are listed alphabetically.
- Query IDs are listed.

Also, some of the queries had the wrong name (query message rather than the
actual query name). These have been fixed.
2019-11-27 12:10:28 +01:00
Taus
8372039205 Apply suggestions from documentation review
Co-Authored-By: Felicity Chapman <felicitymay@github.com>
2019-11-27 11:50:37 +01:00
Anders Schack-Mulligen
42b51d4ebb Merge pull request #2449 from felicitymay/1.23/SD-4095-finalize-change-notes-java2
Update data-flow note to match that for C/C++
2019-11-27 08:50:31 +01:00
semmle-qlci
380a5fc166 Merge pull request #2444 from esbena/js/flow-spread-prop-types
Approved by max-schaefer
2019-11-26 22:42:23 +00:00
Felicity Chapman
403565bb06 Update data-flow note to match that for C/C++ 2019-11-26 18:07:51 +00:00
Felicity Chapman
3b7ab8f734 Update shared data-flow note to match that for C/C++ 2019-11-26 18:02:09 +00:00
Jonas Jensen
95bceae915 Merge pull request #2434 from felicitymay/1.23/SD-4095-finalize-change-notes-cpp
1.23: SD-4095 finalize change notes for C/C++
2019-11-26 18:56:22 +01:00
Felicity Chapman
4f6660887c Update shared data-flow note for feedback 2019-11-26 16:41:30 +00:00
Taus
e585f1ba85 Merge pull request #1332 from lcartey/python/change-kind
Python: Update filter queries to have appropriate kind
2019-11-26 17:15:38 +01:00
Esben Sparre Andreasen
9ffe03bcce JS: support additional Flow syntax: ... in object types 2019-11-26 15:24:27 +01:00
Taus Brock-Nannestad
35e3e3d2a1 Python: Update change note for 1.23. 2019-11-26 13:58:22 +01:00
semmle-qlci
3d5d178b19 Merge pull request #2439 from erik-krogh/useOfReturnlessFunctionHotfix
Approved by max-schaefer
2019-11-26 11:56:57 +00:00
Erik Krogh Kristensen
fed2675f76 remove FP in use-of-returnless-function FP related to calls to super() 2019-11-26 10:17:04 +01:00
Erik Krogh Kristensen
89dac23969 remove 3 FP sources from use-of-returnless-function 2019-11-26 10:16:18 +01:00
yo-h
1a07f215ad Merge pull request #2436 from felicitymay/1.23/SD-4095-finalize-change-notes-java
1.23: SD-4095 finalize change notes for Java
2019-11-25 18:19:25 -05:00
Felicity Chapman
775ed381e1 Update to clarify status of one new query 2019-11-25 17:35:01 +00:00
Felicity Chapman
87fca1fde6 Remove backticks from 'struct' 2019-11-25 15:56:29 +00:00
Felicity Chapman
49bdf7ed1c Fix table sort order 2019-11-25 15:36:58 +00:00
Felicity Chapman
f75b61e2f0 Minor text changes 2019-11-25 15:36:37 +00:00
Felicity Chapman
f5bf877671 Fix table sort order 2019-11-25 15:18:30 +00:00
Felicity Chapman
dc258f13e3 Minor text changes 2019-11-25 15:17:02 +00:00
Geoffrey White
1d26d4c5e4 Merge pull request #2404 from jbj/signed-overflow-macro
C++: Fix SignedOverflowCheck.ql performance
2019-11-25 15:15:57 +00:00
Dave Bartolomeo
4a21123107 Merge pull request #2427 from jbj/comparison-with-wider-type-notc
C++: Stricter loop-variant check
2019-11-25 07:38:02 -07:00
Felicity Chapman
419c1c6311 Fix table sort order 2019-11-25 14:29:13 +00:00
Felicity Chapman
b5a88586ab Minor text changes to C# notes 2019-11-25 12:39:54 +00:00
shati-patel
9b5437c91e Merge pull request #2318 from rdmarsh2/rdmarsh/docs/cpp/taint-tracking-sanitizer-example
C++/Docs: add example based on NtohlArrayNoBound
2019-11-25 12:24:01 +00:00
Jonas Jensen
5ee19c5a66 C++: Stricter loop-variant check
The `loopVariant` predicate in `ComparisonWithWiderType.ql` is intended
to identify loop counters, but it was too much of a stretch to apply it
to any subexpression of the small side of the comparison.

This change fixes two false positives on arvidn/libtorrent and many
others seen in the wild (on Linux, CoreCLR, ffmpeg, ...).
2019-11-25 11:31:41 +01:00
Jonas Jensen
eb0b0d1e7f C++: Fix remaining FP on MAME
This should fix a FP in libretro/mame2003-plus-libretro.
2019-11-22 16:05:17 +01:00
Geoffrey White
9471134064 Merge pull request #2417 from jbj/enclosing-reeval
C++: Prevent cached stages from being re-evaluated
2019-11-22 09:55:01 +00:00
Jonas Jensen
bd4fa10ffb C++: Tie macro exclusion to <, not +
This fixes a failing qltest and makes the exclusion similar to what's in
`PointerOverflow.ql`. It's possible we should exclude based on both `+`
and `<`, but we can revisit that if false positives show up.
2019-11-22 09:20:00 +01:00
Jonas Jensen
ca1b91aab2 Merge pull request #2414 from dbartol/dbartol/FixWarnings
C++/C#: Fix QL compilation warnings/errors
2019-11-22 09:14:33 +01:00
Jonas Jensen
0e4ed1cbbf C++: Prevent cached stages from being re-evaluated
Before this change, evaluating `cpp/constant-comparison` followed by
`cpp/signed-overflow-check` would result in re-evaluation of almost all
the cached stages they share: CFG, basic blocks, SSA, and range
analysis. The same effect could be seen on `cpp/bad-strncpy-size`, which
also uses the GVN library.
2019-11-22 08:45:49 +01:00
Robert Marsh
a5e6b83dbd Merge pull request #2400 from jbj/1.23-changenote
C++: Tweak 1.23 change note
2019-11-21 13:53:28 -08:00
Dave Bartolomeo
fb67d3eae4 C++: Fix override errors in MagicDraw.qll 2019-11-21 13:18:45 -07:00
Dave Bartolomeo
27cc6b1e4f C++/C#: Fix compilation error in PrintSSA.qll
We were privately importing `semmle.code.<lang>.ir.internal.Overlap`, but `PrintSSA.qll` was depending on it being public. This is made a little more complicated by the presence of cross-langage pyrameterized modules.
2019-11-21 13:18:25 -07:00
James Fletcher
0b274e5b23 Merge pull request #2386 from shati-patel/docs/demos
QL docs: Update links to blog/demos
2019-11-21 13:53:05 +00:00
Jonas Jensen
f98cd673fd C++: Autoformat 2019-11-21 14:02:53 +01:00
Jonas Jensen
7f26f078eb C++: Fix isFromMacroDefinition join order
This fixes the performance of `SignedOverflowCheck.ql` on
jluttine/suitesparse.
2019-11-21 11:01:50 +01:00
Jonas Jensen
82499b035b C++: Use isFromMacroDefinition for exclusion
The `SignedOverflowCheck.ql` query was very slow on certain snapshots
(jluttine/suitesparse and Chromium) due to bad magic in
`MacroInvocation::getAnAffectedElement_dispred#fb`. This commit doesn't
fix the bad magic but changes the exclusion mechanism to use a predicate
where we can better control the magic and optimization.

The query should also give more good results due to this new exclusion
mechanism, which is the same one used in its sibling,
`PointerOverflow.ql`.
2019-11-21 10:40:36 +01:00
Robert Marsh
15f50e6a38 Update docs/language/learn-ql/cpp/dataflow.rst
Co-Authored-By: James Fletcher <42464962+jf205@users.noreply.github.com>
2019-11-20 15:44:29 -08:00
Jonas Jensen
6616eb852e C++: Mention flow through fields 2019-11-20 16:25:13 +01:00
Jonas Jensen
4ad8995440 C++: Group all the 1.23 data flow changes 2019-11-20 15:34:49 +01:00
Jonas Jensen
a48f347db9 C++: Don't mention predicate hasStdName
This predicate was removed before #1585 was merged, but we forgot to
remove it from the change note.
2019-11-20 15:33:32 +01:00
Robert Marsh
53709deb9d Merge pull request #2342 from jbj/overflow-doc-fixes
C++: Signed Overflow Check qhelp improvements
2019-11-19 15:37:52 -08:00
Shati Patel
49c2398bda QL docs: Update links to blog/demos 2019-11-19 15:06:26 +00:00
Jonas Jensen
466f7fe6b2 C++: Use <ol> for recommendations 2019-11-19 12:57:02 +01:00
James Fletcher
c73ae5399d Merge pull request #2380 from shati-patel/docs/blog-links
Docs: Update links from blog to security lab
2019-11-19 11:09:13 +00:00
Shati Patel
820a11294d Docs: Update links from blog to security lab 2019-11-19 10:54:19 +00:00
yh-semmle
3d837542e8 Merge pull request #2373 from aschackmull/java/changenote-update
Java: Update change note to cover #2304 and #2346.
2019-11-18 12:14:07 -05:00
James Fletcher
e6574cc259 Merge pull request #2370 from shati-patel/docs/readme
Docs: Update readme in docs folder (cherry-pick from master)
2019-11-18 12:29:41 +00:00
Anders Schack-Mulligen
645cc99383 Java: Update change note to cover #2304 and #2346. 2019-11-18 13:26:50 +01:00
semmle-qlci
34f4b11416 Merge pull request #2368 from asger-semmle/regexp-max-length
Approved by max-schaefer
2019-11-18 11:49:46 +00:00
James Fletcher
21832a8550 Merge pull request #2350 from shati-patel/docs/vscode
Docs: Update links to new products
2019-11-18 11:14:53 +00:00
shati-patel
08c91b05ac Docs: Update readme in docs folder 2019-11-18 09:38:53 +00:00
Shati Patel
d6a673c91a Docs: Update links to new products 2019-11-18 09:34:00 +00:00
Asger F
c02863842c JS: Raise limit to 1000 2019-11-18 08:33:26 +00:00
Jonas Jensen
74ca0e428d Merge pull request #2334 from rdmarsh2/rdmarsh/cpp/reword-pointeroverflow-qhelp
C++: simplify PointerOverflow.qhelp
2019-11-18 08:37:19 +01:00
Asger F
6f15eff954 JS: Cap length of extracted string 2019-11-17 23:06:47 +00:00
shati-patel
e7705b0a1a Merge pull request #2348 from hmakholm/pr/point-to-vsc
README.md: Don't speak of QL4E anymore
2019-11-15 20:24:17 +00:00
Robert Marsh
85314c42a9 Update cpp/ql/src/Likely Bugs/Memory Management/PointerOverflow.qhelp
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-15 10:38:58 -08:00
Henning Makholm
3e9757caf6 Update README.md
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-11-15 19:31:07 +01:00
Erik Krogh Kristensen
ddd217628f Merge pull request #2347 from esbena/js/fix-mjs-check
JS: fix the check for an "mjs" extension on an extensionless file
2019-11-15 17:39:10 +01:00
Tom Hvitved
c95db9e6f8 Merge pull request #2331 from calumgrant/cs/default-interface-methods
C#: Tests for default interface methods
2019-11-15 16:36:47 +01:00
Henning Makholm
a44c004ca3 README.md: Don't speak of QL4E anymore 2019-11-15 16:30:36 +01:00
yh-semmle
810a046428 Merge pull request #2346 from aschackmull/java/rangeanalysis-integral-fix2
Java: Fix range analysis bug where int was assumed.
2019-11-15 09:54:48 -05:00
Calum Grant
f5598db070 Merge pull request #2343 from hvitved/csharp/dataflow/assignment-flow
C#: Add missing assignment data flow steps
2019-11-15 14:21:13 +00:00
Anders Schack-Mulligen
81a90943c0 Java: Fix range analysis bug where int was assumed. 2019-11-15 15:08:14 +01:00
Taus
78109db243 Merge pull request #2181 from RasmusWL/python-modernise-pyramid-library
Python: modernise pyramid library
2019-11-15 15:05:44 +01:00
Taus
cb94e7db72 Merge pull request #2140 from RasmusWL/python-fix-flask
Python: Modernise flask + correctly handle flask.make_response
2019-11-15 14:55:27 +01:00
Esben Sparre Andreasen
8e8215893f JS: fix mjs check for extensionless files 2019-11-15 14:38:27 +01:00
Erik Krogh Kristensen
f813e06680 Merge pull request #2345 from Semmle/esbena-patch-3
Update FlowSteps.qll
2019-11-15 14:04:14 +01:00
semmle-qlci
2f63b89941 Merge pull request #2338 from esbena/js/model-get-them-args
Approved by max-schaefer
2019-11-15 11:50:45 +00:00
Max Schaefer
217eda374d Merge pull request #2252 from asger-semmle/regexp
JS: Parse regular expressions from string literals
2019-11-15 11:47:33 +00:00
Esben Sparre Andreasen
a3deb7d4e0 Update FlowSteps.qll 2019-11-15 12:44:04 +01:00
Tom Hvitved
f9bff172d4 C#: Add missing assignment data flow steps 2019-11-15 11:36:05 +01:00
Tom Hvitved
f8791c884f C#: Add more data flow tests for assignments 2019-11-15 11:30:40 +01:00
Jonas Jensen
7d7d166113 C++: Remove whitespace at end of line 2019-11-15 11:21:08 +01:00
Jonas Jensen
6bdfebea96 C++: Rename i to n1 in all examples
I see no reason why the Recommendation and Example sections should use
different variable names for the same thing.
2019-11-15 11:20:00 +01:00
Jonas Jensen
9b89602a86 C++: Make var name in qhelp match source snippet 2019-11-15 11:16:34 +01:00
Calum Grant
aac360463b C#: Tests for default interface methods. 2019-11-15 10:13:04 +00:00
Jonas Jensen
7485cc76b2 C++: Edit Recommendation section
1. The two last examples were misleading at best. The first of those two
   recommended casting to non-negative `int`s to `unsigned int` and then
   checking if their addition would overflow, but overflow was
   impossible because their sum (on 32-bit two's complement) could be at
   most 2^32 - 2. The second example could lead to the wrong condition
   (unsigned overflow) being checked if taken literally. Instead of
   keeping that example, I reworeded the first paragraph of the
   Recommendation section.
2. The assumptions about `delta` being positive was relaxed to
   non-negative.
3. There was no need to assume that an unsigned short was non-negative.
4. Some of the suggestions were missing `i >`.
2019-11-15 11:05:00 +01:00
Esben Sparre Andreasen
a6dbf5fbad Update change-notes/1.23/analysis-javascript.md
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-15 10:43:04 +01:00
Esben Sparre Andreasen
c3fdfdecab JS: rename DefaultParsedCommandLineArgumentsAsSource 2019-11-15 10:40:15 +01:00
Asger F
7a489afdda JS: Add change note 2019-11-15 09:27:21 +00:00
Asger F
66db38266b JS: Add qldoc to HostnameRegexpShared 2019-11-15 09:27:21 +00:00
Asger F
6809eed543 JS: Stats and upgrade script 2019-11-15 09:27:21 +00:00
Asger F
607aed37ee Update javascript/ql/src/semmle/javascript/Expr.qll
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-15 09:27:21 +00:00
Asger F
77e5305b9b Update javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.ql
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-15 09:27:21 +00:00
Asger F
37aa85fe81 JS: Fix parsing of non-BMP chars before a quantifier 2019-11-15 09:27:21 +00:00
Asger F
8fcf7a265a JS: Remove unused OffsetTranslationBuilder class 2019-11-15 09:27:21 +00:00
Asger F
4d1f7836f2 JS: Check for [^.] 2019-11-15 09:27:21 +00:00
Asger F
a7a90b4b7e JS: Disregard capture groups in lookaround assertions 2019-11-15 09:27:20 +00:00
Asger F
2242df920f JS: More qldoc 2019-11-15 09:27:20 +00:00
Asger F
dc6c15cbb9 Update javascript/ql/src/semmle/javascript/Regexp.qll
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-15 09:27:20 +00:00
Asger F
dd9274e42c JS: Docs regarding regexp terms in string literals 2019-11-15 09:27:20 +00:00
Asger F
c2e0c8cb39 JS: Do not extract string literal types as regexps 2019-11-15 09:27:20 +00:00
Asger F
57a9cad721 JS: Fix offsets of octal and unicode escape 2019-11-15 09:27:20 +00:00
Asger F
4680e3a89a JS: Simplify charpred of Match 2019-11-15 09:27:20 +00:00
Asger F
c01005a610 JS: Remove outdated comment 2019-11-15 09:27:20 +00:00
Asger F
e01a9846d8 JS: Update test annotations 2019-11-15 09:27:20 +00:00
Asger F
153d34638b JS: Fix a FP 2019-11-15 09:27:20 +00:00
Asger F
8c5b9b9195 JS: Add missing post-anchor case to MissingRegExpAnchor 2019-11-15 09:27:20 +00:00
Asger F
17ad97812e JS: Fix FPs from TLDs without a domain name 2019-11-15 09:27:20 +00:00
Asger F
20fb7717d8 JS: Use type inference to refine regexp string tracking 2019-11-15 09:27:20 +00:00
Asger F
e45c361d64 JS: Port IncompleteHostnameRegExp 2019-11-15 09:27:20 +00:00
Asger F
9ecab1b5d5 JS: Port unanchored RegExp query but for hostnames only 2019-11-15 09:27:20 +00:00
Asger F
e5f2f9e43e JS: Do not flag semi-anchored regexps in .replace() 2019-11-15 09:27:20 +00:00
Asger F
cae09a447b JS: Update test case 2019-11-15 09:27:20 +00:00
Asger F
3e37950170 JS: Whitelist one more FP case 2019-11-15 09:27:20 +00:00
Asger F
2b151cd587 JS: Include anchor direction in message 2019-11-15 09:27:20 +00:00
Asger F
3e952cf564 JS: Restrict semi-anchored regex query more 2019-11-15 09:27:19 +00:00
Asger F
0726bd8cac JS: Add double semi-anchored test case 2019-11-15 09:27:19 +00:00
Asger F
9fa9729470 JS: Shift line numbers in SemiAnchoredRegExp testcase 2019-11-15 09:27:19 +00:00
Asger F
8bc89ee254 JS: Update semi-anchored regex query 2019-11-15 09:27:19 +00:00
Asger F
c21d095d38 JS: Restrict RegExp queries to actual regular expressions 2019-11-15 09:27:19 +00:00
Asger F
b8711fc642 JS: Extend RegExpTerm in ReDoS 2019-11-15 09:27:19 +00:00
Asger F
b6c1c174a9 JS: Deabstractify RegExpTerm classes 2019-11-15 09:27:19 +00:00
Asger F
e0bdc777b9 JS: Make ReDoS check string-based regexes 2019-11-15 09:27:19 +00:00
Asger F
97e5da1046 JS: Update ReDoS query 2019-11-15 09:27:19 +00:00
Asger F
57de6382cd JS: Update QL API 2019-11-15 09:27:19 +00:00
Asger F
d3302c39c0 JS: Fix offsets in regexes parsed from strings with escapes 2019-11-15 09:27:19 +00:00
Asger F
2901b5e8bd JS: Add OffsetTranslation table (preserving behavior) 2019-11-15 09:27:19 +00:00
Asger F
c327ee5d4f JS: Update TRAP 2019-11-15 09:27:19 +00:00
Asger F
591fffc5cc JS: Add test case for wide constants in char class 2019-11-15 09:27:19 +00:00
Asger F
68d23bcf8c JS: Extract surrogate pairs as one constant node 2019-11-15 09:27:19 +00:00
Asger F
6e1c995f2f JS: Merge consecutive constants in RegExps 2019-11-15 09:27:19 +00:00
Asger F
0e1246c0e5 JS: Extract RegExp ASTs from string literals 2019-11-15 09:27:18 +00:00
Asger F
0cf191f70d JS: Bump extractor version string 2019-11-15 09:27:18 +00:00
Jonas Jensen
73d9cc2e7b Merge pull request #2309 from geoffw0/cpp418
CPP: QLDoc enhancements
2019-11-15 08:46:08 +01:00
Esben Sparre Andreasen
8e6a19b3d3 JS: add DefaultParsedCommandLineArgumentsAsSource 2019-11-15 08:42:02 +01:00
Tom Hvitved
74b464ded9 Merge pull request #2321 from calumgrant/cs/netcore-3.0b
C#: Upgrade extractor to .NET Core 3.0
2019-11-15 06:21:17 +01:00
Robert Marsh
562f62879f C++: rename variables in PointerOverflow examples 2019-11-14 15:21:26 -08:00
Robert Marsh
c6d848caf9 C++: simplify PointerOverflow.qhelp 2019-11-14 15:11:39 -08:00
Robert Marsh
dad1c96902 Docs: reword description of isSanitizer example 2019-11-14 14:54:37 -08:00
Dave Bartolomeo
81262d5948 Merge pull request #2328 from geoffw0/routinetest
CPP: Add a quick test of RoutineType.
2019-11-14 15:49:13 -07:00
Esben Sparre Andreasen
2ea7d141c8 Merge pull request #2310 from max-schaefer/js/insufficient-url-scheme-check
JavaScript: Add query `IncompleteUrlSchemeCheck`
2019-11-14 22:13:02 +01:00
semmle-qlci
0638907825 Merge pull request #2324 from esbena/js/torrent-as-remote-source
Approved by max-schaefer
2019-11-14 20:28:07 +00:00
Calum Grant
f3c92c5527 C#: Address review comment 2019-11-14 17:14:51 +00:00
Calum Grant
09356a377f C#: Improved CIL instruction types to pass type consistency checks 2019-11-14 17:14:51 +00:00
Calum Grant
051dd6b3dc C#: Update qltests. 2019-11-14 17:14:51 +00:00
Calum Grant
a2e0ae1e79 C#: Update project files to netcoreapp3.0 2019-11-14 17:14:51 +00:00
Max Schaefer
3b1e6c362c JavaScript: Address review comments. 2019-11-14 17:11:59 +00:00
Geoffrey White
7408726f41 Merge pull request #2312 from jbj/pointer-wraparound-query
C++: New query: Pointer overflow check
2019-11-14 16:13:04 +00:00
Taus
d5edb651e1 Merge pull request #2329 from RasmusWL/python-codeowners
CODEOWNERS: Add python team
2019-11-14 17:00:46 +01:00
Rasmus Wriedt Larsen
54f89c8eda CODEOWNERS: Add python team
(and reorder cpp, so it all follows the same pattern)
2019-11-14 16:42:12 +01:00
Geoffrey White
f2b7af7437 CPP: Add example code for RoutineType. 2019-11-14 15:25:00 +00:00
Geoffrey White
dc34fa366c CPP: Add a test of RoutineType. 2019-11-14 15:13:52 +00:00
James Fletcher
4b35d35eed Merge pull request #2326 from shati-patel/docs/snapshot
Docs: Use "database" consistently
2019-11-14 14:05:03 +00:00
Henning Makholm
e46d9158db Merge pull request #2314 from Semmle/lgtm.com
Mergback lgtm.com branch into master
2019-11-14 14:55:26 +01:00
Jonas Jensen
c35229f062 Merge pull request #2327 from nickrolfe/missing_backtick
C++: add missing backtick in qldoc comment
2019-11-14 14:40:12 +01:00
Nick Rolfe
f5513342d6 C++: add missing backtick in qldoc comment 2019-11-14 13:20:41 +00:00
Shati Patel
f64633b2fe Docs: Use "database" 2019-11-14 13:11:40 +00:00
Esben Sparre Andreasen
cc768345d0 JS: add security tests for malicious torrents 2019-11-14 13:54:19 +01:00
Esben Sparre Andreasen
bea59ec8ad JS: add some parsed torrent properties as remote flow sources 2019-11-14 13:54:19 +01:00
Geoffrey White
beb3602253 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:49:02 +00:00
Geoffrey White
6724632413 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:48:50 +00:00
Rasmus Wriedt Larsen
1159344972 Merge pull request #2320 from tausbn/python-add-walrus-support
Python: Add AST classes for walrus operator.
2019-11-14 13:48:05 +01:00
Geoffrey White
45cc6c445c Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:48:05 +00:00
Geoffrey White
0bb37c17f2 CPP: Delete parenthesized comment. 2019-11-14 12:46:43 +00:00
James Fletcher
f085b81e51 Merge pull request #2323 from shati-patel/docs/rename
Docs: Tidy up links in relevant topics
2019-11-14 12:44:54 +00:00
Geoffrey White
8b30baf656 CPP: Delete 'compiler-generated'. 2019-11-14 12:43:54 +00:00
Geoffrey White
f96cffa1f3 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:41:10 +00:00
Geoffrey White
82c6ff02b2 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:40:53 +00:00
Geoffrey White
6262cee27d Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:40:41 +00:00
Geoffrey White
fe5bd42203 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:40:29 +00:00
Geoffrey White
d8aeedfe01 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:40:11 +00:00
Geoffrey White
877e9ba6d8 Update cpp/ql/src/semmle/code/cpp/exprs/BuiltInOperations.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:39:54 +00:00
Geoffrey White
acefadda8c Update cpp/ql/src/semmle/code/cpp/exprs/Assignment.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:35:15 +00:00
Geoffrey White
b1dfc60422 Update cpp/ql/src/semmle/code/cpp/exprs/Cast.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 12:34:13 +00:00
Shati Patel
557b95ccb1 Docs: Tidy up links in relevant topics 2019-11-14 12:32:21 +00:00
Anders Schack-Mulligen
6a2edce040 Merge pull request #2205 from rneatherway/java/hamcrest-nullness
Java: Respect Hamcrest assertThat(X, notNullValue())
2019-11-14 13:09:56 +01:00
Jonas Jensen
c7176e50ca C++: Tweak wording in docs 2019-11-14 13:03:34 +01:00
James Fletcher
2eaf91e1fb Merge pull request #2322 from shati-patel/docs/typo
Docs: Typo fix
2019-11-14 11:56:39 +00:00
Shati Patel
3cdaef7211 Docs: Typo fix 2019-11-14 11:50:43 +00:00
Geoffrey White
79a000d88f Update cpp/ql/src/semmle/code/cpp/exprs/Expr.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:31:27 +00:00
Geoffrey White
0f2a2cb956 Update cpp/ql/src/semmle/code/cpp/exprs/Expr.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:31:01 +00:00
Geoffrey White
25db90021b Update cpp/ql/src/semmle/code/cpp/exprs/Expr.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:29:03 +00:00
Geoffrey White
01b25199d0 CPP: Lesser than -> Less than. 2019-11-14 11:27:15 +00:00
Geoffrey White
238918c394 Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:24:54 +00:00
Geoffrey White
b3bda421bc Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:24:15 +00:00
Geoffrey White
90909d211c Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:24:00 +00:00
Geoffrey White
7d2babd9db Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:22:16 +00:00
Geoffrey White
97559857bf Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-14 11:22:07 +00:00
Taus Brock-Nannestad
dcffd1dbc3 Python: Add AST classes for walrus operator.
Happily, these were already present in the `dbscheme`.
2019-11-14 12:10:04 +01:00
Jonas Jensen
931b0f1445 Apply suggestions from code review
Co-Authored-By: Alistair <54933897+hubwriter@users.noreply.github.com>
2019-11-14 12:06:02 +01:00
Tom Hvitved
94583cde10 Merge pull request #2245 from calumgrant/cs/nullability-refactor
C#: Store nullability on the side
2019-11-14 11:44:39 +01:00
Calum Grant
7c406861a0 Merge pull request #2317 from dave-bartolomeo/dbartol/QLPack
Port QLPack changes to enable IntelliSense and Go to Definition
2019-11-14 10:25:14 +00:00
semmle-qlci
67963a5b9d Merge pull request #2258 from asger-semmle/js-ignore-codesql-databases
Approved by esbena
2019-11-14 08:34:23 +00:00
Robert Marsh
f0b2aace1a C++/Docs: add isAdditionalTaintStep to example 2019-11-13 14:04:55 -08:00
Dave Bartolomeo
08620046ab Merge pull request #2068 from rdmarsh2/rdmarsh/cpp/ir-constructor-side-effects
C++: side effect instrs for constructor qualifiers
2019-11-13 14:56:24 -07:00
Robert Marsh
9e8455406f C++/Docs: add example based on NtohlArrayNoBound 2019-11-13 13:17:44 -08:00
Dave Bartolomeo
c2313cbe12 Add QL test directories to .codeqlmanifest.json 2019-11-13 13:31:46 -07:00
Max Schaefer
f93dab4864 Add qlpack.yml files for test folders. 2019-11-13 13:31:34 -07:00
Dave Bartolomeo
55010d030d Merge pull request #2315 from geoffw0/errtest
CPP: Add a quick test of ErroneousType.
2019-11-13 13:24:39 -07:00
Henning Makholm
e1467a77e8 Merge pull request #2316 from dave-bartolomeo/dbartol/TestManifests
Add QL test directories to `.codeqlmanifest.json`
2019-11-13 20:58:59 +01:00
Dave Bartolomeo
dd0f04b949 Add QL test directories to .codeqlmanifest.json 2019-11-13 12:37:51 -07:00
Dave Bartolomeo
e89ecc19e3 Merge pull request #2302 from max-schaefer/test-qlpacks
Add `qlpack.yml` files for test folders.
2019-11-13 12:21:19 -07:00
Robert Marsh
0175c44a14 C#: update IR test expectations 2019-11-13 10:58:38 -08:00
Geoffrey White
32b5501177 CPP: Add a test of ErroneousType. 2019-11-13 18:53:43 +00:00
semmle-qlci
252e1c76a6 Merge pull request #2313 from erik-krogh/quickFixreflectiveCallNode
Approved by max-schaefer
2019-11-13 17:00:38 +00:00
Geoffrey White
44ffb600d6 CPP: Improve the UnknwonType example as suggested. 2019-11-13 16:55:32 +00:00
Geoffrey White
2b73af09e4 CPP: Consistency. 2019-11-13 16:39:51 +00:00
Geoffrey White
e72bf2d35e CPP: *lvalue* -> _lvalue_ and similar. 2019-11-13 16:36:18 +00:00
Geoffrey White
e883220de3 CPP: Remove other comments about equivalence. 2019-11-13 16:28:50 +00:00
Jonas Jensen
81d06e2ce6 C++: Update annotation in test file 2019-11-13 16:58:25 +01:00
Geoffrey White
5e15265b50 Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-13 15:53:34 +00:00
Geoffrey White
da6fa7adfc Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-13 15:52:49 +00:00
Geoffrey White
4c6fd004e6 Update cpp/ql/src/semmle/code/cpp/Type.qll
Co-Authored-By: Jonas Jensen <jbj@github.com>
2019-11-13 15:52:15 +00:00
Calum Grant
38f82d8377 Merge remote-tracking branch 'upstream/master' into cs/nullability-refactor 2019-11-13 15:31:45 +00:00
Tom Hvitved
46bc804562 Merge pull request #2286 from calumgrant/cs/windows-tests
C#: Make qltests pass on all platforms
2019-11-13 16:21:08 +01:00
Calum Grant
6e24a92179 Merge remote-tracking branch 'upstream/master' into cs/nullability-refactor 2019-11-13 14:58:58 +00:00
Erik Krogh Kristensen
538690eee6 remove duplicate reflectiveCallNode method, and removing redundant getExpr() method 2019-11-13 15:53:21 +01:00
Calum Grant
18d6138320 C#: Address review comment. 2019-11-13 14:47:06 +00:00
Henning Makholm
b78d081973 Merge pull request #2311 from alexet/fix-suite
Suites: Fix suite definition.
2019-11-13 14:56:08 +01:00
Jonas Jensen
4ddac749af C++: Add change note
Also fix discrepancies between `SignedOverflowCheck.ql` and its change
note.
2019-11-13 14:43:30 +01:00
Jonas Jensen
2d72a9cdec C++: Rename query
This new name is similar to its sister query "Signed overflow check".
2019-11-13 14:40:27 +01:00
Jonas Jensen
1b849dbf0e C++: More principled macro exclusion
We no longer exclude macros based on their name, which means we can now
find results inside arguments to the `likely` macro in Linux (except
that Linux is compiled with `-fno-strict-overflow`).
2019-11-13 14:22:38 +01:00
Jonas Jensen
db33053422 C++: Add test for macro exclusions 2019-11-13 14:21:29 +01:00
semmle-qlci
b11a7427c2 Merge pull request #2270 from erik-krogh/reflectiveExpr
Approved by max-schaefer
2019-11-13 13:08:40 +00:00
Jonas Jensen
8d79634f8c C++: Factor out isFromMacroDefinition predicate
This trick for excluding elements from macro bodies but not macro
arguments looks promising and should probably be used much more. With
this commit, it's now easy to use from any query.

Performance is still good because the new predicate gets appropriately
magiced.
2019-11-13 14:07:33 +01:00
Jonas Jensen
d2009c53dc C++: Support GCC flags making ptr overflow defined 2019-11-13 14:07:33 +01:00
Jonas Jensen
463bf964a9 C++: Test showing FP with -fno-strict-overflow 2019-11-13 14:07:33 +01:00
Jonas Jensen
8ed991759c C++: Rename PointerWrapAround to PointerOverflow
Overflow was the terminology I found for this in the C standard (C11
6.5.6-8).
2019-11-13 14:06:58 +01:00
Jonas Jensen
bd08c64933 C++: Apply my own review comments from #2218 2019-11-13 14:05:23 +01:00
Geoffrey White
abcf9e0d78 CPP: Autoformat. 2019-11-13 12:35:26 +00:00
Geoffrey White
86bea78413 CPP: Fix bad merge. 2019-11-13 12:34:35 +00:00
Tom Hvitved
9c9744620e Merge pull request #2291 from calumgrant/cs/assembly-prefix
C#: Fix prefixing assembly IDs to type IDs
2019-11-13 13:25:15 +01:00
Max Schaefer
f804d316d7 Update javascript/ql/src/Security/CWE-020/IncompleteUrlSchemeCheck.ql
Co-Authored-By: Esben Sparre Andreasen <esbena@github.com>
2019-11-13 12:24:19 +00:00
Calum Grant
b65ab15d46 C#: Delete unused file. 2019-11-13 12:16:05 +00:00
alexet
2570f81aa7 Suites: Fix suite definition. 2019-11-13 12:03:13 +00:00
Geoffrey White
93b4985532 CPP: Backticks. 2019-11-13 10:42:28 +00:00
Max Schaefer
4fe09e8e73 JavaScript: Sort new query change notes alphabetically. 2019-11-13 10:27:18 +00:00
Max Schaefer
ab583b7994 JavaScript: Add query IncompleteUrlSchemeCheck.ql. 2019-11-13 10:27:18 +00:00
Calum Grant
3b775a9ecb Merge pull request #2095 from hvitved/csharp/type-unification
C#: Type unification library
2019-11-13 09:48:59 +00:00
Geoffrey White
a5d2fbd25d CPP: Resolve remaining comments from the original PR. 2019-11-13 09:46:09 +00:00
semmle-qlci
f34025c5a0 Merge pull request #2306 from Semmle/revert-2247-odasa-8149
Approved by asger-semmle
2019-11-13 09:04:22 +00:00
Jonas Jensen
8a9ee8fcdd Merge pull request #2300 from geoffw0/names
CPP: Rename/relocate some queries and libraries
2019-11-13 09:11:24 +01:00
Max Schaefer
155cea7b5b Revert "JavaScript: Improve double-escaping query" 2019-11-12 22:54:12 +00:00
Robert Marsh
3de590763e C++: autoformat 2019-11-12 13:57:49 -08:00
yh-semmle
429c307832 Merge pull request #2304 from aschackmull/java/rangeanalysis-integral-fix
Java: Fix range analysis bug in integral inequality bounds.
2019-11-12 16:33:12 -05:00
yh-semmle
6a16eb838d Merge pull request #2305 from aschackmull/java/overflowcheck-conditionalexpr
Java: Add ConditionalExpr to overflow candidate pattern.
2019-11-12 16:32:09 -05:00
Dave Bartolomeo
5b33255e44 Merge pull request #1585 from rdmarsh2/rdmarsh/cpp/hasGlobalOrStdName
C++: add Declaration.hasGlobalOrStdName()
2019-11-12 12:00:17 -07:00
Robert Marsh
47f87c214c Merge branch 'master' into rdmarsh/cpp/ir-constructor-side-effects 2019-11-12 10:31:04 -08:00
Geoffrey White
db26b85fa3 CPP: Fix test (I missed a file in the move). 2019-11-12 18:25:20 +00:00
Robert Marsh
9554513cd6 autoformat 2019-11-12 10:16:01 -08:00
Ziemowit Laski
5cc92b7502 [CPP-418] Mention that GNU vector initializers are syntactically
similar to array initializers.
2019-11-12 17:35:50 +00:00
Ziemowit Laski
d0069fcacd [CPP-418] Literals. 2019-11-12 17:35:50 +00:00
Ziemowit Laski
20e28b8a97 [CPP-418] Reformat. 2019-11-12 17:35:50 +00:00
Ziemowit Laski
2baa748390 Address further review comments. 2019-11-12 17:35:50 +00:00
Ziemowit Laski
faf4342d8e [CPP-418] Update references to BuiltInOperationBuiltInOffsetOf and __builtin_offsetof. 2019-11-12 17:35:50 +00:00
Ziemowit Laski
6eac51dba4 [CPP-418] Address review comments. 2019-11-12 17:35:49 +00:00
Ziemowit Laski
e2d5a82735 [CPP-418] Expressions. 2019-11-12 17:35:49 +00:00
Ziemowit Laski
1f337e943f [CPP-418] Typo. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
98eca4743a [CPP-418] Calls, casts, assignments and other goodness. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
e647dc341a [CPP-418] Fill in examples for ErroneousType, UnknownType, and
assorted complex/imaginary arithmetic operations.
2019-11-12 17:33:08 +00:00
Ziemowit Laski
09f538a4bf [CPP-418] Merge detritus. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
f255977027 [CPP-418] Some more complex numbers, vectors. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
89655612b0 [CPP-418] Tweak vector initializer syntax. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
ecb700c8f4 [CPP-418] Some assignments and call expressions. Some could not be divined. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
113481d096 [CPP-418] Add concrete syntax for arithmetic operation, EXCEPT for assorted complex number operations, where surface syntax could not be determined. 2019-11-12 17:33:08 +00:00
Ziemowit Laski
e328e781b5 [CPP-418] Address @geoffw0's review comments. 2019-11-12 17:33:07 +00:00
Ziemowit Laski
3fdf84ddb4 [CPP-418] Logical and comparison operators; reformat built-ins. 2019-11-12 17:33:07 +00:00
Ziemowit Laski
b0a93481cb [CPP-418] Add QLDoc entries for typedef types, user types, bitwise operations and built-in operations. 2019-11-12 17:33:07 +00:00
semmle-qlci
6c9f92666e Merge pull request #2285 from asger-semmle/dataflow-syntax-examples
Approved by max-schaefer
2019-11-12 16:50:29 +00:00
Ziemowit Laski
1f35f4bb52 [CPP-418] Add descriptions for QL classes in Type.qll. (Still need to figure out how to describe unknown and erroneous types.) 2019-11-12 16:47:29 +00:00
Ziemowit Laski
f54e0d0d07 [CPP-418] Initial modifications to Type.qll. To be continued. 2019-11-12 16:47:29 +00:00
Anders Schack-Mulligen
7619275c8b Java: Fix range analysis bug in integral inequality bounds. 2019-11-12 17:28:40 +01:00
Anders Schack-Mulligen
8cd6b51763 Java: Add ConditionalExpr to overflow candidate pattern. 2019-11-12 17:27:18 +01:00
Geoffrey White
ea9e3bb1a8 CPP: Rename VirtualDispatch again. 2019-11-12 16:17:03 +00:00
Max Schaefer
5b2e32b051 Add qlpack.yml files for test folders. 2019-11-12 15:03:02 +00:00
Geoffrey White
5c87ed5ab2 CPP: Remove unused code. 2019-11-12 14:45:43 +00:00
Geoffrey White
0343bd6b9c CPP: Inline BufferAccess into NtohlArrayNoBound.qll (we'd prefer other queries to be written with the models library or Security.BufferAccess). 2019-11-12 14:44:20 +00:00
Geoffrey White
f50dd84c49 CPP: Rename good and bad example files. 2019-11-12 14:09:54 +00:00
Calum Grant
e990bea248 C#: Update upgrade script 2019-11-12 13:40:58 +00:00
Calum Grant
7c21ebb526 C#: Change dbscheme from nullability_member to nullability_parent 2019-11-12 13:40:58 +00:00
Calum Grant
41b441614b C#: Address review comments part 1. 2019-11-12 13:40:58 +00:00
Calum Grant
fe83bac0fb C#: Fix up test output
C#: Fix a qltest whereby a tuple type having multiple underlying types was causing an issue with the IR sanity checks.
C#: Revert more changes.
C#: Fix tests and remove dead code.
2019-11-12 13:40:58 +00:00
Calum Grant
a261cbaeef C#: Fix type ID generation from merge 2019-11-12 13:40:58 +00:00
Calum Grant
ce188c0c22 C#: Autoformat 2019-11-12 13:40:58 +00:00
Calum Grant
4d13957eed C#: Modify db upgrade script 2019-11-12 13:40:58 +00:00
Calum Grant
657c839e2b C#: Change varchar to string in the dbscheme. 2019-11-12 13:40:58 +00:00
Calum Grant
61630118fe C#: Fix ql tests. 2019-11-12 13:40:58 +00:00
Calum Grant
58e14af9cd C#: Address review comments. Create a TNullability type annotation and restructure TAnnotation. 2019-11-12 13:40:58 +00:00
Calum Grant
f00276a82c C#: Remove non-essential changes 2019-11-12 13:40:58 +00:00
Calum Grant
a0fa7dad79 C#: Autoformat 2019-11-12 13:40:58 +00:00
Calum Grant
c8225adf1b C#: Add missing file & minor fixes. 2019-11-12 13:40:58 +00:00
Calum Grant
e7f5fd6b4b C#: DB upgrade script 2019-11-12 13:40:58 +00:00
Calum Grant
163b931d49 C#: Update db stats 2019-11-12 13:40:58 +00:00
Calum Grant
9fd4a9ceb6 C#: Implement NullabilityEntity to model structured nullability on the side 2019-11-12 13:40:57 +00:00
Calum Grant
61ab9431ab C#: Fix DB inconsistencies, and rework id generation. 2019-11-12 13:40:57 +00:00
Tom Hvitved
05684b350f C#: Add change note 2019-11-12 12:13:19 +01:00
Tom Hvitved
28141c9d4d C#: Teach unification library about tuple types 2019-11-12 12:09:58 +01:00
Tom Hvitved
ee2496ab7c C#: Add unification tests for tuple types 2019-11-12 12:08:03 +01:00
semmle-qlci
39a45ceefe Merge pull request #2297 from erik-krogh/returnlessAttr
Approved by max-schaefer
2019-11-12 10:26:12 +00:00
Geoffrey White
d198b56b3a CPP: Move VirtualDispatch.qll into the controlflow directory (I don't see the point in having a subdirectory for one file, when we don't anticipate any other files ever being added there). 2019-11-12 09:55:23 +00:00
Geoffrey White
60c7cb38e8 CPP: Relocate the test as well. 2019-11-12 09:55:22 +00:00
Geoffrey White
dff490e658 CPP: Remove the 'boostorg' subdirectory (these queries could be extended to support other libraries, as their names and descriptions already suggest). 2019-11-12 09:55:22 +00:00
Geoffrey White
784c3047da CPP: Merge the duplicate IgnoreReturnValueSAL.ql query into the older existing one. 2019-11-12 09:54:56 +00:00
Geoffrey White
806703b929 CPP: Relocate the test as well. 2019-11-12 09:54:55 +00:00
Geoffrey White
2b9428df32 CPP: Remove the 'Buffer Overflow' subdirectory (we have many buffer overflow queries, putting one in a special directory will only create confusion). 2019-11-12 09:54:46 +00:00
Geoffrey White
b917264770 CPP: Rename NtohlArrayNoBoundOpenSource.ql -> NtohlArrayNoBound.ql (I believe the 'OpenSource' part is a remnant from the way the contributor organizes their queries). 2019-11-12 09:53:59 +00:00
Rasmus Wriedt Larsen
54246660c6 Python: Add test-case to password_in_cookie 2019-11-12 10:36:12 +01:00
Rasmus Wriedt Larsen
3ad43f32b6 Python: Add flask xss examples to flask tests 2019-11-12 10:36:10 +01:00
Jonas Jensen
18cc539c8d Merge branch 'master' into pointer-wraparound-query 2019-11-12 10:22:46 +01:00
Anders Schack-Mulligen
e6d0a2eca5 Merge pull request #2215 from yh-semmle/java-remove-obsolete-queries
Java: remove some obsolete metric queries
2019-11-12 10:14:55 +01:00
Jonas Jensen
c36b73f09c Merge pull request #2232 from geoffw0/formatsymbols
CPP: Fully support n$ in format strings
2019-11-12 09:43:20 +01:00
Erik Krogh Kristensen
6f6c4c4fcc fix tests after change from tabs to spaces 2019-11-12 08:48:01 +01:00
Dave Bartolomeo
303bab61b5 Merge pull request #2289 from jbj/ConvertToNonVirtualBaseInstruction
C++ IR: clearly distinguish between virtual and non-virtual base conversions
2019-11-11 13:37:07 -07:00
Rasmus Wriedt Larsen
8476bc7d42 Python: correctly handle flask.make_response
Fixes https://github.com/Semmle/ql/issues/1572

Adjust mock so it's more aligned with what the flask code actually does. Tests
were passing before, even though we didn't handle the case in real code :\
2019-11-11 17:24:36 +01:00
Rasmus Wriedt Larsen
002190f8db Python: Autoformat flask library 2019-11-11 17:18:26 +01:00
Rasmus Wriedt Larsen
a9d43a2c49 Python: Modernise flask library 2019-11-11 17:18:26 +01:00
Rasmus Wriedt Larsen
edfcf39137 Python: Add flask tests from internal repo 2019-11-11 17:18:26 +01:00
Jonas Jensen
ec79bfacf8 Merge pull request #2249 from geoffw0/tlsperf
CPP: TlsSettingsMisconfiguration.ql performance and cleanup
2019-11-11 16:47:53 +01:00
Geoffrey White
a4250be72f CPP: Un-deprecate getNumArgNeeded(n). Turns out I missed a place where it's used. 2019-11-11 15:28:09 +00:00
Geoffrey White
ed87f25886 CPP: Performance improvement. 2019-11-11 15:28:09 +00:00
Geoffrey White
695d4ff511 CPP: Change note. 2019-11-11 15:28:08 +00:00
Geoffrey White
a9fbe221ba CPP: Try to make the predicate names and qldoc a bit more consistent. 2019-11-11 15:27:23 +00:00
Geoffrey White
dff21e02db CPP: Fully support positional arguments. 2019-11-11 15:27:23 +00:00
Geoffrey White
2430bf4c83 CPP: Deprecate helper version of getNumArgNeeded. 2019-11-11 15:27:23 +00:00
Geoffrey White
27478640f2 CPP: Bring the logic for argument indices together in getFormatArgumentIndexFor. 2019-11-11 15:27:22 +00:00
Geoffrey White
760884051c CPP: Add test cases using various combinations of width and precision specifiers, positional arguments, and flags. 2019-11-11 15:27:22 +00:00
Jonas Jensen
f2a9876c2a Merge pull request #2003 from geoffw0/formatarg
CPP: WrongTypeFormatArguments.ql Fix
2019-11-11 16:07:37 +01:00
Jonas Jensen
d9bdb2cd4e Merge pull request #2274 from geoffw0/oddsends
CPP: Clean up new queries and libraries
2019-11-11 16:05:20 +01:00
Taus
e576395c90 Merge pull request #2241 from RasmusWL/python-always-legacy-conf
Python: Always enable legacy taint tracking configuration
2019-11-11 16:00:04 +01:00
Jonas Jensen
eb55d964a8 C++: Fix semantic merge conflict
This test output must have been wrong because I produced it with an
extractor that didn't have #2153 applied.
2019-11-11 15:39:53 +01:00
Erik Krogh Kristensen
67b38ed301 correctly weed out benign calls inside attributes 2019-11-11 15:30:33 +01:00
James Fletcher
c33d28542e Merge pull request #2294 from felicitymay/1.22-mergeback-master
1.22 mergeback master
2019-11-11 14:14:09 +00:00
Geoffrey White
e77fefaf9e Merge pull request #2295 from jbj/self-comparison-templates
C++: Suppress PointlessSelfComparison.ql on templates
2019-11-11 14:12:55 +00:00
Felicity Chapman
37c78bf1ea Fix poor conflict resolution in training slides 2019-11-11 13:11:28 +00:00
Jonas Jensen
97cc0ebc8c C++: Suppress PointlessSelfComparison on templates
It's a bit crude to suppress all results in instantiations, but we're
already using this kind of suppression in `PointlessComparison.ql`
(without the `Self`) because there is no convenient alternative. It
means we lose some good results but also suppress a new false positive
in Boost that surfaced after we added support for non-type template
parameters.
2019-11-11 14:00:00 +01:00
Jonas Jensen
281d512178 C++: Add tests for self-comparison template FP 2019-11-11 13:52:22 +01:00
Felicity Chapman
b3c3677cbf Merge branch 'rc/1.22' into 1.22-mergeback-master
Conflicts resolved in favour of master:
	docs/language/learn-ql/cpp/conversions-classes.rst
	docs/language/learn-ql/cpp/function-classes.rst
	docs/language/learn-ql/cpp/introduce-libraries-cpp.rst
	docs/language/learn-ql/csharp/ql-for-csharp.rst
	docs/language/learn-ql/javascript/introduce-libraries-ts.rst
	docs/language/learn-ql/python/introduce-libraries-python.rst
	docs/language/ql-training/cpp/bad-overflow-guard.rst
	docs/language/ql-training/cpp/control-flow-cpp.rst
	docs/language/ql-training/cpp/global-data-flow-cpp.rst
	docs/language/ql-training/cpp/intro-ql-cpp.rst
	docs/language/ql-training/cpp/program-representation-cpp.rst
	docs/language/ql-training/cpp/snprintf.rst
	docs/language/ql-training/index.rst
	docs/language/ql-training/java/global-data-flow-java.rst
	docs/language/ql-training/java/intro-ql-java.rst
	docs/language/ql-training/java/program-representation-java.rst
	docs/language/ql-training/java/query-injection-java.rst
2019-11-11 10:18:43 +00:00
Rasmus Wriedt Larsen
9151a7e433 Python: Always enable legacy taint tracking configuration
If the legacy configuration is only enabled if there are no other
configurations, defining a configuration in an imported library can lead to
unwanted results. For example, code that uses `any(MyTaintKind t).taints(node)`
would *stop* working, if it did not define its own configuration. (this actually
happened to us)

We performed a dist-compare to ensure there is not a performance deg ration by
doing this. Results at https://git.semmle.com/gist/rasmuswl/a1eca07f3a92f5f65ee78d733e5d260e

Tests that were affected by this:

- RockPaperScissors + Simple: new edges because no configuration was defined for
  SqlInjectionTaint or CommandInjectionTaint
- CleartextLogging + CleartextStorage: new edges because no configuration was
  defined before, AND duplicate deges.
- TestNode: new edges because no configuration was defined before

- PathInjection: Duplicate edges
- TarSlip: Duplicate edges
- CommandInjection: Duplicate edges
- ReflectedXss: Duplicate edges
- SqlInjection: Duplicate edges
- CodeInjection: Duplicate edges
- StackTraceExposure: Duplicate edges
- UnsafeDeserialization: Duplicate edges
- UrlRedirect: Duplicate edges
2019-11-11 11:17:21 +01:00
Anders Schack-Mulligen
b0fecbce28 Merge pull request #2230 from yh-semmle/java-move-cwe502-lib
Java: move `UnsafeDeserialization.qll` to standard library location
2019-11-11 10:44:52 +01:00
Felicity Chapman
c4f958d396 Merge pull request #2263 from sauyon/master
Update links to OWASP cheat sheet
2019-11-11 08:51:52 +00:00
Jonas Jensen
751263db91 C++: Use ConvertToBaseInstruction in IR data flow
This should make virtual dispatch work also for virtual bases.
2019-11-10 11:17:35 +01:00
Jonas Jensen
7758b43e34 C++: Add ConvertToBase{Opcode,Instruction} classes
These should make it easy to match base-class conversions when it's not
important whether the base class is virtual.
2019-11-10 11:09:54 +01:00
Jonas Jensen
279fc16b60 C++: ConvertToBase -> ConvertToNonVirtualBase
This rename was done with

    perl -p -i -e's/ConvertToBase/ConvertToNonVirtualBase/g' **/*.ql* **/*.expected

followed by re-running the affected tests.
2019-11-10 10:35:53 +01:00
James Fletcher
aa05908d19 Merge pull request #2287 from felicitymay/1.22/support-codeql
1.22: Update for support info for CodeQL term change
2019-11-09 22:07:34 +00:00
Felicity Chapman
25eb1d0cc9 Update for CodeQL term change and port nav changes 2019-11-09 14:36:35 +00:00
Jonas Jensen
f3e691b5ec Merge pull request #2075 from zlaski-semmle/zlaski/cpp434
[CPP-434] Detect signed overflow checks
2019-11-09 09:57:23 +01:00
Ziemowit Laski
7a4c4b62f6 [zlaski/pointer-overflow-check] Rename PointerOverflowCheck -> PointerWrapAround. 2019-11-08 14:54:20 -08:00
Ziemowit Laski
f2105867a8 [zlaski/pointer-overflow-check] Enhance qhelp and test case. 2019-11-08 14:36:33 -08:00
Robert Marsh
64b34ad975 Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/ir-constructor-side-effects 2019-11-08 14:06:36 -08:00
Robert Marsh
1dc0cb89d0 Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/ir-constructor-side-effects 2019-11-08 12:47:27 -08:00
Robert Marsh
b812a0338d Merge pull request #2268 from dave-bartolomeo/dbartol/StringLiteralAlias
C++/C#: Treat string literals like read-only global variables for alias purposes
2019-11-08 12:43:57 -08:00
Robert Marsh
7e8a67a046 Merge branch 'master' into rdmarsh/cpp/hasGlobalOrStdName 2019-11-08 11:33:35 -08:00
Dave Bartolomeo
c365b2f2f0 Merge from master
Resolve conflicts in test output
2019-11-08 10:42:29 -07:00
Dave Bartolomeo
2b89139d5f Merge pull request #2269 from rdmarsh2/rdmarsh/cpp/uninit-string-initializers
C++: uninit instr for string literal initializers
2019-11-08 10:33:57 -07:00
Calum Grant
9715d8849a C#: Disable a CIL consistency check that seems to be invalid. 2019-11-08 16:50:51 +00:00
Calum Grant
4e2e64e949 C#: Fix up CallableReturns tests. 2019-11-08 16:42:22 +00:00
Asger F
a2ff4e9494 JS: member -> property 2019-11-08 16:23:59 +00:00
Calum Grant
e12a33d4e0 C#: Disposal tests do not depend on external DLLs. 2019-11-08 16:22:47 +00:00
Asger F
2a473fb9e7 Update javascript/ql/src/semmle/javascript/dataflow/Nodes.qll
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-08 16:15:08 +00:00
Asger F
4ad03a9061 Update javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-08 16:14:53 +00:00
Geoffrey White
58b6fc6bbf CPP: Autoformat. 2019-11-08 16:06:23 +00:00
Taus
7527f13443 Merge pull request #2283 from RasmusWL/python-fix-python2-specific-tests
Python: fix python2 specific tests
2019-11-08 17:03:54 +01:00
Geoffrey White
983a970c36 CPP: Autoformat. 2019-11-08 15:59:04 +00:00
Asger F
53d470da2f JS: Add syntax examples to DataFlow classes 2019-11-08 15:51:26 +00:00
Calum Grant
d64c244257 C#: Fix test for AspLine. 2019-11-08 15:48:56 +00:00
Geoffrey White
d434f909a5 CPP: Correct change note. 2019-11-08 15:10:44 +00:00
Geoffrey White
b4fb98dc7c CPP: Fix comments. 2019-11-08 15:10:13 +00:00
Geoffrey White
821d5061a7 CPP: Correct the tests. 2019-11-08 15:10:13 +00:00
Geoffrey White
73b55f019d CPP: Autoformat. 2019-11-08 15:10:13 +00:00
Geoffrey White
0063fa2974 CPP: Change note. 2019-11-08 15:10:13 +00:00
Geoffrey White
cd3bccf73a CPP: Fix FPs. 2019-11-08 15:09:46 +00:00
Geoffrey White
1cf4449314 CPP: Test for NonConstantFormat with multiple definitons. 2019-11-08 15:09:45 +00:00
Geoffrey White
144cda7dd9 CPP: Test for WrongTypeFormatArguments with multiple definitions. 2019-11-08 15:09:45 +00:00
semmle-qlci
9986de87c4 Merge pull request #2284 from shati-patel/ql-codeql-1
Approved by jf205
2019-11-08 14:37:26 +00:00
semmle-qlci
d9c7549dbe Merge pull request #2279 from max-schaefer/js/touchstone-files
Approved by asger-semmle
2019-11-08 14:33:23 +00:00
shati-patel
fe654a9c99 update to match support page 2019-11-08 14:32:59 +00:00
shati-patel
3f51260fb4 Docs: Update sidebar 2019-11-08 14:04:44 +00:00
Esben Sparre Andreasen
9b346b1d52 Merge pull request #2260 from max-schaefer/js/_min
JavaScript: Classify files with names ending in `_min` as minified.
2019-11-08 13:52:33 +01:00
Rasmus Wriedt Larsen
358964b1e2 Python: Accept changes in Python 2 specific six tests
We don't use a locked-down version of six, so some internal things probably
changed from the version used last time, and the versoin I have installed.

Long term fix would be to use a specific version of six for tests!
2019-11-08 13:49:52 +01:00
Rasmus Wriedt Larsen
6c259e5608 Python: Temporarily accept changes in Python 2 specific MRO tests
Due to internal PR#35123 we now actually run the tests under
`python/ql/test/2/...`

These seems like a regression, since the tests state that N is ok, but A and J
should not be allowed.

For now we can accept them, so we don't block all other Python PRs
2019-11-08 13:48:21 +01:00
Rasmus Wriedt Larsen
89a13213e2 Python: Accept changes in Python 2 specific tests
Due to internal PR#35123 we now actually run the tests under
`python/ql/test/2/...`

Since we haven't done this in a while, test output has changed a bit. These
changes look perfectly fine.
2019-11-08 13:48:14 +01:00
Tom Hvitved
af5c60c341 C#: Use type unification library in virtual dispatch library 2019-11-08 12:06:05 +01:00
Tom Hvitved
f4b92137d9 C#: Add more virtual dispatch tests 2019-11-08 12:06:05 +01:00
Tom Hvitved
ae54852fa4 C#: Add type unification library 2019-11-08 12:06:05 +01:00
semmle-qlci
867ed16777 Merge pull request #2276 from asger-semmle/inclusion-test
Approved by max-schaefer
2019-11-08 10:57:11 +00:00
Max Schaefer
d7831d2680 JavaScript: Short-circuit bad-header check on empty files. 2019-11-08 10:30:53 +00:00
Felicity Chapman
8ed0d726ee Merge pull request #2280 from jf205/codeql-homepage-links
docs: update banner links
2019-11-08 10:06:27 +00:00
james
0554de06a1 docs: update banner links 2019-11-08 09:32:20 +00:00
Max Schaefer
e8510fe71a TypeScript: Skip Touchstone files. 2019-11-08 09:17:05 +00:00
Dave Bartolomeo
17f76c2516 C++: Fix merge conflicts 2019-11-07 22:02:15 -07:00
Ziemowit Laski
4ea8569081 [CPP-434] Squelch query alerts if ALL files were compiled
with `-fwrapv` or `-fno-strict-overflow`
2019-11-07 16:40:03 -08:00
Robert Marsh
2582b69e17 Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/ir-constructor-side-effects 2019-11-07 15:46:08 -08:00
Robert Marsh
e93dcdb16c Merge branch 'master' into rdmarsh/cpp/ir-constructor-side-effects 2019-11-07 15:19:46 -08:00
Robert Marsh
f483ec152b Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/uninit-string-initializers 2019-11-07 14:36:58 -08:00
Robert Marsh
ee185ea92e Merge pull request #2273 from geoffw0/ntohl
CPP: Add tests of NtohlArrayNoBoundOpenSource.ql.
2019-11-07 14:06:32 -08:00
Robert Marsh
ae1377447e C++: only generate uninits when needed 2019-11-07 13:55:49 -08:00
Dave Bartolomeo
6c1d219c86 Merge from master 2019-11-07 14:50:04 -07:00
Robert Marsh
c5396d9980 Merge pull request #2262 from jbj/ir-virtual-dispatch-local
C++: Rudimentary support for IR data flow virtual dispatch
2019-11-07 13:09:24 -08:00
Dave Bartolomeo
df1d64fbeb Merge pull request #2244 from jbj/IRType-cached
C++: Minimal caching of the IR type system
2019-11-07 12:44:16 -07:00
Dave Bartolomeo
f808dcefab Merge pull request #2277 from ian-semmle/cfg_diffs
C++: Remove tests for CFG differences
2019-11-07 12:41:40 -07:00
Dave Bartolomeo
64480c2ace Merge pull request #1999 from jbj/ir-copy-unloaded-result
C++: Make sure there's a Instruction for each Expr
2019-11-07 12:31:54 -07:00
Dave Bartolomeo
2c88848d2f Merge pull request #2272 from jbj/getIRTypeForPRValue-join-order
C++/C#: Fix getIRTypeForPRValue join order
2019-11-07 12:22:39 -07:00
Ian Lynagh
b5af4e5acd C++: Remove tests for CFG differences
Now that we have switched over, they are no longer interesting.
2019-11-07 16:32:18 +00:00
igfoo
c8c37c4976 Merge pull request #2271 from matt-gretton-dann/cpp-172-template-members
Template members
2019-11-07 16:30:08 +00:00
shati-patel
ec2008d57a Merge pull request #2275 from jf205/sd-4017
Learn CodeQL docs: add short note about new terminology
2019-11-07 16:12:12 +00:00
Asger F
812ee34bbc JS: Use Files.exists() instead 2019-11-07 15:53:29 +00:00
semmle-qlci
e65271dfad Merge pull request #2251 from asger-semmle/barrier-guard-improvements
Approved by esbena
2019-11-07 15:50:23 +00:00
semmle-qlci
f79c2a7630 Merge pull request #2224 from asger-semmle/access-paths-with-source-node-root
Approved by max-schaefer
2019-11-07 15:46:14 +00:00
James Fletcher
8178e3e671 Update docs/language/learn-ql/terminology-note.rst
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-11-07 14:40:04 +00:00
James Fletcher
d31ec56ea6 Update docs/language/learn-ql/index.rst
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-11-07 14:39:52 +00:00
Rasmus Wriedt Larsen
9ffb67a460 Merge pull request #2266 from tausbn/python-multiple-calls-to-init-join-order-fix
Python: Fix bad join order for `py/multiple-calls-to-init`.
2019-11-07 15:38:43 +01:00
Asger F
8544850945 JS: Generalize StringOps::Includes to ::InclusionTest 2019-11-07 14:35:17 +00:00
james
db2039d8a7 docs: learn codeql terminology note 2019-11-07 14:32:05 +00:00
semmle-qlci
2b120def01 Merge pull request #2211 from hvitved/csharp/unsafe-deserialization
Approved by jf205
2019-11-07 14:16:13 +00:00
Matthew Gretton-Dann
ddf1ef8a7d C++: Add new test case for template member change
We now output literals for accesses to members of template parameters:

So for `foo` in the following example:

```
template<typename T> void bar(T& t) {
  T.foo(1)
}
```
2019-11-07 14:08:25 +00:00
Matthew Gretton-Dann
c0884e9a88 C++: Update expected results. 2019-11-07 14:08:25 +00:00
Erik Krogh Kristensen
0c080a82be fix expected output 2019-11-07 14:31:09 +01:00
Erik Krogh Kristensen
232e875274 add test for getEnclosingExpr 2019-11-07 14:29:31 +01:00
Erik Krogh Kristensen
e4f6f41634 add DataFlow::getEnclosingExpr to get the an Expr from a potentially reflective call 2019-11-07 14:29:31 +01:00
semmle-qlci
3a7f9a588d Merge pull request #2267 from max-schaefer/js/qltest-extractor-options
Approved by asger-semmle
2019-11-07 11:36:45 +00:00
shati-patel
7394d5c726 Merge pull request #2242 from felicitymay/codeql/SD-4059-markdown
Docs: update terminology in markdown files (SD-4059)
2019-11-07 11:30:32 +00:00
Jonas Jensen
6385528d5f C++/C#: Fix getIRTypeForPRValue join order
This predicate was taking 39s on a snapshot of Facebook Fizz because it
had disjuncts like this:

    43685     ~0%     {1} r34 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>
    43685     ~1%     {2} r35 = JOIN r34 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r34.<0>
    170371500 ~2%     {2} r36 = JOIN r35 WITH IRType::IRSizedType#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r35.<1>
    43685     ~6%     {2} r37 = JOIN r36 WITH IRType::IRFunctionAddressType#class#ff AS R ON FIRST 1 OUTPUT r36.<1>, r36.<0>

Instead of fixing the joins in `getIRTypeForPRValue` itself, I've
changed the `IRType::getByteSize` predicate such that the optimiser
knows how to join with it efficiently.

The disjunct shown above now looks like this instead:

    43685  ~0%     {1} r26 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>
    43685  ~1%     {2} r27 = JOIN r26 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r26.<0>
    43685  ~6%     {2} r28 = JOIN r27 WITH IRType::IRFunctionAddressType::getByteSize#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r27.<1>, R.<1>
2019-11-07 11:48:16 +01:00
Max Schaefer
e314869e5c JavaScript: Classify files with names ending in _min as minified.
We already do the same for `-min` and `.min`. [Here](https://github.com/antoniogarrote/rdfstore-js/blob/master/dist/rdfstore_min.js) is a real-world example.
2019-11-07 10:33:47 +00:00
Sauyon Lee
0040c9fb4c Update links to OWASP cheat sheet 2019-11-06 20:21:47 -08:00
Robert Marsh
81ad11090e C++: uninit instr for string literal initializers 2019-11-06 13:37:03 -08:00
Robert Marsh
51c4ef4f7f C++: add SSA IR test for array initializers 2019-11-06 13:32:35 -08:00
Dave Bartolomeo
a9e3bfbd11 C++/C#: Treat string literals like read-only global variables for alias purposes.
Previously, we didn't track string literals as known memory locations at all, so they all just got marked as `UnknownMemoryLocation`, just like an aribtrary read from a random pointer. This led to some confusing def-use chains, where it would look like the contents of a string literal were being written to by the side effect of an earlier function call, which of course is impossible.

To fix this, I've made two changes. First, each string literal is now given a corresponding `IRVariable` (specifically `IRStringLiteral`), since a string literal behaves more or less as a read-only global variable. Second, the `IRVariable` for each string literal is now marked `isReadOnly()`, which the alias analysis uses to determine that an arbitrary write to aliased memory will not overwrite the contents of a string literal.

I originally planned to treat all string literals with the same value as being the same memory location, since this is the usual behavior of modern compilers. However, this made implementing `IRVariable.getAST()` tricky for string literals, so I left them unpooled.
2019-11-06 13:08:28 -07:00
Robin Neatherway
7850d67a78 Remove TODO comment
I've checked Hamcrest versions 1.3, 2.0, 2.1 and 2.2
2019-11-06 17:47:02 +00:00
Geoffrey White
6c38f55e28 CPP: QLDoc protocols.qll. 2019-11-06 17:06:57 +00:00
semmle-qlci
717490b670 Merge pull request #2265 from tausbn/python-fix-unused-import-global-name-used-join-order
Approved by RasmusWL
2019-11-06 16:38:07 +00:00
Max Schaefer
54e40a8977 JavaScript: Move --html all extractor options into options file. 2019-11-06 16:30:01 +00:00
Geoffrey White
e886cf7297 CPP: 'i.e.' -> 'that is'. 2019-11-06 16:27:06 +00:00
Taus Brock-Nannestad
2b24eb2e70 Python: Fix bad join order for py/multiple-calls-to-init.
The `multiple_invocation_paths` predicate had a bad join order where
we (essentially) joined `i1` with `i2` and only then joined `i1` and `i2`
separately to reduce the number of tuples. The join coming from `i1 != i2` had
little impact, but `i1.getFunction() = multi` made a big difference (and
similarly for `i2`). I factored out the code so that these joins would be done
more eagerly. Thus, we went from

```
[2019-11-06 16:53:05] (38s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2ce75a
[2019-11-06 16:53:35] (68s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff:
                      134547    ~9%       {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<0>, I.<2>
                      235284431 ~3%       {4} r2 = JOIN r1 WITH CallGraph::TInvocation#fff AS R ON FIRST 1 OUTPUT r1.<0>, r1.<1>, R.<1>, R.<2>
                      235149884 ~3%       {4} r3 = SELECT r2 ON r2.<3> != r2.<1>
                      235149884 ~4%       {3} r4 = SCAN r3 OUTPUT r3.<1>, r3.<0>, r3.<3>
                      166753634 ~5%       {4} r5 = JOIN r4 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r4.<2>, r4.<1>, r4.<0>
                      129778    ~0%       {4} r6 = JOIN r5 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 2 OUTPUT r5.<0>, r5.<3>, r5.<1>, r5.<2>
                                          return r6
[2019-11-06 16:53:35] (68s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv
[2019-11-06 16:53:35] (68s)  >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns.
```

to

```
[2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff/4@586aec
[2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff:
                      134547 ~0%     {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0>
                      88111  ~4%     {3} r2 = JOIN r1 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0>
                      761305 ~0%     {4} r3 = JOIN r2 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<0>, R.<1>
                      673194 ~0%     {4} r4 = SELECT r3 ON r3.<3> != r3.<1>
                      673194 ~0%     {4} r5 = SCAN r4 OUTPUT r4.<2>, r4.<1>, r4.<3>, r4.<0>
                                     return r5
[2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff + [] with content 20edaaecf25nldgp24d9c4et8m3kv
[2019-11-06 17:22:22] (25s)  >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff with 673194 rows and 4 columns.
[2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs/4@9e5441
[2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs:
                      673194 ~0%     {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths_helper#ffff AS I OUTPUT I.<2>, I.<3>, I.<0>, I.<1>
                                     return r1
[2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs + [] with content 2069301e655fi9mcovngg9hetfqas
[2019-11-06 17:22:22] (25s)  >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs with 673194 rows and 4 columns.
[2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2f7c34
[2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff:
                      134547 ~0%     {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0>
                      129778 ~0%     {4} r2 = JOIN r1 WITH MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs AS R ON FIRST 2 OUTPUT R.<2>, R.<3>, r1.<0>, r1.<1>
                                     return r2
[2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv
[2019-11-06 17:22:22] (25s)  >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns.
[2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs/4@9f9146
[2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs:
                      129778 ~0%     {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths#ffff AS I OUTPUT I.<0>, I.<3>, I.<1>, I.<2>
                                     return r1
[2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs + [] with content 17c3fe1fcbf6ghhdr7hiukqp41rst
[2019-11-06 17:22:22] (25s)  >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs with 129778 rows and 4 columns.
```

Execution time on `salt` went from 29.5s to somewhere below 299ms (the predicate
was not listed in the timing report).
2019-11-06 17:27:03 +01:00
Geoffrey White
81c58d5a64 CPP: Improve QLDoc comments. 2019-11-06 16:20:39 +00:00
Geoffrey White
0c3f4e530f CPP: Make some library predicates private. 2019-11-06 16:07:28 +00:00
Geoffrey White
399ac1f112 CPP: Rename 'getAssertedFalseCondition' to something less misleading. 2019-11-06 15:57:44 +00:00
Taus Brock-Nannestad
43148083eb Python: Fix bad join order for global_name_used.
As it turns out, there was a further bad join-order in the `global_name_used`
predicate. In this case, there was a common subexpression in the RA that was
being factored out and evaluated separately, producing a large number of tuples.
2019-11-06 16:37:01 +01:00
Nick Rolfe
5b00b21713 Merge pull request #2153 from matt-gretton-dann/cpp-447-support-non-type-template-parameters
RFC: C++ Support non type template parameter values
2019-11-06 15:11:34 +00:00
Rasmus Wriedt Larsen
47a292b241 Merge pull request #2264 from tausbn/python-fix-unused-import-join-order
Python: Fix bad join order in `py/unused-import`
2019-11-06 16:09:44 +01:00
Jonas Jensen
8ffd7c1055 Merge pull request #2222 from geoffw0/libraryperf
CPP: Improvements for ConditionallyInitializedVariable.ql
2019-11-06 15:54:16 +01:00
Jonas Jensen
217ecd3551 C++: Add <p> tags to split text into paragraphs
Without this, the rendered output is one big paragraph.
2019-11-06 15:50:08 +01:00
shati-patel
5d1d7ea075 Merge pull request #2257 from jf205/codeql-training-material
docs: update terminology in training material
2019-11-06 14:43:55 +00:00
Asger F
d9beb54dde Merge pull request #2102 from erik-krogh/deferredModel
JS: add Deferred model in js/use-of-returnless-function
2019-11-06 14:30:03 +00:00
Jonas Jensen
76a3db9eed Merge remote-tracking branch 'upstream/master' into ir-copy-unloaded-result 2019-11-06 15:21:22 +01:00
Taus Brock-Nannestad
b6f16dee81 Python: Fix bad join order in py/unused-import 2019-11-06 15:14:48 +01:00
semmle-qlci
f73caac88d Merge pull request #2254 from asger-semmle/for-of-propread
Approved by max-schaefer
2019-11-06 13:44:55 +00:00
Geoffrey White
f9feb05a72 CPP: Add a test of NtohlArrayNoBoundOpenSource.ql. 2019-11-06 13:36:31 +00:00
Jonas Jensen
aa841c306d C++: Use virtual dispatch in DefaultTaintTracking
This bit is only used by the compatibility code that sends flow into
parameters of functions without body.
2019-11-06 14:04:07 +01:00
Jonas Jensen
ec9ef33486 C++: IR data flow through inheritance conversions
This makes IR data flow behave more like AST data flow, and it makes IR
virtual dispatch work without further changes.
2019-11-06 14:04:07 +01:00
Jonas Jensen
49008c9ff5 C++: IR data flow local virtual dispatch
This is just good enough to cause no performance regressions and pass
the virtual-dispatch tests we have for `security.TaintTracking`. In
particular, it fixes the tests for `UncontrolledProcessOperation.ql`
when enabling `DefaultTaintTracking.qll`.
2019-11-06 14:04:02 +01:00
Max Schaefer
725059deea JavaScript: Remove --source-type module extractor options. 2019-11-06 13:01:59 +00:00
Max Schaefer
3ad5af7cef JavaScript: Move --extract-program-text extractor options into options files. 2019-11-06 13:01:55 +00:00
Max Schaefer
6b817203fd JavaScript: Move --tolerate-parse-errors extractor options into options file. 2019-11-06 13:01:28 +00:00
Max Schaefer
5681565d4a JavaScript: Move --html elements extractor options into options file. 2019-11-06 13:01:28 +00:00
Max Schaefer
8fdf6298b9 JavaScript: Remove --platform node extractor options. 2019-11-06 13:01:28 +00:00
Max Schaefer
4848372435 JavaScript: Replace --externs extractor flag with /** @externs */ comment. 2019-11-06 13:01:28 +00:00
Max Schaefer
1fa8c43a8c JavaScript: Remove a redundant extractor option. 2019-11-06 13:01:28 +00:00
Max Schaefer
79f1079460 JavaScript: Add options files with --experimental extractor options. 2019-11-06 13:01:23 +00:00
James Fletcher
2e7bd4db6f Update docs/language/ql-training/cpp/program-representation-cpp.rst
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-11-06 12:59:45 +00:00
Max Schaefer
a4bf361f64 JavaScript: Remove remaining --experimental extractor options. 2019-11-06 12:54:44 +00:00
james
24615f2bdb docs: further review comments 2019-11-06 12:44:45 +00:00
Erik Krogh Kristensen
19554ff6e7 change "e.g." to "for example" in qldoc 2019-11-06 13:37:54 +01:00
Erik Krogh Kristensen
dc923ef694 remove change note
Co-Authored-By: Esben Sparre Andreasen <esbena@github.com>
2019-11-06 13:28:46 +01:00
Asger F
81723ab92a JS: Update GlobalAccessPaths test 2019-11-06 11:58:06 +00:00
Asger F
3ec95881b4 Update javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-06 11:58:06 +00:00
Asger F
7e80823cb6 JS: Fix deprecated API usage 2019-11-06 11:58:06 +00:00
Asger F
b373901e11 JS: Avoid leading dot in access paths 2019-11-06 11:58:06 +00:00
Asger F
c365833731 JS: Refactor the public access path API 2019-11-06 11:58:06 +00:00
Asger F
e90516d4d8 JS: Dont use getALocalSource in fromRhs 2019-11-06 11:58:06 +00:00
Asger F
bc35f24f31 JS: Generalize access paths to arbitrary root nodes 2019-11-06 11:58:06 +00:00
Asger F
7a7a8b2b09 JS: More steps in getImmediatePredecessor 2019-11-06 11:58:06 +00:00
Max Schaefer
2bcd418c23 Merge pull request #2261 from Semmle/esbena-patch-2
Doc: Add missing `t` in `support`.
2019-11-06 09:24:30 +00:00
Esben Sparre Andreasen
21d4e5f186 Doc: Add missing t in support. 2019-11-06 10:16:43 +01:00
semmle-qlci
04f0c22f24 Merge pull request #2203 from erik-krogh/ignorePureFunction
Approved by max-schaefer, mchammer01
2019-11-06 09:09:11 +00:00
Jonas Jensen
fca7d9a391 C#: Cache IRType like for C++ 2019-11-06 07:42:34 +01:00
Ziemowit Laski
1f82ea7750 [zlaski/pointer-overflow-check] Refine query to exclude macros (other than 'assert'). 2019-11-05 18:25:41 -08:00
Ziemowit Laski
0df3d2ce60 [zlaski/pointer-overflow-check] Improve test case. 2019-11-05 13:00:55 -08:00
james
8d02a740dd docs: address remaining comments 2019-11-05 20:03:47 +00:00
James Fletcher
488ce15888 Apply suggestions from code review
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
Co-Authored-By: Felicity Chapman <felicitymay@github.com>
2019-11-05 19:57:24 +00:00
Taus
e9336fe30e Merge pull request #2129 from RasmusWL/python-update-django
Python: update django support
2019-11-05 20:51:55 +01:00
Dave Bartolomeo
c90fa1b3b1 Merge pull request #2255 from jbj/localInstructionFlow
C++: localInstruction{Flow,Taint} helpers
2019-11-05 11:57:06 -07:00
Asger F
f3850e580c JS: Skip codeql databases in AutoBuild 2019-11-05 16:30:57 +00:00
james
0b6592f650 docs: version number and small css tweaks
(cherry picked from commit ff78feeeea)
2019-11-05 16:06:13 +00:00
james
2d00ca5773 docs: semmle logo
(cherry picked from commit 4a8e8fa0de)
2019-11-05 16:06:11 +00:00
james
69d7baa9bc docs: update snapshot terminology 2019-11-05 16:06:11 +00:00
james
8661de11f2 docs: update ql terminology 2019-11-05 16:06:04 +00:00
Max Schaefer
3e92d0ffb5 JavaScript: Remove redundant --experimental extractor options. 2019-11-05 15:59:24 +00:00
Erik Krogh Kristensen
16b63b3d01 move deferred model to the query where it is used 2019-11-05 15:45:17 +01:00
Matthew Gretton-Dann
20ae183c16 C++: Tidy up formatting 2019-11-05 14:18:29 +00:00
Erik Krogh Kristensen
7045cd2648 Merge remote-tracking branch 'upstream/master' into deferredModel 2019-11-05 15:08:47 +01:00
Jonas Jensen
df2fbfb3d0 C++: localInstruction{Flow,Taint} helpers
These are analogous to the existing `localExpr{Flow,Taint}` predicates.
2019-11-05 14:13:20 +01:00
Geoffrey White
7456a92d6d CPP: Autoformat. 2019-11-05 13:10:19 +00:00
Geoffrey White
5106626bd0 CPP: QLDoc helper predicates. 2019-11-05 13:06:43 +00:00
semmle-qlci
1fe5a9e7e7 Merge pull request #2236 from max-schaefer/js/data-flow-exploration
Approved by erik-krogh, esbena
2019-11-05 12:15:00 +00:00
Matthew Gretton-Dann
8eef953cd7 C++: Update 1.23 change notes 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
afe666500f C++: Simplify getTemplateArgument*() impl. 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
6b4506dbea C++: Update schema stats 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
6fe22a76da C++: Change API for exposing template parameters.
Note that Declaration::getTemplateArgumentType() and
Declaration::getTemplateArgumentValue() need to be public so that they
can be overriden in derived classes.
2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
45ec8527c3 C++: Update expected test output. 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
afeaa6254d C++: Improve Template Value docs. 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
809d97de02 C++: Print print nontype template params 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
f1c3ce04d1 C++: Correct spelling mistake 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
ca898d4be0 C++: Further nontype template testcases. 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
57cd9b3990 C++: Update test results
We now support getting the name used for non-type template parameters
2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
469832668f C++: Add some simple non-type template tests 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
4ab87291f3 C++: Further use of TemplateArgumentValue 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
6334ad92c5 C++: Add DB Upgrade script. 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
faf5ba432b C++: Update expected test results 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
df7d21220b C++: Basic lib support for template param values 2019-11-05 11:39:22 +00:00
Matthew Gretton-Dann
48c7d1d7c1 C++: add *_template_parameter_value() tuples 2019-11-05 11:39:22 +00:00
semmle-qlci
794d5bda6d Merge pull request #2116 from erik-krogh/arrayCBRet
Approved by max-schaefer
2019-11-05 11:32:13 +00:00
Geoffrey White
8c16b36c7f Merge pull request #2231 from semmledocs-ac/newqueries-docscheck
CPP & C#: Review of qhelp (SD-4028)
2019-11-05 11:11:34 +00:00
Asger F
c373be0dee JS: Update TaintBarriers test 2019-11-05 10:26:04 +00:00
Asger F
d8ac0abb7f JS: Add test 2019-11-05 10:06:21 +00:00
Asger F
d8f3a2c550 JS: Add lvalue of for..of loop as a PropRead 2019-11-05 10:01:18 +00:00
semmle-qlci
eb6e8866fa Merge pull request #2247 from max-schaefer/odasa-8149
Approved by asger-semmle, esbena
2019-11-05 09:40:54 +00:00
Erik Krogh Kristensen
df3c70e57e add js/ignore-array-result to correctness-core suite 2019-11-05 10:40:14 +01:00
Ziemowit Laski
3aafcf4604 [zlaski/pointer-overflow-check] Minor tweak to Qhelp. 2019-11-04 17:00:06 -08:00
Ziemowit Laski
9228844604 [zlaski/pointer-overflow-check] Expand test case. 2019-11-04 17:00:06 -08:00
Ziemowit Laski
9407ba1a35 [zlaski/pointer-overflow-check] Initial version. 2019-11-04 17:00:06 -08:00
Ziemowit Laski
398896a4b2 [CPP-434] Change list items to ordinary paragraphs in the Recommendation section. 2019-11-04 16:44:31 -08:00
Ziemowit Laski
ce8ba86f2d [CPP-434] Use a bullet list instead of a table in order to placate Jenkins. 2019-11-04 12:30:52 -08:00
Erik Krogh Kristensen
bdb81c268c change tense 2019-11-04 18:56:03 +01:00
Erik Krogh Kristensen
aa47e3f6d2 update change-note to reflect changed query 2019-11-04 18:55:13 +01:00
Erik Krogh Kristensen
8ebfe15f0d apply doc feedback from mchammer01
Co-Authored-By: mc <42146119+mchammer01@users.noreply.github.com>
2019-11-04 18:54:43 +01:00
Erik Krogh Kristensen
6cac9619d3 add missing not
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-11-04 18:44:13 +01:00
Max Schaefer
016808b92e JavaScript: Address review comments. 2019-11-04 17:00:12 +00:00
Max Schaefer
770a4703c9 Merge pull request #2237 from asger-semmle/typescript3.7-rc
TS: Add support for TypeScript 3.7
2019-11-04 16:36:11 +00:00
semmle-qlci
d71fe0bffd Merge pull request #2246 from esbena/js/classify-doxygen
Approved by max-schaefer
2019-11-04 15:30:06 +00:00
Asger F
57aa166bff TS: Clean up yarn.lock 2019-11-04 14:59:42 +00:00
Asger F
b6f4ce0244 TS: Depend on typescript 3.7.2 2019-11-04 14:58:38 +00:00
Tom Hvitved
508b09f565 C#: Address review comments 2019-11-04 13:43:39 +01:00
Tom Hvitved
fd63246f44 Merge remote-tracking branch 'upstream/master' into csharp/unsafe-deserialization 2019-11-04 13:42:35 +01:00
Esben Sparre Andreasen
7f55e3f336 JS: classify Doxygen-generated files as "generated" 2019-11-04 09:57:41 +01:00
Asger F
2d7443ef98 TS: Add upgrade script 2019-11-04 07:55:20 +00:00
Asger F
79dbdac8fa TS: Support declare modifier for fields 2019-11-04 07:54:38 +00:00
Asger F
9bc45f351c TS: Fix typo in stats file 2019-11-04 07:54:38 +00:00
Asger F
09a2542477 TS: Update a javadoc comment 2019-11-04 07:54:38 +00:00
Asger F
1b8335a4e9 JS: Update change note 2019-11-04 07:54:38 +00:00
Asger F
4846e53a10 TS: Blacklist another cyclic property 2019-11-04 07:54:38 +00:00
Asger F
7dfd4e0687 TS: Stop using the deprecated TypeReference.typeArguments 2019-11-04 07:54:38 +00:00
Asger F
341c11523c TS: Add recursive type alias tests (already works) 2019-11-04 07:54:38 +00:00
Asger F
b81931e402 TS: Support assertion types 2019-11-04 07:54:38 +00:00
Asger F
4e7b987fa3 TS: Rename IsTypeExpr -> PredicateTypeExpr 2019-11-04 07:54:38 +00:00
Asger F
f50f3b48c4 TS: Add test for ?? operator (already works) 2019-11-04 07:54:38 +00:00
Asger F
869fe4558f TS: Support optional chaining 2019-11-04 07:54:38 +00:00
Asger F
f76006e490 JS: Delete duplicate test case (typo) 2019-11-04 07:54:38 +00:00
Asger F
36b6c32f4f TS: Update expected output 2019-11-04 07:54:37 +00:00
Asger F
637394fb62 TS: Add TypeScript-3.7.1-rc 2019-11-04 07:54:37 +00:00
Jonas Jensen
fb4dac597c C++: Minimal caching of the IR type system
This was the minimal amount of predicates I could easily cache without
introducing extra cached stages. The predicates that are not cached
here, like `CppType::getTypeSize` and `getCanonicalLanguageType`, appear
to be cheap.

I've tested that this avoids recomputation of the IR type system by
running

    grep -c 'Starting to evaluate predicate CppType::CppType::getIRType_dispred'

on the evaluator log for `IRSanity.ql`. It drops from 4 to 1. The
pretty-printed DIL drops from 79,175 lines to 76,326 lines.
2019-11-03 16:40:30 +01:00
Ziemowit Laski
2bad9394b7 [CPP-434] Squelch alerts for expressions inside macros; try to make Qhelp Jenkins-friendly. 2019-11-01 15:24:22 -07:00
Geoffrey White
c2812197a9 CPP: Further speedup. 2019-11-01 18:16:12 +00:00
Geoffrey White
08293d0009 CPP: Simplify. 2019-11-01 17:58:29 +00:00
Geoffrey White
98b9afd83f CPP: Remove apparently irrelevant parts of the query.
This is not strictly behaviour preserving, but I believe the parts I've removed or simplified weren't intended to do what they were doing.
2019-11-01 17:54:13 +00:00
Geoffrey White
c08493670b CPP: Speed up ExistsAnyFlowConfig. 2019-11-01 17:40:44 +00:00
Geoffrey White
6a865ed580 CPP: De-duplicate TlsSettingsMisconfiguration.ql. 2019-11-01 17:40:41 +00:00
Geoffrey White
fa203254ce CPP: Add test cases. 2019-11-01 17:40:27 +00:00
Asger F
f48d16fcb7 JS: Support barrier guards that are reflective calls 2019-11-01 15:23:38 +00:00
Asger F
d6158427c5 JS: Generalize SanitizerFunction to data flow configs and flow labels 2019-11-01 15:23:38 +00:00
Asger F
e2b0ec5696 JS: Handle multiple and/or operators in SanitizerFunction 2019-11-01 15:23:38 +00:00
Felicity Chapman
458108f66b Make 'open source' consistent on the page and with other docs 2019-11-01 14:08:50 +00:00
Felicity Chapman
692e977a71 Update docs/query-metadata-style-guide.md
Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com>
2019-11-01 13:44:23 +00:00
Felicity Chapman
236e1f7955 Update change notes for name change 2019-11-01 12:27:43 +00:00
Felicity Chapman
570e55190d Update style guides for name change 2019-11-01 12:22:05 +00:00
Felicity Chapman
02bb142e7c Update repository artifacts for name change 2019-11-01 12:21:24 +00:00
Ziemowit Laski
3e1fd4a737 [CPP-434] Add table of constructs to Qhelp. Rewrite examples section. 2019-10-31 18:03:34 -07:00
Robert Marsh
31f25c8cfc C++: primary instrs for constructor side effects 2019-10-31 11:43:47 -07:00
Robert Marsh
86b5e97f76 Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/ir-constructor-side-effects 2019-10-31 11:34:22 -07:00
Max Schaefer
03c9a40ba3 JavaScript: Add libraries for forward and backward data-flow exploration. 2019-10-31 12:37:31 +00:00
Robin Neatherway
d3016e5b98 Run autoformatter 2019-10-31 11:21:57 +00:00
alistair
27d0b51c6b CPP & C#: Review of qhelp
PR #2151 got merged without a review of the qhelp
by a technical writer.
The current PR makes changes I would have suggested on that PR.
2019-10-30 16:10:03 +00:00
yh-semmle
8620b0513e Java: move UnsafeDeserialization.qll to standard library location 2019-10-30 11:18:36 -04:00
Max Schaefer
3bbded57d3 JavaScript: Autoformat. 2019-10-30 14:49:18 +00:00
Max Schaefer
bb0771b36c JavaScript: Deal with escape-unescape-escape (and similar) chains. 2019-10-30 14:49:01 +00:00
Max Schaefer
8c133ff61d JavaScript: Deal with (un-)escaping on captured variables. 2019-10-30 14:46:50 +00:00
Max Schaefer
a8214ce7ee JavaScript: Fix regexes for escaping schemes. 2019-10-30 14:15:59 +00:00
Max Schaefer
5349e0f881 JavaScript: Recognise wrapped chains of replacements. 2019-10-30 13:14:38 +00:00
Max Schaefer
02d16b1dc9 JavaScript: Recognise wrapped string replacement functions. 2019-10-30 13:01:17 +00:00
Max Schaefer
aaeca32519 JavaScript: Recognize string escaping using .replace with a callback. 2019-10-30 12:45:32 +00:00
Max Schaefer
bd1c99d8a4 JavaScript: Recognise JSON.stringify and JSON.parse as escaper/unescaper. 2019-10-30 12:38:05 +00:00
Max Schaefer
63f24476e9 JavaScript: Refactor DoubleEscaping.ql. 2019-10-30 10:59:14 +00:00
Robin Neatherway
96f9a01355 Correct minor compilation errors in test code 2019-10-29 17:52:13 +00:00
Robin Neatherway
84202ff2e1 Java: Respect Hamcrest assertThat(X, notNullValue()) 2019-10-29 17:52:13 +00:00
Rasmus Wriedt Larsen
fc851b46c3 Python: Fix Django class-based views 2019-10-29 13:58:07 +01:00
Rasmus Wriedt Larsen
fb864b7262 Python: Consolidate tests for django
The tests in 3/ was not Python 3 specific anymore
2019-10-29 13:58:07 +01:00
Rasmus Wriedt Larsen
91f269ed7b Python: Remove unused django sinks
This would find instances of `thing = MyThing.objects.get(field=userinput)`, and
what seems to be a query that wants to match on `thing = MyThing();
thing.field=userinput`. Both are not vulnerable to user-input, due to the
build-in escaping by django.

The DjangoModelFieldWrite actually matches on `MyThing.field=userinput` and not
`thing.field=userinput`. I suspect this to be a mistake.

Matching on `thing.field=userinput`, would require this CodeQL:

attr.getObject(_).pointsTo().getClass() = model
2019-10-29 13:58:07 +01:00
Rasmus Wriedt Larsen
471318369b Python: Don't quote %s in django example
This is vulnerable to SQL injection because of the quotes around %s -- added
some code that highlights this in test.py

Since our examples did this in the safe query, I ended up rewriting them
completely, causing a lot of trouble for myself :D
2019-10-29 13:58:07 +01:00
Rasmus Wriedt Larsen
afe7a0536c Python: Support positional arguments in Django routes 2019-10-29 13:58:07 +01:00
Rasmus Wriedt Larsen
49dd2216a6 Python: Refactor django library
Use General.qll for routing, like in other web libraries
2019-10-29 13:58:07 +01:00
Erik Krogh Kristensen
2d01e7c5ed simplify the callsArray predicate 2019-10-29 12:13:01 +01:00
Erik Krogh Kristensen
563f32193c suggestions from @max-schaefer
Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com>
2019-10-29 12:10:12 +01:00
Geoffrey White
3584c0b2e5 CPP: Speed up InitializationFunctions.qll's getTarget. 2019-10-28 19:54:10 +00:00
Geoffrey White
2d64fedeb0 CPP: Speed up VirtualDispatch.qll's getAViableTarget. 2019-10-28 19:54:10 +00:00
Geoffrey White
c40c88ec4b CPP: Add test cases for ConditionallyUninitializedVariables.ql. 2019-10-28 18:43:00 +00:00
Geoffrey White
d693eb8c20 CPP: Correct the ConditionallyUninitializedVariable examples. 2019-10-28 17:39:45 +00:00
Tom Hvitved
3f5ee5138b C#: Add change notes 2019-10-28 14:22:59 +01:00
Tom Hvitved
eb990525d7 C#: Add precision tags to UnsafeDeserialization[UntrustedInput].ql 2019-10-28 14:19:40 +01:00
Tom Hvitved
b0cf7cb39a C#: Move UnsafeDeserialization.qll 2019-10-28 13:38:53 +01:00
Ziemowit Laski
1500148c76 [CPP-434] Clarify Qhelp. 2019-10-27 11:23:54 -07:00
Erik Krogh Kristensen
b2c31701f3 add documentation to two predicates 2019-10-27 09:12:56 +01:00
Erik Krogh Kristensen
92cebea235 update tests to include empty reciever case 2019-10-27 00:25:59 +02:00
Erik Krogh Kristensen
c6f53199d4 ignore when the reciever is the empty array 2019-10-27 00:24:38 +02:00
Erik Krogh Kristensen
da23898eba update tests 2019-10-26 23:26:45 +02:00
Ziemowit Laski
6ee3d7d788 [CPP-434] Address more comments re .cpp test cases. 2019-10-25 15:50:00 -07:00
Ziemowit Laski
7204e13746 [CPP-434] Address comments re .cpp test cases. 2019-10-25 14:37:28 -07:00
Ziemowit Laski
f964fe8b0e [CPP-434] Address comments regarding .ql and .qhelp. 2019-10-25 14:08:30 -07:00
Ziemowit Laski
1d052a8e62 [CPP-434] Address comments re change notes. 2019-10-25 13:07:54 -07:00
Erik Krogh Kristensen
841dac1aba address review feedback 2019-10-25 17:46:55 +02:00
Erik Krogh Kristensen
5b26d03f1c introduce backtracking, and also marking join/slice calls 2019-10-25 16:50:09 +02:00
Erik Krogh Kristensen
5489a80372 add query for detecting ignored calls to Array.prototype.concat 2019-10-24 16:17:19 +02:00
Erik Krogh Kristensen
5c07750286 simplify the heuristic for Deferred promises 2019-10-24 15:51:36 +02:00
Jonas Jensen
11da4a5328 C++: Accept test results for GVN and sign analysis 2019-10-24 15:17:16 +02:00
Rasmus Wriedt Larsen
2874c54133 Python: Move pyramid tests from internal repo
Use minimal mock instead of full library
2019-10-23 16:28:46 +02:00
Rasmus Wriedt Larsen
7c44c37d8b Python: Autoformat (4 spaces) pyramid library 2019-10-23 16:28:46 +02:00
Rasmus Wriedt Larsen
4463b30ce7 Python: Update pyramid library to use correct response class
Tested with pyramid 1.10.4 and python 3.6.8
2019-10-23 16:28:46 +02:00
Rasmus Wriedt Larsen
66a0e153a5 Python: Modernise pyramid library 2019-10-23 16:28:46 +02:00
Rasmus Wriedt Larsen
59e09d6d5d Python: Add nullary pointsTo to Expr class
Like the one existing in ControlFlowNode.

This is useful for checking class of value being poitned to, as

    expr.pointsTo().getClass() = someClass

Without this you need to do

    exists(Value v | v.getClass() = someClass | expr.pointsTo(v))
2019-10-23 16:28:46 +02:00
Jonas Jensen
7a6ec83572 C++: No CopyValue for immediately discarded exprs
Expressions like the `e` in `e;` or `e, e2`, whose result is immediately
discarded, should not get a synthetic `CopyValue`. This removes a lot of
redundancy from the IR.

To prevent these expressions from being confused with the expressions
from which they get their result, the predicate
`getInstructionConvertedResultExpression` now suppresses results for
expressions that don't produce their own result. This should fix the
mapping between expressions and IR data-flow nodes.
2019-10-23 11:56:30 +02:00
Jonas Jensen
cbbe9b4718 Merge remote-tracking branch 'upstream/master' into ir-copy-unloaded-result
Fixed conflicts by accepting new qltest output.

Conflicts:
      cpp/ql/test/library-tests/ir/ir/raw_ir.expected
      cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected
      cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected
      cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected
      cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected
2019-10-23 08:46:39 +02:00
Ziemowit Laski
6eb0f0709a [CPP-434] Update Qhelp. 2019-10-22 17:28:35 -07:00
Ziemowit Laski
ad5aa182df [CPP-434] When analyzing overflow, discard any explicit casts.
Use the simple range analysis library to detect which
          additions may in fact overflow.
2019-10-22 15:21:30 -07:00
Ziemowit Laski
06f63c5477 [CPP-434] Incremental changes to SignedOverflowCheck.cpp test suite. 2019-10-22 13:06:33 -07:00
Erik Krogh Kristensen
ad3185c558 simplify lastStatementHasNoEffect and use the control-flow to determine which statement is the last 2019-10-22 10:33:05 +02:00
Erik Krogh Kristensen
db22916850 fix the alwaysHasNoEffect predicate, and rename it to lastStatementHasNoEffect 2019-10-22 09:37:19 +02:00
Ziemowit Laski
9bc4c2d9a5 [CPP-434] Ctrl + Shift + F. 2019-10-21 18:40:20 -07:00
Ziemowit Laski
2292518933 [CPP-434] Change query so it flags overflows that were cast to unsigned. 2019-10-21 17:04:46 -07:00
Erik Krogh Kristensen
2e0244cda6 address review feedback 2019-10-21 20:32:45 +02:00
yh-semmle
28720679ad Java: remove some obsolete metric queries 2019-10-19 20:55:46 -04:00
Ziemowit Laski
6772fa1352 [CPP-434] Reformat QHelp. 2019-10-17 17:21:14 -07:00
Ziemowit Laski
70441edacf [CPP-434] Additional test case; improve QHelp by including themes from the BadAdditionOverflowCheck QHelp. 2019-10-17 16:41:17 -07:00
Robert Marsh
6cef936046 C++: add function info to duplicateChiOperand 2019-10-16 15:59:00 -07:00
Ziemowit Laski
fb625c12ef [CPP-434] Move SignedOverflowCheck test to BadAdditionOverflowCheck directory; add additional tests. 2019-10-16 14:31:11 -07:00
Ziemowit Laski
f40c21bf6e [CPP-434] Add release note. 2019-10-14 08:06:02 -07:00
Erik Krogh Kristensen
28056791a5 add .getALocalSource() when testing for lodash-members 2019-10-14 14:14:26 +02:00
Ziemowit Laski
5558922b31 [CPP-434] Drop the requirement that RHS not be cast to unsigned, since overflow occurs on LHS. Adjust test case. 2019-10-11 17:01:16 -07:00
Erik Krogh Kristensen
a7c1c34e1e fix test output, and add new test for array callbacks 2019-10-11 17:14:58 +02:00
Erik Krogh Kristensen
592cb18bf4 add array callbacks to useOfReturnlessFunction query 2019-10-11 16:26:27 +02:00
Erik Krogh Kristensen
31009d979d add type tracking to detect instances 2019-10-11 12:04:34 +02:00
Ziemowit Laski
33cd6de729 [CPP-434] Improved query and test suite. 2019-10-10 18:11:35 -07:00
Erik Krogh Kristensen
0a6b343820 add "class Deferred{...}" as potential Deferred implementation to fix the tests 2019-10-10 11:50:34 +02:00
Ziemowit Laski
1ab965761b [CPP-434] Incorporate test from BadAdditionOverflowCheck. 2019-10-09 17:30:30 -07:00
Ziemowit Laski
7fc47d496a [CPP-434] Much improved query (producing only true positives on a run of 75 projects). 2019-10-09 16:40:19 -07:00
Erik Krogh Kristensen
4ec825b5b6 made model of Deferred more precise 2019-10-09 16:18:04 +02:00
Erik Krogh Kristensen
c7eb0f17a9 add TaintTracking test for new Deferred model 2019-10-09 13:59:00 +02:00
Erik Krogh Kristensen
411ed702fb change change-notes 2019-10-09 13:50:12 +02:00
Erik Krogh Kristensen
0ccc0057f9 add Deferred model to Promises.qll 2019-10-09 11:04:19 +02:00
Ziemowit Laski
e617a05a1f [CPP-434] One bad usage is undetected; adjust test accordingly. 2019-10-08 17:20:25 -07:00
Ziemowit Laski
bd87d7bc76 [CPP-434] Switch to global value numbering (GVN). Improve qlhelp doc. 2019-10-08 16:33:05 -07:00
Ziemowit Laski
afa34b5054 [CPP-434] Improvements to Qhelp; hashCons-ify query. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
872054a89a [CPP-434] Narrow down query. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
341dc12fc8 [CPP-434] Adjust expected output. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
16411d1b6e [CPP-434] Remove references to underflow and subtraction. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
8c6caf2b4e [CPP-434] Rename everything to SignedOverflowCheck. Add .qlhelp. Deal with addition only, not subtraction. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
c9a9aff221 [CPP-434] Expected result. 2019-10-08 14:12:35 -07:00
Ziemowit Laski
55c26a8880 [CPP-434] Initial version of query + test cases. 2019-10-08 14:12:34 -07:00
Robert Marsh
7fa367d6cf C++: autoformat 2019-10-07 16:37:35 -07:00
Robert Marsh
5c084f8b39 C++: respond to more PR comments 2019-10-07 14:17:56 -07:00
Robert Marsh
b60e7c204d C++: autoformat and accept test output 2019-10-07 14:07:25 -07:00
Robert Marsh
057c634fe4 C++: fix identical chi node operands 2019-10-04 13:05:47 -07:00
Robert Marsh
17e14348d5 C++: sanity test for identical Chi node operands 2019-10-04 12:57:30 -07:00
Robert Marsh
3377f88494 C++: generate Chi nodes on total IndirectMayWrites 2019-10-04 11:59:22 -07:00
Robert Marsh
5f8a3054d1 C++: add UninitializedInstructions for direct init 2019-10-04 11:34:14 -07:00
Sam Lanning
b67c5f2cbc Merge pull request #2083 from jf205/training-logo
QL training: add semmle logo image to title slide
2019-10-04 11:33:06 -07:00
james
4a8e8fa0de docs: semmle logo 2019-10-04 09:28:45 +01:00
Robert Marsh
bc973973df C++: accept test changes 2019-10-03 14:43:54 -07:00
Robert Marsh
a76c4d9b3b C++: index for constructor qualifier side effects 2019-10-03 12:39:32 -07:00
Robert Marsh
47b9c497fa C++: IR SSA tests for explicit constructor calls 2019-10-03 12:25:41 -07:00
Robert Marsh
4018ed67a6 C++: respond to PR comments 2019-10-02 11:38:20 -07:00
Robert Marsh
68c38ba34a C++: Add change note 2019-10-02 11:38:20 -07:00
Robert Marsh
03f72d207c C++: use Declaration.hasGlobalOrStdName 2019-10-02 11:37:37 -07:00
Robert Marsh
bff68a00ac C++: Add Declaration.hasStdName 2019-10-02 11:37:37 -07:00
Robert Marsh
98b97b09be C++: add hasGlobalOrStdName to Declaration 2019-10-02 11:37:37 -07:00
Robert Marsh
53f522c7f6 C++: respond to PR comments and autoformat 2019-10-02 10:11:58 -07:00
semmle-qlci
47024dc6ec Merge pull request #2069 from felicitymay/1.22/SD-3940-golang
Approved by jf205
2019-10-02 10:40:38 +01:00
Felicity Chapman
56ed2f618d Add alias for easier user-searching 2019-10-02 09:05:31 +01:00
Robert Marsh
bace8c723d C++: side effect instrs for constructor qualifiers
This adds IndirectMustWriteSideEffects for constructor qualifiers. The
introduced sanity failures result from constructor calls without qualifier
operands in the IR
2019-10-01 14:53:37 -07:00
shati-patel
ff093c26a1 Merge pull request #2057 from jf205/small-fixes
QL training slides: increase release number and small css tweaks
2019-09-30 14:28:30 +01:00
james
ff78feeeea docs: version number and small css tweaks 2019-09-30 12:15:26 +01:00
Felicity Chapman
91a8391c84 Merge pull request #2037 from jf205/python-docs-fixes
docs: fix some formatting issues
2019-09-27 08:47:49 +01:00
james
3a4cef646d docs: fix some formatting issues 2019-09-26 16:04:01 +01:00
shati-patel
d4fa14a177 Merge pull request #2030 from jf205/python-docs-fixes
Learn QL: QL for Python doc fixes for 1.22
2019-09-26 10:54:21 +01:00
Rasmus Wriedt Larsen
94d876e8a3 Learn QL: Fix query link in Python Points-to tutorial
(cherry picked from commit c6c565bc37)
2019-09-26 10:44:29 +01:00
Rasmus Wriedt Larsen
9511465f04 Learn QL: Minor formatting fix in python/statements-expressions
(cherry picked from commit c47a4e0c44)
2019-09-26 10:44:29 +01:00
Jonas Jensen
b75bf06649 C++: Accept test changes in other IR tests 2019-09-24 13:00:21 +02:00
semmle-qlci
18a52c3825 Merge pull request #2006 from felicitymay/1.22/supported-systems
Approved by jf205, xiemaisi
2019-09-24 09:20:25 +01:00
Felicity Chapman
61b372b062 Add Go to supported languages topic and update release number 2019-09-23 17:52:02 +01:00
Jonas Jensen
a34c0d4200 C++: Autoformat TranslatedExpr.qll 2019-09-23 15:39:32 +02:00
Jonas Jensen
cd5f3b84a8 C++: Make sure there's a Instruction for each Expr
This change ensures that all `Expr`s (except parentheses) have a
`TranslatedExpr` with a `getResult` that's one of its own instructions,
not an instruction from one of its operands. This means that when we
translate back and forth between `Expr` and `Instruction`, like in
`DataFlow::exprNode`, we will not conflate `e` with `&e` or `... = e`.
2019-09-23 15:23:31 +02:00
semmledocs-ac
573796c0ea Merge pull request #1984 from jf205/ql-links/sd-3902
docs: fix links in QL topics
2019-09-20 11:37:59 +01:00
james
06b391ef9b docs: fix links 2019-09-20 11:14:16 +01:00
Luke Cartey
5e409a3eaa Python: Change invalid @kind. 2019-05-16 12:33:02 +01:00
1031 changed files with 52587 additions and 31238 deletions

View File

@@ -1,4 +1,5 @@
{ "provide": [ "*/ql/src/qlpack.yml",
"*/ql/test/qlpack.yml",
"*/upgrades/qlpack.yml",
"misc/legacy-support/*/qlpack.yml",
"misc/suite-helpers/qlpack.yml",

View File

@@ -1,7 +1,8 @@
/cpp/ @Semmle/cpp-analysis
/csharp/ @Semmle/cs
/java/ @Semmle/java
/javascript/ @Semmle/js
/cpp/ @Semmle/cpp-analysis
/python/ @Semmle/python
/cpp/**/*.qhelp @hubwriter
/csharp/**/*.qhelp @jf205
/java/**/*.qhelp @felicitymay

View File

@@ -1,4 +1,4 @@
# Contributing to QL
# Contributing to CodeQL
We welcome contributions to our standard library and standard checks. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request!
@@ -9,13 +9,13 @@ Before we accept your pull request, we require that you have agreed to our Contr
If you have an idea for a query that you would like to share with other Semmle users, please open a pull request to add it to this repository.
Follow the steps below to help other users understand what your query does, and to ensure that your query is consistent with the other Semmle queries.
1. **Consult the QL documentation for query writers**
1. **Consult the documentation for query writers**
There is lots of useful documentation to help you write QL, ranging from information about query file structure to language-specific tutorials. For more information on the documentation available, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com).
2. **Format your QL correctly**
2. **Format your code correctly**
All of Semmle's standard QL queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all QL contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md).
All of Semmle's standard queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all contributions follow the same formatting guidelines. If you use CodeQL for VS Code, you can autoformat your query in the [Editor](https://help.semmle.com/codeql/codeql-for-vscode/reference/editor.html#autoformatting). For more information, see the [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md).
3. **Make sure your query has the correct metadata**
@@ -26,10 +26,10 @@ Follow the steps below to help other users understand what your query does, and
4. **Make sure the `select` statement is compatible with the query type**
The `select` statement of your query must be compatible with the query type (determined by the `@kind` metadata property) for alert or path results to be displayed correctly in LGTM and QL for Eclipse.
The `select` statement of your query must be compatible with the query type (determined by the `@kind` metadata property) for alert or path results to be displayed correctly in LGTM and CodeQL for VS Code.
For more information on `select` statement format, see [Introduction to query files](https://help.semmle.com/QL/learn-ql/writing-queries/introduction-to-queries.html#select-clause) on help.semmle.com.
5. **Save your query in a `.ql` file in correct language directory in this repository**
5. **Save your query in a `.ql` file in the correct language directory in this repository**
There are five language-specific directories in this repository:
@@ -54,7 +54,7 @@ repositories, which might be made public. We might also use this information
to contact you in relation to your contributions, as well as in the
normal course of software development. We also store records of your
CLA agreements. Under GDPR legislation, we do this
on the basis of our legitimate interest in creating the QL product.
on the basis of our legitimate interest in creating the CodeQL product.
Please do get in touch (privacy@semmle.com) if you have any questions about
this or our data protection policies.

View File

@@ -1,16 +1,16 @@
# Semmle QL
# CodeQL
This open source repository contains the standard QL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide.
This open source repository contains the standard CodeQL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide.
## How do I learn QL and run queries?
## How do I learn CodeQL and run queries?
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing QL.
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open-source project that's currently being analyzed.
There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL.
You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode.html) extension to try out your queries on any open source project that's currently being analyzed.
## Contributing
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your QL for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query.
## License
The QL queries in this repository are licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com).
The code in this repository is licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com).

View File

@@ -2,55 +2,65 @@
The following changes in version 1.23 affect C/C++ analysis in all applications.
## General improvements
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). |
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). Results are not shown on LGTM by default. |
| Pointer overflow check (`cpp/pointer-overflow-check`) | correctness, security | Finds overflow checks that rely on pointer addition to overflow, which has undefined behavior. Example: `ptr + a < ptr`. Results are shown on LGTM by default. |
| Signed overflow check (`cpp/signed-overflow-check`) | correctness, security | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. Results are shown on LGTM by default. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------------------------------------------------------------|
| Query name (`query id`) | Expected impact | Message. |
| Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. |
| Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. |
| Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`) | Deprecated | This query has been deprecated. Use the new combined query Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) instead. |
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | More correct results | This query now checks for the beginning date of the Reiwa era (1st May 2019). |
| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Fixed false positive results triggrered by mismatching declarations of a formatting function. |
| Sign check of bitwise operation (`cpp/bitwise-sign-check`) | Fewer false positive results | Results involving `>=` or `<=` are no longer reported. |
| Too few arguments to formatting function (`cpp/wrong-number-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
| Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. |
| Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. |
| Too few arguments to formatting function (`cpp/wrong-number-format-arguments`) | Fewer false positive results | Fixed false positive results triggered by mismatching declarations of a formatting function. |
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positive results triggered by mismatching declarations of a formatting function. |
| Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positive results involving template classes and functions have been fixed. |
| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | More correct results and fewer false positive results | This query now understands explicitly-specified argument numbers in format strings, such as the `1$` in `%1$s`. |
## Changes to QL libraries
## Changes to libraries
* The data-flow library has been extended with a new feature to aid debugging.
Instead of specifying `isSink(Node n) { any() }` on a configuration to
explore the possible flow from a source, it is recommended to use the new
`Configuration::hasPartialFlow` predicate, as this gives a more complete
picture of the partial flow paths from a given source. The feature is
disabled by default and can be enabled for individual configurations by
overriding `int explorationLimit()`.
* The data-flow library now supports flow out of C++ reference parameters.
* The data-flow library now allows flow through the address-of operator (`&`).
* The `DataFlow::DefinitionByReferenceNode` class now considers `f(x)` to be a
definition of `x` when `x` is a variable of pointer type. It no longer
considers deep paths such as `f(&x.myField)` to be definitions of `x`. These
changes are in line with the user expectations we've observed.
* The data-flow library now makes it easier to specify barriers/sanitizers
arising from guards by overriding the predicate
`isBarrierGuard`/`isSanitizerGuard` on data-flow and taint-tracking
configurations respectively.
* There is now a `DataFlow::localExprFlow` predicate and a
`TaintTracking::localExprTaint` predicate to make it easy to use the most
common case of local data flow and taint: from one `Expr` to another.
* The data-flow library in `semmle.code.cpp.dataflow.DataFlow` and
`semmle.code.cpp.dataflow.TaintTracking` have had extensive changes:
* Data flow through fields is now more complete and reliable.
* The data-flow library has been extended with a new feature to aid debugging.
Previously, to explore the possible flow from all sources you could specify `isSink(Node n) { any() }` on a configuration.
Now you can use the new `Configuration::hasPartialFlow` predicate,
which gives a more complete picture of the partial flow paths from a given source, including flow that doesn't reach any sink.
The feature is disabled by default and can be enabled for individual configurations by overriding `int explorationLimit()`.
* There is now flow out of C++ reference parameters.
* There is now flow through the address-of operator (`&`).
* The `DataFlow::DefinitionByReferenceNode` class now considers `f(x)` to be a
definition of `x` when `x` is a variable of pointer type. It no longer
considers deep paths such as `f(&x.myField)` to be definitions of `x`. These
changes are in line with the user expectations we've observed.
* It's now easier to specify barriers/sanitizers
arising from guards by overriding the predicate
`isBarrierGuard`/`isSanitizerGuard` on data-flow and taint-tracking
configurations respectively.
* There is now a `DataFlow::localExprFlow` predicate and a
`TaintTracking::localExprTaint` predicate to make it easy to use the most
common case of local data flow and taint: from one `Expr` to another.
* The member predicates of the `FunctionInput` and `FunctionOutput` classes have been renamed for
clarity (e.g. `isOutReturnPointer()` to `isReturnValueDeref()`). The existing member predicates
clarity (for example, `isOutReturnPointer()` to `isReturnValueDeref()`). The existing member predicates
have been deprecated, and will be removed in a future release. Code that uses the old member
predicates should be updated to use the corresponding new member predicate.
* The predicate `Declaration.hasGlobalOrStdName` has been added, making it
easier to recognize C library functions called from C++.
* The control-flow graph is now computed in QL, not in the extractor. This can
lead to regressions (or improvements) in how queries are optimized because
lead to changes in how queries are optimized because
optimization in QL relies on static size estimates, and the control-flow edge
relations will now have different size estimates than before.
* Support has been added for non-type template arguments. This means that the
return type of `Declaration::getTemplateArgument()` and
`Declaration::getATemplateArgument` have changed to `Locatable`. For details, see the
CodeQL library documentation for `Declaration::getTemplateArgument()` and
`Declaration::getTemplateArgumentKind()`.

View File

@@ -4,46 +4,42 @@ The following changes in version 1.23 affect C# analysis in all applications.
## New queries
## New queries
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. |
| Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. |
| Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. |
| Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. Results are shown on LGTM by default. |
| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security, external/cwe/cwe-502 | Finds flow of untrusted input to calls to unsafe deserializers. Results are shown on LGTM by default. |
| Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. Results are not shown on LGTM by default. |
| Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. Results are not shown on LGTM by default. |
| Unsafe deserializer (`cs/unsafe-deserialization`) | security, external/cwe/cwe-502 | Finds calls to unsafe deserializers. By default, the query is not run on LGTM. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|------------------------------|------------------------|-----------------------------------|
| Dereferenced variable may be null (`cs/dereferenced-value-may-be-null`) | Fewer false positive results | More `null` checks are now taken into account, including `null` checks for `dynamic` expressions and `null` checks such as `object alwaysNull = null; if (x != alwaysNull) ...`. |
| Missing Dispose call on local IDisposable (`cs/local-not-disposed`) | Fewer false positive results | The query has been rewritten in order to identify more dispose patterns. For example, a local `IDisposable` that is disposed of by passing through a fluent API is no longer reported. |
## Removal of old queries
| Missing Dispose call on local IDisposable (`cs/local-not-disposed`) | Fewer false positive results | The query has been rewritten in order to identify more dispose patterns. For example, a local `IDisposable` that is disposed of by passing through a fluent API is no longer reported as missing a dispose call. |
## Changes to code extraction
* `nameof` expressions are now extracted correctly when the name is a namespace.
## Changes to QL libraries
## Changes to libraries
* The new class `NamespaceAccess` models accesses to namespaces, for example in `nameof` expressions.
* The data-flow library now makes it easier to specify barriers/sanitizers
arising from guards by overriding the predicate
arising from guards. You can override the predicate
`isBarrierGuard`/`isSanitizerGuard` on data-flow and taint-tracking
configurations respectively.
* The data-flow library has been extended with a new feature to aid debugging.
Instead of specifying `isSink(Node n) { any() }` on a configuration to
explore the possible flow from a source, it is recommended to use the new
`Configuration::hasPartialFlow` predicate, as this gives a more complete
picture of the partial flow paths from a given source. The feature is
disabled by default and can be enabled for individual configurations by
Previously, to explore the possible flow from all sources you could specify `isSink(Node n) { any() }` on a configuration.
Now you can use the new `Configuration::hasPartialFlow` predicate,
which gives a more complete picture of the partial flow paths from a given source, including flow that doesn't reach any sink.
The feature is disabled by default and can be enabled for individual configurations by
overriding `int explorationLimit()`.
* `foreach` statements where the body is guaranteed to be executed at least once, such as `foreach (var x in new string[]{ "a", "b", "c" }) { ... }`, are now recognized by all analyses based on the control flow graph (such as SSA, data flow and taint tracking).
* Fixed the control flow graph for `switch` statements where the `default` case was not the last case. This had caused the remaining cases to be unreachable. `SwitchStmt.getCase(int i)` now puts the `default` case last.
* `foreach` statements where the body is guaranteed to be executed at least once, such as `foreach (var x in new string[]{ "a", "b", "c" }) { ... }`, are now recognized by all analyses based on the control-flow graph (such as SSA, data flow and taint tracking).
* Fixed the control-flow graph for `switch` statements where the `default` case was not the last case. This had caused the remaining cases to be unreachable. `SwitchStmt.getCase(int i)` now puts the `default` case last.
* There is now a `DataFlow::localExprFlow` predicate and a
`TaintTracking::localExprTaint` predicate to make it easy to use the most
common case of local data flow and taint: from one `Expr` to another.
* Data is now tracked through null-coalescing expressions (`??`).
## Changes to autobuilder
* A new library `semmle.code.csharp.Unification` has been added. This library exposes two predicates `unifiable` and `subsumes` for calculating type unification and type subsumption, respectively.

View File

@@ -6,25 +6,24 @@ The following changes in version 1.23 affect Java analysis in all applications.
| **Query** | **Tags** | **Purpose** |
|-----------------------------|-----------|--------------------------------------------------------------------|
| Continue statement that does not continue (`java/continue-in-false-loop`) | correctness | Finds `continue` statements in `do { ... } while (false)` loops. |
| Continue statement that does not continue (`java/continue-in-false-loop`) | correctness | Finds `continue` statements in `do { ... } while (false)` loops. Results are shown on LGTM by default. |
| Disabled Netty HTTP header validation (`java/netty-http-response-splitting`) | security, external/cwe/cwe-113 | Finds response-splitting vulnerabilities due to Netty HTTP header validation being disabled. Results are shown on LGTM by default. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|------------------------------|------------------------|-----------------------------------|
| Dereferenced variable may be null (`java/dereferenced-value-may-be-null`) | Fewer false positives | Certain indirect null guards involving two auxiliary variables known to be equal can now be detected. |
| Non-synchronized override of synchronized method (`java/non-sync-override`) | Fewer false positives | Results are now only reported if the immediately overridden method is synchronized. |
| Query built from user-controlled sources (`java/sql-injection`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. |
| Query built from local-user-controlled sources (`java/sql-injection-local`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. |
| Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. |
| Useless comparison test (`java/constant-comparison`) | Fewer false positives | Additional overflow check patterns are now recognized and no longer reported. |
| Dereferenced variable may be null (`java/dereferenced-value-may-be-null`) | Fewer false positive results | Additional indirect null guards are detected, where two auxiliary variables are known to be equal. |
| Non-synchronized override of synchronized method (`java/non-sync-override`) | Fewer false positive results | Results are now only reported if the immediately overridden method is synchronized. |
| Query built from local-user-controlled sources (`java/sql-injection-local`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as sinks for SQL expressions. |
| Query built from user-controlled sources (`java/sql-injection`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as sinks for SQL expressions. |
| Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as sinks for SQL expressions. |
| Useless comparison test (`java/constant-comparison`) | Fewer false positive results | Additional overflow check patterns are now recognized and no longer reported. Also, a few bug fixes in the range analysis for floating-point variables gives a further reduction in false positive results. |
## Changes to QL libraries
## Changes to libraries
* The data-flow library has been extended with a new feature to aid debugging.
Instead of specifying `isSink(Node n) { any() }` on a configuration to
explore the possible flow from a source, it is recommended to use the new
`Configuration::hasPartialFlow` predicate, as this gives a more complete
picture of the partial flow paths from a given source. The feature is
disabled by default and can be enabled for individual configurations by
overriding `int explorationLimit()`.
The data-flow library has been extended with a new feature to aid debugging.
Previously, to explore the possible flow from all sources you could specify `isSink(Node n) { any() }` on a configuration.
Now you can use the new `Configuration::hasPartialFlow` predicate,
which gives a more complete picture of the partial flow paths from a given source, including flow that doesn't reach any sink.
The feature is disabled by default and can be enabled for individual configurations by overriding `int explorationLimit()`.

View File

@@ -2,68 +2,81 @@
## General improvements
* Suppor for `globalThis` has been added.
* Automatic classification of generated and minified files has been improved, in particular files generated by Doxygen are now recognized.
* Support for `globalThis` has been added.
* Support for the following frameworks and libraries has been improved:
- [firebase](https://www.npmjs.com/package/firebase)
- [get-them-args](https://www.npmjs.com/package/get-them-args)
- [minimist](https://www.npmjs.com/package/minimist)
- [mongodb](https://www.npmjs.com/package/mongodb)
- [mongoose](https://www.npmjs.com/package/mongoose)
- [optimist](https://www.npmjs.com/package/optimist)
- [parse-torrent](https://www.npmjs.com/package/parse-torrent)
- [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible)
- [yargs](https://www.npmjs.com/package/yargs)
* The call graph has been improved to resolve method calls in more cases. This may produce more security alerts.
* TypeScript 3.6 features are supported.
* TypeScript 3.6 and 3.7 features are now supported.
## New queries
| **Query** | **Tags** | **Purpose** |
|---------------------------------------------------------------------------|-------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Unused index variable (`js/unused-index-variable`) | correctness | Highlights loops that iterate over an array, but do not use the index variable to access array elements, indicating a possible typo or logic error. Results are shown on LGTM by default. |
| Loop bound injection (`js/loop-bound-injection`) | security, external/cwe/cwe-834 | Highlights loops where a user-controlled object with an arbitrary .length value can trick the server to loop indefinitely. Results are shown on LGTM by default. |
| Suspicious method name (`js/suspicious-method-name-declaration`) | correctness, typescript, methods | Highlights suspiciously named methods where the developer likely meant to write a constructor or function. Results are shown on LGTM by default. |
| Ignoring result from pure array method (`js/ignore-array-result`) | maintainability, correctness | Highlights calls to array methods without side effects where the return value is ignored. Results are shown on LGTM by default. |
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | security, correctness, external/cwe/cwe-020 | Highlights checks for `javascript:` URLs that do not take `data:` or `vbscript:` URLs into account. Results are shown on LGTM by default. |
| Loop bound injection (`js/loop-bound-injection`) | security, external/cwe/cwe-834 | Highlights loops where a user-controlled object with an arbitrary `.length` value can trick the server into looping indefinitely. Results are shown on LGTM by default. |
| Shell command built from environment values (`js/shell-command-injection-from-environment`) | correctness, security, external/cwe/cwe-078, external/cwe/cwe-088 | Highlights shell commands that may change behavior inadvertently depending on the execution environment, indicating a possible violation of [CWE-78](https://cwe.mitre.org/data/definitions/78.html). Results are shown on LGTM by default.|
| Suspicious method name (`js/suspicious-method-name-declaration`) | correctness, typescript, methods | Highlights suspiciously named methods where the developer likely meant to write a constructor or function. Results are shown on LGTM by default. |
| Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. |
| Unused index variable (`js/unused-index-variable`) | correctness | Highlights loops that iterate over an array, but do not use the index variable to access array elements, indicating a possible typo or logic error. Results are shown on LGTM by default. |
| Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. |
| Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. |
| Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. |
## Changes to existing queries
| **Query** | **Expected impact** | **Change** |
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. |
| Client-side cross-site scripting (`js/xss`) | More results, fewer false-positive results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized, and more sanitizers are detected. |
| Client-side cross-site scripting (`js/xss`) | More results, fewer false positive results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized, and more sanitizers are detected. |
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. |
| Hard-coded credentials (`js/hardcoded-credentials`) | Fewer false-positive results | This rule now flags fewer password examples. |
| Illegal invocation (`js/illegal-invocation`) | Fewer false-positive results | This rule now correctly handles methods named `call` and `apply`. |
| Incorrect suffix check (`js/incorrect-suffix-check`) | Fewer false-positive results | The query recognizes valid checks in more cases. |
| Network data written to file (`js/http-to-file-access`) | Fewer false-positive results | This query has been renamed to better match its intended purpose, and now only considers network data untrusted. |
| Password in configuration file (`js/password-in-configuration-file`) | Fewer false-positive results | This rule now flags fewer password examples. |
| Hard-coded credentials (`js/hardcoded-credentials`) | Fewer false positive results | This rule now flags fewer password examples. |
| Illegal invocation (`js/illegal-invocation`) | Fewer false positive results | This rule now correctly handles methods named `call` and `apply`. |
| Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false positive results | This rule now recognizes additional ways delimiters can be stripped away. |
| Incorrect suffix check (`js/incorrect-suffix-check`) | Fewer false positive results | The query recognizes valid checks in more cases. |
| Network data written to file (`js/http-to-file-access`) | Fewer false positive results | This query has been renamed to better match its intended purpose, and now only considers network data untrusted. |
| Password in configuration file (`js/password-in-configuration-file`) | Fewer false positive results | This rule now flags fewer password examples. |
| Prototype pollution (`js/prototype-pollution`) | More results | The query now highlights vulnerable uses of jQuery and Angular, and the results are shown on LGTM by default. |
| Reflected cross-site scripting (`js/reflected-xss`) | Fewer false-positive results | The query now recognizes more sanitizers. |
| Stored cross-site scripting (`js/stored-xss`) | Fewer false-positive results | The query now recognizes more sanitizers. |
| Reflected cross-site scripting (`js/reflected-xss`) | Fewer false positive results | The query now recognizes more sanitizers. |
| Stored cross-site scripting (`js/stored-xss`) | Fewer false positive results | The query now recognizes more sanitizers. |
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now treats responses from servers as untrusted. |
| Uncontrolled data used in path expression (`js/path-injection`) | Fewer false-positive results | This query now recognizes calls to Express `sendFile` as safe in some cases. |
| Uncontrolled data used in path expression (`js/path-injection`) | Fewer false positive results | This query now recognizes calls to Express `sendFile` as safe in some cases. |
| Unknown directive (`js/unknown-directive`) | Fewer false positive results | This query no longer flags uses of ":", which is sometimes used like a directive. |
## Changes to QL libraries
## Changes to libraries
* `Expr.getDocumentation()` now handles chain assignments.
* String literals are now parsed as regular expressions.
Consequently, a `RegExpTerm` may occur as part of a string literal or
as a regular expression literal. Queries that search for regular expressions may need to
use `RegExpTerm.isPartOfRegExpLiteral` or `RegExpTerm.isUsedAsRegExp` to restrict the search.
A regular expression AST can be obtained from a string literal using `StringLiteral.asRegExp`.
## Removal of deprecated queries
The following queries (deprecated since 1.17) are no longer available in the distribution:
* Builtin redefined (js/builtin-redefinition)
* Inefficient method definition (js/method-definition-in-constructor)
* Bad parity check (js/incomplete-parity-check)
* Potentially misspelled property or variable name (js/wrong-capitalization)
* Unknown JSDoc tag (js/jsdoc/unknown-tag-type)
* Builtin redefined (js/builtin-redefinition)
* Call to parseInt without radix (js/parseint-without-radix)
* Inefficient method definition (js/method-definition-in-constructor)
* Invalid JSLint directive (js/jslint/invalid-directive)
* Malformed JSLint directive (js/jslint/malformed-directive)
* Use of HTML comments (js/html-comment)
* Multi-line string literal (js/multi-line-string)
* Octal literal (js/octal-literal)
* Potentially misspelled property or variable name (js/wrong-capitalization)
* Reserved word used as variable name (js/use-of-reserved-word)
* Trailing comma in array or object expressions (js/trailing-comma-in-array-or-object)
* Call to parseInt without radix (js/parseint-without-radix)
* Unknown JSDoc tag (js/jsdoc/unknown-tag-type)
* Use of HTML comments (js/html-comment)

View File

@@ -3,7 +3,19 @@
## General improvements
### Python 3.8 support
Python 3.8 syntax is now supported. In particular, the following constructs are parsed correctly:
- Assignment expressions using the "walrus" operator, such as `while chunk := file.read(1024): ...`.
- The positional argument separator `/`, such as in `def foo(a, /, b, *, c): ...`.
- Self-documenting expressions in f-strings, such as `f"{var=}"`.
### General query improvements
Following the replacement of the `Object` API (for example, `ClassObject`) in favor of the
`Value` API (for example, `ClassValue`) in the 1.21 release, many of the standard queries have been updated
to use the `Value` API. This should result in more precise results.
## New queries
@@ -18,5 +30,23 @@
| **Query** | **Expected impact** | **Change** |
|----------------------------|------------------------|------------|
| Unreachable code | Fewer false positives | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. |
| `__iter__` method returns a non-iterator | Better alert message | Alert now highlights which class is expected to be an iterator. |
| Explicit export is undefined (`py/undefined-export`) | Fewer false positive results | Instances where an exported value may be defined in a module that lacks points-to information are no longer flagged. |
| Module-level cyclic import (`py/unsafe-cyclic-import`) | Fewer false positive results | Instances where one of the links in an import cycle is never actually executed are no longer flagged. |
| Non-iterable used in for loop (`py/non-iterable-in-for-loop`) | Fewer false positive results | `__aiter__` is now recognized as an iterator method. |
| Unreachable code (`py/unreachable-statement`) | Fewer false positive results | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. |
| Unreachable code (`py/unreachable-statement`) | Fewer false positive results | Unreachable `else` branches that do nothing but `assert` their non-reachability are no longer flagged. |
| Unused import (`py/unused-import`) | Fewer false positive results | Instances where a module is used in a forward-referenced type annotation, or only during type checking are no longer flagged. |
| `__iter__` method returns a non-iterator (`py/iter-returns-non-iterator`) | Better alert message | Alert now highlights which class is expected to be an iterator. |
| `__init__` method returns a value (`py/explicit-return-in-init`) | Fewer false positive results | Instances where the `__init__` method returns the value of a call to a procedure are no longer flagged. |
## Changes to QL libraries
* Django library now recognizes positional arguments from a `django.conf.urls.url` regex (Django version 1.x)
* Instances of the `Value` class now support the `isAbsent` method, indicating
whether that `Value` lacks points-to information, but inference
suggests that it exists. For instance, if a file contains `import
django`, but `django` was not extracted properly, there will be a
`ModuleValue` corresponding to this "unknown" module, and the `isAbsent`
method will hold for this `ModuleValue`.
* The `Expr` class now has a nullary method `pointsTo` that returns the possible
instances of `Value` that this expression may have.

View File

@@ -7,17 +7,17 @@
* Asynchronous generator methods are now parsed correctly and no longer cause a spurious syntax error.
* Files in `node_modules` and `bower_components` folders are no longer extracted by default. If you still want to extract files from these folders, you can add the following filters to your `lgtm.yml` file (or add them to existing filters):
```yaml
extraction:
javascript:
index:
filters:
- include: "**/node_modules"
- include: "**/bower_components"
```
```yaml
extraction:
javascript:
index:
filters:
- include: "**/node_modules"
- include: "**/bower_components"
```
* Additional [Flow](https://flow.org/) syntax is now supported.
* Recognition of CommonJS modules has improved. As a result, some files that were previously extracted as
global scripts are now extracted as modules.
* Top-level `await` is now supported.
* A bug was fixed in how the TypeScript extractor handles default-exported anonymous classes.
* A bug was fixed in how the TypeScript extractor handles computed instance field names.
* Bugs were fixed in how the TypeScript extractor handles default-exported anonymous classes and computed-instance field names.

View File

@@ -1,6 +1,6 @@
# Files moved to ``docs`` directory
Now that all of the QL documentation is in this repository,
Now that all of the CodeQL documentation is in this repository,
notes on the languages, compilers, and frameworks supported have moved.
They're now stored as part of the Sphinx ``support`` project with the other documentation:
``docs/language/support``.

View File

@@ -23,6 +23,8 @@
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/BitwiseSignCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/SignedOverflowCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/PointerOverflow.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/NestedLoopSameVar.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/UseInOwnInitializer.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewArrayDeleteMismatch.ql: /Correctness/Common Errors

View File

@@ -24,6 +24,8 @@
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/FloatComparison.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/BitwiseSignCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/BadAdditionOverflowCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Arithmetic/SignedOverflowCheck.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/Memory Management/PointerOverflow.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/NestedLoopSameVar.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Likely Bugs/UseInOwnInitializer.ql: /Correctness/Common Errors
+ semmlecode-cpp-queries/Critical/NewArrayDeleteMismatch.ql: /Correctness/Common Errors

View File

@@ -13,7 +13,7 @@ import semmle.code.cpp.pointsto.PointsTo
import Negativity
predicate closeCall(FunctionCall fc, Variable v) {
fc.getTarget().hasGlobalName("close") and v.getAnAccess() = fc.getArgument(0)
fc.getTarget().hasGlobalOrStdName("close") and v.getAnAccess() = fc.getArgument(0)
or
exists(FunctionCall midcall, Function mid, int arg |
fc.getArgument(arg) = v.getAnAccess() and

View File

@@ -13,7 +13,7 @@ import semmle.code.cpp.pointsto.PointsTo
predicate closed(Expr e) {
exists(FunctionCall fc |
fc.getTarget().hasGlobalName("close") and
fc.getTarget().hasGlobalOrStdName("close") and
fc.getArgument(0) = e
)
}

View File

@@ -53,7 +53,7 @@ predicate allocCallOrIndirect(Expr e) {
* can cause memory leaks.
*/
predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode verified) {
reallocCall.getTarget().hasGlobalName("realloc") and
reallocCall.getTarget().hasGlobalOrStdName("realloc") and
reallocCall.getArgument(0) = v.getAnAccess() and
(
exists(Variable newV, ControlFlowNode node |
@@ -79,7 +79,7 @@ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode
predicate freeCallOrIndirect(ControlFlowNode n, Variable v) {
// direct free call
freeCall(n, v.getAnAccess()) and
not n.(FunctionCall).getTarget().hasGlobalName("realloc")
not n.(FunctionCall).getTarget().hasGlobalOrStdName("realloc")
or
// verified realloc call
verifiedRealloc(_, v, n)

View File

@@ -13,10 +13,7 @@
import cpp
class MallocCall extends FunctionCall {
MallocCall() {
this.getTarget().hasGlobalName("malloc") or
this.getTarget().hasQualifiedName("std", "malloc")
}
MallocCall() { this.getTarget().hasGlobalOrStdName("malloc") }
Expr getAllocatedSize() {
if this.getArgument(0) instanceof VariableAccess
@@ -36,12 +33,12 @@ predicate spaceProblem(FunctionCall append, string msg) {
malloc.getAllocatedSize() = add and
buffer.getAnAccess() = strlen.getStringExpr() and
(
insert.getTarget().hasGlobalName("strcpy") or
insert.getTarget().hasGlobalName("strncpy")
insert.getTarget().hasGlobalOrStdName("strcpy") or
insert.getTarget().hasGlobalOrStdName("strncpy")
) and
(
append.getTarget().hasGlobalName("strcat") or
append.getTarget().hasGlobalName("strncat")
append.getTarget().hasGlobalOrStdName("strcat") or
append.getTarget().hasGlobalOrStdName("strncat")
) and
malloc.getASuccessor+() = insert and
insert.getArgument(1) = buffer.getAnAccess() and

View File

@@ -25,7 +25,7 @@ import semmle.code.cpp.security.TaintTracking
predicate sourceSized(FunctionCall fc, Expr src) {
exists(string name |
(name = "strncpy" or name = "strncat" or name = "memcpy" or name = "memmove") and
fc.getTarget().hasGlobalName(name)
fc.getTarget().hasGlobalOrStdName(name)
) and
exists(Expr dest, Expr size, Variable v |
fc.getArgument(0) = dest and

View File

@@ -60,19 +60,19 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) {
predicate bufferAndSizeFunction(Function f, int buf, int size) {
f.hasGlobalName("read") and buf = 1 and size = 2
or
f.hasGlobalName("fgets") and buf = 0 and size = 1
f.hasGlobalOrStdName("fgets") and buf = 0 and size = 1
or
f.hasGlobalName("strncpy") and buf = 0 and size = 2
f.hasGlobalOrStdName("strncpy") and buf = 0 and size = 2
or
f.hasGlobalName("strncat") and buf = 0 and size = 2
f.hasGlobalOrStdName("strncat") and buf = 0 and size = 2
or
f.hasGlobalName("memcpy") and buf = 0 and size = 2
f.hasGlobalOrStdName("memcpy") and buf = 0 and size = 2
or
f.hasGlobalName("memmove") and buf = 0 and size = 2
f.hasGlobalOrStdName("memmove") and buf = 0 and size = 2
or
f.hasGlobalName("snprintf") and buf = 0 and size = 1
f.hasGlobalOrStdName("snprintf") and buf = 0 and size = 1
or
f.hasGlobalName("vsnprintf") and buf = 0 and size = 1
f.hasGlobalOrStdName("vsnprintf") and buf = 0 and size = 1
}
class CallWithBufferSize extends FunctionCall {

View File

@@ -17,12 +17,12 @@ import cpp
class Allocation extends FunctionCall {
Allocation() {
exists(string name |
this.getTarget().hasGlobalName(name) and
this.getTarget().hasGlobalOrStdName(name) and
(name = "malloc" or name = "calloc" or name = "realloc")
)
}
private string getName() { this.getTarget().hasGlobalName(result) }
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
int getSize() {
this.getName() = "malloc" and

View File

@@ -17,12 +17,12 @@ import cpp
class Allocation extends FunctionCall {
Allocation() {
exists(string name |
this.getTarget().hasGlobalName(name) and
this.getTarget().hasGlobalOrStdName(name) and
(name = "malloc" or name = "calloc" or name = "realloc")
)
}
private string getName() { this.getTarget().hasGlobalName(result) }
private string getName() { this.getTarget().hasGlobalOrStdName(result) }
int getSize() {
this.getName() = "malloc" and

View File

@@ -16,7 +16,7 @@ import semmle.code.cpp.controlflow.LocalScopeVariableReachability
predicate isFreeExpr(Expr e, LocalScopeVariable v) {
exists(VariableAccess va | va.getTarget() = v |
exists(FunctionCall fc | fc = e |
fc.getTarget().hasGlobalName("free") and
fc.getTarget().hasGlobalOrStdName("free") and
va = fc.getArgument(0)
)
or

View File

@@ -59,7 +59,7 @@ class Options extends string {
predicate exits(Function f) {
f.getAnAttribute().hasName("noreturn")
or
exists(string name | f.hasGlobalName(name) |
exists(string name | f.hasGlobalOrStdName(name) |
name = "exit" or
name = "_exit" or
name = "abort" or
@@ -91,7 +91,7 @@ class Options extends string {
* By default holds only for `fgets`.
*/
predicate alwaysCheckReturnValue(Function f) {
f.hasGlobalName("fgets") or
f.hasGlobalOrStdName("fgets") or
CustomOptions::alwaysCheckReturnValue(f) // old Options.qll
}

View File

@@ -13,17 +13,13 @@
import cpp
import PointlessSelfComparison
import semmle.code.cpp.commons.Exclusions
from ComparisonOperation cmp
where
pointlessSelfComparison(cmp) and
not nanTest(cmp) and
not overflowTest(cmp) and
not exists(MacroInvocation mi |
// cmp is in mi
mi.getAnExpandedElement() = cmp and
// and cmp was apparently not passed in as a macro parameter
cmp.getLocation().getStartLine() = mi.getLocation().getStartLine() and
cmp.getLocation().getStartColumn() = mi.getLocation().getStartColumn()
)
not cmp.isFromTemplateInstantiation(_) and
not isFromMacroDefinition(cmp)
select cmp, "Self comparison."

View File

@@ -0,0 +1,3 @@
bool foo(int n1, unsigned short delta) {
return n1 + delta < n1; // BAD
}

View File

@@ -0,0 +1,4 @@
bool bar(unsigned short n1, unsigned short delta) {
// NB: Comparison is always false
return n1 + delta < n1; // GOOD (but misleading)
}

View File

@@ -0,0 +1,4 @@
#include <limits.h>
bool foo(int n1, unsigned short delta) {
return n1 > INT_MAX - delta; // GOOD
}

View File

@@ -0,0 +1,3 @@
bool bar(unsigned short n1, unsigned short delta) {
return (unsigned short)(n1 + delta) < n1; // GOOD
}

View File

@@ -0,0 +1,105 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When checking for integer overflow, you may often write tests like
<code>a + b &lt; a</code>. This works fine if <code>a</code> or
<code>b</code> are unsigned integers, since any overflow in the addition
will cause the value to simply "wrap around." However, using
<i>signed</i> integers is problematic because signed overflow has undefined
behavior according to the C and C++ standards. If the addition overflows
and has an undefined result, the comparison will likewise be undefined;
it may produce an unintended result, or may be deleted entirely by an
optimizing compiler.
</p>
</overview>
<recommendation>
<p>
Solutions to this problem can be thought of as falling into one of two
categories:
</p>
<ol>
<li>Rewrite the signed expression so that overflow cannot occur
but the signedness remains.</li>
<li>Change the variables and all their uses to be unsigned.</li>
</ol>
<p>
The following cases all fall into the first category.
</p>
<ol>
<li>
Given <code>unsigned short n1, delta</code> and <code>n1 + delta &lt; n1</code>,
it is possible to rewrite it as <code>(unsigned short)(n1 + delta)&nbsp;&lt;&nbsp;n1</code>.
Note that <code>n1 + delta</code> does not actually overflow, due to <code>int</code> promotion.
</li>
<li>
Given <code>unsigned short n1, delta</code> and <code>n1 + delta &lt; n1</code>,
it is also possible to rewrite it as <code>n1 &gt; USHORT_MAX - delta</code>. The
<code>limits.h</code> or <code>climits</code> header must then be included.
</li>
<li>
Given <code>int n1, delta</code> and <code>n1 + delta &lt; n1</code>,
it is possible to rewrite it as <code>n1 &gt; INT_MAX - delta</code>. It must be true
that <code>delta &gt;= 0</code> and the <code>limits.h</code> or <code>climits</code>
header has been included.
</li>
</ol>
</recommendation>
<example>
<p>
In the following example, even though <code>delta</code> has been declared
<code>unsigned short</code>, C/C++ type promotion rules require that its
type is promoted to the larger type used in the addition and comparison,
namely a <code>signed int</code>. Addition is performed on
signed integers, and may have undefined behavior if an overflow occurs.
As a result, the entire (comparison) expression may also have an undefined
result.
</p>
<sample src="SignedOverflowCheck-bad1.cpp" />
<p>
The following example builds upon the previous one. Instead of
performing an addition (which could overflow), we have re-framed the
solution so that a subtraction is used instead. Since <code>delta</code>
is promoted to a <code>signed int</code> and <code>INT_MAX</code> denotes
the largest possible positive value for an <code>signed int</code>,
the expression <code>INT_MAX - delta</code> can never be less than zero
or more than <code>INT_MAX</code>. Hence, any overflow and underflow
are avoided.
</p>
<sample src="SignedOverflowCheck-good1.cpp" />
<p>
In the following example, even though both <code>n</code> and <code>delta</code>
have been declared <code>unsigned short</code>, both are promoted to
<code>signed int</code> prior to addition. Because we started out with the
narrower <code>short</code> type, the addition is guaranteed not to overflow
and is therefore defined. But the fact that <code>n1 + delta</code> never
overflows means that the condition <code>n1 + delta &lt; n1</code> will never
hold true, which likely is not what the programmer intended. (see also the
<code>cpp/bad-addition-overflow-check</code> query).
</p>
<sample src="SignedOverflowCheck-bad2.cpp" />
<p>
The next example provides a solution to the previous one. Even though
<code>n1 + delta</code> does not overflow, casting it to an
<code>unsigned short</code> truncates the addition modulo 2^16,
so that <code>unsigned short</code> "wrap around" may now be observed.
Furthermore, since the left-hand side is now of type <code>unsigned short</code>,
the right-hand side does not need to be promoted to a <code>signed int</code>.
</p>
<sample src="SignedOverflowCheck-good2.cpp" />
</example>
<references>
<li><a href="http://c-faq.com/expr/preservingrules.html">comp.lang.c FAQ list · Question 3.19 (Preserving rules)</a></li>
<li><a href="https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data">INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data</a></li>
<li>W. Dietz, P. Li, J. Regehr, V. Adve. <a href="https://www.cs.utah.edu/~regehr/papers/overflow12.pdf">Understanding Integer Overflow in C/C++</a></li>
</references>
</qhelp>

View File

@@ -0,0 +1,32 @@
/**
* @name Signed overflow check
* @description Testing for overflow by adding a value to a variable
* to see if it "wraps around" works only for
* unsigned integer values.
* @kind problem
* @problem.severity warning
* @precision high
* @id cpp/signed-overflow-check
* @tags correctness
* security
*/
import cpp
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
private import semmle.code.cpp.commons.Exclusions
from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2
where
ro.getAnOperand() = add and
add.getAnOperand() = expr1 and
ro.getAnOperand() = expr2 and
globalValueNumber(expr1) = globalValueNumber(expr2) and
add.getUnspecifiedType().(IntegralType).isSigned() and
not isFromMacroDefinition(ro) and
exprMightOverflowPositively(add) and
exists(Compilation c | c.getAFileCompiled() = ro.getFile() |
not c.getAnArgument() = "-fwrapv" and
not c.getAnArgument() = "-fno-strict-overflow"
)
select ro, "Testing for signed overflow may produce undefined results."

View File

@@ -15,24 +15,33 @@ class ConstantZero extends Expr {
}
}
/**
* Holds if `candidate` is an expression such that if it's unsigned then we
* want an alert at `ge`.
*/
private predicate lookForUnsignedAt(GEExpr ge, Expr candidate) {
// Base case: `candidate >= 0`
ge.getRightOperand() instanceof ConstantZero and
candidate = ge.getLeftOperand().getFullyConverted() and
// left operand was a signed or unsigned IntegralType before conversions
// (not a pointer, checking a pointer >= 0 is an entirely different mistake)
// (not an enum, as the fully converted type of an enum is compiler dependent
// so checking an enum >= 0 is always reasonable)
ge.getLeftOperand().getUnderlyingType() instanceof IntegralType
or
// Recursive case: `...(largerType)candidate >= 0`
exists(Conversion conversion |
lookForUnsignedAt(ge, conversion) and
candidate = conversion.getExpr() and
conversion.getType().getSize() > candidate.getType().getSize()
)
}
class UnsignedGEZero extends GEExpr {
UnsignedGEZero() {
this.getRightOperand() instanceof ConstantZero and
// left operand was a signed or unsigned IntegralType before conversions
// (not a pointer, checking a pointer >= 0 is an entirely different mistake)
// (not an enum, as the fully converted type of an enum is compiler dependent
// so checking an enum >= 0 is always reasonable)
getLeftOperand().getUnderlyingType() instanceof IntegralType and
exists(Expr ue |
// ue is some conversion of the left operand
ue = getLeftOperand().getConversion*() and
// ue is unsigned
ue.getUnderlyingType().(IntegralType).isUnsigned() and
// ue may be converted to zero or more strictly larger possibly signed types
// before it is fully converted
forall(Expr following | following = ue.getConversion+() |
following.getType().getSize() > ue.getType().getSize()
)
lookForUnsignedAt(this, ue) and
ue.getUnderlyingType().(IntegralType).isUnsigned()
)
}
}

View File

@@ -1,33 +0,0 @@
import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.controlflow.Guards
import BufferAccess
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
class NetworkFunctionCall extends FunctionCall {
NetworkFunctionCall() {
getTarget().hasName("ntohd") or
getTarget().hasName("ntohf") or
getTarget().hasName("ntohl") or
getTarget().hasName("ntohll") or
getTarget().hasName("ntohs")
}
}
class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
override predicate isSink(DataFlow::Node node) {
node.asExpr() = any(BufferAccess ba).getAccessedLength()
}
override predicate isBarrier(DataFlow::Node node) {
exists(GuardCondition gc, GVN gvn |
gc.getAChild*() = gvn.getAnExpr() and
globalValueNumber(node.asExpr()) = gvn and
gc.controls(node.asExpr().getBasicBlock(), _)
)
}
}

View File

@@ -14,7 +14,7 @@ byte order function, such as <code>ntohl</code>.
The use of a network-to-host byte order function is therefore a good indicator that the returned
value is unvalidated data retrieved from the network, and should not be used without further
validation. In particular, the returned value should not be used as an array index or array length
value without validation, which may result in a buffer overflow vulnerability.
value without validation, as this could result in a buffer overflow vulnerability.
</p>
</overview>
@@ -31,10 +31,10 @@ it to host byte order. The data is then used as an index in an array access expr
there is no validation that the data returned by <code>ntohl</code> is within the bounds of the array,
which could lead to reading outside the bounds of the buffer.
</p>
<sample src="NtohlArrayBad.cpp" />
<sample src="NtohlArrayNoBound-bad.cpp" />
<p>In the corrected example, the returned data is validated against the known size of the buffer,
before being used as an array index.</p>
<sample src="NtohlArrayGood.cpp" />
<sample src="NtohlArrayNoBound-good.cpp" />
</example>
<references>

View File

@@ -1,55 +1,7 @@
import cpp
import semmle.code.cpp.dataflow.TaintTracking
private import semmle.code.cpp.dataflow.RecursionPrevention
/**
* A buffer which includes an allocation size.
*/
abstract class BufferWithSize extends DataFlow::Node {
abstract Expr getSizeExpr();
BufferAccess getAnAccess() {
any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer()))
}
}
/** An allocation function. */
abstract class Alloc extends Function { }
/**
* Allocation functions identified by the QL for C/C++ standard library.
*/
class DefaultAlloc extends Alloc {
DefaultAlloc() { allocationFunction(this) }
}
/** A buffer created through a call to an allocation function. */
class AllocBuffer extends BufferWithSize {
FunctionCall call;
AllocBuffer() {
asExpr() = call and
call.getTarget() instanceof Alloc
}
override Expr getSizeExpr() { result = call.getArgument(0) }
}
/**
* Find accesses of buffers for which we have a size expression.
*/
private class BufferWithSizeConfig extends TaintTracking::Configuration {
BufferWithSizeConfig() { this = "BufferWithSize" }
override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) }
override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() }
override predicate isSanitizer(DataFlow::Node s) {
s = any(BufferWithSize b) and
s.asExpr().getControlFlowScope() instanceof Alloc
}
}
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* An access (read or write) to a buffer, provided as a pair of
@@ -172,3 +124,31 @@ class MallocSizeExpr extends BufferAccess, FunctionCall {
override Expr getAccessedLength() { result = getArgument(1) }
}
class NetworkFunctionCall extends FunctionCall {
NetworkFunctionCall() {
getTarget().hasName("ntohd") or
getTarget().hasName("ntohf") or
getTarget().hasName("ntohl") or
getTarget().hasName("ntohll") or
getTarget().hasName("ntohs")
}
}
class NetworkToBufferSizeConfiguration extends DataFlow::Configuration {
NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" }
override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall }
override predicate isSink(DataFlow::Node node) {
node.asExpr() = any(BufferAccess ba).getAccessedLength()
}
override predicate isBarrier(DataFlow::Node node) {
exists(GuardCondition gc, GVN gvn |
gc.getAChild*() = gvn.getAnExpr() and
globalValueNumber(node.asExpr()) = gvn and
gc.controls(node.asExpr().getBasicBlock(), _)
)
}
}

View File

@@ -0,0 +1,3 @@
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
return ptr + i >= ptr_end || ptr + i < ptr; // BAD
}

View File

@@ -0,0 +1,3 @@
bool not_in_range(T *ptr, T *ptr_end, size_t i) {
return i >= ptr_end - ptr; // GOOD
}

View File

@@ -0,0 +1,67 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
When checking for integer overflow, you may often write tests like
<code>p + i &lt; p</code>. This works fine if <code>p</code> and
<code>i</code> are unsigned integers, since any overflow in the addition
will cause the value to simply "wrap around." However, using this pattern when
<code>p</code> is a pointer is problematic because pointer overflow has
undefined behavior according to the C and C++ standards. If the addition
overflows and has an undefined result, the comparison will likewise be
undefined; it may produce an unintended result, or may be deleted entirely by an
optimizing compiler.
</p>
</overview>
<recommendation>
<p>
To check whether an index <code>i</code> is less than the length of an array,
simply compare these two numbers as unsigned integers: <code>i &lt; ARRAY_LENGTH</code>.
If the length of the array is defined as the difference between two pointers
<code>ptr</code> and <code>p_end</code>, write <code>i &lt; p_end - ptr</code>.
If <code>i</code> is signed, cast it to unsigned
in order to guard against negative <code>i</code>. For example, write
<code>(size_t)i &lt; p_end - ptr</code>.
</p>
</recommendation>
<example>
<p>
An invalid check for pointer overflow is most often seen as part of checking
whether a number <code>a</code> is too large by checking first if adding the
number to <code>ptr</code> goes past the end of an allocation and then
checking if adding it to <code>ptr</code> creates a pointer so large that it
overflows and wraps around.
</p>
<sample src="PointerOverflow-bad.cpp" />
<p>
In both of these checks, the operations are performed in the wrong order.
First, an expression that may cause undefined behavior is evaluated
(<code>ptr + i</code>), and then the result is checked for being in range.
But once undefined behavior has happened in the pointer addition, it cannot
be recovered from: it's too late to perform the range check after a possible
pointer overflow.
</p>
<p>
While it's not the subject of this query, the expression <code>ptr + i &lt;
ptr_end</code> is also an invalid range check. It's undefined behavor in
C/C++ to create a pointer that points more than one past the end of an
allocation.
</p>
<p>
The next example shows how to portably check whether an unsigned number is outside the
range of an allocation between <code>ptr</code> and <code>ptr_end</code>.
</p>
<sample src="PointerOverflow-good.cpp" />
</example>
<references>
<li>Embedded in Academia: <a href="https://blog.regehr.org/archives/1395">Pointer Overflow Checking</a>.</li>
<li>LWN: <a href="https://lwn.net/Articles/278137/">GCC and pointer overflows</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,31 @@
/**
* @name Pointer overflow check
* @description Adding a value to a pointer to check if it overflows relies
* on undefined behavior and may lead to memory corruption.
* @kind problem
* @problem.severity error
* @precision high
* @id cpp/pointer-overflow-check
* @tags reliability
* security
*/
import cpp
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
private import semmle.code.cpp.commons.Exclusions
from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2
where
ro.getAnOperand() = add and
add.getAnOperand() = expr1 and
ro.getAnOperand() = expr2 and
globalValueNumber(expr1) = globalValueNumber(expr2) and
// Exclude macros but not their arguments
not isFromMacroDefinition(ro) and
// There must be a compilation of this file without a flag that makes pointer
// overflow well defined.
exists(Compilation c | c.getAFileCompiled() = ro.getFile() |
not c.getAnArgument() = "-fwrapv-pointer" and
not c.getAnArgument() = "-fno-strict-overflow"
)
select ro, "Range check relying on pointer overflow."

View File

@@ -13,32 +13,33 @@ import semmle.code.cpp.security.boostorg.asio.protocols
class ExistsAnyFlowConfig extends DataFlow::Configuration {
ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" }
override predicate isSource(DataFlow::Node source) { any() }
override predicate isSource(DataFlow::Node source) {
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) { any() }
override predicate isSink(DataFlow::Node sink) {
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
f.getACallToThisFunction() = fcSetOptions and
fcSetOptions.getQualifier() = sink.asExpr()
)
}
}
bindingset[flag]
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
exists(
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
Expr optionsSink
|
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
exists(VariableAccess contextSetOptions |
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions |
anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
)
)
@@ -46,43 +47,18 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
bindingset[flag]
predicate isOptionNotSet(ConstructorCall cc, int flag) {
not exists(
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
Expr optionsSink
|
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
exists(VariableAccess contextSetOptions |
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f |
f.getACallToThisFunction() = fcSetOptions
|
contextSetOptions = fcSetOptions.getQualifier() and
forall(
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
Expr optionArgumentSource
|
optionArgument = fcSetOptions.getArgument(0) and
optionArgConfig
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
|
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
)
)
)
)
not exists(FunctionCall fcSetOptions | isOptionSet(cc, flag, fcSetOptions))
}
from
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor,
BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink,
ConstructorCall cc, Expr e, string msg
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource,
Expr protocolSink, ConstructorCall cc, Expr e, string msg
where
configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
cc.getArgument(0) = protocolSink and
(
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
not exists(Expr optionsSink |
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
not (
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
@@ -91,8 +67,7 @@ where
or
BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and
not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
not exists(Expr optionsSink |
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
not (
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2())

View File

@@ -7,6 +7,10 @@
* @id cpp/ignore-return-value-sal
* @problem.severity warning
* @tags reliability
* external/cwe/cwe-573
* external/cwe/cwe-252
* @opaque-id SM02344
* @microsoft.severity Important
*/
import SAL

View File

@@ -126,7 +126,7 @@ class SALParameter extends Parameter {
}
/**
* A SAL element, i.e. a SAL annotation or a declaration entry
* A SAL element, that is, a SAL annotation or a declaration entry
* that may have SAL annotations.
*/
library class SALElement extends Element {

View File

@@ -1,25 +0,0 @@
/**
* @name SAL requires inspecting return value
* @description When a return value is discarded even though the SAL annotation
* requires inspecting it, a recoverable error may turn into a
* whole-program crash.
* @kind problem
* @problem.severity warning
* @tags reliability
* external/cwe/cwe-573
* external/cwe/cwe-252
* @opaque-id SM02344
* @microsoft.severity Important
* @id cpp/ignorereturnvaluesal
*/
import Microsoft.SAL
from Function f, FunctionCall call
where
call.getTarget() = f and
call instanceof ExprInVoidContext and
any(SALCheckReturn a).getDeclaration() = f and
not any(Options o).okToIgnoreReturnValue(call)
select call, "Return value of $@ discarded although a SAL annotation " + "requires inspecting it.",
f, f.getName()

View File

@@ -34,8 +34,10 @@ class FileFunction extends FunctionWithWrappers {
nme.matches("CreateFile%")
)
or
this.hasQualifiedName("std", "fopen")
or
// on any of the fstream classes, or filebuf
exists(string nme | this.getDeclaringType().getSimpleName() = nme |
exists(string nme | this.getDeclaringType().hasQualifiedName("std", nme) |
nme = "basic_fstream" or
nme = "basic_ifstream" or
nme = "basic_ofstream" or

View File

@@ -34,7 +34,7 @@ characters before writing to the HTML page.</p>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet">XSS
<a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html">XSS
(Cross Site Scripting) Prevention Cheat Sheet</a>.
</li>
<li>

View File

@@ -17,8 +17,8 @@ import semmle.code.cpp.security.TaintTracking
/** A call that prints its arguments to `stdout`. */
class PrintStdoutCall extends FunctionCall {
PrintStdoutCall() {
getTarget().hasGlobalName("puts") or
getTarget().hasGlobalName("printf")
getTarget().hasGlobalOrStdName("puts") or
getTarget().hasGlobalOrStdName("printf")
}
}

View File

@@ -19,10 +19,7 @@ import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.models.implementations.Memcpy
class MallocCall extends FunctionCall {
MallocCall() {
this.getTarget().hasGlobalName("malloc") or
this.getTarget().hasQualifiedName("std", "malloc")
}
MallocCall() { this.getTarget().hasGlobalOrStdName("malloc") }
Expr getAllocatedSize() {
if this.getArgument(0) instanceof VariableAccess

View File

@@ -44,7 +44,7 @@ Element friendlyLoc(Expr e) {
not e instanceof Access and not e instanceof Call and result = e
}
from Loop l, RelationalOperation rel, Expr small, Expr large
from Loop l, RelationalOperation rel, VariableAccess small, Expr large
where
small = rel.getLesserOperand() and
large = rel.getGreaterOperand() and
@@ -60,7 +60,7 @@ where
not getComparisonSize(large.(SubExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and
not getComparisonSize(large.(RShiftExpr).getLeftOperand().getExplicitlyConverted()) <= getComparisonSize(small) and
// ignore loop-invariant smaller variables
loopVariant(small.getAChild*(), l)
loopVariant(small, l)
select rel,
"Comparison between $@ of type " + small.getType().getName() + " and $@ of wider type " +
large.getType().getName() + ".", friendlyLoc(small), small.toString(), friendlyLoc(large),

View File

@@ -37,7 +37,7 @@ which is then subsequently accessed to fetch properties of the device. However,
check the return value from the function call to <code>initDeviceConfig</code>. If the
device number passed to the <code>notify</code> function was invalid, the
<code>initDeviceConfig</code> function will leave the <code>config</code> variable uninitialized,
which would result in the <code>notify</code> function accessing uninitialized memory.</p>
which will result in the <code>notify</code> function accessing uninitialized memory.</p>
<sample src="ConditionallyUninitializedVariableBad.c" />

View File

@@ -2,7 +2,7 @@
* @name Conditionally uninitialized variable
* @description When an initialization function is used to initialize a local variable, but the
* returned status code is not checked, the variable may be left in an uninitialized
* state, and reading the variable may result in undefined behaviour.
* state, and reading the variable may result in undefined behavior.
* @kind problem
* @problem.severity warning
* @opaque-id SM02313

View File

@@ -19,7 +19,7 @@ int notify(int deviceNumber) {
DeviceConfig config;
initDeviceConfig(&config, deviceNumber);
// BAD: Using config without checking the status code that is returned
if (config->isEnabled) {
notifyChannel(config->channel);
if (config.isEnabled) {
notifyChannel(config.channel);
}
}
}

View File

@@ -20,8 +20,8 @@ void notify(int deviceNumber) {
int statusCode = initDeviceConfig(&config, deviceNumber);
if (statusCode == 0) {
// GOOD: Status code returned by initialization function is checked, so this is safe
if (config->isEnabled) {
notifyChannel(config->channel);
if (config.isEnabled) {
notifyChannel(config.channel);
}
}
}
}

View File

@@ -4,7 +4,7 @@
import cpp
import external.ExternalArtifact
private import semmle.code.cpp.dispatch.VirtualDispatch
private import semmle.code.cpp.dispatch.VirtualDispatchPrototype
import semmle.code.cpp.NestedFields
import Microsoft.SAL
import semmle.code.cpp.controlflow.Guards
@@ -89,9 +89,9 @@ class ParameterNullCheck extends ParameterCheck {
(
va = this.(NotExpr).getOperand() or
va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = getAssertedFalseCondition(this) or
va = getCheckedFalseCondition(this) or
va = any(NEExpr eq |
eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
)
or
@@ -101,7 +101,7 @@ class ParameterNullCheck extends ParameterCheck {
va = this or
va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or
va = any(EQExpr eq |
eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0"
).getAnOperand()
)
)
@@ -567,7 +567,7 @@ Expr getAnInitializedArgument(Call call) { result = call.getArgument(initialized
* the call, under the given context and evidence.
*/
pragma[nomagic]
int conditionallyInitializedArgument(
private int conditionallyInitializedArgument(
Call call, ConditionalInitializationFunction target, Context c, Evidence e
) {
target = getTarget(call) and
@@ -588,7 +588,7 @@ Expr getAConditionallyInitializedArgument(
/**
* Gets the type signature for the functions parameters.
*/
string typeSig(Function f) {
private string typeSig(Function f) {
result = concat(int i, Type pt |
pt = f.getParameter(i).getType()
|
@@ -599,7 +599,7 @@ string typeSig(Function f) {
/**
* Holds where qualifiedName and typeSig make up the signature for the function.
*/
predicate functionSignature(Function f, string qualifiedName, string typeSig) {
private predicate functionSignature(Function f, string qualifiedName, string typeSig) {
qualifiedName = f.getQualifiedName() and
typeSig = typeSig(f)
}
@@ -611,7 +611,7 @@ predicate functionSignature(Function f, string qualifiedName, string typeSig) {
* This is useful for identifying call to target dependencies across libraries, where the libraries
* are never statically linked together.
*/
Function getAPossibleDefinition(Function undefinedFunction) {
private Function getAPossibleDefinition(Function undefinedFunction) {
not undefinedFunction.isDefined() and
exists(string qn, string typeSig |
functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig)
@@ -620,32 +620,47 @@ Function getAPossibleDefinition(Function undefinedFunction) {
}
/**
* Gets a possible target for the Call, using the name and parameter matching if we did not associate
* Helper predicate for `getTarget`, that computes possible targets of a `Call`.
*
* If there is at least one defined target after performing some simple virtual dispatch
* resolution, then the result is all the defined targets.
*/
private Function getTarget1(Call c) {
result = VirtualDispatch::getAViableTarget(c) and
result.isDefined()
}
/**
* Helper predicate for `getTarget`, that computes possible targets of a `Call`.
*
* If we can use the heuristic matching of functions to find definitions for some of the viable
* targets, return those.
*/
private Function getTarget2(Call c) {
not exists(getTarget1(c)) and
result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c))
}
/**
* Helper predicate for `getTarget`, that computes possible targets of a `Call`.
*
* Otherwise, the result is the undefined `Function` instances.
*/
private Function getTarget3(Call c) {
not exists(getTarget1(c)) and
not exists(getTarget2(c)) and
result = VirtualDispatch::getAViableTarget(c)
}
/**
* Gets a possible target for the `Call`, using the name and parameter matching if we did not associate
* this call with a specific definition at link or compile time, and performing simple virtual
* dispatch resolution.
*/
Function getTarget(Call c) {
if VirtualDispatch::getAViableTarget(c).isDefined()
then
/*
* If there is at least one defined target after performing some simple virtual dispatch
* resolution, then the result is all the defined targets.
*/
result = VirtualDispatch::getAViableTarget(c) and
result.isDefined()
else
if exists(getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)))
then
/*
* If we can use the heuristic matching of functions to find definitions for some of the viable
* targets, return those.
*/
result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c))
else
// Otherwise, the result is the undefined `Function` instances
result = VirtualDispatch::getAViableTarget(c)
result = getTarget1(c) or
result = getTarget2(c) or
result = getTarget3(c)
}
/**
@@ -669,7 +684,7 @@ FieldAccess getAFieldAccess(Variable v) {
}
/**
* Gets a condition which is asserted to be false by the given `ne` expression, according to this pattern:
* Gets a condition which is checked to be false by the given `ne` expression, according to this pattern:
* ```
* int a = !!result;
* if (!a) { // <- ne
@@ -677,7 +692,7 @@ FieldAccess getAFieldAccess(Variable v) {
* }
* ```
*/
Expr getAssertedFalseCondition(NotExpr ne) {
private Expr getCheckedFalseCondition(NotExpr ne) {
exists(LocalVariable v |
result = v.getInitializer().getExpr().(NotExpr).getOperand().(NotExpr).getOperand() and
ne.getOperand() = v.getAnAccess() and

View File

@@ -190,11 +190,11 @@ private predicate windowsSystemInfo(FunctionCall source, Element use) {
// void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
// void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo);
(
source.getTarget().hasName("GetVersionEx") or
source.getTarget().hasName("GetVersionExA") or
source.getTarget().hasName("GetVersionExW") or
source.getTarget().hasName("GetSystemInfo") or
source.getTarget().hasName("GetNativeSystemInfo")
source.getTarget().hasGlobalName("GetVersionEx") or
source.getTarget().hasGlobalName("GetVersionExA") or
source.getTarget().hasGlobalName("GetVersionExW") or
source.getTarget().hasGlobalName("GetSystemInfo") or
source.getTarget().hasGlobalName("GetNativeSystemInfo")
) and
use = source.getArgument(0)
}
@@ -216,9 +216,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) {
// _In_ BOOL fCreate
// );
(
source.getTarget().hasName("SHGetSpecialFolderPath") or
source.getTarget().hasName("SHGetSpecialFolderPathA") or
source.getTarget().hasName("SHGetSpecialFolderPathW")
source.getTarget().hasGlobalName("SHGetSpecialFolderPath") or
source.getTarget().hasGlobalName("SHGetSpecialFolderPathA") or
source.getTarget().hasGlobalName("SHGetSpecialFolderPathW")
) and
use = source.getArgument(1)
or
@@ -228,7 +228,7 @@ private predicate windowsFolderPath(FunctionCall source, Element use) {
// _In_opt_ HANDLE hToken,
// _Out_ PWSTR *ppszPath
// );
source.getTarget().hasName("SHGetKnownFolderPath") and
source.getTarget().hasGlobalName("SHGetKnownFolderPath") and
use = source.getArgument(3)
or
// HRESULT SHGetFolderPath(
@@ -239,9 +239,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) {
// _Out_ LPTSTR pszPath
// );
(
source.getTarget().hasName("SHGetFolderPath") or
source.getTarget().hasName("SHGetFolderPathA") or
source.getTarget().hasName("SHGetFolderPathW")
source.getTarget().hasGlobalName("SHGetFolderPath") or
source.getTarget().hasGlobalName("SHGetFolderPathA") or
source.getTarget().hasGlobalName("SHGetFolderPathW")
) and
use = source.getArgument(4)
or
@@ -254,9 +254,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) {
// _Out_ LPTSTR pszPath
// );
(
source.getTarget().hasName("SHGetFolderPathAndSubDir") or
source.getTarget().hasName("SHGetFolderPathAndSubDirA") or
source.getTarget().hasName("SHGetFolderPathAndSubDirW")
source.getTarget().hasGlobalName("SHGetFolderPathAndSubDir") or
source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirA") or
source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirW")
) and
use = source.getArgument(5)
}
@@ -273,9 +273,9 @@ class WindowsFolderPath extends SystemData {
private predicate logonUser(FunctionCall source, VariableAccess use) {
(
source.getTarget().hasName("LogonUser") or
source.getTarget().hasName("LogonUserW") or
source.getTarget().hasName("LogonUserA")
source.getTarget().hasGlobalName("LogonUser") or
source.getTarget().hasGlobalName("LogonUserW") or
source.getTarget().hasGlobalName("LogonUserA")
) and
use = source.getAnArgument()
}
@@ -297,9 +297,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) {
// _Inout_opt_ PLONG lpcbValue
// );
(
source.getTarget().hasName("RegQueryValue") or
source.getTarget().hasName("RegQueryValueA") or
source.getTarget().hasName("RegQueryValueW")
source.getTarget().hasGlobalName("RegQueryValue") or
source.getTarget().hasGlobalName("RegQueryValueA") or
source.getTarget().hasGlobalName("RegQueryValueW")
) and
use = source.getArgument(2)
or
@@ -311,9 +311,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) {
// _Inout_opt_ LPDWORD ldwTotsize
// );
(
source.getTarget().hasName("RegQueryMultipleValues") or
source.getTarget().hasName("RegQueryMultipleValuesA") or
source.getTarget().hasName("RegQueryMultipleValuesW")
source.getTarget().hasGlobalName("RegQueryMultipleValues") or
source.getTarget().hasGlobalName("RegQueryMultipleValuesA") or
source.getTarget().hasGlobalName("RegQueryMultipleValuesW")
) and
use = source.getArgument(3)
or
@@ -326,9 +326,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) {
// _Inout_opt_ LPDWORD lpcbData
// );
(
source.getTarget().hasName("RegQueryValueEx") or
source.getTarget().hasName("RegQueryValueExA") or
source.getTarget().hasName("RegQueryValueExW")
source.getTarget().hasGlobalName("RegQueryValueEx") or
source.getTarget().hasGlobalName("RegQueryValueExA") or
source.getTarget().hasGlobalName("RegQueryValueExW")
) and
use = source.getArgument(4)
or
@@ -342,9 +342,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) {
// _Inout_opt_ LPDWORD pcbData
// );
(
source.getTarget().hasName("RegGetValue") or
source.getTarget().hasName("RegGetValueA") or
source.getTarget().hasName("RegGetValueW")
source.getTarget().hasGlobalName("RegGetValue") or
source.getTarget().hasGlobalName("RegGetValueA") or
source.getTarget().hasGlobalName("RegGetValueW")
) and
use = source.getArgument(5)
}

View File

@@ -15,5 +15,5 @@ import cpp
from FunctionCall call, Function target
where
call.getTarget() = target and
target.hasGlobalName("gets")
target.hasGlobalOrStdName("gets")
select call, "gets does not guard against buffer overflow"

View File

@@ -22,7 +22,7 @@ predicate acquireExpr(Expr acquire, string kind) {
exists(FunctionCall fc, Function f, string name |
fc = acquire and
f = fc.getTarget() and
f.hasGlobalName(name) and
f.hasGlobalOrStdName(name) and
(
name = "fopen" and
kind = "file"
@@ -46,7 +46,7 @@ predicate releaseExpr(Expr release, Expr resource, string kind) {
exists(FunctionCall fc, Function f, string name |
fc = release and
f = fc.getTarget() and
f.hasGlobalName(name) and
f.hasGlobalOrStdName(name) and
(
name = "fclose" and
resource = fc.getArgument(0) and

View File

@@ -22,8 +22,8 @@ predicate containsArray(Type t) {
or
containsArray(t.getUnderlyingType()) and
not exists(TypedefType allowed | allowed = t |
allowed.hasGlobalName("jmp_buf") or
allowed.hasGlobalName("va_list")
allowed.hasGlobalOrStdName("jmp_buf") or
allowed.hasGlobalOrStdName("va_list")
)
}

View File

@@ -605,15 +605,6 @@ class Class extends UserType {
class_instantiation(underlyingElement(this), unresolveElement(c))
}
/**
* Gets the `i`th template argument used to instantiate this class from a
* class template. When called on a class template, this will return the
* `i`th template parameter.
*/
override Type getTemplateArgument(int i) {
class_template_argument(underlyingElement(this), i, unresolveElement(result))
}
/**
* Holds if this class/struct is polymorphic (has a virtual function, or
* inherits one).
@@ -623,7 +614,7 @@ class Class extends UserType {
}
override predicate involvesTemplateParameter() {
getATemplateArgument().involvesTemplateParameter()
getATemplateArgument().(Type).involvesTemplateParameter()
}
/** Holds if this class, struct or union was declared 'final'. */

View File

@@ -123,6 +123,13 @@ abstract class Declaration extends Locatable, @declaration {
/** Holds if this declaration has the given name in the global namespace. */
predicate hasGlobalName(string name) { this.hasQualifiedName("", "", name) }
/** Holds if this declaration has the given name in the global namespace or the `std` namespace. */
predicate hasGlobalOrStdName(string name) {
this.hasGlobalName(name)
or
this.hasQualifiedName("std", "", name)
}
/** Gets a specifier of this declaration. */
abstract Specifier getASpecifier();
@@ -193,20 +200,83 @@ abstract class Declaration extends Locatable, @declaration {
/**
* Gets a template argument used to instantiate this declaration from a template.
* When called on a template, this will return a template parameter.
* When called on a template, this will return a template parameter type for
* both typed and non-typed parameters.
*/
final Type getATemplateArgument() { result = getTemplateArgument(_) }
final Locatable getATemplateArgument() { result = getTemplateArgument(_) }
/**
* Gets a template argument used to instantiate this declaration from a template.
* When called on a template, this will return a non-typed template
* parameter value.
*/
final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) }
/**
* Gets the `i`th template argument used to instantiate this declaration from a
* template. When called on a template, this will return the `i`th template parameter.
* template.
*
* For example:
*
* `template<typename T, T X> class Foo;`
*
* Will have `getTemplateArgument(0)` return `T`, and
* `getTemplateArgument(1)` return `X`.
*
* `Foo<int, 1> bar;`
*
* Will have `getTemplateArgument())` return `int`, and
* `getTemplateArgument(1)` return `1`.
*/
Type getTemplateArgument(int index) { none() }
final Locatable getTemplateArgument(int index) {
if exists(getTemplateArgumentValue(index))
then result = getTemplateArgumentValue(index)
else result = getTemplateArgumentType(index)
}
/**
* Gets the `i`th template argument value used to instantiate this declaration
* from a template. When called on a template, this will return the `i`th template
* parameter value if it exists.
*
* For example:
*
* `template<typename T, T X> class Foo;`
*
* Will have `getTemplateArgumentKind(1)` return `T`, and no result for
* `getTemplateArgumentKind(0)`.
*
* `Foo<int, 10> bar;
*
* Will have `getTemplateArgumentKind(1)` return `int`, and no result for
* `getTemplateArgumentKind(0)`.
*/
final Locatable getTemplateArgumentKind(int index) {
if exists(getTemplateArgumentValue(index))
then result = getTemplateArgumentType(index)
else none()
}
/** Gets the number of template arguments for this declaration. */
final int getNumberOfTemplateArguments() {
result = count(int i | exists(getTemplateArgument(i)))
}
private Type getTemplateArgumentType(int index) {
class_template_argument(underlyingElement(this), index, unresolveElement(result))
or
function_template_argument(underlyingElement(this), index, unresolveElement(result))
or
variable_template_argument(underlyingElement(this), index, unresolveElement(result))
}
private Expr getTemplateArgumentValue(int index) {
class_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
function_template_argument_value(underlyingElement(this), index, unresolveElement(result))
or
variable_template_argument_value(underlyingElement(this), index, unresolveElement(result))
}
}
/**

View File

@@ -13,6 +13,11 @@ Element stmtEnclosingElement(Stmt s) {
/**
* Gets the enclosing element of expression `e`.
*/
// The `pragma[nomagic]` is a workaround to prevent this cached stage (and all
// subsequent stages) from being evaluated twice. See QL-888. It has the effect
// of making the `Conversion` class predicate get the same optimization in all
// queries.
pragma[nomagic]
cached
Element exprEnclosingElement(Expr e) {
result = exprEnclosingElement(e.getParent())

View File

@@ -343,15 +343,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
function_instantiation(underlyingElement(this), unresolveElement(f))
}
/**
* Gets the `i`th template argument used to instantiate this function from a
* function template. When called on a function template, this will return the
* `i`th template parameter.
*/
override Type getTemplateArgument(int index) {
function_template_argument(underlyingElement(this), index, unresolveElement(result))
}
/**
* Holds if this function is defined in several files. This is illegal in
* C (though possible in some C++ compilers), and likely indicates that
@@ -434,7 +425,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
// ... and likewise for destructors.
this.(Destructor).getADestruction().mayBeGloballyImpure()
else
not exists(string name | this.hasGlobalName(name) |
not exists(string name | this.hasGlobalOrStdName(name) |
// Unless it's a function that we know is side-effect-free, it may
// have side-effects.
name = "strcmp" or

View File

@@ -1,9 +1,8 @@
import cpp
/**
* Gets a `Field` that is nested within the given `Struct`.
*
* This identifies `Field`s which are located in the same memory
* Gets a `Field` that is within the given `Struct`, either directly or nested
* inside one or more levels of member structs.
*/
private Field getANestedField(Struct s) {
result = s.getAField()
@@ -15,7 +14,7 @@ private Field getANestedField(Struct s) {
}
/**
* Unwraps a series of field accesses to determine the inner-most qualifier.
* Unwraps a series of field accesses to determine the outer-most qualifier.
*/
private Expr getUltimateQualifier(FieldAccess fa) {
exists(Expr qualifier | qualifier = fa.getQualifier() |

View File

@@ -35,6 +35,14 @@ private string getParameterTypeString(Type parameterType) {
else result = parameterType.(DumpType).getTypeIdentityString()
}
private string getTemplateArgumentString(Declaration d, int i) {
if exists(d.getTemplateArgumentKind(i))
then
result = d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " +
d.getTemplateArgument(i)
else result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString()
}
/**
* A `Declaration` extended to add methods for generating strings useful only for dumps and debugging.
*/
@@ -56,7 +64,7 @@ abstract private class DumpDeclaration extends Declaration {
strictconcat(int i |
exists(this.getTemplateArgument(i))
|
this.getTemplateArgument(i).(DumpType).getTypeIdentityString(), ", " order by i
getTemplateArgumentString(this, i), ", " order by i
) + ">"
else result = ""
}

View File

@@ -5,6 +5,8 @@ private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ type.
*
* This QL class represents the root of the C/C++ type hierarchy.
*/
class Type extends Locatable, @type {
Type() { isType(underlyingElement(this)) }
@@ -210,7 +212,7 @@ class Type extends Locatable, @type {
// A function call that provides an explicit template argument that refers to T uses T.
// We exclude calls within instantiations, since they do not appear directly in the source.
exists(FunctionCall c |
c.getAnExplicitTemplateArgument().refersTo(this) and
c.getAnExplicitTemplateArgument().(Type).refersTo(this) and
result = c and
not c.getEnclosingFunction().isConstructedFrom(_)
)
@@ -289,6 +291,13 @@ class Type extends Locatable, @type {
/**
* A C/C++ built-in primitive type (int, float, void, and so on). See 4.1.1.
* In the following example, `unsigned int` and `double` denote primitive
* built-in types:
* ```
* double a;
* unsigned int ua[40];
* typedef double LargeFloat;
* ```
*/
class BuiltInType extends Type, @builtintype {
override string toString() { result = this.getName() }
@@ -301,7 +310,14 @@ class BuiltInType extends Type, @builtintype {
}
/**
* An erroneous type.
* An erroneous type. This type has no corresponding C/C++ syntax.
*
* `ErroneousType` is the type of `ErrorExpr`, which in turn refers to an illegal
* language construct. In the example below, a temporary (`0`) cannot be bound
* to an lvalue reference (`int &`):
* ```
* int &intref = 0;
* ```
*/
class ErroneousType extends BuiltInType {
ErroneousType() { builtintypes(underlyingElement(this), _, 1, _, _, _) }
@@ -310,7 +326,18 @@ class ErroneousType extends BuiltInType {
}
/**
* The unknown type.
* The unknown type. This type has no corresponding C/C++ syntax.
*
* Unknown types usually occur inside _uninstantiated_ template functions.
* In the example below, the expressions `x.a` and `x.b` have unknown type
* in the _uninstantiated_ template.
* ```
* template<typename T>
* bool check(T x) {
* if (x.a == x.b)
* abort();
* }
* ```
*/
class UnknownType extends BuiltInType {
UnknownType() { builtintypes(underlyingElement(this), _, 2, _, _, _) }
@@ -326,6 +353,10 @@ private predicate isArithmeticType(@builtintype type, int kind) {
/**
* The C/C++ arithmetic types. See 4.1.1.
*
* This includes primitive types on which arithmetic, bitwise or logical
* operations may be performed. Examples of arithmetic types include
* `char`, `int`, `float`, and `bool`.
*/
class ArithmeticType extends BuiltInType {
ArithmeticType() { isArithmeticType(underlyingElement(this), _) }
@@ -349,11 +380,20 @@ private predicate isIntegralType(@builtintype type, int kind) {
}
/**
* A C/C++ integral or enum type.
* The definition of "integral type" in the C++ Standard excludes enum types,
* but because an enum type holds a value of its underlying integral type,
* A C/C++ integral or `enum` type.
*
* The definition of "integral type" in the C++ standard excludes `enum` types,
* but because an `enum` type holds a value of its underlying integral type,
* it is often useful to have a common category that includes both integral
* and enum types.
* and `enum` types.
*
* In the following example, `a`, `b` and `c` are all declared with an
* integral or `enum` type:
* ```
* unsigned long a;
* enum e1 { val1, val2 } b;
* enum class e2: short { val3, val4 } c;
* ```
*/
class IntegralOrEnumType extends Type {
IntegralOrEnumType() {
@@ -426,7 +466,17 @@ private predicate integralTypeMapping(int original, int canonical, int unsigned,
}
/**
* The C/C++ integral types. See 4.1.1.
* The C/C++ integral types. See 4.1.1. These are types that are represented
* as integers of varying sizes. Both `enum` types and floating-point types
* are excluded.
*
* In the following examples, `a`, `b` and `c` are declared using integral
* types:
* ```
* unsigned int a;
* long long b;
* char c;
* ```
*/
class IntegralType extends ArithmeticType, IntegralOrEnumType {
int kind;
@@ -497,7 +547,12 @@ class IntegralType extends ArithmeticType, IntegralOrEnumType {
}
/**
* The C/C++ boolean type. See 4.2.
* The C/C++ boolean type. See 4.2. This is the C `_Bool` type
* or the C++ `bool` type. For example:
* ```
* extern bool a, b; // C++
* _Bool c, d; // C
* ```
*/
class BoolType extends IntegralType {
BoolType() { builtintypes(underlyingElement(this), _, 4, _, _, _) }
@@ -506,12 +561,23 @@ class BoolType extends IntegralType {
}
/**
* The C/C++ character types. See 4.3.
* The C/C++ character types. See 4.3. This includes the `char`,
* `signed char` and `unsigned char` types, all of which are
* distinct from one another. For example:
* ```
* char a, b;
* signed char c, d;
* unsigned char e, f;
* ```
*/
abstract class CharType extends IntegralType { }
/**
* The C/C++ char type (which is different to signed char and unsigned char).
* The C/C++ `char` type (which is distinct from `signed char` and
* `unsigned char`). For example:
* ```
* char a, b;
* ```
*/
class PlainCharType extends CharType {
PlainCharType() { builtintypes(underlyingElement(this), _, 5, _, _, _) }
@@ -520,7 +586,11 @@ class PlainCharType extends CharType {
}
/**
* The C/C++ unsigned char type (which is different to plain char, even when chars are unsigned by default).
* The C/C++ `unsigned char` type (which is distinct from plain `char`
* even when `char` is `unsigned` by default).
* ```
* unsigned char e, f;
* ```
*/
class UnsignedCharType extends CharType {
UnsignedCharType() { builtintypes(underlyingElement(this), _, 6, _, _, _) }
@@ -529,7 +599,11 @@ class UnsignedCharType extends CharType {
}
/**
* The C/C++ signed char type (which is different to plain char, even when chars are signed by default).
* The C/C++ `signed char` type (which is distinct from plain `char`
* even when `char` is `signed` by default).
* ```
* signed char c, d;
* ```
*/
class SignedCharType extends CharType {
SignedCharType() { builtintypes(underlyingElement(this), _, 7, _, _, _) }
@@ -538,7 +612,11 @@ class SignedCharType extends CharType {
}
/**
* The C/C++ short types. See 4.3.
* The C/C++ short types. See 4.3. This includes `short`, `signed short`
* and `unsigned short`.
* ```
* signed short ss;
* ```
*/
class ShortType extends IntegralType {
ShortType() {
@@ -551,7 +629,11 @@ class ShortType extends IntegralType {
}
/**
* The C/C++ integer types. See 4.4.
* The C/C++ integer types. See 4.4. This includes `int`, `signed int`
* and `unsigned int`.
* ```
* unsigned int ui;
* ```
*/
class IntType extends IntegralType {
IntType() {
@@ -564,7 +646,11 @@ class IntType extends IntegralType {
}
/**
* The C/C++ long types. See 4.4.
* The C/C++ long types. See 4.4. This includes `long`, `signed long`
* and `unsigned long`.
* ```
* long l;
* ```
*/
class LongType extends IntegralType {
LongType() {
@@ -577,7 +663,11 @@ class LongType extends IntegralType {
}
/**
* The C/C++ long long types. See 4.4.
* The C/C++ long long types. See 4.4. This includes `long long`, `signed long long`
* and `unsigned long long`.
* ```
* signed long long sll;
* ```
*/
class LongLongType extends IntegralType {
LongLongType() {
@@ -590,7 +680,12 @@ class LongLongType extends IntegralType {
}
/**
* The GNU C __int128 types.
* The GNU C __int128 primitive types. They are not part of standard C/C++.
*
* This includes `__int128`, `signed __int128` and `unsigned __int128`.
* ```
* unsigned __int128 ui128;
* ```
*/
class Int128Type extends IntegralType {
Int128Type() {
@@ -598,10 +693,18 @@ class Int128Type extends IntegralType {
builtintypes(underlyingElement(this), _, 36, _, _, _) or
builtintypes(underlyingElement(this), _, 37, _, _, _)
}
override string getCanonicalQLClass() { result = "Int128Type" }
}
/**
* The C/C++ floating point types. See 4.5.
* The C/C++ floating point types. See 4.5. This includes `float`,
* `double` and `long double` types.
* ```
* float f;
* double d;
* long double ld;
* ```
*/
class FloatingPointType extends ArithmeticType {
FloatingPointType() {
@@ -619,7 +722,10 @@ class FloatingPointType extends ArithmeticType {
}
/**
* The C/C++ float type.
* The C/C++ `float` type.
* ```
* float f;
* ```
*/
class FloatType extends FloatingPointType {
FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) }
@@ -628,7 +734,10 @@ class FloatType extends FloatingPointType {
}
/**
* The C/C++ double type.
* The C/C++ `double` type.
* ```
* double d;
* ```
*/
class DoubleType extends FloatingPointType {
DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) }
@@ -637,7 +746,10 @@ class DoubleType extends FloatingPointType {
}
/**
* The C/C++ long double type.
* The C/C++ `long double` type.
* ```
* long double ld;
* ```
*/
class LongDoubleType extends FloatingPointType {
LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) }
@@ -646,35 +758,58 @@ class LongDoubleType extends FloatingPointType {
}
/**
* The GNU C __float128 type.
* The GNU C `__float128` primitive type. This is not standard C/C++.
* ```
* __float128 f128;
* ```
*/
class Float128Type extends FloatingPointType {
Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) }
override string getCanonicalQLClass() { result = "Float128Type" }
}
/**
* The GNU C _Decimal32 type.
* The GNU C `_Decimal32` primitive type. This is not standard C/C++.
* ```
* _Decimal32 d32;
* ```
*/
class Decimal32Type extends FloatingPointType {
Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) }
override string getCanonicalQLClass() { result = "Decimal32Type" }
}
/**
* The GNU C _Decimal64 type.
* The GNU C `_Decimal64` primitive type. This is not standard C/C++.
* ```
* _Decimal64 d64;
* ```
*/
class Decimal64Type extends FloatingPointType {
Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) }
override string getCanonicalQLClass() { result = "Decimal64Type" }
}
/**
* The GNU C _Decimal128 type.
* The GNU C `_Decimal128` primitive type. This is not standard C/C++.
* ```
* _Decimal128 d128;
* ```
*/
class Decimal128Type extends FloatingPointType {
Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) }
override string getCanonicalQLClass() { result = "Decimal128Type" }
}
/**
* The C/C++ void type. See 4.7.
* The C/C++ `void` type. See 4.7.
* ```
* void foo();
* ```
*/
class VoidType extends BuiltInType {
VoidType() { builtintypes(underlyingElement(this), _, 3, _, _, _) }
@@ -688,6 +823,9 @@ class VoidType extends BuiltInType {
* Note that on some platforms `wchar_t` doesn't exist as a built-in
* type but a typedef is provided. Consider using the `Wchar_t` QL
* class to include these types.
* ```
* wchar_t wc;
* ```
*/
class WideCharType extends IntegralType {
WideCharType() { builtintypes(underlyingElement(this), _, 33, _, _, _) }
@@ -696,7 +834,10 @@ class WideCharType extends IntegralType {
}
/**
* The C/C++ `char16_t` type.
* The C/C++ `char16_t` type. This is available starting with C11 and C++11.
* ```
* char16_t c16;
* ```
*/
class Char16Type extends IntegralType {
Char16Type() { builtintypes(underlyingElement(this), _, 43, _, _, _) }
@@ -705,7 +846,10 @@ class Char16Type extends IntegralType {
}
/**
* The C/C++ `char32_t` type.
* The C/C++ `char32_t` type. This is available starting with C11 and C++11.
* ```
* char32_t c32;
* ```
*/
class Char32Type extends IntegralType {
Char32Type() { builtintypes(underlyingElement(this), _, 44, _, _, _) }
@@ -714,13 +858,13 @@ class Char32Type extends IntegralType {
}
/**
* The type of the C++11 nullptr constant.
*
* Note that this is not `nullptr_t`, as `nullptr_t` is defined as:
* The (primitive) type of the C++11 `nullptr` constant. It is a
* distinct type, denoted by `decltype(nullptr)`, that is not itself a pointer
* type or a pointer to member type. The `<cstddef>` header usually defines
* the `std::nullptr_t` type as follows:
* ```
* typedef decltype(nullptr) nullptr_t;
* typedef decltype(nullptr) nullptr_t;
* ```
* Instead, this is the unspeakable type given by `decltype(nullptr)`.
*/
class NullPointerType extends BuiltInType {
NullPointerType() { builtintypes(underlyingElement(this), _, 34, _, _, _) }
@@ -731,8 +875,13 @@ class NullPointerType extends BuiltInType {
/**
* A C/C++ derived type.
*
* These are pointer and reference types, array and vector types, and const and volatile types.
* In all cases, the type is formed from a single base type.
* These are pointer and reference types, array and GNU vector types, and `const` and `volatile` types.
* In all cases, the type is formed from a single base type. For example:
* ```
* int *pi;
* int &ri = *pi;
* const float fa[40];
* ```
*/
class DerivedType extends Type, @derivedtype {
override string toString() { result = this.getName() }
@@ -777,9 +926,15 @@ class DerivedType extends Type, @derivedtype {
}
/**
* An instance of the C++11 decltype operator.
* An instance of the C++11 `decltype` operator. For example:
* ```
* int a;
* decltype(a) b;
* ```
*/
class Decltype extends Type, @decltype {
override string getCanonicalQLClass() { result = "Decltype" }
/**
* The expression whose type is being obtained by this decltype.
*/
@@ -790,17 +945,17 @@ class Decltype extends Type, @decltype {
*/
Type getBaseType() { decltypes(underlyingElement(this), _, unresolveElement(result), _) }
override string getCanonicalQLClass() { result = "Decltype" }
/**
* Whether an extra pair of parentheses around the expression would change the semantics of this decltype.
*
* The following example shows the effect of an extra pair of parentheses:
* struct A { double x; };
* const A* a = new A();
* decltype( a->x ); // type is double
* decltype((a->x)); // type is const double&amp;
* Consult the C++11 standard for more details.
* ```
* 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.
*/
predicate parenthesesWouldChangeMeaning() { decltypes(underlyingElement(this), _, _, true) }
@@ -843,6 +998,10 @@ class Decltype extends Type, @decltype {
/**
* A C/C++ pointer type. See 4.9.1.
* ```
* void *ptr;
* void **ptr2 = &ptr;
* ```
*/
class PointerType extends DerivedType {
PointerType() { derivedtypes(underlyingElement(this), _, 1, _) }
@@ -865,8 +1024,8 @@ class PointerType extends DerivedType {
/**
* A C++ reference type. See 4.9.1.
*
* For C++11 code bases, this includes both lvalue references (&amp;) and rvalue references (&amp;&amp;).
* To distinguish between them, use the LValueReferenceType and RValueReferenceType classes.
* For C++11 code bases, this includes both _lvalue_ references (`&`) and _rvalue_ references (`&&`).
* To distinguish between them, use the LValueReferenceType and RValueReferenceType QL classes.
*/
class ReferenceType extends DerivedType {
ReferenceType() {
@@ -891,7 +1050,11 @@ class ReferenceType extends DerivedType {
}
/**
* A C++11 lvalue reference type (e.g. int&amp;).
* A C++11 lvalue reference type (e.g. `int &`).
* ```
* int a;
* int& b = a;
* ```
*/
class LValueReferenceType extends ReferenceType {
LValueReferenceType() { derivedtypes(underlyingElement(this), _, 2, _) }
@@ -900,7 +1063,14 @@ class LValueReferenceType extends ReferenceType {
}
/**
* A C++11 rvalue reference type (e.g. int&amp;&amp;).
* A C++11 rvalue reference type (e.g., `int &&`). It is used to
* implement "move" semantics for object construction and assignment.
* ```
* class C {
* E e;
* C(C&& from): e(std::move(from.e)) { }
* };
* ```
*/
class RValueReferenceType extends ReferenceType {
RValueReferenceType() { derivedtypes(underlyingElement(this), _, 8, _) }
@@ -912,6 +1082,10 @@ class RValueReferenceType extends ReferenceType {
/**
* A type with specifiers.
* ```
* const int a;
* volatile char v;
* ```
*/
class SpecifiedType extends DerivedType {
SpecifiedType() { derivedtypes(underlyingElement(this), _, 3, _) }
@@ -957,6 +1131,9 @@ class SpecifiedType extends DerivedType {
/**
* A C/C++ array type. See 4.9.1.
* ```
* char table[32];
* ```
*/
class ArrayType extends DerivedType {
ArrayType() { derivedtypes(underlyingElement(this), _, 4, _) }
@@ -1003,10 +1180,16 @@ class ArrayType extends DerivedType {
* A GNU/Clang vector type.
*
* In both Clang and GNU compilers, vector types can be introduced using the
* __attribute__((vector_size(byte_size))) syntax. The Clang compiler also
* allows vector types to be introduced using the ext_vector_type,
* neon_vector_type, and neon_polyvector_type attributes (all of which take
* an element type rather than a byte size).
* `__attribute__((vector_size(byte_size)))` syntax. The Clang compiler also
* allows vector types to be introduced using the `ext_vector_type`,
* `neon_vector_type`, and `neon_polyvector_type` attributes (all of which take
* an element count rather than a byte size).
*
* In the example below, both `v4si` and `float4` are GNU vector types:
* ```
* typedef int v4si __attribute__ (( vector_size(4*sizeof(int)) ));
* typedef float float4 __attribute__((ext_vector_type(4)));
* ```
*/
class GNUVectorType extends DerivedType {
GNUVectorType() { derivedtypes(underlyingElement(this), _, 5, _) }
@@ -1045,7 +1228,10 @@ class GNUVectorType extends DerivedType {
}
/**
* A C/C++ pointer to function. See 7.7.
* A C/C++ pointer to a function. See 7.7.
* ```
* int(* pointer)(const void *element1, const void *element2);
* ```
*/
class FunctionPointerType extends FunctionPointerIshType {
FunctionPointerType() { derivedtypes(underlyingElement(this), _, 6, _) }
@@ -1060,7 +1246,10 @@ class FunctionPointerType extends FunctionPointerIshType {
}
/**
* A C/C++ reference to function.
* A C++ reference to a function.
* ```
* int(& reference)(const void *element1, const void *element2);
* ```
*/
class FunctionReferenceType extends FunctionPointerIshType {
FunctionReferenceType() { derivedtypes(underlyingElement(this), _, 7, _) }
@@ -1075,10 +1264,14 @@ class FunctionReferenceType extends FunctionPointerIshType {
}
/**
* A block type, for example int(^)(char, float).
* A block type, for example, `int(^)(char, float)`.
*
* Block types (along with blocks themselves) are a language extension
* supported by Clang, and by Apple's branch of GCC.
* ```
* int(^ block)(const char *element1, const char *element2)
* = ^int (const char *element1, const char *element2) { return element1 - element 2; }
* ```
*/
class BlockType extends FunctionPointerIshType {
BlockType() { derivedtypes(underlyingElement(this), _, 10, _) }
@@ -1091,7 +1284,9 @@ class BlockType extends FunctionPointerIshType {
}
/**
* A C/C++ pointer to function, or a block.
* A C/C++ pointer to a function, a C++ function reference, or a clang/Apple block.
*
* See `FunctionPointerType`, `FunctionReferenceType` and `BlockType` for more information.
*/
class FunctionPointerIshType extends DerivedType {
FunctionPointerIshType() {
@@ -1136,7 +1331,13 @@ class FunctionPointerIshType extends DerivedType {
}
/**
* A C++ pointer to member. See 15.5.
* A C++ pointer to data member. See 15.5.
* ```
* class C { int m; };
* int C::* p = &C::m; // pointer to data member m of class C
* class C *;
* int val = c.*p; // access data member
* ```
*/
class PointerToMemberType extends Type, @ptrtomember {
/** a printable representation of this named element */
@@ -1173,7 +1374,14 @@ class PointerToMemberType extends Type, @ptrtomember {
}
/**
* A C/C++ routine type. This is what results from stripping away the pointer from a function pointer type.
* A C/C++ routine type. Conceptually, this is what results from stripping
* away the pointer from a function pointer type. It can also occur in C++
* code, for example the base type of `myRoutineType` in the following code:
* ```
* using myRoutineType = int(int);
*
* myRoutineType *fp = 0;
* ```
*/
class RoutineType extends Type, @routinetype {
/** a printable representation of this named element */
@@ -1233,7 +1441,13 @@ class RoutineType extends Type, @routinetype {
}
/**
* A C++ typename template parameter.
* A C++ `typename` (or `class`) template parameter.
*
* In the example below, `T` is a template parameter:
* ```
* template <class T>
* class C { };
* ```
*/
class TemplateParameter extends UserType {
TemplateParameter() {
@@ -1245,7 +1459,16 @@ class TemplateParameter extends UserType {
override predicate involvesTemplateParameter() { any() }
}
/** A C++ template template parameter, e.g. template &lt;template &lt;typename,typename> class T>. */
/**
* A C++ template template parameter.
*
* In the example below, `T` is a template template parameter (although its name
* may be omitted):
* ```
* template <template <typename T> class Container, class Elem>
* void foo(const Container<Elem> &value) { }
* ```
*/
class TemplateTemplateParameter extends TemplateParameter {
TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) }
@@ -1253,7 +1476,10 @@ class TemplateTemplateParameter extends TemplateParameter {
}
/**
* A type representing the use of the C++11 auto keyword.
* A type representing the use of the C++11 `auto` keyword.
* ```
* auto val = some_typed_expr();
* ```
*/
class AutoType extends TemplateParameter {
AutoType() { usertypes(underlyingElement(this), "auto", 7) }

View File

@@ -2,12 +2,11 @@ import semmle.code.cpp.Type
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ typedef type. See 4.9.1.
*
* Represents either of the following typedef styles:
*
* * CTypedefType: typedef <type> <name>;
* * UsingAliasTypedefType: using <name> = <type>;
* A C/C++ typedef type. See 4.9.1. For example the types declared on each line of the following code:
* ```
* typedef int my_int;
* using my_int2 = int;
* ```
*/
class TypedefType extends UserType {
TypedefType() {
@@ -48,7 +47,10 @@ class TypedefType extends UserType {
}
/**
* A traditional C/C++ typedef type. See 4.9.1.
* A traditional C/C++ typedef type. See 4.9.1. For example the type declared in the following code:
* ```
* typedef int my_int;
* ```
*/
class CTypedefType extends TypedefType {
CTypedefType() { usertypes(underlyingElement(this), _, 5) }
@@ -61,7 +63,10 @@ class CTypedefType extends TypedefType {
}
/**
* A using alias C++ typedef type.
* A using alias C++ typedef type. For example the type declared in the following code:
* ```
* using my_int2 = int;
* ```
*/
class UsingAliasTypedefType extends TypedefType {
UsingAliasTypedefType() { usertypes(underlyingElement(this), _, 14) }
@@ -74,7 +79,11 @@ class UsingAliasTypedefType extends TypedefType {
}
/**
* A C++ typedef type that is directly enclosed by a function.
* A C++ `typedef` type that is directly enclosed by a function. For example the type declared inside the function `foo` in
* the following code:
* ```
* int foo(void) { typedef int local; }
* ```
*/
class LocalTypedefType extends TypedefType {
LocalTypedefType() { isLocal() }
@@ -83,7 +92,11 @@ class LocalTypedefType extends TypedefType {
}
/**
* A C++ typedef type that is directly enclosed by a class, struct or union.
* A C++ `typedef` type that is directly enclosed by a `class`, `struct` or `union`. For example the type declared inside
* the class `C` in the following code:
* ```
* class C { typedef int nested; };
* ```
*/
class NestedTypedefType extends TypedefType {
NestedTypedefType() { this.isMember() }

View File

@@ -5,8 +5,14 @@ import semmle.code.cpp.Function
private import semmle.code.cpp.internal.ResolveClass
/**
* A C/C++ user-defined type. Examples include `Class`, `Struct`, `Union`,
* `Enum`, and `TypedefType`.
* A C/C++ user-defined type. Examples include `class`, `struct`, `union`,
* `enum` and `typedef` types.
* ```
* enum e1 { val1, val2 } b;
* enum class e2: short { val3, val4 } c;
* typedef int my_int;
* class C { int a, b; };
* ```
*/
class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @usertype {
/**
@@ -88,6 +94,10 @@ class UserType extends Type, Declaration, NameQualifyingElement, AccessHolder, @
/**
* A particular definition or forward declaration of a C/C++ user-defined type.
* ```
* class C;
* typedef int ti;
* ```
*/
class TypeDeclarationEntry extends DeclarationEntry, @type_decl {
override UserType getDeclaration() { result = getType() }

View File

@@ -155,15 +155,6 @@ class Variable extends Declaration, @variable {
variable_instantiation(underlyingElement(this), unresolveElement(v))
}
/**
* Gets the `i`th template argument used to instantiate this variable from a
* variable template. When called on a variable template, this will return the
* `i`th template parameter.
*/
override Type getTemplateArgument(int index) {
variable_template_argument(underlyingElement(this), index, unresolveElement(result))
}
/**
* Holds if this is a compiler-generated variable. For example, a
* [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for)

View File

@@ -5,13 +5,17 @@ import cpp
*/
predicate allocationFunction(Function f) {
exists(string name |
f.hasGlobalName(name) and
f.hasGlobalOrStdName(name) and
(
name = "malloc" or
name = "calloc" or
name = "realloc" or
name = "strdup" or
name = "wcsdup" or
name = "wcsdup"
)
or
f.hasGlobalName(name) and
(
name = "_strdup" or
name = "_wcsdup" or
name = "_mbsdup" or
@@ -59,7 +63,7 @@ predicate allocationCall(FunctionCall fc) {
allocationFunction(fc.getTarget()) and
(
// realloc(ptr, 0) only frees the pointer
fc.getTarget().hasGlobalName("realloc") implies not fc.getArgument(1).getValue() = "0"
fc.getTarget().hasGlobalOrStdName("realloc") implies not fc.getArgument(1).getValue() = "0"
)
}
@@ -73,7 +77,10 @@ predicate freeFunction(Function f, int argNum) {
name = "free" and argNum = 0
or
name = "realloc" and argNum = 0
or
)
or
f.hasGlobalOrStdName(name) and
(
name = "ExFreePoolWithTag" and argNum = 0
or
name = "ExFreeToLookasideListEx" and argNum = 1

View File

@@ -44,7 +44,7 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) {
aoe.getAddressable() = v
)
or
exists(BuiltInOperationOffsetOf oo |
exists(BuiltInOperationBuiltInOffsetOf oo |
// `offsetof(c, v)` using a builtin
oo.getAChild().(VariableAccess).getTarget() = v
)

View File

@@ -28,7 +28,7 @@ class EnvironmentRead extends Expr {
private predicate readsEnvironment(Expr read, string sourceDescription) {
exists(FunctionCall call, string name |
read = call and
call.getTarget().hasGlobalName(name) and
call.getTarget().hasGlobalOrStdName(name) and
(name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and
sourceDescription = name
)

View File

@@ -79,3 +79,33 @@ predicate functionContainsPreprocCode(Function f) {
pbdStartLine >= fBlockStartLine
)
}
/**
* Holds if `e` is completely or partially from a macro definition, as opposed
* to being passed in as an argument.
*
* In the following example, the call to `f` is from a macro definition,
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
* from `M` refers to a macro.
* ```
* #define M(x) f(x)
* ...
* M(y + 1);
* ```
*/
predicate isFromMacroDefinition(Element e) {
exists(MacroInvocation mi, Location eLocation, Location miLocation |
mi.getAnExpandedElement() = e and
eLocation = e.getLocation() and
miLocation = mi.getLocation() and
// If the location of `e` coincides with the macro invocation, then `e` did
// not come from a macro argument. The inequalities here could also be
// equalities, but that confuses the join orderer into joining on the source
// locations too early.
// There are cases where the start location of a non-argument element comes
// right after the invocation's open parenthesis, so it appears to be more
// robust to match on the end location instead.
eLocation.getEndLine() >= miLocation.getEndLine() and
eLocation.getEndColumn() >= miLocation.getEndColumn()
)
}

View File

@@ -5,7 +5,7 @@ import cpp
*/
predicate fopenCall(FunctionCall fc) {
exists(Function f | f = fc.getTarget() |
f.hasGlobalName("fopen") or
f.hasGlobalOrStdName("fopen") or
f.hasGlobalName("open") or
f.hasGlobalName("_open") or
f.hasGlobalName("_wopen") or
@@ -23,7 +23,7 @@ predicate fopenCall(FunctionCall fc) {
*/
predicate fcloseCall(FunctionCall fc, Expr closed) {
exists(Function f | f = fc.getTarget() |
f.hasGlobalName("fclose") and
f.hasGlobalOrStdName("fclose") and
closed = fc.getArgument(0)
or
f.hasGlobalName("close") and
@@ -32,7 +32,7 @@ predicate fcloseCall(FunctionCall fc, Expr closed) {
f.hasGlobalName("_close") and
closed = fc.getArgument(0)
or
f.hasGlobalName("CloseHandle") and
f.hasGlobalOrStdName("CloseHandle") and
closed = fc.getArgument(0)
)
}

View File

@@ -8,25 +8,32 @@ import semmle.code.cpp.commons.StringAnalysis
import semmle.code.cpp.models.interfaces.FormattingFunction
import semmle.code.cpp.models.implementations.Printf
class PrintfFormatAttribute extends FormatAttribute {
PrintfFormatAttribute() {
getArchetype() = "printf" or
getArchetype() = "__printf__"
}
}
/**
* A function that can be identified as a `printf` style formatting
* function by its use of the GNU `format` attribute.
*/
class AttributeFormattingFunction extends FormattingFunction {
FormatAttribute printf_attrib;
override string getCanonicalQLClass() { result = "AttributeFormattingFunction" }
AttributeFormattingFunction() {
printf_attrib = getAnAttribute() and
(
printf_attrib.getArchetype() = "printf" or
printf_attrib.getArchetype() = "__printf__"
) and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
exists(PrintfFormatAttribute printf_attrib |
printf_attrib = getAnAttribute() and
exists(printf_attrib.getFirstFormatArgIndex()) // exclude `vprintf` style format functions
)
}
override int getFormatParameterIndex() { result = printf_attrib.getFormatIndex() }
override int getFormatParameterIndex() {
forex(PrintfFormatAttribute printf_attrib | printf_attrib = getAnAttribute() |
result = printf_attrib.getFormatIndex()
)
}
}
/**
@@ -124,15 +131,17 @@ class FormattingFunctionCall extends Expr {
}
/**
* Gets the argument corresponding to the nth conversion specifier
* Gets the argument corresponding to the nth conversion specifier.
*/
Expr getConversionArgument(int n) {
exists(FormatLiteral fl, int b, int o |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
o = fl.getNumArgNeeded(n) and
o > 0 and
result = this.getFormatArgument(b + o - 1)
(
result = this.getFormatArgument(fl.getParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 2)) and
not exists(fl.getParameterFieldValue(n))
)
)
}
@@ -142,11 +151,14 @@ class FormattingFunctionCall extends Expr {
* an explicit minimum field width).
*/
Expr getMinFieldWidthArgument(int n) {
exists(FormatLiteral fl, int b |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
fl.hasImplicitMinFieldWidth(n) and
result = this.getFormatArgument(b)
(
result = this.getFormatArgument(fl.getMinFieldWidthParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 0)) and
not exists(fl.getMinFieldWidthParameterFieldValue(n))
)
)
}
@@ -156,12 +168,14 @@ class FormattingFunctionCall extends Expr {
* precision).
*/
Expr getPrecisionArgument(int n) {
exists(FormatLiteral fl, int b, int o |
exists(FormatLiteral fl |
fl = this.getFormat() and
b = sum(int i, int toSum | i < n and toSum = fl.getNumArgNeeded(i) | toSum) and
(if fl.hasImplicitMinFieldWidth(n) then o = 1 else o = 0) and
fl.hasImplicitPrecision(n) and
result = this.getFormatArgument(b + o)
(
result = this.getFormatArgument(fl.getPrecisionParameterFieldValue(n))
or
result = this.getFormatArgument(fl.getFormatArgumentIndexFor(n, 1)) and
not exists(fl.getPrecisionParameterFieldValue(n))
)
)
}
@@ -361,6 +375,14 @@ class FormatLiteral extends Literal {
*/
string getParameterField(int n) { this.parseConvSpec(n, _, result, _, _, _, _, _) }
/**
* Gets the parameter field of the nth conversion specifier (if it has one) as a
* zero-based number.
*/
int getParameterFieldValue(int n) {
result = this.getParameterField(n).regexpCapture("([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the flags of the nth conversion specifier.
*/
@@ -430,6 +452,14 @@ class FormatLiteral extends Literal {
*/
int getMinFieldWidth(int n) { result = this.getMinFieldWidthOpt(n).toInt() }
/**
* Gets the zero-based parameter number of the minimum field width of the nth
* conversion specifier, if it is implicit and uses a parameter field (such as `*1$`).
*/
int getMinFieldWidthParameterFieldValue(int n) {
result = this.getMinFieldWidthOpt(n).regexpCapture("\\*([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the precision of the nth conversion specifier (empty string if none is given).
*/
@@ -460,6 +490,14 @@ class FormatLiteral extends Literal {
else result = this.getPrecisionOpt(n).regexpCapture("\\.([0-9]*)", 1).toInt()
}
/**
* Gets the zero-based parameter number of the precision of the nth conversion
* specifier, if it is implicit and uses a parameter field (such as `*1$`).
*/
int getPrecisionParameterFieldValue(int n) {
result = this.getPrecisionOpt(n).regexpCapture("\\.\\*([0-9]*)\\$", 1).toInt() - 1
}
/**
* Gets the length flag of the nth conversion specifier.
*/
@@ -777,19 +815,49 @@ class FormatLiteral extends Literal {
)
}
/**
* Holds if the nth conversion specifier of this format string (if `mode = 2`), it's
* minimum field width (if `mode = 0`) or it's precision (if `mode = 1`) requires a
* format argument.
*
* Most conversion specifiers require a format argument, whereas minimum field width
* and precision only require a format argument if they are present and a `*` was
* used for it's value in the format string.
*/
private predicate hasFormatArgumentIndexFor(int n, int mode) {
mode = 0 and
this.hasImplicitMinFieldWidth(n)
or
mode = 1 and
this.hasImplicitPrecision(n)
or
mode = 2 and
exists(this.getConvSpecOffset(n)) and
not this.getConversionChar(n) = "m"
}
/**
* Gets the computed format argument index for the nth conversion specifier of this
* format string (if `mode = 2`), it's minimum field width (if `mode = 0`) or it's
* precision (if `mode = 1`). Has no result if that element is not present. Does
* not account for positional arguments (`$`).
*/
int getFormatArgumentIndexFor(int n, int mode) {
hasFormatArgumentIndexFor(n, mode) and
(3 * n) + mode = rank[result + 1](int n2, int mode2 |
hasFormatArgumentIndexFor(n2, mode2)
|
(3 * n2) + mode2
)
}
/**
* Gets the number of arguments required by the nth conversion specifier
* of this format string.
*/
int getNumArgNeeded(int n) {
exists(this.getConvSpecOffset(n)) and
not this.getConversionChar(n) = "%" and
exists(int n1, int n2, int n3 |
(if this.hasImplicitMinFieldWidth(n) then n1 = 1 else n1 = 0) and
(if this.hasImplicitPrecision(n) then n2 = 1 else n2 = 0) and
(if this.getConversionChar(n) = "m" then n3 = 0 else n3 = 1) and
result = n1 + n2 + n3
)
result = count(int mode | hasFormatArgumentIndexFor(n, mode))
}
/**
@@ -801,7 +869,7 @@ class FormatLiteral extends Literal {
// At least one conversion specifier has a parameter field, in which case,
// they all should have.
result = max(string s | this.getParameterField(_) = s + "$" | s.toInt())
else result = sum(int n, int toSum | toSum = this.getNumArgNeeded(n) | toSum)
else result = count(int n, int mode | hasFormatArgumentIndexFor(n, mode))
}
/**

View File

@@ -53,8 +53,8 @@ class AnalysedString extends Expr {
*/
class StrlenCall extends FunctionCall {
StrlenCall() {
this.getTarget().hasGlobalName("strlen") or
this.getTarget().hasGlobalName("wcslen") or
this.getTarget().hasGlobalOrStdName("strlen") or
this.getTarget().hasGlobalOrStdName("wcslen") or
this.getTarget().hasGlobalName("_mbslen") or
this.getTarget().hasGlobalName("_mbslen_l") or
this.getTarget().hasGlobalName("_mbstrlen") or

View File

@@ -6,7 +6,7 @@ import Nullness
*/
predicate callDereferences(FunctionCall fc, int i) {
exists(string name |
fc.getTarget().hasGlobalName(name) and
fc.getTarget().hasGlobalOrStdName(name) and
(
name = "bcopy" and i in [0 .. 1]
or

View File

@@ -264,9 +264,9 @@ predicate callMayReturnNull(Call call) {
* Holds if `f` may, directly or indirectly, return a null literal.
*/
predicate mayReturnNull(Function f) {
f.hasGlobalName("malloc")
f.hasGlobalOrStdName("malloc")
or
f.hasGlobalName("calloc")
f.hasGlobalOrStdName("calloc")
or
// f.hasGlobalName("strchr")
// or

View File

@@ -132,7 +132,7 @@ private predicate excludeNodeAndNodesBelow(Expr e) {
* control flow in them.
*/
private predicate excludeNodesStrictlyBelow(Node n) {
n instanceof BuiltInOperationOffsetOf
n instanceof BuiltInOperationBuiltInOffsetOf
or
n instanceof BuiltInIntAddr
or

View File

@@ -360,7 +360,7 @@ private module ImplCommon {
*/
cached
predicate read(Node node1, Content f, Node node2) {
readStep(node1, f, node2) and storeStep(_, f, _)
readStep(node1, f, node2)
or
exists(DataFlowCall call, ReturnKind kind |
read0(call, kind, node1, f) and

View File

@@ -28,6 +28,19 @@ module VirtualDispatch {
not result.hasName("IUnknown")
}
/**
* Helper predicate for `getAViableTarget`, which computes the viable targets for
* virtual calls based on the qualifier type.
*/
private Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) {
exists(Class qualifierSubType |
result = getAPossibleImplementation(staticTarget) and
qualifierType = qualifierSubType.getABaseClass*() and
mayInherit(qualifierSubType, result) and
not cannotInherit(qualifierSubType, result)
)
}
/**
* Gets a viable target for the given function call.
*
@@ -42,18 +55,9 @@ module VirtualDispatch {
* If `c` is not a virtual call, the result will be `c.getTarget()`.
*/
Function getAViableTarget(Call c) {
exists(Function staticTarget | staticTarget = c.getTarget() |
if c.(FunctionCall).isVirtual() and staticTarget instanceof MemberFunction
then
exists(Class qualifierType, Class qualifierSubType |
result = getAPossibleImplementation(staticTarget) and
qualifierType = getCallQualifierType(c) and
qualifierType = qualifierSubType.getABaseClass*() and
mayInherit(qualifierSubType, result) and
not cannotInherit(qualifierSubType, result)
)
else result = staticTarget
)
if c.(FunctionCall).isVirtual() and c.getTarget() instanceof MemberFunction
then result = getAViableVirtualCallTarget(getCallQualifierType(c), c.getTarget())
else result = c.getTarget()
}
/** Holds if `f` is declared in `c` or a transitive base class of `c`. */
@@ -63,7 +67,7 @@ module VirtualDispatch {
/**
* Holds if `c` cannot inherit the member function `f`,
* i.e. `c` or one of its supertypes overrides `f`.
* that is, `c` or one of its supertypes overrides `f`.
*/
private predicate cannotInherit(Class c, MemberFunction f) {
exists(Class overridingType, MemberFunction override |

View File

@@ -1,12 +1,17 @@
import semmle.code.cpp.exprs.Expr
/**
* A C/C++ arithmetic operation.
* A C/C++ unary arithmetic operation.
*
* This is an abstract base QL class.
*/
abstract class UnaryArithmeticOperation extends UnaryOperation { }
/**
* A C/C++ unary minus expression.
* ```
* b = - a;
* ```
*/
class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
override string getOperator() { result = "-" }
@@ -18,6 +23,9 @@ class UnaryMinusExpr extends UnaryArithmeticOperation, @arithnegexpr {
/**
* A C/C++ unary plus expression.
* ```
* b = + a;
* ```
*/
class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
override string getOperator() { result = "+" }
@@ -28,7 +36,13 @@ class UnaryPlusExpr extends UnaryArithmeticOperation, @unaryplusexpr {
}
/**
* A C/C++ GNU conjugation expression.
* A C/C++ GNU conjugation expression. It operates on `_Complex` or
* `__complex__ `numbers, and is similar to the C99 `conj`, `conjf` and `conjl`
* functions.
* ```
* _Complex double a = ( 1.0, 2.0 );
* _Complex double b = ~ a; // ( 1.0, - 2.0 )
* ```
*/
class ConjugationExpr extends UnaryArithmeticOperation, @conjugation {
override string getOperator() { result = "~" }
@@ -39,7 +53,9 @@ class ConjugationExpr extends UnaryArithmeticOperation, @conjugation {
/**
* A C/C++ `++` or `--` expression (either prefix or postfix).
*
* Note that this doesn't include calls to user-defined `operator++`
* This is the abstract base QL class for increment and decrement operations.
*
* Note that this does not include calls to user-defined `operator++`
* or `operator--`.
*/
abstract class CrementOperation extends UnaryArithmeticOperation {
@@ -58,35 +74,38 @@ abstract class CrementOperation extends UnaryArithmeticOperation {
/**
* A C/C++ `++` expression (either prefix or postfix).
*
* Note that this doesn't include calls to user-defined `operator++`.
* Note that this does not include calls to user-defined `operator++`.
*/
abstract class IncrementOperation extends CrementOperation { }
/**
* A C/C++ `--` expression (either prefix or postfix).
*
* Note that this doesn't include calls to user-defined `operator--`.
* Note that this does not include calls to user-defined `operator--`.
*/
abstract class DecrementOperation extends CrementOperation { }
/**
* A C/C++ `++` or `--` prefix expression.
*
* Note that this doesn't include calls to user-defined operators.
* Note that this does not include calls to user-defined operators.
*/
abstract class PrefixCrementOperation extends CrementOperation { }
/**
* A C/C++ `++` or `--` postfix expression.
*
* Note that this doesn't include calls to user-defined operators.
* Note that this does not include calls to user-defined operators.
*/
abstract class PostfixCrementOperation extends CrementOperation { }
/**
* A C/C++ prefix increment expression, as in `++x`.
*
* Note that this doesn't include calls to user-defined `operator++`.
* Note that this does not include calls to user-defined `operator++`.
* ```
* b = ++a;
* ```
*/
class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preincrexpr {
override string getOperator() { result = "++" }
@@ -99,7 +118,10 @@ class PrefixIncrExpr extends IncrementOperation, PrefixCrementOperation, @preinc
/**
* A C/C++ prefix decrement expression, as in `--x`.
*
* Note that this doesn't include calls to user-defined `operator--`.
* Note that this does not include calls to user-defined `operator--`.
* ```
* b = --a;
* ```
*/
class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predecrexpr {
override string getOperator() { result = "--" }
@@ -112,7 +134,10 @@ class PrefixDecrExpr extends DecrementOperation, PrefixCrementOperation, @predec
/**
* A C/C++ postfix increment expression, as in `x++`.
*
* Note that this doesn't include calls to user-defined `operator++`.
* Note that this does not include calls to user-defined `operator++`.
* ```
* b = a++;
* ```
*/
class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @postincrexpr {
override string getOperator() { result = "++" }
@@ -127,7 +152,10 @@ class PostfixIncrExpr extends IncrementOperation, PostfixCrementOperation, @post
/**
* A C/C++ postfix decrement expression, as in `x--`.
*
* Note that this doesn't include calls to user-defined `operator--`.
* Note that this does not include calls to user-defined `operator--`.
* ```
* b = a--;
* ```
*/
class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @postdecrexpr {
override string getOperator() { result = "--" }
@@ -140,7 +168,12 @@ class PostfixDecrExpr extends DecrementOperation, PostfixCrementOperation, @post
}
/**
* A C/C++ GNU real part expression.
* A C/C++ GNU real part expression. It operates on `_Complex` or
* `__complex__` numbers.
* ```
* _Complex double f = { 2.0, 3.0 };
* double d = __real(f); // 2.0
* ```
*/
class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
override string getOperator() { result = "__real" }
@@ -149,7 +182,12 @@ class RealPartExpr extends UnaryArithmeticOperation, @realpartexpr {
}
/**
* A C/C++ GNU imaginary part expression.
* A C/C++ GNU imaginary part expression. It operates on `_Complex` or
* `__complex__` numbers.
* ```
* _Complex double f = { 2.0, 3.0 };
* double d = __imag(f); // 3.0
* ```
*/
class ImaginaryPartExpr extends UnaryArithmeticOperation, @imagpartexpr {
override string getOperator() { result = "__imag" }
@@ -159,11 +197,16 @@ class ImaginaryPartExpr extends UnaryArithmeticOperation, @imagpartexpr {
/**
* A C/C++ binary arithmetic operation.
*
* This is an abstract base QL class for all binary arithmetic operations.
*/
abstract class BinaryArithmeticOperation extends BinaryOperation { }
/**
* A C/C++ add expression.
* ```
* c = a + b;
* ```
*/
class AddExpr extends BinaryArithmeticOperation, @addexpr {
override string getOperator() { result = "+" }
@@ -175,6 +218,9 @@ class AddExpr extends BinaryArithmeticOperation, @addexpr {
/**
* A C/C++ subtract expression.
* ```
* c = a - b;
* ```
*/
class SubExpr extends BinaryArithmeticOperation, @subexpr {
override string getOperator() { result = "-" }
@@ -186,6 +232,9 @@ class SubExpr extends BinaryArithmeticOperation, @subexpr {
/**
* A C/C++ multiply expression.
* ```
* c = a * b;
* ```
*/
class MulExpr extends BinaryArithmeticOperation, @mulexpr {
override string getOperator() { result = "*" }
@@ -197,6 +246,9 @@ class MulExpr extends BinaryArithmeticOperation, @mulexpr {
/**
* A C/C++ divide expression.
* ```
* c = a / b;
* ```
*/
class DivExpr extends BinaryArithmeticOperation, @divexpr {
override string getOperator() { result = "/" }
@@ -208,6 +260,9 @@ class DivExpr extends BinaryArithmeticOperation, @divexpr {
/**
* A C/C++ remainder expression.
* ```
* c = a % b;
* ```
*/
class RemExpr extends BinaryArithmeticOperation, @remexpr {
override string getOperator() { result = "%" }
@@ -218,7 +273,13 @@ class RemExpr extends BinaryArithmeticOperation, @remexpr {
}
/**
* A C/C++ multiply expression with an imaginary number.
* A C/C++ multiply expression with an imaginary number. This is specific to
* C99 and later.
* ```
* double z;
* _Imaginary double x, y;
* z = x * y;
* ```
*/
class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
override string getOperator() { result = "*" }
@@ -229,7 +290,13 @@ class ImaginaryMulExpr extends BinaryArithmeticOperation, @jmulexpr {
}
/**
* A C/C++ divide expression with an imaginary number.
* A C/C++ divide expression with an imaginary number. This is specific to
* C99 and later.
* ```
* double z;
* _Imaginary double y;
* z = z / y;
* ```
*/
class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
override string getOperator() { result = "/" }
@@ -240,7 +307,14 @@ class ImaginaryDivExpr extends BinaryArithmeticOperation, @jdivexpr {
}
/**
* A C/C++ add expression with a real term and an imaginary term.
* A C/C++ add expression with a real term and an imaginary term. This is
* specific to C99 and later.
* ```
* double z;
* _Imaginary double x;
* _Complex double w;
* w = z + x;
* ```
*/
class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
override string getOperator() { result = "+" }
@@ -251,7 +325,14 @@ class RealImaginaryAddExpr extends BinaryArithmeticOperation, @fjaddexpr {
}
/**
* A C/C++ add expression with an imaginary term and a real term.
* A C/C++ add expression with an imaginary term and a real term. This is
* specific to C99 and later.
* ```
* double z;
* _Imaginary double x;
* _Complex double w;
* w = x + z;
* ```
*/
class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
override string getOperator() { result = "+" }
@@ -262,7 +343,14 @@ class ImaginaryRealAddExpr extends BinaryArithmeticOperation, @jfaddexpr {
}
/**
* A C/C++ subtract expression with a real term and an imaginary term.
* A C/C++ subtract expression with a real term and an imaginary term. This is
* specific to C99 and later.
* ```
* double z;
* _Imaginary double x;
* _Complex double w;
* w = z - x;
* ```
*/
class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
override string getOperator() { result = "-" }
@@ -273,7 +361,14 @@ class RealImaginarySubExpr extends BinaryArithmeticOperation, @fjsubexpr {
}
/**
* A C/C++ subtract expression with an imaginary term and a real term.
* A C/C++ subtract expression with an imaginary term and a real term. This is
* specific to C99 and later.
* ```
* double z;
* _Imaginary double x;
* _Complex double w;
* w = x - z;
* ```
*/
class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
override string getOperator() { result = "-" }
@@ -285,6 +380,9 @@ class ImaginaryRealSubExpr extends BinaryArithmeticOperation, @jfsubexpr {
/**
* A C/C++ GNU min expression.
* ```
* c = a <? b;
* ```
*/
class MinExpr extends BinaryArithmeticOperation, @minexpr {
override string getOperator() { result = "<?" }
@@ -294,6 +392,9 @@ class MinExpr extends BinaryArithmeticOperation, @minexpr {
/**
* A C/C++ GNU max expression.
* ```
* c = a >? b;
* ```
*/
class MaxExpr extends BinaryArithmeticOperation, @maxexpr {
override string getOperator() { result = ">?" }
@@ -308,6 +409,10 @@ abstract class PointerArithmeticOperation extends BinaryArithmeticOperation { }
/**
* A C/C++ pointer add expression.
* ```
* foo *ptr = &f[0];
* ptr = ptr + 2;
* ```
*/
class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
override string getOperator() { result = "+" }
@@ -319,6 +424,10 @@ class PointerAddExpr extends PointerArithmeticOperation, @paddexpr {
/**
* A C/C++ pointer subtract expression.
* ```
* foo *ptr = &f[3];
* ptr = ptr - 2;
* ```
*/
class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
override string getOperator() { result = "-" }
@@ -330,6 +439,10 @@ class PointerSubExpr extends PointerArithmeticOperation, @psubexpr {
/**
* A C/C++ pointer difference expression.
* ```
* foo *start = &f[0], *end = &f[4];
* int size = end - size;
* ```
*/
class PointerDiffExpr extends PointerArithmeticOperation, @pdiffexpr {
override string getOperator() { result = "-" }

View File

@@ -4,11 +4,13 @@ import semmle.code.cpp.exprs.BitwiseOperation
/**
* A non-overloaded binary assignment operation, including `=`, `+=`, `&=`,
* etc. A C++ overloaded operation looks syntactically identical but is instead
* etc. A C++ overloaded assignment operation looks syntactically identical but is instead
* a `FunctionCall`.
*
* This is an abstract root QL class for all (non-overloaded) assignments.
*/
abstract class Assignment extends Operation {
/** Gets the lvalue of this assignment. */
/** Gets the _lvalue_ of this assignment. */
Expr getLValue() { this.hasChild(result, 0) }
/** Gets the rvalue of this assignment. */
@@ -30,6 +32,9 @@ abstract class Assignment extends Operation {
/**
* A non-overloaded assignment operation with the operator `=`.
* ```
* a = b;
* ```
*/
class AssignExpr extends Assignment, @assignexpr {
override string getOperator() { result = "=" }
@@ -48,13 +53,16 @@ abstract class AssignOperation extends Assignment {
}
/**
* A non-overloaded arithmetic assignment operation on a non-pointer lvalue:
* A non-overloaded arithmetic assignment operation on a non-pointer _lvalue_:
* `+=`, `-=`, `*=`, `/=` and `%=`.
*/
abstract class AssignArithmeticOperation extends AssignOperation { }
/**
* A non-overloaded `+=` assignment expression on a non-pointer lvalue.
* A non-overloaded `+=` assignment expression on a non-pointer _lvalue_.
* ```
* a += b;
* ```
*/
class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
override string getCanonicalQLClass() { result = "AssignAddExpr" }
@@ -63,7 +71,10 @@ class AssignAddExpr extends AssignArithmeticOperation, @assignaddexpr {
}
/**
* A non-overloaded `-=` assignment expression on a non-pointer lvalue.
* A non-overloaded `-=` assignment expression on a non-pointer _lvalue_.
* ```
* a -= b;
* ```
*/
class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
override string getCanonicalQLClass() { result = "AssignSubExpr" }
@@ -73,6 +84,9 @@ class AssignSubExpr extends AssignArithmeticOperation, @assignsubexpr {
/**
* A non-overloaded `*=` assignment expression.
* ```
* a *= b;
* ```
*/
class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
override string getCanonicalQLClass() { result = "AssignMulExpr" }
@@ -82,6 +96,9 @@ class AssignMulExpr extends AssignArithmeticOperation, @assignmulexpr {
/**
* A non-overloaded `/=` assignment expression.
* ```
* a /= b;
* ```
*/
class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
override string getCanonicalQLClass() { result = "AssignDivExpr" }
@@ -91,6 +108,9 @@ class AssignDivExpr extends AssignArithmeticOperation, @assigndivexpr {
/**
* A non-overloaded `%=` assignment expression.
* ```
* a %= b;
* ```
*/
class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
override string getCanonicalQLClass() { result = "AssignRemExpr" }
@@ -105,7 +125,10 @@ class AssignRemExpr extends AssignArithmeticOperation, @assignremexpr {
abstract class AssignBitwiseOperation extends AssignOperation { }
/**
* A non-overloaded `&=` assignment expression.
* A non-overloaded AND (`&=`) assignment expression.
* ```
* a &= b;
* ```
*/
class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
override string getCanonicalQLClass() { result = "AssignAndExpr" }
@@ -114,7 +137,10 @@ class AssignAndExpr extends AssignBitwiseOperation, @assignandexpr {
}
/**
* A non-overloaded `|=` assignment expression.
* A non-overloaded OR (`|=`) assignment expression.
* ```
* a |= b;
* ```
*/
class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
override string getCanonicalQLClass() { result = "AssignOrExpr" }
@@ -123,7 +149,10 @@ class AssignOrExpr extends AssignBitwiseOperation, @assignorexpr {
}
/**
* A non-overloaded `^=` assignment expression.
* A non-overloaded XOR (`^=`) assignment expression.
* ```
* a ^= b;
* ```
*/
class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
override string getCanonicalQLClass() { result = "AssignXorExpr" }
@@ -133,6 +162,9 @@ class AssignXorExpr extends AssignBitwiseOperation, @assignxorexpr {
/**
* A non-overloaded `<<=` assignment expression.
* ```
* a <<= b;
* ```
*/
class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
override string getCanonicalQLClass() { result = "AssignLShiftExpr" }
@@ -142,6 +174,9 @@ class AssignLShiftExpr extends AssignBitwiseOperation, @assignlshiftexpr {
/**
* A non-overloaded `>>=` assignment expression.
* ```
* a >>= b;
* ```
*/
class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
override string getCanonicalQLClass() { result = "AssignRShiftExpr" }
@@ -151,6 +186,9 @@ class AssignRShiftExpr extends AssignBitwiseOperation, @assignrshiftexpr {
/**
* A non-overloaded `+=` pointer assignment expression.
* ```
* ptr += index;
* ```
*/
class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
override string getCanonicalQLClass() { result = "AssignPointerAddExpr" }
@@ -160,6 +198,9 @@ class AssignPointerAddExpr extends AssignOperation, @assignpaddexpr {
/**
* A non-overloaded `-=` pointer assignment expression.
* ```
* ptr -= index;
* ```
*/
class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
override string getCanonicalQLClass() { result = "AssignPointerSubExpr" }
@@ -168,11 +209,16 @@ class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
}
/**
* A C++ variable declaration in an expression where a condition is expected.
* For example, on the `ConditionDeclExpr` in `if (bool c = x < y)`,
* `getVariableAccess()` is an access to `c` (with possible casts),
* `getVariable()` is the variable `c` (which has an initializer `x < y`), and
* `getInitializingExpr()` is `x < y`.
* A C++ variable declaration inside the conditional expression of a `while`, `if` or
* `for` compound statement. Declaring a variable this way narrows its lifetime and
* scope to be strictly the compound statement itself. For example:
* ```
* extern int x, y;
* if (bool c = x < y) { do_something_with(c); }
* // c is no longer in scope
* while (int d = x - y) { do_something_else_with(d); }
* // d is no longer is scope
* ```
*/
class ConditionDeclExpr extends Expr, @condition_decl {
/**

View File

@@ -7,6 +7,9 @@ abstract class UnaryBitwiseOperation extends UnaryOperation { }
/**
* A C/C++ complement expression.
* ```
* unsigned c = ~a;
* ```
*/
class ComplementExpr extends UnaryBitwiseOperation, @complementexpr {
override string getOperator() { result = "~" }
@@ -23,6 +26,9 @@ abstract class BinaryBitwiseOperation extends BinaryOperation { }
/**
* A C/C++ left shift expression.
* ```
* unsigned c = a << b;
* ```
*/
class LShiftExpr extends BinaryBitwiseOperation, @lshiftexpr {
override string getOperator() { result = "<<" }
@@ -34,6 +40,9 @@ class LShiftExpr extends BinaryBitwiseOperation, @lshiftexpr {
/**
* A C/C++ right shift expression.
* ```
* unsigned c = a >> b;
* ```
*/
class RShiftExpr extends BinaryBitwiseOperation, @rshiftexpr {
override string getOperator() { result = ">>" }
@@ -44,7 +53,10 @@ class RShiftExpr extends BinaryBitwiseOperation, @rshiftexpr {
}
/**
* A C/C++ bitwise and expression.
* A C/C++ bitwise AND expression.
* ```
* unsigned c = a & b;
* ```
*/
class BitwiseAndExpr extends BinaryBitwiseOperation, @andexpr {
override string getOperator() { result = "&" }
@@ -55,7 +67,10 @@ class BitwiseAndExpr extends BinaryBitwiseOperation, @andexpr {
}
/**
* A C/C++ bitwise or expression.
* A C/C++ bitwise OR expression.
* ```
* unsigned c = a | b;
* ```
*/
class BitwiseOrExpr extends BinaryBitwiseOperation, @orexpr {
override string getOperator() { result = "|" }
@@ -66,7 +81,10 @@ class BitwiseOrExpr extends BinaryBitwiseOperation, @orexpr {
}
/**
* A C/C++ bitwise xor expression.
* A C/C++ bitwise XOR expression.
* ```
* unsigned c = a ^ b;
* ```
*/
class BitwiseXorExpr extends BinaryBitwiseOperation, @xorexpr {
override string getOperator() { result = "^" }

View File

@@ -1,14 +1,20 @@
import semmle.code.cpp.exprs.Expr
/**
* A C/C++ builtin operation.
* A C/C++ builtin operation. This is the root QL class encompassing
* built-in functionality.
*/
abstract class BuiltInOperation extends Expr {
override string getCanonicalQLClass() { result = "BuiltInOperation" }
}
/**
* A C/C++ `__builtin_va_start` expression (used by some implementations of `va_start`).
* A C/C++ `__builtin_va_start` built-in operation (used by some
* implementations of `va_start`).
* ```
* __builtin_va_list ap;
* __builtin_va_start(ap, last_named_param);
* ```
*/
class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
override string toString() { result = "__builtin_va_start" }
@@ -17,7 +23,13 @@ class BuiltInVarArgsStart extends BuiltInOperation, @vastartexpr {
}
/**
* A C/C++ `__builtin_va_end` expression (used by some implementations of `va_end`).
* A C/C++ `__builtin_va_end` built-in operation (used by some implementations
* of `va_end`).
* ```
* __builtin_va_start(ap, last_named_param);
* ap = __builtin_va_arg(ap, long);
* __builtin_va_end(ap);
* ```
*/
class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
override string toString() { result = "__builtin_va_end" }
@@ -26,7 +38,11 @@ class BuiltInVarArgsEnd extends BuiltInOperation, @vaendexpr {
}
/**
* A C/C++ `__builtin_va_arg` expression (used by some implementations of `va_arg`).
* A C/C++ `__builtin_va_arg` built-in operation (used by some implementations
* of `va_arg`).
* ```
* ap = __builtin_va_arg(ap, long);
* ```
*/
class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
override string toString() { result = "__builtin_va_arg" }
@@ -35,7 +51,13 @@ class BuiltInVarArg extends BuiltInOperation, @vaargexpr {
}
/**
* A C/C++ `__builtin_va_copy` expression (used by some implementations of `va_copy`).
* A C/C++ `__builtin_va_copy` built-in operation (used by some implementations
* of `va_copy`).
* ```
* va_list ap, aq;
* __builtin_va_start(ap, last_named_param);
* va_copy(aq, ap);
* ```
*/
class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
override string toString() { result = "__builtin_va_copy" }
@@ -45,6 +67,9 @@ class BuiltInVarArgCopy extends BuiltInOperation, @vacopyexpr {
/**
* A Microsoft C/C++ `__noop` expression, which does nothing.
* ```
* __noop;
* ```
*/
class BuiltInNoOp extends BuiltInOperation, @noopexpr {
override string toString() { result = "__noop" }
@@ -53,16 +78,37 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
}
/**
* A C++ `__offsetof` expression (used by some implementations of offsetof in the presence of user-defined `operator&`).
* DEPRECATED: Use `BuiltInOperationBuiltInOffsetOf` instead.
*/
class BuiltInOperationOffsetOf extends BuiltInOperation, @offsetofexpr {
override string toString() { result = "__offsetof" }
deprecated class BuiltInOperationOffsetOf = BuiltInOperationBuiltInOffsetOf;
override string getCanonicalQLClass() { result = "BuiltInOperationOffsetOf" }
/**
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is a GNU/Clang extension.
* ```
* struct S {
* int a, b;
* };
* int d = __builtin_offsetof(struct S, b); // usually 4
* ```
*/
class BuiltInOperationBuiltInOffsetOf extends BuiltInOperation, @offsetofexpr {
override string toString() { result = "__builtin_offsetof" }
override string getCanonicalQLClass() { result = "BuiltInOperationBuiltInOffsetOf" }
}
/**
* A C/C++ `__INTADDR__` expression, used by EDG to implement `offsetof` in the presence of user-defined `operator&`.
* A C/C++ `__INTADDR__` built-in operation (used by some implementations
* of `offsetof`). The operation retains its semantics even in the presence
* of an overloaded `operator &`). This is an EDG extension.
* ```
* struct S {
* int a, b;
* };
* int d = __INTADDR__(struct S, b); // usually 4
* ```
*/
class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
override string toString() { result = "__INTADDR__" }
@@ -71,7 +117,13 @@ class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
}
/**
* A C++ `__has_assign` expression (used by some implementations of the type_traits header).
* A C++ `__has_assign` built-in operation (used by some implementations of
* the `<type_traits>` header).
*
* Returns `true` if the type has a copy assignment operator.
* ```
* bool v = __has_assign(MyType);
* ```
*/
class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
override string toString() { result = "__has_assign" }
@@ -80,7 +132,13 @@ class BuiltInOperationHasAssign extends BuiltInOperation, @hasassignexpr {
}
/**
* A C++ `__has_copy` expression (used by some implementations of the type_traits header).
* A C++ `__has_copy` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type has a copy constructor.
* ```
* std::integral_constant< bool, __has_copy(_Tp)> hc;
* ```
*/
class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
override string toString() { result = "__has_copy" }
@@ -89,7 +147,14 @@ class BuiltInOperationHasCopy extends BuiltInOperation, @hascopyexpr {
}
/**
* A C++ `__has_nothrow_assign` expression (used by some implementations of the type_traits header).
* A C++ `__has_nothrow_assign` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if a copy assignment operator has an empty exception
* specification.
* ```
* std::integral_constant< bool, __has_nothrow_assign(_Tp)> hnta;
* ```
*/
class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassign {
override string toString() { result = "__has_nothrow_assign" }
@@ -98,7 +163,14 @@ class BuiltInOperationHasNoThrowAssign extends BuiltInOperation, @hasnothrowassi
}
/**
* A C++ `__has_nothrow_constructor` expression (used by some implementations of the type_traits header).
* A C++ `__has_nothrow_constructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the default constructor has an empty exception
* specification.
* ```
* bool v = __has_nothrow_constructor(MyType);
* ```
*/
class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothrowconstr {
override string toString() { result = "__has_nothrow_constructor" }
@@ -107,7 +179,13 @@ class BuiltInOperationHasNoThrowConstructor extends BuiltInOperation, @hasnothro
}
/**
* A C++ `__has_nothrow_copy` expression (used by some implementations of the type_traits header).
* A C++ `__has_nothrow_copy` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the copy constructor has an empty exception specification.
* ```
* std::integral_constant< bool, __has_nothrow_copy(MyType) >;
* ```
*/
class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
override string toString() { result = "__has_nothrow_copy" }
@@ -116,7 +194,14 @@ class BuiltInOperationHasNoThrowCopy extends BuiltInOperation, @hasnothrowcopy {
}
/**
* A C++ `__has_trivial_assign` expression (used by some implementations of the type_traits header).
* A C++ `__has_trivial_assign` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type has a trivial assignment
* operator (`operator =`).
* ```
* bool v = __has_trivial_assign(MyType);
* ```
*/
class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassign {
override string toString() { result = "__has_trivial_assign" }
@@ -125,7 +210,13 @@ class BuiltInOperationHasTrivialAssign extends BuiltInOperation, @hastrivialassi
}
/**
* A C++ `__has_trivial_constructor` expression (used by some implementations of the type_traits header).
* A C++ `__has_trivial_constructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type has a trivial constructor.
* ```
* bool v = __has_trivial_constructor(MyType);
* ```
*/
class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivialconstr {
override string toString() { result = "__has_trivial_constructor" }
@@ -134,7 +225,13 @@ class BuiltInOperationHasTrivialConstructor extends BuiltInOperation, @hastrivia
}
/**
* A C++ `__has_trivial_copy` expression (used by some implementations of the type_traits header).
* A C++ `__has_trivial_copy` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns true if the type has a trivial copy constructor.
* ```
* std::integral_constant< bool, __has_trivial_copy(MyType) > htc;
* ```
*/
class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
override string toString() { result = "__has_trivial_copy" }
@@ -143,7 +240,13 @@ class BuiltInOperationHasTrivialCopy extends BuiltInOperation, @hastrivialcopy {
}
/**
* A C++ `__has_trivial_destructor` expression (used by some implementations of the type_traits header).
* A C++ `__has_trivial_destructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type has a trivial destructor.
* ```
* bool v = __has_trivial_destructor(MyType);
* ```
*/
class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivialdestructor {
override string toString() { result = "__has_trivial_destructor" }
@@ -152,7 +255,13 @@ class BuiltInOperationHasTrivialDestructor extends BuiltInOperation, @hastrivial
}
/**
* A C++ `__has_user_destructor` expression (used by some implementations of the type_traits header).
* A C++ `__has_user_destructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if the type has a user-declared destructor.
* ```
* bool v = __has_user_destructor(MyType);
* ```
*/
class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr {
override string toString() { result = "__has_user_destructor" }
@@ -161,7 +270,16 @@ class BuiltInOperationHasUserDestructor extends BuiltInOperation, @hasuserdestr
}
/**
* A C++ `__has_virtual_destructor` expression (used by some implementations of the type_traits header).
* A C++ `__has_virtual_destructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type has a virtual destructor.
* ```
* template<typename _Tp>
* struct has_virtual_destructor
* : public integral_constant<bool, __has_virtual_destructor(_Tp)>
* { };
* ```
*/
class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtualdestr {
override string toString() { result = "__has_virtual_destructor" }
@@ -170,7 +288,13 @@ class BuiltInOperationHasVirtualDestructor extends BuiltInOperation, @hasvirtual
}
/**
* A C++ `__is_abstract` expression (used by some implementations of the type_traits header).
* A C++ `__is_abstract` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the class has at least one pure virtual function.
* ```
* bool v = __is_abstract(MyType);
* ```
*/
class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
override string toString() { result = "__is_abstract" }
@@ -179,7 +303,13 @@ class BuiltInOperationIsAbstract extends BuiltInOperation, @isabstractexpr {
}
/**
* A C++ `__is_base_of` expression (used by some implementations of the type_traits header).
* A C++ `__is_base_of` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the first type is a base class of the second type, of if both types are the same.
* ```
* bool v = __is_base_of(MyType, OtherType);
* ```
*/
class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
override string toString() { result = "__is_base_of" }
@@ -188,7 +318,13 @@ class BuiltInOperationIsBaseOf extends BuiltInOperation, @isbaseofexpr {
}
/**
* A C++ `__is_class` expression (used by some implementations of the type_traits header).
* A C++ `__is_class` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type is a `class` or a `struct`.
* ```
* bool v = __is_class(MyType);
* ```
*/
class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
override string toString() { result = "__is_class" }
@@ -197,7 +333,13 @@ class BuiltInOperationIsClass extends BuiltInOperation, @isclassexpr {
}
/**
* A C++ `__is_convertible_to` expression (used by some implementations of the type_traits header).
* A C++ `__is_convertible_to` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the first type can be converted to the second type.
* ```
* bool v = __is_convertible_to(MyType, OtherType);
* ```
*/
class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
override string toString() { result = "__is_convertible_to" }
@@ -206,7 +348,13 @@ class BuiltInOperationIsConvertibleTo extends BuiltInOperation, @isconvtoexpr {
}
/**
* A C++ `__is_empty` expression (used by some implementations of the type_traits header).
* A C++ `__is_empty` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type has no instance data members.
* ```
* bool v = __is_empty(MyType);
* ```
*/
class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
override string toString() { result = "__is_empty" }
@@ -215,7 +363,13 @@ class BuiltInOperationIsEmpty extends BuiltInOperation, @isemptyexpr {
}
/**
* A C++ `__is_enum` expression (used by some implementations of the type_traits header).
* A C++ `__is_enum` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns true if the type is an `enum`.
* ```
* bool v = __is_enum(MyType);
* ```
*/
class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
override string toString() { result = "__is_enum" }
@@ -224,7 +378,15 @@ class BuiltInOperationIsEnum extends BuiltInOperation, @isenumexpr {
}
/**
* A C++ `__is_pod` expression (used by some implementations of the type_traits header).
* A C++ `__is_pod` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type is a `class`, `struct` or `union`, WITHOUT
* (1) constructors, (2) private or protected non-static members, (3) base
* classes, or (4) virtual functions.
* ```
* bool v = __is_pod(MyType);
* ```
*/
class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
override string toString() { result = "__is_pod" }
@@ -233,7 +395,13 @@ class BuiltInOperationIsPod extends BuiltInOperation, @ispodexpr {
}
/**
* A C++ `__is_polymorphic` expression (used by some implementations of the type_traits header).
* A C++ `__is_polymorphic` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type has at least one virtual function.
* ```
* bool v = __is_polymorphic(MyType);
* ```
*/
class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
override string toString() { result = "__is_polymorphic" }
@@ -242,7 +410,13 @@ class BuiltInOperationIsPolymorphic extends BuiltInOperation, @ispolyexpr {
}
/**
* A C++ `__is_union` expression (used by some implementations of the type_traits header).
* A C++ `__is_union` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the type is a `union`.
* ```
* bool v = __is_union(MyType);
* ```
*/
class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
override string toString() { result = "__is_union" }
@@ -256,7 +430,16 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
deprecated class BuiltInOperationBuiltInTypes = BuiltInOperationBuiltInTypesCompatibleP;
/**
* A C++ `__builtin_types_compatible_p` expression (used by some implementations of the type_traits header).
* A C++ `__builtin_types_compatible_p` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the two types are the same (modulo qualifiers).
* ```
* template<typename _Tp1, typename _Tp2>
* struct types_compatible
* : public integral_constant<bool, __builtin_types_compatible_p(_Tp1, _Tp2) >
* { };
* ```
*/
class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typescompexpr {
override string toString() { result = "__builtin_types_compatible_p" }
@@ -264,6 +447,15 @@ class BuiltInOperationBuiltInTypesCompatibleP extends BuiltInOperation, @typesco
/**
* A clang `__builtin_shufflevector` expression.
*
* It outputs a permutation of elements from one or two input vectors.
* Please see
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#langext-builtin-shufflevector
* for more information.
* ```
* // Concatenate every other element of 4-element vectors V1 and V2.
* V3 = __builtin_shufflevector(V1, V2, 0, 2, 4, 6);
* ```
*/
class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshufflevector {
override string toString() { result = "__builtin_shufflevector" }
@@ -273,6 +465,17 @@ class BuiltInOperationBuiltInShuffleVector extends BuiltInOperation, @builtinshu
/**
* A clang `__builtin_convertvector` expression.
*
* Allows for conversion of vectors of equal element count and compatible
* element types. Please see
* https://releases.llvm.org/3.7.0/tools/clang/docs/LanguageExtensions.html#builtin-convertvector
* for more information.
* ```
* float vf __attribute__((__vector_size__(16)));
* typedef double vector4double __attribute__((__vector_size__(32)));
* // convert from a vector of 4 floats to a vector of 4 doubles.
* vector4double vd = __builtin_convertvector(vf, vector4double);
* ```
*/
class BuiltInOperationBuiltInConvertVector extends BuiltInOperation, @builtinconvertvector {
override string toString() { result = "__builtin_convertvector" }
@@ -281,7 +484,14 @@ class BuiltInOperationBuiltInConvertVector extends BuiltInOperation, @builtincon
}
/**
* A clang `__builtin_addressof` expression (can be used to implement C++'s std::addressof).
* A clang `__builtin_addressof` function (can be used to implement C++'s
* `std::addressof`).
*
* This function disregards any overloads created for `operator &`.
* ```
* int a = 1;
* int *b = __builtin_addressof(a);
* ```
*/
class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation, @builtinaddressof {
/** Gets the function or variable whose address is taken. */
@@ -298,7 +508,17 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation,
}
/**
* The `__is_trivially_constructible` type trait.
* The `__is_trivially_constructible` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type has a trivial default
* constructor, copy constructor or move constructor.
* ```
* template<typename T, typename... Args>
* struct is_trivially_constructible
* : public integral_constant<bool, __is_trivially_constructible(T, Args...) >
* { };
* ```
*/
class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
@istriviallyconstructibleexpr {
@@ -308,7 +528,15 @@ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation,
}
/**
* The `__is_destructible` type trait.
* The `__is_destructible` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type's destructor is not `delete`d and is accessible
* in derived `class`es, and whose base `class` and all non-static data members
* are also destructible.
* ```
* bool v = __is_destructible(MyType);
* ```
*/
class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleexpr {
override string toString() { result = "__is_destructible" }
@@ -317,7 +545,15 @@ class BuiltInOperationIsDestructible extends BuiltInOperation, @isdestructibleex
}
/**
* The `__is_nothrow_destructible` type trait.
* The `__is_nothrow_destructible` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is destructible and whose destructor, and those
* of member data and any super`class`es all have an empty exception
* specification.
* ```
* bool v = __is_nothrow_destructible(MyType);
* ```
*/
class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrowdestructibleexpr {
override string toString() { result = "__is_nothrow_destructible" }
@@ -326,7 +562,14 @@ class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrow
}
/**
* The `__is_trivially_destructible` type trait.
* The `__is_trivially_destructible` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is destructible and whose destructor, and those
* of member data and any superclasses are all trivial.
* ```
* bool v = __is_trivially_destructible(MyType);
* ```
*/
class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr {
override string toString() { result = "__is_trivially_destructible" }
@@ -335,7 +578,17 @@ class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istrivi
}
/**
* The `__is_trivially_assignable` type trait.
* The `__is_trivially_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the assignment operator `C::operator =(const C& c)` is
* trivial.
* ```
* template<typename T>
* struct is_trivially_assignable
* : public integral_constant<bool, __is_trivially_assignable(T) >
* { };
* ```
*/
class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istriviallyassignableexpr {
override string toString() { result = "__is_trivially_assignable" }
@@ -344,7 +597,14 @@ class BuiltInOperationIsTriviallyAssignable extends BuiltInOperation, @istrivial
}
/**
* The `__is_nothrow_assignable` type trait.
* The `__is_nothrow_assignable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if there exists a `C::operator =(const C& c) nothrow`
* assignment operator (i.e, with an empty exception specification).
* ```
* bool v = __is_nothrow_assignable(MyType);
* ```
*/
class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowassignableexpr {
override string toString() { result = "__is_nothrow_assignable" }
@@ -353,7 +613,18 @@ class BuiltInOperationIsNothrowAssignable extends BuiltInOperation, @isnothrowas
}
/**
* The `__is_standard_layout` type trait.
* The `__is_standard_layout` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type is a primitive type, or a `class`, `struct` or
* `union` WITHOUT (1) virtual functions or base classes, (2) reference member
* variable or (3) multiple occurrences of base `class` objects, among other
* restrictions. Please see
* https://en.cppreference.com/w/cpp/named_req/StandardLayoutType
* for more information.
* ```
* bool v = __is_standard_layout(MyType);
* ```
*/
class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayoutexpr {
override string toString() { result = "__is_standard_layout" }
@@ -362,7 +633,12 @@ class BuiltInOperationIsStandardLayout extends BuiltInOperation, @isstandardlayo
}
/**
* The `__is_trivially_copyable` type trait.
* The `__is_trivially_copyable` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if instances of this type can be copied by trivial
* means. The copying is done in a manner similar to the `memcpy`
* function.
*/
class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istriviallycopyableexpr {
override string toString() { result = "__is_trivially_copyable" }
@@ -371,7 +647,18 @@ class BuiltInOperationIsTriviallyCopyable extends BuiltInOperation, @istrivially
}
/**
* The `__is_literal_type` type trait.
* The `__is_literal_type` built-in operation (used by some implementations of
* the `<type_traits>` header).
*
* Returns `true` if the type is a scalar type, a reference type or an array of
* literal types, among others. Please see
* https://en.cppreference.com/w/cpp/named_req/LiteralType
* for more information.
*
* ```
* template <typename _Tp>
* std::integral_constant< bool, __is_literal_type(_Tp)> ilt;
* ```
*/
class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr {
override string toString() { result = "__is_literal_type" }
@@ -380,7 +667,15 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr
}
/**
* The `__has_trivial_move_constructor` type trait.
* The `__has_trivial_move_constructor` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns true if the move (`&&`) constructor can be generated by the
* compiler, with semantics of the `memcpy` operation.
* ```
* template <typename _Tp>
* std::integral_constant< bool, __has_trivial_move_constructor(_Tp)> htmc;
* ```
*/
class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
@hastrivialmoveconstructorexpr {
@@ -390,7 +685,16 @@ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation,
}
/**
* The `__has_trivial_move_assign` type trait.
* The `__has_trivial_move_assign` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns if the move-assign operator `C::operator =(C &&c)` is trivial.
* ```
* template<typename T>
* struct has_trivial_move_assign
* : public integral_constant<bool, __has_trivial_move_assign(T) >
* { };
* ```
*/
class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivialmoveassignexpr {
override string toString() { result = "__has_trivial_move_assign" }
@@ -399,7 +703,14 @@ class BuiltInOperationHasTrivialMoveAssign extends BuiltInOperation, @hastrivial
}
/**
* The `__has_nothrow_move_assign` type trait.
* The `__has_nothrow_move_assign` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type has a `C::operator=(C&& c) nothrow`, that is,
* an assignment operator with an empty exception specification.
* ```
* bool v = __has_nothrow_move_assign(MyType);
* ```
*/
class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrowmoveassignexpr {
override string toString() { result = "__has_nothrow_move_assign" }
@@ -408,7 +719,17 @@ class BuiltInOperationHasNothrowMoveAssign extends BuiltInOperation, @hasnothrow
}
/**
* The `__is_constructible` type trait.
* The `__is_constructible` built-in operation (used by some implementations
* of the `<type_traits>` header).
*
* Returns `true` if the type can be constructed using specified arguments
* (or none).
* ```
* template<typename T, typename... Args>
* struct is_constructible
* : public integral_constant<bool, __is_constructible(T, Args...) >
* { };
* ```
*/
class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructibleexpr {
override string toString() { result = "__is_constructible" }
@@ -417,7 +738,14 @@ class BuiltInOperationIsConstructible extends BuiltInOperation, @isconstructible
}
/**
* The `__is_nothrow_constructible` type trait.
* The `__is_nothrow_constructible` built-in operation (used by some
* implementations of the `<type_traits>` header).
*
* Returns `true` if the type is constructable and all its constructors have an
* empty exception specification (i.e., are declared with `nothrow`);
* ```
* bool v = __is_nothrow_constructible(MyType);
* ```
*/
class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothrowconstructibleexpr {
override string toString() { result = "__is_nothrow_constructible" }
@@ -426,7 +754,13 @@ class BuiltInOperationIsNothrowConstructible extends BuiltInOperation, @isnothro
}
/**
* The `__has_finalizer` type trait.
* The `__has_finalizer` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type defines a _finalizer_ `C::!C(void)`, to be called
* from either the regular destructor or the garbage collector.
* ```
* bool v = __has_finalizer(MyType);
* ```
*/
class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
override string toString() { result = "__has_finalizer" }
@@ -435,7 +769,12 @@ class BuiltInOperationHasFinalizer extends BuiltInOperation, @hasfinalizerexpr {
}
/**
* The `__is_delegate` type trait.
* The `__is_delegate` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the function has been declared as a `delegate`, used in
* message forwarding. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/delegate-cpp-component-extensions
* for more information.
*/
class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
override string toString() { result = "__is_delegate" }
@@ -444,7 +783,11 @@ class BuiltInOperationIsDelegate extends BuiltInOperation, @isdelegateexpr {
}
/**
* The `__is_interface_class` type trait.
* The `__is_interface_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type has been declared as an `interface`. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/interface-class-cpp-component-extensions
* for more information.
*/
class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfaceclassexpr {
override string toString() { result = "__is_interface_class" }
@@ -453,7 +796,15 @@ class BuiltInOperationIsInterfaceClass extends BuiltInOperation, @isinterfacecla
}
/**
* The `__is_ref_array` type trait.
* The `__is_ref_array` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the object passed in is a _platform array_. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/arrays-cpp-component-extensions
* for more information.
* ```
* array<int>^ x = gcnew array<int>(10);
* bool b = __is_ref_array(array<int>);
* ```
*/
class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
override string toString() { result = "__is_ref_array" }
@@ -462,7 +813,15 @@ class BuiltInOperationIsRefArray extends BuiltInOperation, @isrefarrayexpr {
}
/**
* The `__is_ref_class` type trait.
* The `__is_ref_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if the type is a _reference class_. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* for more information.
* ```
* ref class R {};
* bool b = __is_ref_class(R);
* ```
*/
class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
override string toString() { result = "__is_ref_class" }
@@ -471,7 +830,16 @@ class BuiltInOperationIsRefClass extends BuiltInOperation, @isrefclassexpr {
}
/**
* The `__is_sealed` type trait.
* The `__is_sealed` built-in operation. This is a Microsoft extension.
*
* Returns `true` if a given class or virtual function is marked as `sealed`,
* meaning that it cannot be extended or overridden. The `sealed` keyword
* is similar to the C++11 `final` keyword.
* ```
* ref class X sealed {
* virtual void f() sealed { }
* };
* ```
*/
class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
override string toString() { result = "__is_sealed" }
@@ -480,7 +848,17 @@ class BuiltInOperationIsSealed extends BuiltInOperation, @issealedexpr {
}
/**
* The `__is_simple_value_class` type trait.
* The `__is_simple_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type that contains no references to the
* garbage-collected heap.
* ```
* ref class R {}; // __is_simple_value_class(R) == false
* value struct V {}; // __is_simple_value_class(V) == true
* value struct V2 { // __is_simple_value_class(V2) == false
* R ^ r; // not a simple value type
* };
* ```
*/
class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalueclassexpr {
override string toString() { result = "__is_simple_value_class" }
@@ -489,7 +867,15 @@ class BuiltInOperationIsSimpleValueClass extends BuiltInOperation, @issimplevalu
}
/**
* The `__is_value_class` type trait.
* The `__is_value_class` built-in operation. This is a Microsoft extension.
*
* Returns `true` if passed a value type. Please see
* https://docs.microsoft.com/en-us/cpp/extensions/classes-and-structs-cpp-component-extensions
* For more information.
* ```
* value struct V {};
* bool v = __is_value_class(V);
* ```
*/
class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
override string toString() { result = "__is_value_class" }
@@ -498,7 +884,16 @@ class BuiltInOperationIsValueClass extends BuiltInOperation, @isvalueclassexpr {
}
/**
* The `__is_final` type trait.
* The `__is_final` built-in operation (used by some implementations of the
* `<type_traits>` header).
*
* Returns `true` if the `class` has been marked with the `final` specifier.
* ```
* template<typename T>
* struct is_final
* : public integral_constant<bool, __is_final(T) >
* { };
* ```
*/
class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
override string toString() { result = "__is_final" }
@@ -507,17 +902,35 @@ class BuiltInOperationIsFinal extends BuiltInOperation, @isfinalexpr {
}
/**
* The `__builtin_choose_expr` type trait.
* The `__builtin_choose_expr` expression. This is a GNU/Clang extension.
*
* The expression functions similarly to the ternary `?:` operator, except
* that it is evaluated at compile-time.
* ```
* int sz = __builtin_choose_expr(__builtin_types_compatible_p(int, long), 4, 8);
* ```
*/
class BuiltInChooseExpr extends BuiltInOperation, @builtinchooseexpr {
override string toString() { result = "__builtin_choose_expr" }
override string getCanonicalQLClass() { result = "BuiltInChooseExpr" }
}
/**
* Fill operation on a GNU vector.
* Fill operation on a vector. This is a GNU extension.
*
* A single scalar value is used to populate all the elements in a vector.
* In the example below, the scalar value is `25`:
* ```
* typedef int v16i __attribute__((vector_size(16)));
* v16i src, dst;
* dst = src << 25;
* ```
*/
class VectorFillOperation extends UnaryOperation, @vec_fill {
override string getOperator() { result = "(vector fill)" }
override string getCanonicalQLClass() { result = "VectorFillOperation" }
}
/**

View File

@@ -4,6 +4,8 @@ private import semmle.code.cpp.dataflow.EscapesTree
/**
* A C/C++ call.
*
* This is the abstract root QL class for all types of calls.
*/
abstract class Call extends Expr, NameQualifiableElement {
/**
@@ -139,17 +141,29 @@ class FunctionCall extends Call, @funbindexpr {
override string getCanonicalQLClass() { result = "FunctionCall" }
/** Gets an explicit template argument for this call. */
Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) }
/** Gets an explicit template argument value for this call. */
Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) }
/** Gets a template argument for this call. */
Type getATemplateArgument() { result = getTarget().getATemplateArgument() }
Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() }
/** Gets a template argument value for this call. */
Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() }
/** Gets the nth explicit template argument for this call. */
Type getExplicitTemplateArgument(int n) {
Locatable getExplicitTemplateArgument(int n) {
n < getNumberOfExplicitTemplateArguments() and
result = getTemplateArgument(n)
}
/** Gets the nth explicit template argument value for this call. */
Locatable getExplicitTemplateArgumentKind(int n) {
n < getNumberOfExplicitTemplateArguments() and
result = getTemplateArgumentKind(n)
}
/** Gets the number of explicit template arguments for this call. */
int getNumberOfExplicitTemplateArguments() {
if numtemplatearguments(underlyingElement(this), _)
@@ -161,7 +175,10 @@ class FunctionCall extends Call, @funbindexpr {
int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) }
/** Gets the nth template argument for this call (indexed from 0). */
Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) }
Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) }
/** Gets the nth template argument value for this call (indexed from 0). */
Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) }
/** Holds if any template arguments for this call are implicit / deduced. */
predicate hasImplicitTemplateArguments() {
@@ -213,7 +230,7 @@ class FunctionCall extends Call, @funbindexpr {
* Gets the function called by this call.
*
* In the case of virtual function calls, the result is the most-specific function in the override tree (as
* determined by the compiler) such that the target at runtime will be one of result.getAnOverridingFunction*().
* determined by the compiler) such that the target at runtime will be one of `result.getAnOverridingFunction*()`.
*/
override Function getTarget() { funbind(underlyingElement(this), unresolveElement(result)) }
@@ -258,7 +275,11 @@ class FunctionCall extends Call, @funbindexpr {
}
/**
* An instance of unary operator * applied to a user-defined type.
* An instance of a _user-defined_ unary `operator*` applied to its argument.
* ```
* T1 operator*(const T2 &);
* T1 a; T2 b;
* a = *b;
*/
class OverloadedPointerDereferenceExpr extends FunctionCall {
OverloadedPointerDereferenceExpr() {
@@ -266,6 +287,8 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
getTarget().getEffectiveNumberOfParameters() = 1
}
override string getCanonicalQLClass() { result = "OverloadedPointerDereferenceExpr" }
/**
* Gets the expression this operator * applies to.
*/
@@ -302,11 +325,18 @@ class OverloadedPointerDereferenceExpr extends FunctionCall {
}
/**
* An instance of operator [] applied to a user-defined type.
* An instance of a _user-defined_ binary `operator[]` applied to its arguments.
* ```
* struct T2 { T1 operator[](const T3 &); };
* T1 a; T2 b; T3 c;
* a = b[c];
* ```
*/
class OverloadedArrayExpr extends FunctionCall {
OverloadedArrayExpr() { getTarget().hasName("operator[]") }
override string getCanonicalQLClass() { result = "OverloadedArrayExpr" }
/**
* Gets the expression being subscripted.
*/
@@ -324,6 +354,12 @@ class OverloadedArrayExpr extends FunctionCall {
/**
* A C/C++ call which is performed through a function pointer.
*
* In the call below, `(*funcptr)` may be simplified to just `funcptr`.
* ```
* extern int (*funcptr)(int a, int b);
* int c = (*funcptr)(1, 2);
* ```
*/
class ExprCall extends Call, @callexpr {
/**
@@ -346,6 +382,11 @@ class ExprCall extends Call, @callexpr {
/**
* A C/C++ call which is performed through a variable of function pointer type.
* ```
* int call_via_ptr(int (*pfn)(int)) {
* return pfn(5);
* }
* ```
*/
class VariableCall extends ExprCall {
VariableCall() { this.getExpr() instanceof VariableAccess }
@@ -360,6 +401,10 @@ class VariableCall extends ExprCall {
/**
* A call to a constructor.
* ```
* struct S { S(void) {} };
* S s;
* ```
*/
class ConstructorCall extends FunctionCall {
ConstructorCall() { super.getTarget() instanceof Constructor }
@@ -372,6 +417,9 @@ class ConstructorCall extends FunctionCall {
/**
* A C++ `throw` expression.
* ```
* throw Exc(2);
* ```
*/
class ThrowExpr extends Expr, @throw_expr {
/**
@@ -389,6 +437,9 @@ class ThrowExpr extends Expr, @throw_expr {
/**
* A C++ `throw` expression with no argument (which causes the current exception to be re-thrown).
* ```
* throw;
* ```
*/
class ReThrowExpr extends ThrowExpr {
ReThrowExpr() { this.getType() instanceof VoidType }
@@ -400,6 +451,10 @@ class ReThrowExpr extends ThrowExpr {
/**
* A call to a destructor.
* ```
* struct S { ~S(void) {} } *s;
* s->~S();
* ```
*/
class DestructorCall extends FunctionCall {
DestructorCall() { super.getTarget() instanceof Destructor }
@@ -416,6 +471,11 @@ class DestructorCall extends FunctionCall {
* For example, given a plain old data type `pod_t`, the syntax `ptr->~pod_t()` is
* a vacuous destructor call, as `~pod_t` isn't actually a function. This can also
* occur in instantiated templates, as `ptr->~T()` becomes vacuous when `T` is `int`.
* ```
* typedef int pod_t;
* pod_t *s;
* s->~pod_t();
* ```
*/
class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
/**
@@ -431,6 +491,9 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
/**
* An initialization of a base class or member variable performed as part
* of a constructor's explicit initializer list or implicit actions.
*
* This is a QL root class for reprenting various types of constructor
* initializations.
*/
class ConstructorInit extends Expr, @ctorinit {
override string getCanonicalQLClass() { result = "ConstructorInit" }
@@ -447,6 +510,15 @@ class ConstructorBaseInit extends ConstructorInit, ConstructorCall {
/**
* A call to a constructor of a direct non-virtual base class as part of a
* constructor's initializer list or compiler-generated actions.
* ```
* struct S {
* int a;
* S(int b): a(b) {}
* };
* struct T: S {
* T(): S(33) {} // S(33) is a constructor call
* };
* ```
*/
class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
override string getCanonicalQLClass() { result = "ConstructorDirectInit" }
@@ -458,6 +530,15 @@ class ConstructorDirectInit extends ConstructorBaseInit, @ctordirectinit {
*
* If the virtual base class has already been initialized, then this
* call won't be performed.
* ```
* struct S {
* int a;
* S(int b): a(b) {}
* };
* struct T: virtual S {
* T(): S(33) {} // S(33) is a call to a virtual base constructor
* };
* ```
*/
class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
override string getCanonicalQLClass() { result = "ConstructorVirtualInit" }
@@ -466,6 +547,13 @@ class ConstructorVirtualInit extends ConstructorBaseInit, @ctorvirtualinit {
/**
* A call to a constructor of the same class as part of a constructor's
* initializer list, which delegates object construction (C++11 only).
* ```
* struct S {
* int a;
* S(int b): a(b) { }
* S(): S(0) { } // delegation to another constructor
* };
* ```
*/
class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit {
override string getCanonicalQLClass() { result = "ConstructorDelegationInit" }
@@ -474,6 +562,14 @@ class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit
/**
* An initialization of a member variable performed as part of a
* constructor's explicit initializer list or implicit actions.
* In the example below, member variable `b` is being initialized by
* constructor parameter `a`:
* ```
* struct S {
* int b;
* S(int a): b(a) {}
* } s(2);
* ```
*/
class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit {
/** Gets the field being initialized. */
@@ -515,6 +611,12 @@ class DestructorBaseDestruction extends DestructorCall, DestructorDestruction {
/**
* A call to a destructor of a direct non-virtual base class as part of a
* destructor's compiler-generated actions.
* ```
* struct S { ~S(void) {} };
* struct T: S {
* ~T(void) {} // will call ~S()
* };
* ```
*/
class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirectdestruct {
override string getCanonicalQLClass() { result = "DestructorDirectDestruction" }
@@ -526,6 +628,12 @@ class DestructorDirectDestruction extends DestructorBaseDestruction, @dtordirect
*
* If the virtual base class wasn't initialized by the ConstructorVirtualInit
* in the corresponding constructor, then this call won't be performed.
* ```
* struct S { ~S(void) {} };
* struct T: virtual S {
* ~T(void) {} // will call ~S()
* };
* ```
*/
class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtualdestruct {
override string getCanonicalQLClass() { result = "DestructorVirtualDestruction" }
@@ -534,6 +642,13 @@ class DestructorVirtualDestruction extends DestructorBaseDestruction, @dtorvirtu
/**
* A destruction of a member variable performed as part of a
* destructor's compiler-generated actions.
* ```
* struct S { ~S(void) {} };
* struct T {
* S s;
* ~T(void) {} // will call s.~S()
* };
* ```
*/
class DestructorFieldDestruction extends DestructorDestruction, @dtorfielddestruct {
/** Gets the field being destructed. */

View File

@@ -22,7 +22,7 @@ abstract class Conversion extends Expr {
/**
* A C/C++ cast expression.
*
* To get the type which the expression is being cast to, use getType().
* To get the type which the expression is being cast to, use `Cast::getType()`.
*
* There are two groups of subtypes of `Cast`. The first group differentiates
* between the different cast syntax forms, e.g. `CStyleCast`, `StaticCast`,
@@ -33,6 +33,9 @@ abstract class Conversion extends Expr {
* cast that is syntactically as `CStyleCast` may also be an `IntegralConversion`,
* a `PointerBaseClassConversion`, or some other semantic conversion. Similarly,
* a `PointerDerivedClassConversion` may also be a `CStyleCast` or a `StaticCast`.
*
* This is an abstract root QL class representing the different casts. For
* specific examples, consult the documentation for any of QL classes mentioned above.
*/
abstract class Cast extends Conversion, @cast {
/**
@@ -71,6 +74,10 @@ module CastSanity {
/**
* A cast expression in C, or a C-style cast expression in C++.
* ```
* float f = 3.0f;
* int i = (int)f;
* ```
*/
class CStyleCast extends Cast, @c_style_cast {
override string toString() { result = "(" + this.getType().getName() + ")..." }
@@ -82,6 +89,14 @@ class CStyleCast extends Cast, @c_style_cast {
/**
* A C++ `static_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/static_cast for
* more information.
* ```
* struct T: S {};
* struct S *s = get_S();
* struct T *t = static_cast<struct T *>(s); // downcast
* ```
*/
class StaticCast extends Cast, @static_cast {
override string toString() { result = "static_cast<" + this.getType().getName() + ">..." }
@@ -93,6 +108,13 @@ class StaticCast extends Cast, @static_cast {
/**
* A C++ `const_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/const_cast for
* more information.
* ```
* const struct S *s = get_S();
* struct S *t = const_cast<struct S *>(s);
* ```
*/
class ConstCast extends Cast, @const_cast {
override string toString() { result = "const_cast<" + this.getType().getName() + ">..." }
@@ -104,6 +126,13 @@ class ConstCast extends Cast, @const_cast {
/**
* A C++ `reinterpret_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/reinterpret_cast for
* more information.
* ```
* struct S *s = get_S();
* std::uintptr_t p = reinterpret_cast<std::uintptr_t>(s);
* ```
*/
class ReinterpretCast extends Cast, @reinterpret_cast {
override string toString() { result = "reinterpret_cast<" + this.getType().getName() + ">..." }
@@ -135,7 +164,11 @@ private predicate isPointerToMemberOrNullPointer(Type type) {
}
/**
* A conversion from one arithmetic or enum type to another.
* A conversion from one arithmetic or `enum` type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class ArithmeticConversion extends Cast {
ArithmeticConversion() {
@@ -149,6 +182,10 @@ class ArithmeticConversion extends Cast {
/**
* A conversion from one integral or enum type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralConversion extends ArithmeticConversion {
IntegralConversion() {
@@ -164,7 +201,11 @@ class IntegralConversion extends ArithmeticConversion {
}
/**
* A conversion from one floating point type to another.
* A conversion from one floating point type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class FloatingPointConversion extends ArithmeticConversion {
FloatingPointConversion() {
@@ -181,6 +222,10 @@ class FloatingPointConversion extends ArithmeticConversion {
/**
* A conversion from a floating point type to an integral or enum type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class FloatingPointToIntegralConversion extends ArithmeticConversion {
FloatingPointToIntegralConversion() {
@@ -197,6 +242,10 @@ class FloatingPointToIntegralConversion extends ArithmeticConversion {
/**
* A conversion from an integral or enum type to a floating point type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralToFloatingPointConversion extends ArithmeticConversion {
IntegralToFloatingPointConversion() {
@@ -212,9 +261,15 @@ class IntegralToFloatingPointConversion extends ArithmeticConversion {
}
/**
* A conversion from one pointer type to another. The conversion does
* A conversion from one pointer type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*
* The conversion does
* not modify the value of the pointer. For pointer conversions involving
* casts between base and derived classes, see `BaseClassConversion` and
* casts between base and derived classes, please see see `BaseClassConversion` or
* `DerivedClassConversion`.
*/
class PointerConversion extends Cast {
@@ -232,10 +287,16 @@ class PointerConversion extends Cast {
}
/**
* A conversion from one pointer-to-member type to another. The conversion
* does not modify the value of the pointer-to-member. For pointer-to-member
* conversions involving casts between base and derived classes, see
* `PointerToMemberBaseClassConversion` and `PointerToMemberDerivedClassConversion`.
* A conversion from one pointer-to-member type to another.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*
* The conversion does not modify the value of the pointer-to-member.
* For pointer-to-member conversions involving casts between base and
* derived classes, please see `PointerToMemberBaseClassConversion`
* or `PointerToMemberDerivedClassConversion`.
*/
class PointerToMemberConversion extends Cast {
PointerToMemberConversion() {
@@ -263,6 +324,10 @@ class PointerToMemberConversion extends Cast {
/**
* A conversion from a pointer type to an integral or enum type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToIntegralConversion extends Cast {
PointerToIntegralConversion() {
@@ -280,6 +345,10 @@ class PointerToIntegralConversion extends Cast {
/**
* A conversion from an integral or enum type to a pointer type.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class IntegralToPointerConversion extends Cast {
IntegralToPointerConversion() {
@@ -297,7 +366,11 @@ class IntegralToPointerConversion extends Cast {
/**
* A conversion to `bool`. Returns `false` if the source value is zero,
* false, or nullptr. Returns `true` otherwise.
* `false`, or `nullptr`. Returns `true` otherwise.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class BoolConversion extends Cast {
BoolConversion() { conversionkinds(underlyingElement(this), 1) }
@@ -309,6 +382,10 @@ class BoolConversion extends Cast {
/**
* A conversion to `void`.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class VoidConversion extends Cast {
VoidConversion() {
@@ -322,11 +399,16 @@ class VoidConversion extends Cast {
}
/**
* A conversion between two pointers or glvalues related by inheritance. The
* base class will always be either a direct base class of the derived class,
* A conversion between two pointers or _glvalue_s related by inheritance.
*
* The base class will always be either a direct base class of the derived class,
* or a virtual base class of the derived class. A conversion to an indirect
* non-virtual base class will be represented as a sequence of conversions to
* direct base classes.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class InheritanceConversion extends Cast {
InheritanceConversion() {
@@ -377,8 +459,12 @@ private Class getConversionClass(Expr expr) {
}
/**
* A conversion from a pointer or glvalue of a derived class to a pointer or
* glvalue of a direct or virtual base class.
* A conversion from a pointer or _glvalue_ of a derived class to a pointer or
* _glvalue_ of a direct or virtual base class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class BaseClassConversion extends InheritanceConversion {
BaseClassConversion() { conversionkinds(underlyingElement(this), 2) }
@@ -400,8 +486,12 @@ class BaseClassConversion extends InheritanceConversion {
}
/**
* A conversion from a pointer or glvalue to a base class to a pointer or glvalue
* A conversion from a pointer or _glvalue_ to a base class to a pointer or _glvalue_
* to a direct derived class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class DerivedClassConversion extends InheritanceConversion {
DerivedClassConversion() { conversionkinds(underlyingElement(this), 3) }
@@ -420,6 +510,10 @@ class DerivedClassConversion extends InheritanceConversion {
/**
* A conversion from a pointer-to-member of a derived class to a pointer-to-member
* of an immediate base class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToMemberBaseClassConversion extends Cast {
PointerToMemberBaseClassConversion() { conversionkinds(underlyingElement(this), 4) }
@@ -436,6 +530,10 @@ class PointerToMemberBaseClassConversion extends Cast {
/**
* A conversion from a pointer-to-member of a base class to a pointer-to-member
* of an immediate derived class.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PointerToMemberDerivedClassConversion extends Cast {
PointerToMemberDerivedClassConversion() { conversionkinds(underlyingElement(this), 5) }
@@ -450,9 +548,13 @@ class PointerToMemberDerivedClassConversion extends Cast {
}
/**
* A conversion of a glvalue from one type to another. The conversion does not
* modify the address of the glvalue. For glvalue conversions involving base and
* A conversion of a _glvalue_ from one type to another. The conversion does not
* modify the address of the _glvalue_. For _glvalue_ conversions involving base and
* derived classes, see `BaseClassConversion` and `DerivedClassConversion`.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class GlvalueConversion extends Cast {
GlvalueConversion() { conversionkinds(underlyingElement(this), 6) }
@@ -465,18 +567,22 @@ class GlvalueConversion extends Cast {
}
/**
* The adjustment of the type of a class prvalue. Most commonly seen in code
* The adjustment of the type of a class _prvalue_. Most commonly seen in code
* similar to:
*
* ```
* class String { ... };
* String func();
* void caller() {
* const String& r = func();
* }
*
* In the above example, the result of the call to `func` is a prvalue of type
* ```
* In the above example, the result of the call to `func` is a _prvalue_ of type
* `String`, which will be adjusted to type `const String` before being bound
* to the reference.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class PrvalueAdjustmentConversion extends Cast {
PrvalueAdjustmentConversion() { conversionkinds(underlyingElement(this), 7) }
@@ -490,6 +596,14 @@ class PrvalueAdjustmentConversion extends Cast {
/**
* A C++ `dynamic_cast` expression.
*
* Please see https://en.cppreference.com/w/cpp/language/dynamic_cast for
* more information.
* ```
* struct T: S {};
* struct S *s = get_S();
* struct T *t = dynamic_cast<struct T *>(s); // downcast
* ```
*/
class DynamicCast extends Cast, @dynamic_cast {
override string toString() { result = "dynamic_cast<" + this.getType().getName() + ">..." }
@@ -504,6 +618,11 @@ class DynamicCast extends Cast, @dynamic_cast {
/**
* A Microsoft C/C++ `__uuidof` expression that returns the UUID of a type, as
* specified by the `__declspec(uuid)` attribute.
* ```
* struct UUID { char a[16]; };
* struct __declspec(uuid("{01234567-89ab-cdef-0123-456789ABCDEF}")) S {};
* UUID uuid = __uuidof(S);
* ```
*/
class UuidofOperator extends Expr, @uuidof {
override string toString() {
@@ -519,22 +638,18 @@ class UuidofOperator extends Expr, @uuidof {
}
/**
* A C++ `typeid` expression which provides runtime type information
* about an expression or type.
* A C++ `typeid` expression which provides run-time type information (RTTI)
* about its argument.
*
* Please see https://en.cppreference.com/w/cpp/language/typeid for more
* information.
* ```
* Base *ptr = new Derived;
* const std::type_info &info1 = typeid(ptr);
* printf("the type of ptr is: %s\n", typeid(ptr).name());
* ```
*/
class TypeidOperator extends Expr, @type_id {
/**
* Gets the type that is returned by this typeid expression.
*
* For example in the following code the `typeid` returns the
* type `MyClass *`.
*
* ```
* MyClass *ptr;
*
* printf("the type of ptr is: %s\n", typeid(ptr).name);
* ```
*/
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
/**
@@ -566,6 +681,10 @@ class TypeidOperator extends Expr, @type_id {
*
* This expression only appears in templates themselves - in any actual
* instantiations, "sizeof...(x)" will be replaced by its integer value.
* ```
* template < typename... T >
* int count ( T &&... t ) { return sizeof... ( t ); }
* ```
*/
class SizeofPackOperator extends Expr, @sizeof_pack {
override string toString() { result = "sizeof...(...)" }
@@ -586,6 +705,9 @@ abstract class SizeofOperator extends Expr, @runtime_sizeof {
/**
* A C/C++ sizeof expression whose operand is an expression.
* ```
* if (sizeof(a) == sizeof(b)) { c = (b)a; }
* ```
*/
class SizeofExprOperator extends SizeofOperator {
SizeofExprOperator() { exists(Expr e | this.getChild(0) = e) }
@@ -611,6 +733,9 @@ class SizeofExprOperator extends SizeofOperator {
/**
* A C/C++ sizeof expression whose operand is a type name.
* ```
* int szlong = sizeof(int) == sizeof(long)? 4 : 8;
* ```
*/
class SizeofTypeOperator extends SizeofOperator {
SizeofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
@@ -643,6 +768,9 @@ abstract class AlignofOperator extends Expr, @runtime_alignof {
/**
* A C++11 `alignof` expression whose operand is an expression.
* ```
* int addrMask = ~(alignof(expr) - 1);
* ```
*/
class AlignofExprOperator extends AlignofOperator {
AlignofExprOperator() { exists(Expr e | this.getChild(0) = e) }
@@ -662,6 +790,9 @@ class AlignofExprOperator extends AlignofOperator {
/**
* A C++11 `alignof` expression whose operand is a type name.
* ```
* bool proper_alignment = (alingof(T) == alignof(T[0]);
* ```
*/
class AlignofTypeOperator extends AlignofOperator {
AlignofTypeOperator() { sizeof_bind(underlyingElement(this), _) }
@@ -679,6 +810,10 @@ class AlignofTypeOperator extends AlignofOperator {
/**
* A C/C++ array to pointer conversion.
*
* The conversion is either implicit or underlies a particular cast.
* Please see `CStyleCast`, `StaticCast`, `ConstCast`
* or `ReinterpretCast` for more information.
*/
class ArrayToPointerConversion extends Conversion, @array_to_pointer {
/** Gets a textual representation of this conversion. */

View File

@@ -2,6 +2,8 @@ import semmle.code.cpp.exprs.Expr
/**
* A C/C++ comparison operation, that is, either an equality operation or a relational operation.
*
* This is a QL abstract base class for all comparisons.
*/
abstract class ComparisonOperation extends BinaryOperation { }
@@ -14,6 +16,9 @@ abstract class EqualityOperation extends ComparisonOperation {
/**
* A C/C++ equal expression.
* ```
* bool c = (a == b);
* ```
*/
class EQExpr extends EqualityOperation, @eqexpr {
override string getCanonicalQLClass() { result = "EQExpr" }
@@ -23,6 +28,9 @@ class EQExpr extends EqualityOperation, @eqexpr {
/**
* A C/C++ not equal expression.
* ```
* bool c = (a != b);
* ```
*/
class NEExpr extends EqualityOperation, @neexpr {
override string getCanonicalQLClass() { result = "NEExpr" }
@@ -65,6 +73,9 @@ abstract class RelationalOperation extends ComparisonOperation {
/**
* A C/C++ greater than expression.
* ```
* bool c = (a > b);
* ```
*/
class GTExpr extends RelationalOperation, @gtexpr {
override string getCanonicalQLClass() { result = "GTExpr" }
@@ -77,7 +88,10 @@ class GTExpr extends RelationalOperation, @gtexpr {
}
/**
* A C/C++ lesser than expression.
* A C/C++ less than expression.
* ```
* bool c = (a < b);
* ```
*/
class LTExpr extends RelationalOperation, @ltexpr {
override string getCanonicalQLClass() { result = "LTExpr" }
@@ -91,6 +105,9 @@ class LTExpr extends RelationalOperation, @ltexpr {
/**
* A C/C++ greater than or equal expression.
* ```
* bool c = (a >= b);
* ```
*/
class GEExpr extends RelationalOperation, @geexpr {
override string getCanonicalQLClass() { result = "GEExpr" }
@@ -103,7 +120,10 @@ class GEExpr extends RelationalOperation, @geexpr {
}
/**
* A C/C++ lesser than or equal expression.
* A C/C++ less than or equal expression.
* ```
* bool c = (a <= b);
* ```
*/
class LEExpr extends RelationalOperation, @leexpr {
override string getCanonicalQLClass() { result = "LEExpr" }

View File

@@ -5,6 +5,8 @@ private import semmle.code.cpp.internal.AddressConstantExpression
/**
* A C/C++ expression.
*
* This is the root QL class for all expressions.
*/
class Expr extends StmtParent, @expr {
/** Gets the nth child of this expression. */
@@ -163,36 +165,36 @@ class Expr extends StmtParent, @expr {
predicate mayBeGloballyImpure() { any() }
/**
* Holds if this expression is an lvalue. An lvalue is an expression that
* Holds if this expression is an _lvalue_. An _lvalue_ is an expression that
* represents a location, rather than a value.
* See [basic.lval] for more about lvalues.
*/
predicate isLValueCategory() { expr_types(underlyingElement(this), _, 3) }
/**
* Holds if this expression is an xvalue. An xvalue is a location whose
* lifetime is about to end (e.g. an rvalue reference returned from a function
* Holds if this expression is an _xvalue_. An _xvalue_ is a location whose
* lifetime is about to end (e.g. an _rvalue_ reference returned from a function
* call).
* See [basic.lval] for more about xvalues.
*/
predicate isXValueCategory() { expr_types(underlyingElement(this), _, 2) }
/**
* Holds if this expression is a prvalue. A prvalue is an expression that
* Holds if this expression is a _prvalue_. A _prvalue_ is an expression that
* represents a value, rather than a location.
* See [basic.lval] for more about prvalues.
*/
predicate isPRValueCategory() { expr_types(underlyingElement(this), _, 1) }
/**
* Holds if this expression is a glvalue. A glvalue is either an lvalue or an
* xvalue.
* Holds if this expression is a _glvalue_. A _glvalue_ is either an _lvalue_ or an
* _xvalue_.
*/
predicate isGLValueCategory() { isLValueCategory() or isXValueCategory() }
/**
* Holds if this expression is an rvalue. An rvalue is either a prvalue or an
* xvalue.
* Holds if this expression is an _rvalue_. An _rvalue_ is either a _prvalue_ or an
* _xvalue_.
*/
predicate isRValueCategory() { isPRValueCategory() or isXValueCategory() }
@@ -205,7 +207,7 @@ class Expr extends StmtParent, @expr {
* - "prvalue"
* - "prvalue(load)"
*
* The "prvalue(load)" string is used when the expression is a prvalue, but
* The "prvalue(load)" string is used when the expression is a _prvalue_, but
* `hasLValueToRvalueConversion()` holds.
*/
string getValueCategoryString() {
@@ -252,32 +254,32 @@ class Expr extends StmtParent, @expr {
}
/**
* Holds if this expression has undergone an lvalue-to-rvalue conversion to
* Holds if this expression has undergone an _lvalue_-to-_rvalue_ conversion to
* extract its value.
* for example:
* ```
* y = x;
* ```
* The VariableAccess for `x` is a prvalue, and hasLValueToRValueConversion()
* The `VariableAccess` for `x` is a _prvalue_, and `hasLValueToRValueConversion()`
* holds because the value of `x` was loaded from the location of `x`.
* The VariableAccess for `y` is an lvalue, and hasLValueToRValueConversion()
* The `VariableAccess` for `y` is an _lvalue_, and `hasLValueToRValueConversion()`
* does not hold because the value of `y` was not extracted.
*
* See [conv.lval] for more about the lvalue-to-rvalue conversion
* See [conv.lval] for more about the _lvalue_-to-_rvalue_ conversion
*/
predicate hasLValueToRValueConversion() { expr_isload(underlyingElement(this)) }
/**
* Holds if this expression is an LValue, in the sense of having an address.
* Holds if this expression is an _lvalue_, in the sense of having an address.
*
* Being an LValue is best approximated as having an address.
* This is a strict superset of modifiable LValues, which are best approximated by things which could be on the left-hand side of an assignment.
* This is also a strict superset of expressions which provide an LValue, which is best approximated by things whose address is important.
* Being an _lvalue_ is best approximated as having an address.
* This is a strict superset of modifiable _lvalue_s, which are best approximated by things which could be on the left-hand side of an assignment.
* This is also a strict superset of expressions which provide an _lvalue_, which is best approximated by things whose address is important.
*
* See [basic.lval] in the C++ language specification.
* In C++03, every expression is either an LValue or an RValue.
* In C++11, every expression is exactly one of an LValue, an XValue, or a PRValue (with RValues being the union of XValues and PRValues).
* Using the C++11 terminology, this predicate selects expressions whose value category is lvalue.
* In C++03, every expression is either an _lvalue_ or an _rvalue_.
* In C++11, every expression is exactly one of an _lvalue_, an _xvalue_, or a _prvalue_ (with _rvalue_s being the union of _xvalue_s and _prvalue_s).
* Using the C++11 terminology, this predicate selects expressions whose value category is _lvalue_.
*/
predicate isLValue() {
// C++ n3337 - 5.1.1 clause 1
@@ -458,6 +460,8 @@ class Expr extends StmtParent, @expr {
/**
* A C/C++ operation.
*
* This is the QL abstract root class for all operations.
*/
abstract class Operation extends Expr {
/** Gets the operator of this operation. */
@@ -509,7 +513,14 @@ abstract class BinaryOperation extends Operation {
*
* This is used to represent particular syntax within templates where the final
* form of the expression is not known. In actual instantiations, it will have
* been turned into a constructor call or aggregate initializer or similar.
* been turned into either a constructor call or an aggregate initializer or similar.
* ```
* template <typename T>
* struct S {
* T member;
* S() { member = T({ arg1, arg2 }); }
* };
* ```
*/
class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
override string toString() { result = "({...})" }
@@ -519,6 +530,12 @@ class ParenthesizedBracedInitializerList extends Expr, @braced_init_list {
/**
* A C/C++ parenthesis expression.
*
* It is typically used to raise the syntactic precedence of the subexpression that
* it contains. For example:
* ```
* int d = a & ( b | c );
* ```
*/
class ParenthesisExpr extends Conversion, @parexpr {
override string toString() { result = "(...)" }
@@ -528,6 +545,8 @@ class ParenthesisExpr extends Conversion, @parexpr {
/**
* A C/C++ expression that has not been resolved.
*
* It is assigned `ErroneousType` as its type.
*/
class ErrorExpr extends Expr, @errorexpr {
override string toString() { result = "<error expr>" }
@@ -537,6 +556,12 @@ class ErrorExpr extends Expr, @errorexpr {
/**
* A Microsoft C/C++ __assume expression.
*
* Unlike `assert`, `__assume` is evaluated at compile time and
* is treated as a hint to the optimizer
* ```
* __assume(ptr < end_buf);
* ```
*/
class AssumeExpr extends Expr, @assume {
override string toString() { result = "__assume(...)" }
@@ -551,6 +576,9 @@ class AssumeExpr extends Expr, @assume {
/**
* A C/C++ comma expression.
* ```
* int c = compute1(), compute2(), resulting_value;
* ```
*/
class CommaExpr extends Expr, @commaexpr {
override string getCanonicalQLClass() { result = "CommaExpr" }
@@ -583,6 +611,9 @@ class CommaExpr extends Expr, @commaexpr {
/**
* A C/C++ address-of expression.
* ```
* int *ptr = &var;
* ```
*/
class AddressOfExpr extends UnaryOperation, @address_of {
override string getCanonicalQLClass() { result = "AddressOfExpr" }
@@ -605,11 +636,14 @@ class AddressOfExpr extends UnaryOperation, @address_of {
}
/**
* An implicit conversion from type T to type T&amp;.
* An implicit conversion from type `T` to type `T &`.
*
* This typically occurs when an expression of type T is used to initialize a variable or parameter of
* type T&amp;, and is to reference types what AddressOfExpr is to pointer types - though this class is
* This typically occurs when an expression of type `T` is used to initialize a variable or parameter of
* type `T &`, and is to reference types what `AddressOfExpr` is to pointer types, though this class is
* considered to be a conversion rather than an operation, and as such doesn't occur in the main AST.
* ```
* int &var_ref = var;
* ```
*/
class ReferenceToExpr extends Conversion, @reference_to {
override string toString() { result = "(reference to)" }
@@ -620,9 +654,12 @@ class ReferenceToExpr extends Conversion, @reference_to {
}
/**
* An instance of unary operator * applied to a built-in type.
* An instance of the built-in unary `operator *` applied to a type.
*
* For user-defined types, see OverloadedPointerDereferenceExpr.
* For user-defined overloads of `operator *`, see `OverloadedPointerDereferenceExpr`.
* ```
* int var = *varptr;
* ```
*/
class PointerDereferenceExpr extends UnaryOperation, @indirect {
override string getCanonicalQLClass() { result = "PointerDereferenceExpr" }
@@ -650,11 +687,15 @@ class PointerDereferenceExpr extends UnaryOperation, @indirect {
}
/**
* An implicit conversion from type T&amp; to type T.
* An implicit conversion from type `T &` to type `T`.
*
* This typically occurs when an variable of type T&amp; is used in a context which expects type T, and
* is to reference types what PointerDereferenceExpr is to pointer types - though this class is
* This typically occurs when an variable of type `T &` is used in a context which expects type `T`, and
* is to reference types what `PointerDereferenceExpr` is to pointer types - though this class is
* considered to be a conversion rather than an operation, and as such doesn't occur in the main AST.
* ```
* float &f_ref = get_ref();
* float f = f_ref;
* ```
*/
class ReferenceDereferenceExpr extends Conversion, @ref_indirect {
override string toString() { result = "(reference dereference)" }
@@ -756,6 +797,9 @@ class NewOrNewArrayExpr extends Expr, @any_new_expr {
/**
* A C++ `new` (non-array) expression.
* ```
* Foo *ptr = new Foo(3);
* ```
*/
class NewExpr extends NewOrNewArrayExpr, @new_expr {
override string toString() { result = "new" }
@@ -782,6 +826,10 @@ class NewExpr extends NewOrNewArrayExpr, @new_expr {
/**
* A C++ `new[]` (array) expression.
* ```
* Foo *foo = new Foo[]{1, 3, 5};
* Bar *bar = new Bar[5];
* ```
*/
class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
override string toString() { result = "new[]" }
@@ -827,6 +875,9 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
/**
* A C++ `delete` (non-array) expression.
* ```
* delete ptr;
* ```
*/
class DeleteExpr extends Expr, @delete_expr {
override string toString() { result = "delete" }
@@ -902,6 +953,9 @@ class DeleteExpr extends Expr, @delete_expr {
/**
* A C++ `delete[]` (array) expression.
* ```
* delete[] arr;
* ```
*/
class DeleteArrayExpr extends Expr, @delete_array_expr {
override string toString() { result = "delete[]" }
@@ -977,6 +1031,10 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
/**
* A compound statement enclosed in parentheses used as an expression (a GNU extension to C/C++).
* In the example below, `b` is the return value from the compound statement.
* ```
* int a = ({ int b = c + d; b; });
* ```
*/
class StmtExpr extends Expr, @expr_stmt {
override string toString() { result = "(statement expression)" }
@@ -1006,7 +1064,7 @@ private Expr getStmtResultExpr(Stmt stmt) {
}
/**
* A C/C++ this expression.
* A C++ `this` expression.
*/
class ThisExpr extends Expr, @thisaccess {
override string toString() { result = "this" }
@@ -1019,8 +1077,10 @@ class ThisExpr extends Expr, @thisaccess {
}
/**
* A code block expression, for example `^ int (int x, int y) {return x + y;}`.
*
* A code block expression, for example:
* ```
* ^ int (int x, int y) {return x + y;}
* ```
* Blocks are a language extension supported by Clang, and by Apple's
* branch of GCC.
*/
@@ -1036,7 +1096,11 @@ class BlockExpr extends Literal {
}
/**
* A C++11 `noexcept` expression, for example `noexcept(1 + 2)`.
* A C++11 `noexcept` expression, returning `true` if its subexpression is guaranteed
* not to `throw` exceptions. For example:
* ```
* if (noexcept(func_1() + func_2())) { }
* ```
*/
class NoExceptExpr extends Expr, @noexceptexpr {
override string toString() { result = "noexcept(...)" }
@@ -1052,6 +1116,10 @@ class NoExceptExpr extends Expr, @noexceptexpr {
/**
* A C++17 fold expression. This will only appear in an uninstantiated template; any instantiations
* of the template will instead contain the sequence of expressions given by expanding the fold.
* ```
* template < typename... T >
* auto sum ( T... t ) { return ( t + ... + 0 ); }
* ```
*/
class FoldExpr extends Expr, @foldexpr {
override string toString() {

View File

@@ -2,6 +2,8 @@ import semmle.code.cpp.exprs.Expr
/**
* A C/C++ literal.
*
* The is the QL root class for all literals.
*/
class Literal extends Expr, @literal {
/** Gets a textual representation of this literal. */
@@ -26,9 +28,7 @@ class Literal extends Expr, @literal {
* For example:
* ```
* void *label_ptr = &&myLabel; // &&myLabel is a LabelLiteral
*
* goto *label_ptr; // this is a ComputedGotoStmt
*
* myLabel: // this is a LabelStmt
* ```
*/
@@ -84,7 +84,11 @@ abstract class TextLiteral extends Literal {
}
/**
* A character literal, for example `'a'` or `L'a'`.
* A character literal. For example:
* ```
* char c1 = 'a';
* wchar_t c2 = L'b';
* ```
*/
class CharLiteral extends TextLiteral {
CharLiteral() { this.getValueText().regexpMatch("(?s)\\s*L?'.*") }
@@ -98,7 +102,11 @@ class CharLiteral extends TextLiteral {
}
/**
* A string literal, for example `"abcdef"` or `L"123456"`.
* A string literal. For example:
* ```
* const char *s1 = "abcdef";
* const wchar_t *s2 = L"123456";
* ```
*/
class StringLiteral extends TextLiteral {
StringLiteral() {
@@ -111,7 +119,11 @@ class StringLiteral extends TextLiteral {
}
/**
* An octal literal.
* An octal literal. For example:
* ```
* char esc = 033;
* ```
* Octal literals must always start with the digit `0`.
*/
class OctalLiteral extends Literal {
OctalLiteral() { super.getValueText().regexpMatch("\\s*0[0-7]+[uUlL]*\\s*") }
@@ -121,6 +133,9 @@ class OctalLiteral extends Literal {
/**
* A hexadecimal literal.
* ```
* unsigned int32_t minus2 = 0xfffffffe;
* ```
*/
class HexLiteral extends Literal {
HexLiteral() { super.getValueText().regexpMatch("\\s*0[xX][0-9a-fA-F]+[uUlL]*\\s*") }
@@ -130,6 +145,8 @@ class HexLiteral extends Literal {
/**
* A C/C++ aggregate literal.
*
* For example:
*/
class AggregateLiteral extends Expr, @aggregateliteral {
override string getCanonicalQLClass() { result = "AggregateLiteral" }
@@ -153,7 +170,11 @@ class AggregateLiteral extends Expr, @aggregateliteral {
}
/**
* A C/C++ aggregate literal that initializes a class, struct, or union
* A C/C++ aggregate literal that initializes a `class`, `struct`, or `union`.
* For example:
* ```
* S s = { arg1, arg2, { arg3, arg4 }, arg5 };
* ```
*/
class ClassAggregateLiteral extends AggregateLiteral {
Class classType;
@@ -271,6 +292,9 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral {
/**
* A C/C++ aggregate literal that initializes an array
* ```
* S s[4] = { s_1, s_2, s_3, s_n };
* ```
*/
class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral {
ArrayType arrayType;
@@ -286,6 +310,15 @@ class ArrayAggregateLiteral extends ArrayOrVectorAggregateLiteral {
/**
* A C/C++ aggregate literal that initializes a GNU vector type.
*
* Braced initializer lists are used, similarly to what is done
* for arrays.
* ```
* typedef int v4si __attribute__ (( vector_size(4*sizeof(int)) ));
* v4si v = (v4si){ 1, 2, 3, 4 };
* typedef float float4 __attribute__((ext_vector_type(4)));
* float4 vf = {1.0f, 2.0f, 3.0f, 4.0f};
* ```
*/
class VectorAggregateLiteral extends ArrayOrVectorAggregateLiteral {
GNUVectorType vectorType;

View File

@@ -7,6 +7,9 @@ abstract class UnaryLogicalOperation extends UnaryOperation { }
/**
* A C/C++ logical not expression.
* ```
* c = !a;
* ```
*/
class NotExpr extends UnaryLogicalOperation, @notexpr {
override string getOperator() { result = "!" }
@@ -35,7 +38,10 @@ abstract class BinaryLogicalOperation extends BinaryOperation {
}
/**
* A C/C++ logical and expression.
* A C/C++ logical AND expression.
* ```
* if (a && b) { }
* ```
*/
class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
override string getOperator() { result = "&&" }
@@ -53,7 +59,10 @@ class LogicalAndExpr extends BinaryLogicalOperation, @andlogicalexpr {
}
/**
* A C/C++ logical or expression.
* A C/C++ logical OR expression.
* ```
* if (a || b) { }
* ```
*/
class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr {
override string getOperator() { result = "||" }
@@ -72,6 +81,9 @@ class LogicalOrExpr extends BinaryLogicalOperation, @orlogicalexpr {
/**
* A C/C++ conditional ternary expression.
* ```
* a = (b > c ? d : e);
* ```
*/
class ConditionalExpr extends Operation, @conditionalexpr {
/** Gets the condition of this conditional expression. */

View File

@@ -2,6 +2,7 @@ import cpp
import semmle.code.cpp.security.Security
private import semmle.code.cpp.ir.dataflow.DataFlow
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
/**
* A predictable instruction is one where an external user can predict
@@ -145,7 +146,8 @@ GlobalOrNamespaceVariable globalVarFromId(string id) {
}
Function resolveCall(Call call) {
// TODO: improve virtual dispatch. This will help in the test for
// `UncontrolledProcessOperation.ql`.
result = call.getTarget()
exists(CallInstruction callInstruction |
callInstruction.getAST() = call and
result = Dispatch::viableCallable(callInstruction)
)
}

View File

@@ -1,5 +1,6 @@
private import cpp
private import semmle.code.cpp.ir.IR
private import semmle.code.cpp.ir.dataflow.DataFlow
Function viableImpl(CallInstruction call) { result = viableCallable(call) }
@@ -20,6 +21,58 @@ Function viableCallable(CallInstruction call) {
functionSignatureWithBody(qualifiedName, nparams, result) and
strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1
)
or
// Rudimentary virtual dispatch support. It's essentially local data flow
// where the source is a derived-to-base conversion and the target is the
// qualifier of a call.
exists(Class derived, DataFlow::Node thisArgument |
nodeMayHaveClass(derived, thisArgument) and
overrideMayAffectCall(derived, thisArgument, _, result, call)
)
}
/**
* Holds if `call` is a virtual function call with qualifier `thisArgument` in
* `enclosingFunction`, whose static target is overridden by
* `overridingFunction` in `overridingClass`.
*/
pragma[noinline]
private predicate overrideMayAffectCall(
Class overridingClass, DataFlow::Node thisArgument, Function enclosingFunction,
MemberFunction overridingFunction, CallInstruction call
) {
call.getEnclosingFunction() = enclosingFunction and
overridingFunction.getAnOverriddenFunction+() = call.getStaticCallTarget() and
overridingFunction.getDeclaringType() = overridingClass and
thisArgument = DataFlow::instructionNode(call.getThisArgument())
}
/**
* Holds if `node` may have dynamic class `derived`, where `derived` is a class
* that may affect virtual dispatch within the enclosing function.
*
* For the sake of performance, this recursion is written out manually to make
* it a relation on `Class x Node` rather than `Node x Node` or `MemberFunction
* x Node`, both of which would be larger. It's a forward search since there
* should usually be fewer classes than calls.
*
* If a value is cast several classes up in the hierarchy, that will be modeled
* as a chain of `ConvertToBaseInstruction`s and will cause the search to start
* from each of them and pass through subsequent ones. There might be
* performance to gain by stopping before a second upcast and reconstructing
* the full chain in a "big-step" recursion after this one.
*/
private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) {
exists(ConvertToBaseInstruction toBase |
derived = toBase.getDerivedClass() and
overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and
node.asInstruction() = toBase
)
or
exists(DataFlow::Node prev |
nodeMayHaveClass(derived, prev) and
DataFlow::localFlowStep(prev, node)
)
}
/**

View File

@@ -360,7 +360,7 @@ private module ImplCommon {
*/
cached
predicate read(Node node1, Content f, Node node2) {
readStep(node1, f, node2) and storeStep(_, f, _)
readStep(node1, f, node2)
or
exists(DataFlowCall call, ReturnKind kind |
read0(call, kind, node1, f) and

View File

@@ -205,7 +205,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
iTo.(CopyInstruction).getSourceValue() = iFrom or
iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or
// Treat all conversions as flow, even conversions between different numeric types.
iTo.(ConvertInstruction).getUnary() = iFrom
iTo.(ConvertInstruction).getUnary() = iFrom or
iTo.(InheritanceConversionInstruction).getUnary() = iFrom
}
/**
@@ -214,6 +215,14 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
*/
predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) }
/**
* Holds if data can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
predicate localInstructionFlow(Instruction e1, Instruction e2) {
localFlow(instructionNode(e1), instructionNode(e2))
}
/**
* Holds if data can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.

View File

@@ -53,6 +53,14 @@ private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction no
*/
predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) }
/**
* Holds if taint can flow from `i1` to `i2` in zero or more
* local (intra-procedural) steps.
*/
predicate localInstructionTaint(Instruction i1, Instruction i2) {
localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2))
}
/**
* Holds if taint can flow from `e1` to `e2` in zero or more
* local (intra-procedural) steps.

View File

@@ -4,6 +4,7 @@
private import internal.IRTypeInternal
cached
private newtype TIRType =
TIRVoidType() or
TIRUnknownType() or
@@ -42,6 +43,10 @@ class IRType extends TIRType {
*
* This will hold for all `IRType` objects except `IRUnknownType`.
*/
// This predicate is overridden with `pragma[noinline]` in every leaf subclass.
// This allows callers to ask for things like _the_ floating-point type of
// size 4 without getting a join that first finds all types of size 4 and
// _then_ restricts them to floating-point types.
int getByteSize() { none() }
/**
@@ -104,8 +109,6 @@ private class IRSizedType extends IRType {
this = TIRFunctionAddressType(byteSize) or
this = TIROpaqueType(_, byteSize)
}
final override int getByteSize() { result = byteSize }
}
/**
@@ -117,6 +120,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalBooleanType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -141,6 +147,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalSignedIntegerType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -153,6 +162,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalUnsignedIntegerType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -164,6 +176,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalFloatingPointType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -178,6 +193,9 @@ class IRAddressType extends IRSizedType, TIRAddressType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalAddressType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -190,6 +208,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType {
final override Language::LanguageType getCanonicalLanguageType() {
result = Language::getCanonicalFunctionAddressType(byteSize)
}
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
/**
@@ -218,6 +239,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType {
* same size.
*/
final Language::OpaqueTypeTag getTag() { result = tag }
pragma[noinline]
final override int getByteSize() { result = byteSize }
}
module IRTypeSanity {

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