Compare commits

..

195 Commits

Author SHA1 Message Date
Max Schaefer
eb3d0f5b0e Add merlyn.md which explains the changes on this branch. 2021-04-19 15:04:21 +01:00
Max Schaefer
09cf8e8b01 Remove RequestHeaderAccess. 2021-04-19 15:04:21 +01:00
Max Schaefer
bd8212c090 Remove RequestInputAccess. 2021-04-19 15:04:21 +01:00
Max Schaefer
f106d186e4 Remove MultipartyRemoteFlow. 2021-04-19 15:04:21 +01:00
Max Schaefer
e2c84407b4 Revert changes to Express::RequestInputAccess in c45d84f8f3 and 9cacfab7c6. 2021-04-19 15:04:21 +01:00
Max Schaefer
67b15125c7 Revert changes to Express::RequestInputAccess in d84f1b47c2. 2021-04-19 15:04:21 +01:00
Max Schaefer
caf763a969 Revert changes to Express::RequestInputAccess in ed48efe5b4. 2021-04-19 15:04:21 +01:00
Max Schaefer
4f8f5048f3 Revert changes to Express::RequestInputAccess in 83f0514475. 2021-04-19 15:04:21 +01:00
Max Schaefer
2366679d9b Revert changes to Express::RequestInputAccess in e2fbf8a68c. 2021-04-19 15:04:21 +01:00
Max Schaefer
66399c055e Remove MicroBodyParserCall. 2021-04-19 15:04:21 +01:00
Max Schaefer
85c02a430e Remove ServerRequestDataEvent. 2021-04-19 15:04:20 +01:00
Max Schaefer
29945b8ed0 Remove VueRouterFlowSource. 2021-04-19 15:04:20 +01:00
Max Schaefer
a8ef1bc32a Remove ServerlessHandlerEventAsRemoteFlow. 2021-04-19 15:04:20 +01:00
Max Schaefer
0781a138af Remove ReceivedItemAsRemoteFlow. 2021-04-19 15:04:20 +01:00
Max Schaefer
6fd67c4d8e Remove ReactRouterSource. 2021-04-19 15:04:19 +01:00
Max Schaefer
89747ecf83 Revert changes to `PostMessageEventHandler in cb7de27. 2021-04-19 15:03:51 +01:00
Max Schaefer
c013e3f9c3 Remove NodeJSNetServerItemAsRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
3b14b27635 Remove NextParams. 2021-04-19 15:03:51 +01:00
Max Schaefer
2ae32be934 Revert changes to ClientRequestData from 0b55aed626. 2021-04-19 15:03:51 +01:00
Max Schaefer
6647f6b9c4 Remove FormidableRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
41ceb291de Remove BusBoyRemoteFlow. 2021-04-19 15:03:51 +01:00
Max Schaefer
615418d2e3 Remove AngularSource. 2021-04-19 15:03:49 +01:00
Max Schaefer
0ba76f7d0e Revert "JS: Move $() sink into separate dataflow config"
This reverts commit 50a015c73e.
2021-04-19 15:03:11 +01:00
Max Schaefer
d97a10ef8a Revert "JS: Address review comments"
This reverts commit c91cdb5194.
2021-04-19 14:57:18 +01:00
Shati Patel
2d618d6b92 Merge pull request #5625 from shati-patel/docs/cli-manual
Docs: Link to CodeQL CLI manual from the sidebar
2021-04-09 15:30:24 +01:00
Jonas Jensen
e1d0bbb021 Merge pull request #5607 from MathiasVP/smart-pointer-ast-read-store-steps
C++: read and store steps for smart pointers in AST dataflow
2021-04-09 16:11:48 +02:00
CodeQL CI
6fd4a8afff Merge pull request #5567 from asgerf/js/sql-models
Approved by esbena
2021-04-09 07:11:10 -07:00
CodeQL CI
be2fe6e171 Merge pull request #5630 from erik-krogh/urlStep
Approved by esbena
2021-04-09 07:05:43 -07:00
CodeQL CI
8d2768b2ce Merge pull request #5634 from erik-krogh/fileSource
Approved by asgerf
2021-04-09 07:04:42 -07:00
Anders Schack-Mulligen
701e815368 Merge pull request #5628 from hvitved/java/remove-unique
Java: Remove `unique` wrapper from `DataFlow::Node::getEnclosingCallable()`
2021-04-09 15:21:26 +02:00
Mathias Vorreiter Pedersen
cd310eb9d5 C++: Remove unused import. 2021-04-09 15:08:48 +02:00
Tamás Vajk
992a4df12f Merge pull request #5619 from tamasvajk/feature/fix-default-argument-value-extraction
C# Improve default argument value extraction
2021-04-09 14:58:35 +02:00
Mathias Vorreiter Pedersen
996cda9b97 C++: Fix incorrect test annotation. 2021-04-09 14:46:46 +02:00
Mathias Vorreiter Pedersen
80d5b17900 C++: Remove the dataflow rule for smart_ptr -> *smart_ptr. 2021-04-09 14:20:51 +02:00
Mathias Vorreiter Pedersen
cae0060a89 C++: Replace the new rules in DataFlowUtil with a dataflow model for pointer wrapper classes. 2021-04-09 14:06:58 +02:00
Tamas Vajk
46197e6e69 Address review comments 2021-04-09 13:39:37 +02:00
Erik Krogh Kristensen
595bdedb22 rename predicate to getStem, and update regexp 2021-04-09 13:07:54 +02:00
CodeQL CI
652e8b4872 Merge pull request #5586 from asgerf/js/tsconfig-file-inclusion-handling
Approved by esbena
2021-04-09 02:50:51 -07:00
Tom Hvitved
c9c4c067b6 Merge pull request #5633 from hvitved/csharp/get-a-source-type-perf
C#: Improve performance of `Dispatch::SimpleTypeDataFlow::getASourceType()`
2021-04-09 11:42:34 +02:00
Tamás Vajk
a335bb0115 Merge pull request #5609 from tamasvajk/feature/dapper
C#: Dapper support
2021-04-09 10:52:17 +02:00
CodeQL CI
ad267404c9 Merge pull request #5137 from asgerf/js/redux-less
Approved by erik-krogh
2021-04-09 01:24:19 -07:00
Tamas Vajk
d7f0b9a7fa Add change note 2021-04-09 09:58:37 +02:00
Tamas Vajk
749db379ca Address code review findings 2021-04-09 09:55:37 +02:00
Tamas Vajk
dbb3d3dc17 Add change note 2021-04-09 09:50:55 +02:00
Tamás Vajk
8adaee05b6 Merge pull request #5453 from tamasvajk/feature/use_codeql_stubs
C#: Adjust make_stubs.py to use codeql instead of odasa
2021-04-08 16:16:05 +02:00
Anders Schack-Mulligen
6109ef5e88 Merge pull request #5475 from Marcono1234/marcono1234/minus-literal
Java: Improve documentation regarding minus in front of numeric literals
2021-04-08 16:11:14 +02:00
Asger Feldthaus
7d300b53d7 JS: Autoformat 2021-04-08 15:06:48 +01:00
Anders Schack-Mulligen
d42a01cb3a qldoc fixup 2021-04-08 15:45:21 +02:00
Tamas Vajk
e5160929eb Remove ODASA reference from make_stubs.py 2021-04-08 15:04:02 +02:00
Erik Krogh Kristensen
30ba69d991 treat "files" in a package.json as main modules, if "main" is not present 2021-04-08 14:42:12 +02:00
Tom Hvitved
036e181bc1 C#: Improve performance of Dispatch::SimpleTypeDataFlow::getASourceType() 2021-04-08 14:27:28 +02:00
Tom Hvitved
716568ebd1 Merge pull request #5623 from hvitved/csharp/enclosing
C#: Compute enclosing callable as a transitive closure
2021-04-08 14:20:09 +02:00
Tom Hvitved
9820116734 Merge pull request #5603 from hvitved/csharp/dataflow/no-unique
C#: Remove `unique` wrappers from `DataFlow::Node::get(EnclosingCallable|ControlFlowNode)`
2021-04-08 14:19:34 +02:00
Asger Feldthaus
52a2260dc7 JS: Rename change note file 2021-04-08 12:52:23 +01:00
Rasmus Wriedt Larsen
c738f387b1 Merge pull request #5624 from tausbn/python-make-callcfgnode-a-localsourcenode
Python: Improve `CallCfgNode` interface
2021-04-08 13:38:24 +02:00
Taus
cf5f760ecd Merge pull request #5582 from RasmusWL/all-tuple
Python: Add support for `__all__` assigned to tuple
2021-04-08 13:03:27 +02:00
Tamas Vajk
a790eb8110 Fix for unconstrained generic types 2021-04-08 12:20:01 +02:00
Tamas Vajk
a8cbdc92b9 Add more test cases 2021-04-08 12:17:19 +02:00
Tamas Vajk
551a7ce9e5 Fix expression value of struct default argument values 2021-04-08 12:14:53 +02:00
Tamas Vajk
c069c3384e Fix tests 2021-04-08 12:07:36 +02:00
Tamas Vajk
cb9a9db356 C# Improve default argument value extraction 2021-04-08 12:07:22 +02:00
Tamas Vajk
2ac1e60406 C#: Add parameter default value tests 2021-04-08 12:04:18 +02:00
Jonas Jensen
51bab81f56 Merge pull request #5622 from MathiasVP/inline-is-before
C++: Inline Location::isBefore
2021-04-08 11:24:33 +02:00
Erik Krogh Kristensen
99dd5330c2 add taint-step for URL construction in js/request-forgery 2021-04-08 11:10:33 +02:00
CodeQL CI
a9527fd913 Merge pull request #5621 from erik-krogh/shellSink
Approved by esbena
2021-04-08 09:47:45 +01:00
Tom Hvitved
2faf52b6bd Java: Remove unique wrapper from DataFlow::Node::getEnclosingCallable()` 2021-04-08 10:07:19 +02:00
Shati Patel
4cf0b8e725 Merge pull request #5626 from shati-patel/docs/broken-links
Docs: Fix broken link to cached "RemoteFlowSource"
2021-04-07 19:01:33 +01:00
Shati Patel
f372274857 Docs: Fix broken links 2021-04-07 18:02:29 +01:00
Shati Patel
2373bf2dfb Docs: Link to CodeQL CLI manual from the sidebar 2021-04-07 17:55:05 +01:00
Tom Hvitved
1cf30d2a9e C#: Compute enclosing callable as a transitive closure 2021-04-07 17:44:41 +02:00
Jonas Jensen
ab58cb3d44 Merge pull request #5604 from MathiasVP/fix-false-positive-in-assign-where-compare-meant
C++: Fix FP in cpp/assign-where-compare-meant
2021-04-07 16:54:45 +02:00
CodeQL CI
f0491af64c Merge pull request #5529 from erik-krogh/socketInput
Approved by esbena
2021-04-07 15:03:13 +01:00
Asger F
0c724a8427 Merge pull request #5304 from asgerf/js/non-alert-data
JS: Implement new metric queries for line counting
2021-04-07 14:52:51 +01:00
Mathias Vorreiter Pedersen
03b12dbc6d C++: Inline Location::isBefore. 2021-04-07 15:45:08 +02:00
Erik Krogh Kristensen
365b4d722d backtrack string-concatenations from shell-execution sinks 2021-04-07 15:34:54 +02:00
Taus
903f364dab Python: Improve CallCfgNode interface
Call nodes are always local sources (specifically sources of the return
value of the call), and so inheriting from `LocalSourceNode` will have
no effect on results, but _should_ make it a bit more smooth to use the
API.
2021-04-07 13:31:12 +00:00
CodeQL CI
073a43ce74 Merge pull request #5606 from erik-krogh/shellInput
Approved by esbena
2021-04-07 14:30:31 +01:00
Shati Patel
461d4e45af Merge pull request #5608 from shati-patel/docs/telemetry-settings
Docs: Mention telemetry in "customizing settings"
2021-04-07 13:44:32 +01:00
Erik Krogh Kristensen
c9f54ea1ad update expected output 2021-04-07 12:37:17 +00:00
Asger Feldthaus
ee13ff71d6 JS: Add another change note 2021-04-07 12:29:06 +01:00
Asger Feldthaus
26cddc7d04 JS: Update test output 2021-04-07 12:28:45 +01:00
Asger Feldthaus
69973d0fa2 JS: Autoformat 2021-04-07 11:24:11 +01:00
Erik Krogh Kristensen
a66083d685 change "Uncontrolled path" to "Path concatenation" 2021-04-07 08:23:07 +00:00
CodeQL CI
fd4e8f8282 Merge pull request #5526 from erik-krogh/quotedShell
Approved by esbena
2021-04-07 08:39:01 +01:00
CodeQL CI
61880ba90a Merge pull request #5530 from erik-krogh/moreFS
Approved by esbena
2021-04-07 08:37:23 +01:00
Robert Marsh
e22ec50dee Merge pull request #5613 from github/hmakholm/pr/fix-redos
Fix ReDOS in cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql
2021-04-06 15:54:27 -07:00
Henning Makholm
2d615ef503 Fix ReDOS in cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql
The sub-regex `(\s|.)*` aims to capture arbitrary string content
(in contrast to `.*` which doesn't match newlines), but it is
unsafe, since non-newline whitespace can match both alternatives.

This caused an evaluator crash in the wild.

Replace with `[\s\S]*`, which matches everything in a safe way.
2021-04-06 20:10:57 +02:00
Tamas Vajk
ffcb345916 C#: Add Dapper support to SQL injection queries 2021-04-06 17:06:20 +02:00
Shati Patel
9a41c80626 Merge pull request #5574 from github/smowton/admin/update-supported-go-version
Update supported Go version to 1.16
2021-04-06 14:54:36 +01:00
Shati Patel
695b02a94c Docs: Mention telemetry in "customizing settings" 2021-04-06 14:30:17 +01:00
Erik Krogh Kristensen
2c1cc9ead6 use local variable instead of module.exports in example
Co-authored-by: Esben Sparre Andreasen <esbena@github.com>
2021-04-06 15:17:31 +02:00
Tom Hvitved
f45916efda Merge pull request #5605 from hvitved/csharp/exclude-dependency-queries
C#: Remove mentions of `exclude-dependency-queries.yml`
2021-04-06 14:58:49 +02:00
Mathias Vorreiter Pedersen
8382e85901 C++: Add flow into the source of read step and out of the target of a store step for smart pointers in AST dataflow. 2021-04-06 14:05:55 +02:00
Mathias Vorreiter Pedersen
f07d844362 C++: Add a test containing missing read/store dataflow steps for smart pointers. 2021-04-06 13:59:27 +02:00
Tamas Vajk
98001c494f C#: Add Dapper stub and new SqlInjection test cases 2021-04-06 13:30:31 +02:00
Erik Krogh Kristensen
41b89669a9 add joined paths as a sink to js/shell-command-constructed-from-input 2021-04-06 12:14:00 +02:00
Rasmus Wriedt Larsen
bc49bc7095 Python: Add variable with underscore to __all__ tests 2021-04-06 11:54:25 +02:00
Tom Hvitved
e0e58b24ea C#: Remove mentions of exclude-dependency-queries.yml 2021-04-06 11:50:36 +02:00
Rasmus Wriedt Larsen
224d3790b5 Python: Highlight all_indirect.py is not super important
At least not in my mind
2021-04-06 11:50:04 +02:00
Rasmus Wriedt Larsen
b11703cc74 Python: all_dybamic2 => all_indirect 2021-04-06 11:49:55 +02:00
Mathias Vorreiter Pedersen
5eb1f8abbd C++: Add change-note. 2021-04-06 11:47:57 +02:00
Rasmus Wriedt Larsen
0ebb24ebeb Merge pull request #5398 from yoff/python-api-enhancements
Python: Add small api enhancements determined useful during documentation work
2021-04-06 11:44:51 +02:00
Tom Hvitved
667b26b5d9 Merge pull request #5540 from hvitved/csharp/ssa-impl-tweaks
C#: Performance tweaks in `SsaImplCommon.qll`
2021-04-06 11:43:08 +02:00
Mathias Vorreiter Pedersen
a5f4d43d61 C++: Fix false positive by adding another allow-list pattern in AssignWhereCompareMeant. 2021-04-06 11:01:38 +02:00
Mathias Vorreiter Pedersen
7045597139 C++: Add testcase with false positive from #5318. 2021-04-06 10:58:15 +02:00
Erik Krogh Kristensen
c194598d37 recognize headers/url from the HTTP request to a server WebSocket. 2021-04-06 10:11:27 +02:00
Tom Hvitved
e852540254 C#: Remove unique wrappers from DataFlow::Node::get(EnclosingCallable|ControlFlowNode) 2021-04-06 09:56:09 +02:00
Rasmus Lerchedahl Petersen
c777f1d8d7 Merge branch 'main' of github.com:github/codeql into python-api-enhancements 2021-04-06 09:31:26 +02:00
yoff
a23d8deb10 Merge pull request #5483 from RasmusWL/minor-fixup-django
Python: Better text for getSourceType in Django
2021-04-06 08:30:58 +02:00
Asger Feldthaus
32500c834d JS: Change note 2021-04-01 16:41:03 +01:00
Asger Feldthaus
acc28df785 JS: Bugfix in tsconfig file inclusion handling 2021-04-01 16:33:05 +01:00
Asger Feldthaus
564a6873f8 JS: Add baseUrl test 2021-04-01 16:33:05 +01:00
Asger Feldthaus
c4ab6fb7b4 JS: Add ImportGraph meta query 2021-04-01 16:33:05 +01:00
Asger Feldthaus
f07030ba97 JS: Update AdditionalFlowStep -> SharedFlowStep 2021-04-01 13:16:47 +01:00
Asger Feldthaus
a9566728b5 JS: Update an import of Unit type 2021-04-01 13:16:47 +01:00
Asger Feldthaus
7119eda009 JS: Add redux change note 2021-04-01 13:16:47 +01:00
Asger Feldthaus
86bc0eb853 JS: Autoformat 2021-04-01 13:16:47 +01:00
Asger Feldthaus
b43989e6a1 JS: Use API nodes to track dispatch/dispatched value sources 2021-04-01 13:16:47 +01:00
Asger Feldthaus
2850b8e952 JS: Fix RangeAnalysis after BasicBlock.dominates change 2021-04-01 13:16:47 +01:00
Asger Feldthaus
cbfa5ad303 JS: Change type of a parameter 2021-04-01 13:16:47 +01:00
Asger Feldthaus
cee1a12489 JS: Fix typo in qldoc 2021-04-01 13:16:47 +01:00
Asger Feldthaus
c926a47d50 JS: QLDoc and test for HeuristicConnectEntryPoint 2021-04-01 13:16:47 +01:00
Asger Feldthaus
cca38a64be JS: Add test for flow to a closure body under a type guard 2021-04-01 13:16:46 +01:00
Asger Feldthaus
53def60e4f JS: Add test for if-based type check 2021-04-01 13:16:46 +01:00
Asger Feldthaus
1ce7c3448f JS: Address some review comments 2021-04-01 13:16:46 +01:00
Asger Feldthaus
fd7cbd0c96 JS: Tweak BasicBlock.dominates and friends 2021-04-01 13:16:46 +01:00
Asger Feldthaus
8fa3fb0561 JS: Redux model 2021-04-01 13:16:46 +01:00
Asger Feldthaus
314839fc09 JS: Add @reduxjs/toolkit to composed functions 2021-04-01 13:16:46 +01:00
Asger Feldthaus
c1651ad30c JS: Factor out Unit type 2021-04-01 13:16:46 +01:00
Asger Feldthaus
125d1465c8 JS: Add DataFlow::functionForwardingStep 2021-04-01 13:16:46 +01:00
Asger Feldthaus
a3421e7ab2 JS: Add getALocalUse 2021-04-01 13:16:45 +01:00
CodeQL CI
20416ae034 Merge pull request #5585 from asgerf/js/more-metadata
Approved by esbena
2021-04-01 13:13:01 +01:00
Asger Feldthaus
c96ee8671e JS: Update more query metadata 2021-04-01 12:15:54 +01:00
CodeQL CI
a1fab8ac52 Merge pull request #5581 from asgerf/js/dependency-info
Approved by esbena
2021-04-01 09:07:21 +01:00
Shati Patel
36bdee0e8b Merge pull request #5571 from github/docs/bug-fix
Docs: Typo fix
2021-03-31 21:59:43 +01:00
Rasmus Wriedt Larsen
95ac2c8edd Python: Add another dynamic __all__ test 2021-03-31 17:31:55 +02:00
CodeQL CI
f08a0e5653 Merge pull request #5580 from asgerf/js/more-metadata-fix
Approved by esbena
2021-03-31 16:29:33 +01:00
Rasmus Wriedt Larsen
ab3edf37d7 Python: Handle __all__ assigned to a tuple
Examples where this is used in real code:

- 76c0b32f82/django/core/files/temp.py (L24)
- 76c0b32f82/django/contrib/gis/gdal/__init__.py (L44-L49)
2021-03-31 17:25:19 +02:00
Rasmus Wriedt Larsen
43306f4700 Python: Add tests for Module.declaredInAll 2021-03-31 17:24:17 +02:00
Asger Feldthaus
8c8e4e6a70 JS: Add test 2021-03-31 16:17:54 +01:00
Asger Feldthaus
068a9d88e7 JS: Ensure Dependency.info() exists even if version range could not be parsed 2021-03-31 16:08:08 +01:00
Asger Feldthaus
c541390c1b JS: Remove precision tag from ExternalDependencies.ql 2021-03-31 13:54:15 +01:00
Mathias Vorreiter Pedersen
e9e93c0eea Merge pull request #5558 from geoffw0/replace-tostring
Replace toString use
2021-03-31 13:50:41 +02:00
Geoffrey White
85ecfe2723 Update cpp/ql/src/experimental/Security/CWE/CWE-570/WrongInDetectingAndHandlingMemoryAllocationErrors.ql
Co-authored-by: Mathias Vorreiter Pedersen <mathiasvp@github.com>
2021-03-31 11:34:56 +01:00
Calum Grant
49d1937dc4 Merge pull request #5552 from RasmusWL/revert-import-change
Python: Revert #5506 due to bad performance
2021-03-31 09:51:39 +01:00
Asger F
d4877a9038 Merge pull request #5572 from asgerf/js/remove-flow-summary-kinds
JS: Change kind of summary-extraction queries to table
2021-03-31 09:28:56 +01:00
Asger Feldthaus
57784dc746 JS: Update test output 2021-03-31 09:23:47 +01:00
Chris Smowton
4f9b6d1192 Update supported Go version to 1.16 2021-03-31 08:56:27 +01:00
Asger Feldthaus
bc5b477f79 JS: Change kind of summary-extraction queries to table 2021-03-30 21:26:58 +01:00
Dave Bartolomeo
0cc8eaf3b4 Merge pull request #5543 from MathiasVP/smart-ptr-like-class
C++: Add a class that models wrapped pointer types
2021-03-30 16:00:13 -04:00
Rasmus Wriedt Larsen
51c27de049 Merge branch 'main' into revert-import-change 2021-03-30 21:51:53 +02:00
Shati Patel
b9788eb53c Merge pull request #5568 from shati-patel/docs-binding-sets
Docs: Mention that binding sets are available for classes
2021-03-30 18:08:23 +01:00
Sarita Iyer
649286995a Merge pull request #5562 from saritai/saritai/cli-remove-1.23-references
Remove Enterprise 1.23 special instructions and replace references
2021-03-30 13:07:42 -04:00
Shati Patel
fb004bacc3 Describe predicates first 2021-03-30 17:31:20 +01:00
Shati Patel
67835ee273 Address review comments 2021-03-30 17:29:43 +01:00
Shati Patel
23df459c16 remove accidental punctuation 2021-03-30 17:23:33 +01:00
Mathias Vorreiter Pedersen
fe76b0849b Merge pull request #5569 from geoffw0/memoryfree
C++: Add a test of memory freed queries with strdup.
2021-03-30 17:22:18 +02:00
Mathias Vorreiter Pedersen
92839123ae Merge pull request #5570 from geoffw0/mutextest
C++: Add mutex test cases.
2021-03-30 17:16:19 +02:00
Geoffrey White
a8284d5b97 C++: Add mutex test case. 2021-03-30 15:39:21 +01:00
Geoffrey White
244966e216 C++: Add a test with strdup. 2021-03-30 14:49:05 +01:00
Shati Patel
62de15cd22 Docs: Mention that binding sets are available for classes 2021-03-30 14:46:59 +01:00
Asger Feldthaus
f8bbda0cdc JS: Change note 2021-03-30 13:54:01 +01:00
Asger Feldthaus
9db235ac36 JS: Improve @google-cloud/spanner model 2021-03-30 13:54:00 +01:00
Asger Feldthaus
35f294f096 JS: Improve sequelize model 2021-03-30 13:54:00 +01:00
Asger Feldthaus
93500bd95a JS: Improve mssql model 2021-03-30 11:34:01 +01:00
Asger Feldthaus
95937c9ac7 JS: Improve sqlite3 model 2021-03-30 11:34:01 +01:00
Asger Feldthaus
0b21b273ed JS: Improve pg model 2021-03-30 11:33:59 +01:00
Asger Feldthaus
937a620f4d JS: Improve mysql2 model 2021-03-30 11:33:42 +01:00
Sarita Iyer
3db5dd4661 removed 1.23 instructions and replaced references
Removed special instructions for LGTM 1.23, and replaced leftover references to 1.23 with 1.27.
2021-03-29 13:37:55 -04:00
Rasmus Wriedt Larsen
92e0e195a4 Revert "Merge pull request #5506 from tausbn/python-allow-absolute-imports-from-source-directory"
This reverts commit 8d15680af4, reversing
changes made to 63831cc62b.

This PR caused performance problems, so reverting now to clear up immediate
problems.
2021-03-27 18:08:20 +01:00
Geoffrey White
c6e7b8d4fd C++: Repair test. 2021-03-26 19:12:09 +00:00
Geoffrey White
4100d68a71 C++: Test failures. 2021-03-26 18:21:05 +00:00
Geoffrey White
725122decc C++: Replace toString logic. 2021-03-26 17:29:05 +00:00
Mathias Vorreiter Pedersen
b466f0515d C++: Respond to more review comments. (1) Use getClassAndName to ensure a good join order, and (2) unify the two abstract predicates on PointerWrapper. 2021-03-26 16:16:23 +01:00
Mathias Vorreiter Pedersen
0ce08617ba C++: Respond to review comments. 2021-03-26 13:42:18 +01:00
Tom Hvitved
e345064a53 C#: Performance tweaks in SsaImplCommon.qll 2021-03-26 13:24:34 +01:00
Mathias Vorreiter Pedersen
d20a0c9e82 C++: Add a class that models wrapped pointer types. 2021-03-26 11:50:06 +01:00
Erik Krogh Kristensen
5e59f6d558 Update javascript/ql/src/semmle/javascript/security/dataflow/ShellCommandInjectionFromEnvironmentCustomizations.qll
Co-authored-by: intrigus-lgtm <60750685+intrigus-lgtm@users.noreply.github.com>
2021-03-25 19:03:37 +01:00
Erik Krogh Kristensen
3d49b8cb91 consider quoted string concatenations as sanitizers for js/shell-command-injection-from-environment 2021-03-25 15:17:02 +01:00
Erik Krogh Kristensen
3b82452d76 detect fs modules that pass through a reduce call 2021-03-25 14:47:43 +01:00
Rasmus Lerchedahl Petersen
a9af135d7e Python: Remove getALocalTaintSource
and `taintFlowsTo` for now..
2021-03-24 01:22:21 +01:00
Marcono1234
993999f64f Java: Add test for negative numeric literals 2021-03-22 17:43:34 +01:00
Tamas Vajk
7a0bfd1a69 Skip through any stub preamble 2021-03-22 12:29:13 +01:00
Rasmus Wriedt Larsen
f800bf243f Python: Better text for getSourceType in Django 2021-03-22 01:39:19 +01:00
Marcono1234
1534b387bb Java: Improve documentation regarding minus in front of numeric literals 2021-03-22 00:54:14 +01:00
Asger Feldthaus
405c1f3fc7 JS: Update test suite 2021-03-19 16:45:31 +00:00
Asger Feldthaus
fa2ae1420a JS: Rename Diagnostics folder to Summary 2021-03-19 16:43:23 +00:00
Asger Feldthaus
347cbe422d JS: Remove the other summary queries 2021-03-19 16:42:43 +00:00
Asger Feldthaus
0c0556bb38 JS: Update LinesOfCode.ql to match the style from C++ 2021-03-19 16:42:05 +00:00
Asger Feldthaus
6ca425f033 JS: Implement new metric queries for line counting 2021-03-19 16:34:29 +00:00
Tamas Vajk
79d6731ed8 C#: Adjust make_stubs.py to use codeql instead of odasa 2021-03-19 11:01:28 +01:00
Rasmus Lerchedahl Petersen
b3ff3f7ee7 PythonÆ adjust test expectations
I suspect it has to do with ParameterNode being a LocalSourceNode,
but I really have no idea...
2021-03-17 15:11:17 +01:00
Rasmus Lerchedahl Petersen
8f467003d2 Python: More review suggestions 2021-03-17 15:11:17 +01:00
yoff
63b732ce1f Apply suggestions from code review
Co-authored-by: Taus <tausbn@github.com>
2021-03-17 15:11:17 +01:00
Rasmus Lerchedahl Petersen
4d856d4461 Python: Add small api enhancements
determined useful during documentation work.
2021-03-17 15:11:17 +01:00
231 changed files with 4348 additions and 1099 deletions

View File

@@ -70,4 +70,3 @@
## Changes to libraries
* The predicate `TypeAnnotation.hasQualifiedName` now works in more cases when the imported library was not present during extraction.
* The class `DomBasedXss::Configuration` has been deprecated, as it has been split into `DomBasedXss::HtmlInjectionConfiguration` and `DomBasedXss::JQueryHtmlOrSelectorInjectionConfiguration`. Unless specifically working with jQuery sinks, subclasses should instead be based on `HtmlInjectionConfiguration`. To use both configurations in a query, see [Xss.ql](https://github.com/github/codeql/blob/main/javascript/ql/src/Security/CWE-079/Xss.ql) for an example.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The 'Assignment where comparison was intended' (cpp/assign-where-compare-meant) query has been improved to flag fewer benign assignments in conditionals.

View File

@@ -54,7 +54,7 @@ class BooleanControllingAssignmentInExpr extends BooleanControllingAssignment {
override predicate isWhitelisted() {
this.getConversion().(ParenthesisExpr).isParenthesised()
or
// whitelist this assignment if all comparison operations in the expression that this
// Allow this assignment if all comparison operations in the expression that this
// assignment is part of, are not parenthesized. In that case it seems like programmer
// is fine with unparenthesized comparison operands to binary logical operators, and
// the parenthesis around this assignment was used to call it out as an assignment.
@@ -62,6 +62,21 @@ class BooleanControllingAssignmentInExpr extends BooleanControllingAssignment {
forex(ComparisonOperation op | op = getComparisonOperand*(this.getParent+()) |
not op.isParenthesised()
)
or
// Match a pattern like:
// ```
// if((a = b) && use_value(a)) { ... }
// ```
// where the assignment is meant to update the value of `a` before it's used in some other boolean
// subexpression that is guarenteed to be evaluate _after_ the assignment.
this.isParenthesised() and
exists(LogicalAndExpr parent, Variable var, VariableAccess access |
var = this.getLValue().(VariableAccess).getTarget() and
access = var.getAnAccess() and
not access.isUsedAsLValue() and
parent.getRightOperand() = access.getParent*() and
parent.getLeftOperand() = this.getParent*()
)
}
}

View File

@@ -93,7 +93,7 @@ class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Confi
bindingset[s]
predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) {
s.regexpMatch("\"([^\"])*\"(\\s|.)*") // The first element (path) is quoted
s.regexpMatch("\"([^\"])*\"[\\s\\S]*") // The first element (path) is quoted
or
s.regexpMatch("[^\\s]+") // There are no spaces in the string
}

View File

@@ -72,9 +72,9 @@ class WrongCheckErrorOperatorNew extends FunctionCall {
}
/**
* Holds if `(std::nothrow)` exists in call `operator new`.
* Holds if `(std::nothrow)` or `(std::noexcept)` exists in call `operator new`.
*/
predicate isExistsNothrow() { this.getAChild().toString() = "nothrow" }
predicate isExistsNothrow() { getTarget().isNoExcept() or getTarget().isNoThrow() }
}
from WrongCheckErrorOperatorNew op

View File

@@ -72,6 +72,7 @@ class Location extends @location {
}
/** Holds if `this` comes on a line strictly before `l`. */
pragma[inline]
predicate isBefore(Location l) {
this.getFile() = l.getFile() and this.getEndLine() < l.getStartLine()
}

View File

@@ -300,6 +300,14 @@ class FunctionCall extends Call, @funbindexpr {
}
}
/** A _user-defined_ unary `operator*` function. */
class OverloadedPointerDereferenceFunction extends Function {
OverloadedPointerDereferenceFunction() {
this.hasName("operator*") and
this.getEffectiveNumberOfParameters() = 1
}
}
/**
* An instance of a _user-defined_ unary `operator*` applied to its argument.
* ```
@@ -309,8 +317,7 @@ class FunctionCall extends Call, @funbindexpr {
*/
class OverloadedPointerDereferenceExpr extends FunctionCall {
OverloadedPointerDereferenceExpr() {
getTarget().hasName("operator*") and
getTarget().getEffectiveNumberOfParameters() = 1
this.getTarget() instanceof OverloadedPointerDereferenceFunction
}
override string getAPrimaryQlClass() { result = "OverloadedPointerDereferenceExpr" }

View File

@@ -1,10 +1,35 @@
import semmle.code.cpp.models.interfaces.Taint
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.PointerWrapper
/**
* The `std::shared_ptr` and `std::unique_ptr` template classes.
*/
private class UniqueOrSharedPtr extends Class {
private class UniqueOrSharedPtr extends Class, PointerWrapper {
UniqueOrSharedPtr() { this.hasQualifiedName(["std", "bsl"], ["shared_ptr", "unique_ptr"]) }
override MemberFunction getAnUnwrapperFunction() {
result.(OverloadedPointerDereferenceFunction).getDeclaringType() = this
or
result.getClassAndName(["operator->", "get"]) = this
}
}
/** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */
private class PointerWrapperDataFlow extends DataFlowFunction {
PointerWrapperDataFlow() {
this = any(PointerWrapper wrapper).getAnUnwrapperFunction() and
not this.getUnspecifiedType() instanceof ReferenceType
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
input.isQualifierAddress() and output.isReturnValue()
or
input.isQualifierObject() and output.isReturnValueDeref()
or
input.isReturnValueDeref() and
output.isQualifierObject()
}
}
/**

View File

@@ -0,0 +1,14 @@
/** Provides classes for modeling pointer wrapper types and expressions. */
private import cpp
/** A class that wraps a pointer type. For example, `std::unique_ptr` and `std::shared_ptr`. */
abstract class PointerWrapper extends Class {
/**
* Gets a member function of this class that returns the wrapped pointer, if any.
*
* This includes both functions that return the wrapped pointer by value, and functions
* that return a reference to the pointed-to object.
*/
abstract MemberFunction getAnUnwrapperFunction();
}

View File

@@ -14,8 +14,8 @@ using namespace std;
void* operator new(std::size_t _Size);
void* operator new[](std::size_t _Size);
void* operator new( std::size_t count, const std::nothrow_t& tag );
void* operator new[]( std::size_t count, const std::nothrow_t& tag );
void* operator new( std::size_t count, const std::nothrow_t& tag ) noexcept;
void* operator new[]( std::size_t count, const std::nothrow_t& tag ) noexcept;
void badNew_0_0()
{

View File

@@ -3260,15 +3260,59 @@
| smart_pointer.cpp:47:11:47:11 | p | smart_pointer.cpp:47:10:47:10 | call to operator* | TAINT |
| smart_pointer.cpp:51:30:51:50 | call to make_shared | smart_pointer.cpp:52:10:52:10 | p | |
| smart_pointer.cpp:51:52:51:57 | call to source | smart_pointer.cpp:51:30:51:50 | call to make_shared | TAINT |
| smart_pointer.cpp:52:10:52:10 | p | smart_pointer.cpp:52:12:52:14 | call to get | TAINT |
| smart_pointer.cpp:52:10:52:10 | p | smart_pointer.cpp:52:12:52:14 | call to get | |
| smart_pointer.cpp:52:12:52:14 | ref arg call to get | smart_pointer.cpp:52:10:52:10 | ref arg p | |
| smart_pointer.cpp:56:30:56:50 | call to make_unique | smart_pointer.cpp:57:10:57:10 | p | |
| smart_pointer.cpp:56:52:56:57 | call to source | smart_pointer.cpp:56:30:56:50 | call to make_unique | TAINT |
| smart_pointer.cpp:57:10:57:10 | p | smart_pointer.cpp:57:12:57:14 | call to get | TAINT |
| smart_pointer.cpp:57:10:57:10 | p | smart_pointer.cpp:57:12:57:14 | call to get | |
| smart_pointer.cpp:57:12:57:14 | ref arg call to get | smart_pointer.cpp:57:10:57:10 | ref arg p | |
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:66:10:66:10 | p | |
| smart_pointer.cpp:65:28:65:46 | call to make_unique | smart_pointer.cpp:67:10:67:10 | p | |
| smart_pointer.cpp:65:48:65:53 | call to source | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
| smart_pointer.cpp:65:58:65:58 | 0 | smart_pointer.cpp:65:28:65:46 | call to make_unique | TAINT |
| smart_pointer.cpp:66:10:66:10 | p | smart_pointer.cpp:66:11:66:11 | call to operator-> | |
| smart_pointer.cpp:66:10:66:10 | ref arg p | smart_pointer.cpp:67:10:67:10 | p | |
| smart_pointer.cpp:67:10:67:10 | p | smart_pointer.cpp:67:11:67:11 | call to operator-> | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:77:3:77:3 | p | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:78:8:78:8 | p | |
| smart_pointer.cpp:76:45:76:45 | p | smart_pointer.cpp:79:8:79:8 | p | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:81:3:81:3 | q | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:82:8:82:8 | q | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:83:8:83:8 | q | |
| smart_pointer.cpp:76:67:76:67 | q | smart_pointer.cpp:84:8:84:8 | q | |
| smart_pointer.cpp:77:3:77:3 | p | smart_pointer.cpp:77:4:77:4 | call to operator-> | |
| smart_pointer.cpp:77:3:77:3 | ref arg p | smart_pointer.cpp:78:8:78:8 | p | |
| smart_pointer.cpp:77:3:77:3 | ref arg p | smart_pointer.cpp:79:8:79:8 | p | |
| smart_pointer.cpp:77:3:77:17 | ... = ... | smart_pointer.cpp:77:6:77:6 | x [post update] | |
| smart_pointer.cpp:77:3:77:17 | ... = ... | smart_pointer.cpp:78:11:78:11 | x | |
| smart_pointer.cpp:77:4:77:4 | call to operator-> [post update] | smart_pointer.cpp:77:3:77:3 | ref arg p | |
| smart_pointer.cpp:77:10:77:15 | call to source | smart_pointer.cpp:77:3:77:17 | ... = ... | |
| smart_pointer.cpp:78:8:78:8 | p | smart_pointer.cpp:78:9:78:9 | call to operator-> | |
| smart_pointer.cpp:78:8:78:8 | ref arg p | smart_pointer.cpp:79:8:79:8 | p | |
| smart_pointer.cpp:79:8:79:8 | p | smart_pointer.cpp:79:9:79:9 | call to operator-> | |
| smart_pointer.cpp:81:3:81:3 | q | smart_pointer.cpp:81:4:81:4 | call to operator-> | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:82:8:82:8 | q | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:83:8:83:8 | q | |
| smart_pointer.cpp:81:3:81:3 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | |
| smart_pointer.cpp:81:3:81:20 | ... = ... | smart_pointer.cpp:81:9:81:9 | x [post update] | |
| smart_pointer.cpp:81:3:81:20 | ... = ... | smart_pointer.cpp:82:14:82:14 | x | |
| smart_pointer.cpp:81:4:81:4 | call to operator-> [post update] | smart_pointer.cpp:81:3:81:3 | ref arg q | |
| smart_pointer.cpp:81:13:81:18 | call to source | smart_pointer.cpp:81:3:81:20 | ... = ... | |
| smart_pointer.cpp:82:8:82:8 | q | smart_pointer.cpp:82:9:82:9 | call to operator-> | |
| smart_pointer.cpp:82:8:82:8 | ref arg q | smart_pointer.cpp:83:8:83:8 | q | |
| smart_pointer.cpp:82:8:82:8 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | |
| smart_pointer.cpp:83:8:83:8 | q | smart_pointer.cpp:83:9:83:9 | call to operator-> | |
| smart_pointer.cpp:83:8:83:8 | ref arg q | smart_pointer.cpp:84:8:84:8 | q | |
| smart_pointer.cpp:84:8:84:8 | q | smart_pointer.cpp:84:9:84:9 | call to operator-> | |
| smart_pointer.cpp:87:17:87:18 | pa | smart_pointer.cpp:88:5:88:6 | pa | |
| smart_pointer.cpp:88:5:88:20 | ... = ... | smart_pointer.cpp:88:9:88:9 | x [post update] | |
| smart_pointer.cpp:88:13:88:18 | call to source | smart_pointer.cpp:88:5:88:20 | ... = ... | |
| smart_pointer.cpp:92:25:92:50 | call to unique_ptr | smart_pointer.cpp:93:11:93:11 | p | |
| smart_pointer.cpp:92:25:92:50 | call to unique_ptr | smart_pointer.cpp:94:8:94:8 | p | |
| smart_pointer.cpp:93:11:93:11 | p | smart_pointer.cpp:93:13:93:15 | call to get | |
| smart_pointer.cpp:93:11:93:11 | ref arg p | smart_pointer.cpp:94:8:94:8 | p | |
| smart_pointer.cpp:93:13:93:15 | ref arg call to get | smart_pointer.cpp:93:11:93:11 | ref arg p | |
| smart_pointer.cpp:94:8:94:8 | p | smart_pointer.cpp:94:9:94:9 | call to operator-> | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:39:45:39:51 | source1 | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:40:11:40:17 | source1 | |
| standalone_iterators.cpp:39:45:39:51 | source1 | standalone_iterators.cpp:41:12:41:18 | source1 | |
@@ -5213,6 +5257,7 @@
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:17:14:17 | t | |
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:17:14:17 | t | |
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:56:14:56 | t | |
| swap1.cpp:14:17:14:17 | t | swap1.cpp:14:56:14:56 | t | |
| swap1.cpp:24:9:24:13 | this | swap1.cpp:24:31:24:34 | this | |
| swap1.cpp:24:23:24:26 | that | swap1.cpp:24:23:24:26 | that | |
| swap1.cpp:24:23:24:26 | that | swap1.cpp:24:36:24:39 | that | |
@@ -5378,6 +5423,7 @@
| swap2.cpp:14:17:14:17 | t | swap2.cpp:14:17:14:17 | t | |
| swap2.cpp:14:17:14:17 | t | swap2.cpp:14:17:14:17 | t | |
| swap2.cpp:14:17:14:17 | t | swap2.cpp:14:56:14:56 | t | |
| swap2.cpp:14:17:14:17 | t | swap2.cpp:14:56:14:56 | t | |
| swap2.cpp:24:9:24:13 | this | swap2.cpp:24:31:24:34 | this | |
| swap2.cpp:24:23:24:26 | that | swap2.cpp:24:23:24:26 | that | |
| swap2.cpp:24:23:24:26 | that | swap2.cpp:24:36:24:39 | that | |

View File

@@ -65,4 +65,31 @@ void test_shared_field_member() {
std::unique_ptr<A> p = std::make_unique<A>(source(), 0);
sink(p->x); // $ MISSING: ast,ir
sink(p->y); // not tainted
}
struct B {
A a1;
A a2;
int z;
};
void test_operator_arrow(std::unique_ptr<A> p, std::unique_ptr<B> q) {
p->x = source();
sink(p->x); // $ ast MISSING: ir
sink(p->y);
q->a1.x = source();
sink(q->a1.x); // $ ast MISSING: ir
sink(q->a1.y);
sink(q->a2.x);
}
void taint_x(A* pa) {
pa->x = source();
}
void reverse_taint_smart_pointer() {
std::unique_ptr<A> p = std::unique_ptr<A>(new A);
taint_x(p.get());
sink(p->x); // $ ast MISSING: ir
}

View File

@@ -10,3 +10,4 @@
| test.cpp:89:18:89:23 | call to malloc | This memory is never freed |
| test.cpp:156:3:156:26 | new | This memory is never freed |
| test.cpp:157:3:157:26 | new[] | This memory is never freed |
| test.cpp:167:14:167:19 | call to strdup | This memory is never freed |

View File

@@ -156,3 +156,15 @@ int overloadedNew() {
new(std::nothrow) int(3); // BAD
new(std::nothrow) int[2]; // BAD
}
// --- strdup ---
char *strdup(const char *s1);
void output_msg(const char *msg);
void test_strdup() {
char msg[] = "OctoCat";
char *cpy = strdup(msg); // BAD
output_msg(cpy);
}

View File

@@ -19,3 +19,7 @@
| test.cpp:144:32:144:36 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:150:32:150:36 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:153:46:153:50 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:166:22:166:27 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:168:24:168:29 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:169:23:169:28 | ... = ... | Use of '=' where '==' may have been intended. |
| test.cpp:171:7:171:12 | ... = ... | Use of '=' where '==' may have been intended. |

View File

@@ -153,3 +153,21 @@ void f3(int x, int y) {
if((x == 10) || ((z == z) && (x == 1)) && (y = 2)) { // BAD
}
}
bool use(int);
void f4(int x, bool b) {
if((x = 10) && use(x)) {} // GOOD: This is likely just a short-hand way of writing an assignment
// followed by a boolean check.
if((x = 10) && b && use(x)) {} // GOOD: Same reason as above
if((x = 10) && use(x) && b) {} // GOOD: Same reason as above
if((x = 10) && (use(x) && b)) {} // GOOD: Same reason as above
if(use(x) && b && (x = 10)) {} // BAD: The assignment is the last thing that happens in the comparison.
// This doesn't match the usual pattern.
if((use(x) && b) && (x = 10)) {} // BAD: Same reason as above
if(use(x) && (b && (x = 10))) {} // BAD: Same reason as above
if((x = 10) || use(x)) {} // BAD: This doesn't follow the usual style of writing an assignment in
// a boolean check.
}

View File

@@ -7,3 +7,4 @@
| test.cpp:303:11:303:18 | call to try_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
| test.cpp:313:11:313:18 | call to try_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
| test.cpp:442:8:442:17 | call to mutex_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |
| test.cpp:482:2:482:19 | call to pthread_mutex_lock | This lock might not be unlocked or might be locked more times than it is unlocked. |

View File

@@ -445,3 +445,46 @@ bool test_mutex(data_t *data)
return true;
}
// ---
struct pthread_mutex
{
// ...
};
void pthread_mutex_lock(pthread_mutex *m);
void pthread_mutex_unlock(pthread_mutex *m);
class MyClass
{
public:
pthread_mutex lock;
};
bool maybe();
int test_MyClass_good(MyClass *obj)
{
pthread_mutex_lock(&obj->lock);
if (maybe()) {
pthread_mutex_unlock(&obj->lock);
return -1; // GOOD
}
pthread_mutex_unlock(&obj->lock); // GOOD
return 0;
}
int test_MyClass_bad(MyClass *obj)
{
pthread_mutex_lock(&obj->lock);
if (maybe()) {
return -1; // BAD
}
pthread_mutex_unlock(&obj->lock); // GOOD
return 0;
}

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* Support for the Dapper ORM library has been added to the SQL injection checks.

View File

@@ -0,0 +1,2 @@
lgtm,codescanning
* The extractor has been improved to store default argument values for parameters that are extracted from referenced assemblies.

View File

@@ -164,6 +164,39 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
/// <summary>
/// Creates a generated expression for a default argument value.
/// </summary>
public static Expression? CreateGenerated(Context cx, IParameterSymbol parameter, IExpressionParentEntity parent,
int childIndex, Extraction.Entities.Location location)
{
if (!parameter.HasExplicitDefaultValue)
{
return null;
}
var defaultValue = parameter.ExplicitDefaultValue;
if (parameter.Type is INamedTypeSymbol nt && nt.EnumUnderlyingType is not null)
{
// = (MyEnum)1, = MyEnum.Value1, = default(MyEnum), = new MyEnum()
// we're generating a (MyEnum)value cast expression:
defaultValue ??= 0;
Action<Expression, int> createChild = (parent, index) => Literal.CreateGenerated(cx, parent, index, nt.EnumUnderlyingType, defaultValue, location);
return Cast.CreateGenerated(cx, parent, childIndex, parameter.Type, defaultValue, createChild, location);
}
if (defaultValue is null)
{
// = null, = default, = default(T), = new MyStruct()
// we're generating a default expression:
return Default.CreateGenerated(cx, parent, childIndex, location, parameter.Type.IsReferenceType ? ValueAsString(null) : null);
}
// const literal:
return Literal.CreateGenerated(cx, parent, childIndex, parameter.Type, defaultValue, location);
}
/// <summary>
/// Adapt the operator kind depending on whether it's a dynamic call or a user-operator call.
/// </summary>

View File

@@ -14,5 +14,20 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
{
TypeAccess.Create(Context, Syntax.Type, this, 0);
}
public static Expression CreateGenerated(Context cx, IExpressionParentEntity parent, int childIndex, Extraction.Entities.Location location, string? value)
{
var info = new ExpressionInfo(
cx,
null,
location,
ExprKind.DEFAULT,
parent,
childIndex,
true,
value);
return new Expression(info);
}
}
}

View File

@@ -4,6 +4,7 @@ using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Semmle.Extraction.Entities;
using System.IO;
using System;
namespace Semmle.Extraction.CSharp.Entities
{
@@ -124,6 +125,17 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.param_location(this, Context.CreateLocation());
}
if (Symbol.HasExplicitDefaultValue && Context.Defines(Symbol))
{
var defaultValueSyntax = GetDefaultValueFromSyntax(Symbol);
Action defaultValueExpressionCreation = defaultValueSyntax is not null
? () => Expression.Create(Context, defaultValueSyntax.Value, this, 0)
: () => Expression.CreateGenerated(Context, Symbol, this, 0, Location);
Context.PopulateLater(defaultValueExpressionCreation);
}
if (!IsSourceDeclaration || !Symbol.FromSource())
return;
@@ -139,36 +151,28 @@ namespace Semmle.Extraction.CSharp.Entities
TypeMention.Create(Context, syntax.Type!, this, type);
}
}
}
if (Symbol.HasExplicitDefaultValue && Context.Defines(Symbol))
private static EqualsValueClauseSyntax? GetDefaultValueFromSyntax(IParameterSymbol symbol)
{
// This is a slight bug in the dbscheme
// We should really define param_default(param, string)
// And use parameter child #0 to encode the default expression.
var defaultValue = GetParameterDefaultValue(symbol);
if (defaultValue is null)
{
// This is a slight bug in the dbscheme
// We should really define param_default(param, string)
// And use parameter child #0 to encode the default expression.
var defaultValue = GetParameterDefaultValue(Symbol);
if (defaultValue is null)
// In case this parameter belongs to an accessor of an indexer, we need
// to get the default value from the corresponding parameter belonging
// to the indexer itself
if (symbol.ContainingSymbol is IMethodSymbol method)
{
// In case this parameter belongs to an accessor of an indexer, we need
// to get the default value from the corresponding parameter belonging
// to the indexer itself
var method = (IMethodSymbol)Symbol.ContainingSymbol;
if (method is not null)
{
var i = method.Parameters.IndexOf(Symbol);
var indexer = (IPropertySymbol?)method.AssociatedSymbol;
if (indexer is not null)
defaultValue = GetParameterDefaultValue(indexer.Parameters[i]);
}
}
if (defaultValue is not null)
{
Context.PopulateLater(() =>
{
Expression.Create(Context, defaultValue.Value, this, 0);
});
var i = method.Parameters.IndexOf(symbol);
if (method.AssociatedSymbol is IPropertySymbol indexer)
defaultValue = GetParameterDefaultValue(indexer.Parameters[i]);
}
}
return defaultValue;
}
public override bool IsSourceDeclaration => Symbol.IsSourceDeclaration();

View File

@@ -43,12 +43,6 @@ if not foundCS:
print("Test directory does not contain .cs files. Please specify a working qltest directory.")
exit(1)
cmd = ['odasa', 'selfTest']
print('Running ' + ' '.join(cmd))
if subprocess.check_call(cmd):
print("odasa selfTest failed. Ensure odasa is on your current path.")
exit(1)
csharpQueries = os.path.abspath(os.path.dirname(sys.argv[0]))
outputFile = os.path.join(testDir, 'stubs.cs')
@@ -58,56 +52,75 @@ if os.path.isfile(outputFile):
os.remove(outputFile) # It would interfere with the test.
print("Removed previous", outputFile)
cmd = ['odasa', 'qltest', '--optimize', '--leave-temp-files', testDir]
cmd = ['codeql', 'test', 'run', '--keep-databases', testDir]
print('Running ' + ' '.join(cmd))
if subprocess.check_call(cmd):
print("qltest failed. Please fix up the test before proceeding.")
print("codeql test failed. Please fix up the test before proceeding.")
exit(1)
dbDir = os.path.join(testDir, os.path.basename(testDir) + ".testproj", "db-csharp")
dbDir = os.path.join(testDir, os.path.basename(testDir) + ".testproj")
if not os.path.isdir(dbDir):
print("Expected database directory " + dbDir + " not found. Please contact Semmle.")
print("Expected database directory " + dbDir + " not found.")
exit(1)
cmd = ['odasa', 'runQuery', '--query', os.path.join(csharpQueries, 'MinimalStubsFromSource.ql'), '--db', dbDir, '--output-file', outputFile]
cmd = ['codeql', 'query', 'run', os.path.join(
csharpQueries, 'MinimalStubsFromSource.ql'), '--database', dbDir, '--output', outputFile]
print('Running ' + ' '.join(cmd))
if subprocess.check_call(cmd):
print('Failed to run the query to generate output file. Please contact Semmle.')
print('Failed to run the query to generate output file.')
exit(1)
# Remove the leading " and trailing " bytes from the file
len = os.stat(outputFile).st_size
f = open(outputFile, "rb")
try:
quote = f.read(1)
if quote != b'"':
print("Unexpected character in file. Please contact Semmle.")
contents = f.read(len-3)
quote = f.read(1)
if quote != b'"':
print("Unexpected end character. Please contact Semmle.", quote)
finally:
f.close()
# Remove the leading and trailing bytes from the file
length = os.stat(outputFile).st_size
if length < 20:
contents = b''
else:
f = open(outputFile, "rb")
try:
countTillSlash = 0
foundSlash = False
slash = f.read(1)
while slash != b'':
if slash == b'/':
foundSlash = True
break
countTillSlash += 1
slash = f.read(1)
if not foundSlash:
countTillSlash = 0
f.seek(0)
quote = f.read(countTillSlash)
print("Start characters in file skipped.", quote)
post = b'\x0e\x01\x08#select\x01\x01\x00s\x00'
contents = f.read(length - len(post) - countTillSlash)
quote = f.read(len(post))
if quote != post:
print("Unexpected end character in file.", quote)
finally:
f.close()
f = open(outputFile, "wb")
f.write(contents)
f.close()
cmd = ['odasa', 'qltest', '--optimize', testDir]
cmd = ['codeql', 'test', 'run', testDir]
print('Running ' + ' '.join(cmd))
if subprocess.check_call(cmd):
print('\nTest failed. You may need to fix up', outputFile)
print('It may help to view', outputFile, ' in Visual Studio')
print("Next steps:")
print('1. Look at the compilation errors, and fix up', outputFile, 'so that the test compiles')
print('2. Re-run odasa qltest --optimize "' + testDir + '"')
print('3. git add "' + outputFile + '"')
exit(1)
print('\nTest failed. You may need to fix up', outputFile)
print('It may help to view', outputFile, ' in Visual Studio')
print("Next steps:")
print('1. Look at the compilation errors, and fix up',
outputFile, 'so that the test compiles')
print('2. Re-run codeql test run "' + testDir + '"')
print('3. git add "' + outputFile + '"')
exit(1)
print("\nStub generation successful! Next steps:")
print('1. Edit "semmle-extractor-options" in the .cs files to remove unused references')
print('2. Re-run odasa qltest --optimize "' + testDir + '"')
print('2. Re-run codeql test run "' + testDir + '"')
print('3. git add "' + outputFile + '"')
print('4. Commit your changes.')

View File

@@ -2,5 +2,3 @@
- qlpack: codeql-csharp
- apply: code-scanning-selectors.yml
from: codeql-suite-helpers
- apply: codeql-suites/exclude-dependency-queries.yml
from: codeql-csharp

View File

@@ -2,5 +2,3 @@
- qlpack: codeql-csharp
- apply: security-and-quality-selectors.yml
from: codeql-suite-helpers
- apply: codeql-suites/exclude-dependency-queries.yml
from: codeql-csharp

View File

@@ -2,5 +2,3 @@
- qlpack: codeql-csharp
- apply: security-extended-selectors.yml
from: codeql-suite-helpers
- apply: codeql-suites/exclude-dependency-queries.yml
from: codeql-csharp

View File

@@ -321,10 +321,9 @@ private module SsaDefReaches {
}
pragma[noinline]
private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) {
result = getABasicBlockSuccessor(bb) and
not defOccursInBlock(_, bb, def.getSourceVariable()) and
ssaDefReachesEndOfBlock(bb, def, _)
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable())
}
/**
@@ -337,7 +336,11 @@ private module SsaDefReaches {
defOccursInBlock(def, bb1, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid))
exists(BasicBlock mid |
varBlockReaches(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
/**
@@ -355,17 +358,10 @@ private module SsaDefReaches {
private import SsaDefReaches
pragma[noinline]
private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) {
exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) |
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
idom = getImmediateBasicBlockDominator(bb)
)
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
@@ -382,9 +378,14 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
liveAtExit(bb, v)
)
or
ssaDefReachesEndOfBlockRec(bb, def, v) and
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**

View File

@@ -27,9 +27,6 @@ class Element extends DotNet::Element, @element {
/** Gets a location of this element, including sources and assemblies. */
override Location getALocation() { none() }
/** Holds if this element is from an assembly. */
predicate fromLibrary() { this.getFile().fromLibrary() }
/** Gets the parent of this element, if any. */
Element getParent() { result.getAChild() = this }

View File

@@ -1,83 +0,0 @@
/**
* INTERNAL: Do not use.
*
* Provides efficient cached predicates for finding enclosing statements and callables.
*
* There are a number of difficulties. There can be expressions without
* enclosing statements (for example initialisers for fields and constructors)
* or enclosing callables (even if we consider constructor initialisers
* to be enclosed by constructors, field initialisers don't have callables).
*
* The only cases where a `Stmt` has an `Expr` parent are delegate and lambda
* expressions, which are both callable.
*/
import Stmt
private import semmle.code.csharp.ExprOrStmtParent
/**
* INTERNAL: Do not use.
*/
cached
module Internal {
/**
* INTERNAL: Do not use.
*
* Holds if `c` is the enclosing callable of statement `s`.
*/
cached
predicate enclosingCallable(Stmt s, Callable c) {
// Compute the enclosing callable for a statement. This walks up through
// enclosing statements until it hits a callable. It's unambiguous, since
// if a statement has no parent statement, it's either the method body
// or the body of an anonymous function declaration, in each of which cases the
// non-statement parent is in fact the enclosing callable.
c.getAChildStmt+() = s
}
private Expr getAChildExpr(ExprOrStmtParent p) {
result = p.getAChildExpr() or
result = p.(AssignOperation).getExpandedAssignment()
}
/**
* INTERNAL: Do not use.
*
* Holds if `s` is the enclosing statement of expression `e`.
*/
cached
predicate enclosingStmt(Expr e, Stmt s) {
// Compute the enclosing statement for an expression. Note that this need
// not exist, since expressions can occur in contexts where they have no
// enclosing statement (examples include field initialisers, both inline
// and explicit on constructor definitions, and annotation arguments).
getAChildExpr+(s) = e
}
private predicate childExprOfCallable(Callable parent, Expr child) {
child = getAChildExpr(parent)
or
exists(Expr mid | childExprOfCallable(parent, mid) |
not mid instanceof Callable and
child = getAChildExpr(mid)
)
}
/**
* INTERNAL: Do not use.
*
* Holds if `c` is the enclosing callable of expression `e`.
*/
cached
predicate exprEnclosingCallable(Expr e, Callable c) {
// Compute the enclosing callable of an expression. Note that expressions in
// lambda functions should have the lambdas as enclosing callables, and their
// enclosing statement may be the same as the enclosing statement of the
// lambda; thus, it is *not* safe to go up to the enclosing statement and
// take its own enclosing callable.
childExprOfCallable(c, e)
or
not childExprOfCallable(_, e) and
exists(Stmt s | enclosingStmt(e, s) | enclosingCallable(s, c))
}
}

View File

@@ -138,6 +138,54 @@ private module Cached {
)
else expr_parent(child, i, parent)
}
private Expr getAChildExpr(ExprOrStmtParent parent) {
result = parent.getAChildExpr() or
result = parent.(AssignOperation).getExpandedAssignment()
}
private ControlFlowElement getAChild(ExprOrStmtParent parent) {
result = getAChildExpr(parent)
or
result = parent.getAChildStmt()
}
pragma[inline]
private ControlFlowElement enclosingStart(ControlFlowElement cfe) {
result = cfe
or
getAChild(result).(AnonymousFunctionExpr) = cfe
}
private predicate parent(ControlFlowElement child, ExprOrStmtParent parent) {
child = getAChild(parent) and
not child instanceof Callable
}
/** Holds if the enclosing body of `cfe` is `body`. */
cached
predicate enclosingBody(ControlFlowElement cfe, ControlFlowElement body) {
body = any(Callable c).getBody() and
parent*(enclosingStart(cfe), body)
}
/** Holds if the enclosing callable of `cfe` is `c`. */
cached
predicate enclosingCallable(ControlFlowElement cfe, Callable c) {
enclosingBody(cfe, c.getBody())
or
parent*(enclosingStart(cfe), c.(Constructor).getInitializer())
}
/** Holds if the enclosing statement of expression `e` is `s`. */
cached
predicate enclosingStmt(Expr e, Stmt s) {
// Compute the enclosing statement for an expression. Note that this need
// not exist, since expressions can occur in contexts where they have no
// enclosing statement (examples include field initialisers, both inline
// and explicit on constructor definitions, and annotation arguments).
getAChildExpr+(s) = e
}
}
import Cached

View File

@@ -8,7 +8,7 @@ import Element
import Location
import Member
import exprs.Expr
private import semmle.code.csharp.Enclosing::Internal
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.frameworks.System
private import TypeRef

View File

@@ -321,10 +321,9 @@ private module SsaDefReaches {
}
pragma[noinline]
private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) {
result = getABasicBlockSuccessor(bb) and
not defOccursInBlock(_, bb, def.getSourceVariable()) and
ssaDefReachesEndOfBlock(bb, def, _)
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable())
}
/**
@@ -337,7 +336,11 @@ private module SsaDefReaches {
defOccursInBlock(def, bb1, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid))
exists(BasicBlock mid |
varBlockReaches(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
/**
@@ -355,17 +358,10 @@ private module SsaDefReaches {
private import SsaDefReaches
pragma[noinline]
private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) {
exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) |
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
idom = getImmediateBasicBlockDominator(bb)
)
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
@@ -382,9 +378,14 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
liveAtExit(bb, v)
)
or
ssaDefReachesEndOfBlockRec(bb, def, v) and
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**

View File

@@ -47,14 +47,14 @@ class Node extends TNode {
cached
final DataFlowCallable getEnclosingCallable() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = unique(DataFlowCallable c | c = this.(NodeImpl).getEnclosingCallableImpl() | c)
result = this.(NodeImpl).getEnclosingCallableImpl()
}
/** Gets the control flow node corresponding to this node, if any. */
cached
final ControlFlow::Node getControlFlowNode() {
Stages::DataFlowStage::forceCachingInSameStage() and
result = unique(ControlFlow::Node n | n = this.(NodeImpl).getControlFlowNodeImpl() | n)
result = this.(NodeImpl).getControlFlowNodeImpl()
}
/** Gets a textual representation of this node. */

View File

@@ -321,10 +321,9 @@ private module SsaDefReaches {
}
pragma[noinline]
private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) {
result = getABasicBlockSuccessor(bb) and
not defOccursInBlock(_, bb, def.getSourceVariable()) and
ssaDefReachesEndOfBlock(bb, def, _)
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable())
}
/**
@@ -337,7 +336,11 @@ private module SsaDefReaches {
defOccursInBlock(def, bb1, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid))
exists(BasicBlock mid |
varBlockReaches(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
/**
@@ -355,17 +358,10 @@ private module SsaDefReaches {
private import SsaDefReaches
pragma[noinline]
private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) {
exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) |
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
idom = getImmediateBasicBlockDominator(bb)
)
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
@@ -382,9 +378,14 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
liveAtExit(bb, v)
)
or
ssaDefReachesEndOfBlockRec(bb, def, v) and
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**

View File

@@ -321,10 +321,9 @@ private module SsaDefReaches {
}
pragma[noinline]
private BasicBlock getAMaybeLiveSuccessor(Definition def, BasicBlock bb) {
result = getABasicBlockSuccessor(bb) and
not defOccursInBlock(_, bb, def.getSourceVariable()) and
ssaDefReachesEndOfBlock(bb, def, _)
private predicate ssaDefReachesThroughBlock(Definition def, BasicBlock bb) {
ssaDefReachesEndOfBlock(bb, def, _) and
not defOccursInBlock(_, bb, def.getSourceVariable())
}
/**
@@ -337,7 +336,11 @@ private module SsaDefReaches {
defOccursInBlock(def, bb1, _) and
bb2 = getABasicBlockSuccessor(bb1)
or
exists(BasicBlock mid | varBlockReaches(def, bb1, mid) | bb2 = getAMaybeLiveSuccessor(def, mid))
exists(BasicBlock mid |
varBlockReaches(def, bb1, mid) and
ssaDefReachesThroughBlock(def, mid) and
bb2 = getABasicBlockSuccessor(mid)
)
}
/**
@@ -355,17 +358,10 @@ private module SsaDefReaches {
private import SsaDefReaches
pragma[noinline]
private predicate ssaDefReachesEndOfBlockRec(BasicBlock bb, Definition def, SourceVariable v) {
exists(BasicBlock idom | ssaDefReachesEndOfBlock(idom, def, v) |
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
idom = getImmediateBasicBlockDominator(bb)
)
pragma[nomagic]
predicate liveThrough(BasicBlock bb, SourceVariable v) {
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
}
/**
@@ -382,9 +378,14 @@ predicate ssaDefReachesEndOfBlock(BasicBlock bb, Definition def, SourceVariable
liveAtExit(bb, v)
)
or
ssaDefReachesEndOfBlockRec(bb, def, v) and
liveAtExit(bb, v) and
not ssaRef(bb, _, v, SsaDef())
// The construction of SSA form ensures that each read of a variable is
// dominated by its definition. An SSA definition therefore reaches a
// control flow node if it is the _closest_ SSA definition that dominates
// the node. If two definitions dominate a node then one must dominate the
// other, so therefore the definition of _closest_ is given by the dominator
// tree. Thus, reaching definitions can be calculated in terms of dominance.
ssaDefReachesEndOfBlock(getImmediateBasicBlockDominator(bb), def, pragma[only_bind_into](v)) and
liveThrough(bb, pragma[only_bind_into](v))
}
/**

View File

@@ -636,31 +636,41 @@ private module Internal {
)
}
private predicate stepExpr0(Expr succ, Expr pred) {
Steps::stepOpen(pred, succ)
or
exists(Assignable a |
a instanceof Field or
a instanceof Property
|
succ.(AssignableRead) = a.getAnAccess() and
pred = a.getAnAssignedValue() and
a = any(Modifiable m | not m.isEffectivelyPublic())
)
}
private predicate stepExpr(Expr succ, Expr pred) {
stepExpr0(succ, pred) and
private predicate stepExpr(Expr pred, Expr succ) {
Steps::stepOpen(pred, succ) and
// Do not step through down casts
not downCast(succ) and
// Only step when we may learn more about the actual type
typeMayBeImprecise(succ.getType())
}
private predicate stepTC(Expr succ, Expr pred) = fastTC(stepExpr/2)(succ, pred)
private class AnalyzableFieldOrProperty extends Assignable, Modifiable {
AnalyzableFieldOrProperty() {
(
this instanceof Field or
this instanceof Property
) and
not this.isEffectivelyPublic() and
exists(this.getAnAssignedValue())
}
AssignableRead getARead() { result = this.getAnAccess() }
}
private class Source extends Expr {
Source() { not stepExpr(this, _) }
Source() {
not stepExpr(_, this) and
not this = any(AnalyzableFieldOrProperty a).getARead()
}
Type getType(boolean isExact) {
result = this.getType() and
if
this instanceof ObjectCreation or
this instanceof BaseAccess
then isExact = true
else isExact = false
}
}
private class Sink extends Expr {
@@ -680,24 +690,38 @@ private module Internal {
this = any(DispatchCallImpl c).getArgument(_)
}
Source getASource() { stepTC(this, result) }
pragma[nomagic]
Expr getAPred() { stepExpr*(result, this) }
pragma[nomagic]
AnalyzableFieldOrProperty getAPredRead() { this.getAPred() = result.getARead() }
}
/** Holds if the expression `e` has an exact type. */
private predicate hasExactType(Expr e) {
e instanceof ObjectCreation or
e instanceof BaseAccess
/** Gets a source type for sink expression `e`, using simple data flow. */
Type getASourceType(Sink sink, boolean isExact) {
result = sink.getAPred().(Source).getType(isExact)
or
result = sink.getAPredRead().(RelevantFieldOrProperty).getASourceType(isExact)
}
/** Gets a source type for expression `e`, using simple data flow. */
Type getASourceType(Sink e, boolean isExact) {
exists(Source s |
s = e.getASource() or
s = e
|
result = s.getType() and
if hasExactType(s) then isExact = true else isExact = false
)
private class RelevantFieldOrProperty extends AnalyzableFieldOrProperty {
RelevantFieldOrProperty() {
this = any(Sink s).getAPredRead()
or
this = any(RelevantFieldOrProperty a).getAPredRead()
}
pragma[nomagic]
Expr getAPred() { stepExpr*(result, this.getAnAssignedValue()) }
pragma[nomagic]
AnalyzableFieldOrProperty getAPredRead() { this.getAPred() = result.getARead() }
Type getASourceType(boolean isExact) {
result = this.getAPred().(Source).getType(isExact)
or
result = this.getAPredRead().(RelevantFieldOrProperty).getASourceType(isExact)
}
}
}

View File

@@ -20,7 +20,7 @@ import semmle.code.csharp.Location
import semmle.code.csharp.Stmt
import semmle.code.csharp.Type
private import dotnet
private import semmle.code.csharp.Enclosing::Internal
private import semmle.code.csharp.ExprOrStmtParent
private import semmle.code.csharp.frameworks.System
private import semmle.code.csharp.TypeRef
@@ -55,7 +55,7 @@ class Expr extends DotNet::Expr, ControlFlowElement, @expr {
final Stmt getEnclosingStmt() { enclosingStmt(this, result) }
/** Gets the enclosing callable of this expression, if any. */
override Callable getEnclosingCallable() { exprEnclosingCallable(this, result) }
override Callable getEnclosingCallable() { enclosingCallable(this, result) }
/**
* Holds if this expression is generated by the compiler and does not appear

View File

@@ -0,0 +1,42 @@
/**
* Classes for modeling Dapper.
*/
import csharp
private import semmle.code.csharp.frameworks.system.Data
/** Definitions relating to the `Dapper` package. */
module Dapper {
/** The namespace `Dapper`. */
class DapperNamespace extends Namespace {
DapperNamespace() { this.hasQualifiedName("Dapper") }
}
/** A class in `Dapper`. */
class DapperClass extends Class {
DapperClass() { this.getParent() instanceof DapperNamespace }
}
/** A struct in `Dapper`. */
class DapperStruct extends Struct {
DapperStruct() { this.getParent() instanceof DapperNamespace }
}
/** The `Dapper.SqlMapper` class. */
class SqlMapperClass extends DapperClass {
SqlMapperClass() { this.hasName("SqlMapper") }
/** Gets a DB query method. */
ExtensionMethod getAQueryMethod() {
result = this.getAMethod() and
result.getName().regexpMatch("Query.*|Execute.*") and
result.getExtendedType() instanceof SystemDataIDbConnectionInterface and
result.isPublic()
}
}
/** The `Dapper.CommandDefinition` struct. */
class CommandDefinitionStruct extends DapperStruct {
CommandDefinitionStruct() { this.hasName("CommandDefinition") }
}
}

View File

@@ -5,6 +5,8 @@ private import semmle.code.csharp.frameworks.system.Data
private import semmle.code.csharp.frameworks.system.data.SqlClient
private import semmle.code.csharp.frameworks.EntityFramework
private import semmle.code.csharp.frameworks.NHibernate
private import semmle.code.csharp.frameworks.Dapper
private import semmle.code.csharp.dataflow.DataFlow4
/** An expression containing a SQL command. */
abstract class SqlExpr extends Expr {
@@ -83,3 +85,37 @@ class MicrosoftSqlHelperMethodCallSqlExpr extends SqlExpr, MethodCall {
)
}
}
/** A `Dapper.SqlMapper` method that is taking a SQL string argument. */
class DapperSqlMethodCallSqlExpr extends SqlExpr, MethodCall {
DapperSqlMethodCallSqlExpr() {
this.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod()
}
override Expr getSql() { result = this.getArgumentForName("sql") }
}
/** A `Dapper.CommandDefinition` creation that is taking a SQL string argument and is passed to a `Dapper.SqlMapper` method. */
class DapperCommandDefinitionMethodCallSqlExpr extends SqlExpr, ObjectCreation {
DapperCommandDefinitionMethodCallSqlExpr() {
this.getObjectType() instanceof Dapper::CommandDefinitionStruct and
exists(Conf c | c.hasFlow(DataFlow::exprNode(this), _))
}
override Expr getSql() { result = this.getArgumentForName("commandText") }
}
private class Conf extends DataFlow4::Configuration {
Conf() { this = "DapperCommandDefinitionFlowConfig" }
override predicate isSource(DataFlow::Node node) {
node.asExpr().(ObjectCreation).getObjectType() instanceof Dapper::CommandDefinitionStruct
}
override predicate isSink(DataFlow::Node node) {
exists(MethodCall mc |
mc.getTarget() = any(Dapper::SqlMapperClass c).getAQueryMethod() and
node.asExpr() = mc.getArgumentForName("command")
)
}
}

View File

@@ -28,6 +28,9 @@ class Element extends @dotnet_element {
/** Holds if this element is from source code. */
predicate fromSource() { this.getFile().fromSource() }
/** Holds if this element is from an assembly. */
predicate fromLibrary() { this.getFile().fromLibrary() }
/**
* Gets the "language" of this program element, as defined by the extension of the filename.
* For example, C# has language "cs", and Visual Basic has language "vb".

View File

@@ -11,9 +11,15 @@ class SourceControlFlowElement extends ControlFlowElement {
}
class SourceControlFlowNode extends ControlFlow::Node {
SourceControlFlowNode() { not this.getLocation().getFile() instanceof StubFile }
SourceControlFlowNode() {
not this.getLocation().getFile() instanceof StubFile and
not this.getLocation().getFile().fromLibrary()
}
}
class SourceBasicBlock extends ControlFlow::BasicBlock {
SourceBasicBlock() { not this.getLocation().getFile() instanceof StubFile }
SourceBasicBlock() {
not this.getLocation().getFile() instanceof StubFile and
not this.getLocation().getFile().fromLibrary()
}
}

View File

@@ -1,6 +1,7 @@
import csharp
query predicate countSplits(ControlFlowElement cfe, int i) {
not cfe.fromLibrary() and
i = strictcount(ControlFlow::Nodes::ElementNode n | n.getElement() = cfe)
}

View File

@@ -1,4 +1,5 @@
import csharp
from DefaultValueExpr l
where l.fromSource()
select l, l.getValue()

View File

@@ -2,5 +2,7 @@ import csharp
import semmle.code.csharp.dataflow.TaintTracking
from DataFlow::Node pred, DataFlow::Node succ
where TaintTracking::localTaintStep(pred, succ)
where
TaintTracking::localTaintStep(pred, succ) and
not pred.asExpr().fromLibrary()
select pred, succ

View File

@@ -1,5 +1,5 @@
import csharp
from DataFlow::Node pred, DataFlow::Node succ
where DataFlow::localFlowStep(pred, succ)
where not pred.asExpr().fromLibrary() and DataFlow::localFlowStep(pred, succ)
select pred, succ

View File

@@ -1,5 +1,7 @@
import csharp
from DataFlow::Node pred, DataFlow::Node succ
where TaintTracking::localTaintStep(pred, succ)
where
not pred.asExpr().fromLibrary() and
TaintTracking::localTaintStep(pred, succ)
select pred, succ

View File

@@ -4,5 +4,7 @@ import semmle.code.csharp.dataflow.ModulusAnalysis
import semmle.code.csharp.dataflow.Bound
from ControlFlow::Nodes::ExprNode e, Bound b, int delta, int mod
where exprModulus(e, b, delta, mod)
where
not e.getExpr().fromLibrary() and
exprModulus(e, b, delta, mod)
select e, b.toString(), delta, mod

View File

@@ -18,4 +18,5 @@ string getASignString(ControlFlow::Nodes::ExprNode e) {
}
from ControlFlow::Nodes::ExprNode e
where not e.getExpr().fromLibrary()
select e, strictconcat(string s | s = getASignString(e) | s, " ")

View File

@@ -1,5 +1,5 @@
import csharp
from DataFlow::Node pred, DataFlow::Node succ
where DataFlow::localFlowStep(pred, succ)
where not pred.asExpr().fromLibrary() and DataFlow::localFlowStep(pred, succ)
select pred, succ

View File

@@ -1,4 +1,5 @@
import csharp
from Parameter p
where p.fromSource()
select p, p.getDefaultValue()

View File

@@ -1,6 +1,7 @@
import csharp
query predicate edges(ControlFlow::Node node, ControlFlow::Node successor, string attr, string val) {
not node.getElement().fromLibrary() and
exists(ControlFlow::SuccessorType t | successor = node.getASuccessorByType(t) |
attr = "semmle.label" and
val = t.toString()

View File

@@ -0,0 +1,17 @@
public class Parameters
{
public void M1(int a, object b, string c) => throw null;
public void M2(int a, object b = null, string c = "default string") => throw null;
public void M3(int a = 1, object b = null, string c = "null") => throw null;
public void M4(int a = default, object b = default) => throw null;
public void M5(int a = new int(), object b = default) => throw null;
public void M6(MyStruct s1, MyStruct s2 = default(MyStruct), MyStruct s3 = new MyStruct()) => throw null;
public void M7(MyEnum e1, MyEnum e2 = default(MyEnum), MyEnum e3 = new MyEnum(), MyEnum e4 = MyEnum.A, MyEnum e5 = (MyEnum)5) => throw null;
public void M8<T>(T t = default) => throw null;
public void M9<T>(T t = default) where T : struct => throw null;
public void M10<T>(T t = default) where T : class => throw null;
public struct MyStruct { }
public enum MyEnum { A = 1, B = 2 }
}

View File

@@ -0,0 +1,17 @@
public class ParametersDll
{
public void M1(int a, object b, string c) => throw null;
public void M2(int a, object b = null, string c = "default string") => throw null;
public void M3(int a = 1, object b = null, string c = "null") => throw null;
public void M4(int a = default, object b = default) => throw null;
public void M5(int a = new int(), object b = default) => throw null;
public void M6(MyStruct s1, MyStruct s2 = default(MyStruct), MyStruct s3 = new MyStruct()) => throw null;
public void M7(MyEnum e1, MyEnum e2 = default(MyEnum), MyEnum e3 = new MyEnum(), MyEnum e4 = MyEnum.A, MyEnum e5 = (MyEnum)5) => throw null;
public void M8<T>(T t = default) => throw null;
public void M9<T>(T t = default) where T : struct => throw null;
public void M10<T>(T t = default) where T : class => throw null;
public struct MyStruct { }
public enum MyEnum { A = 1, B = 2 }
}

Binary file not shown.

View File

@@ -0,0 +1,50 @@
noDefaultValue
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:24:3:24 | a | 0 |
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:34:3:34 | b | 1 |
| Parameters.cs:3:17:3:18 | M1 | Parameters.cs:3:44:3:44 | c | 2 |
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:24:4:24 | a | 0 |
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:29:8:30 | s1 | 0 |
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:27:9:28 | e1 | 0 |
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | a | 0 |
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | b | 1 |
| Parameters.dll:0:0:0:0 | M1 | Parameters.dll:0:0:0:0 | c | 2 |
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | a | 0 |
| Parameters.dll:0:0:0:0 | M6 | Parameters.dll:0:0:0:0 | s1 | 0 |
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e1 | 0 |
withDefaultValue
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:34:4:34 | b | 1 | Parameters.cs:4:38:4:41 | null | null |
| Parameters.cs:4:17:4:18 | M2 | Parameters.cs:4:51:4:51 | c | 2 | Parameters.cs:4:55:4:70 | "default string" | default string |
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:24:5:24 | a | 0 | Parameters.cs:5:28:5:28 | 1 | 1 |
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:38:5:38 | b | 1 | Parameters.cs:5:42:5:45 | null | null |
| Parameters.cs:5:17:5:18 | M3 | Parameters.cs:5:55:5:55 | c | 2 | Parameters.cs:5:59:5:64 | "null" | null |
| Parameters.cs:6:17:6:18 | M4 | Parameters.cs:6:24:6:24 | a | 0 | Parameters.cs:6:28:6:34 | (...) ... | 0 |
| Parameters.cs:6:17:6:18 | M4 | Parameters.cs:6:44:6:44 | b | 1 | Parameters.cs:6:48:6:54 | default | null |
| Parameters.cs:7:17:7:18 | M5 | Parameters.cs:7:24:7:24 | a | 0 | Parameters.cs:7:28:7:36 | object creation of type Int32 | 0 |
| Parameters.cs:7:17:7:18 | M5 | Parameters.cs:7:46:7:46 | b | 1 | Parameters.cs:7:50:7:56 | default | null |
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:42:8:43 | s2 | 1 | Parameters.cs:8:47:8:63 | default(...) | - |
| Parameters.cs:8:17:8:18 | M6 | Parameters.cs:8:75:8:76 | s3 | 2 | Parameters.cs:8:80:8:93 | object creation of type MyStruct | - |
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:38:9:39 | e2 | 1 | Parameters.cs:9:43:9:57 | default(...) | 0 |
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:67:9:68 | e3 | 2 | Parameters.cs:9:72:9:83 | object creation of type MyEnum | 0 |
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:93:9:94 | e4 | 3 | Parameters.cs:9:98:9:105 | access to constant A | 1 |
| Parameters.cs:9:17:9:18 | M7 | Parameters.cs:9:115:9:116 | e5 | 4 | Parameters.cs:9:120:9:128 | (...) ... | 5 |
| Parameters.cs:11:17:11:21 | M8 | Parameters.cs:11:25:11:25 | t | 0 | Parameters.cs:11:29:11:35 | (...) ... | - |
| Parameters.cs:12:17:12:21 | M9 | Parameters.cs:12:25:12:25 | t | 0 | Parameters.cs:12:29:12:35 | (...) ... | - |
| Parameters.cs:13:17:13:22 | M10 | Parameters.cs:13:26:13:26 | t | 0 | Parameters.cs:13:30:13:36 | (...) ... | null |
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
| Parameters.dll:0:0:0:0 | M2 | Parameters.dll:0:0:0:0 | c | 2 | Parameters.dll:0:0:0:0 | "default string" | default string |
| Parameters.dll:0:0:0:0 | M3 | Parameters.dll:0:0:0:0 | a | 0 | Parameters.dll:0:0:0:0 | 1 | 1 |
| Parameters.dll:0:0:0:0 | M3 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
| Parameters.dll:0:0:0:0 | M3 | Parameters.dll:0:0:0:0 | c | 2 | Parameters.dll:0:0:0:0 | "null" | null |
| Parameters.dll:0:0:0:0 | M4 | Parameters.dll:0:0:0:0 | a | 0 | Parameters.dll:0:0:0:0 | 0 | 0 |
| Parameters.dll:0:0:0:0 | M4 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
| Parameters.dll:0:0:0:0 | M5 | Parameters.dll:0:0:0:0 | a | 0 | Parameters.dll:0:0:0:0 | 0 | 0 |
| Parameters.dll:0:0:0:0 | M5 | Parameters.dll:0:0:0:0 | b | 1 | Parameters.dll:0:0:0:0 | default | null |
| Parameters.dll:0:0:0:0 | M6 | Parameters.dll:0:0:0:0 | s2 | 1 | Parameters.dll:0:0:0:0 | default | - |
| Parameters.dll:0:0:0:0 | M6 | Parameters.dll:0:0:0:0 | s3 | 2 | Parameters.dll:0:0:0:0 | default | - |
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e2 | 1 | Parameters.dll:0:0:0:0 | (...) ... | 0 |
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e3 | 2 | Parameters.dll:0:0:0:0 | (...) ... | 0 |
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e4 | 3 | Parameters.dll:0:0:0:0 | (...) ... | 1 |
| Parameters.dll:0:0:0:0 | M7 | Parameters.dll:0:0:0:0 | e5 | 4 | Parameters.dll:0:0:0:0 | (...) ... | 5 |
| Parameters.dll:0:0:0:0 | M8 | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | - |
| Parameters.dll:0:0:0:0 | M9 | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | - |
| Parameters.dll:0:0:0:0 | M10 | Parameters.dll:0:0:0:0 | t | 0 | Parameters.dll:0:0:0:0 | default | null |

View File

@@ -0,0 +1,19 @@
import csharp
private predicate fromTestLocation(Element e) {
e.fromSource() or e.getFile().getStem() = "Parameters"
}
query predicate noDefaultValue(Parameterizable container, Parameter p, int i) {
fromTestLocation(container) and
not p.hasDefaultValue() and
container.getParameter(i) = p
}
query predicate withDefaultValue(Parameterizable container, Parameter p, int i, Expr e, string value) {
fromTestLocation(container) and
p.hasDefaultValue() and
container.getParameter(i) = p and
p.getDefaultValue() = e and
if exists(e.getValue()) then value = e.getValue() else value = "-"
}

View File

@@ -17,4 +17,6 @@ class UnknownLocalVariableDeclExpr extends LocalVariableDeclAndInitExpr {
override string toString() { result = "(unknown type) " + this.getName() }
}
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2) { n2 = n1.getASuccessor() }
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2) {
not n1.getElement().fromLibrary() and n2 = n1.getASuccessor()
}

View File

@@ -1,4 +1,4 @@
// semmle-extractor-options: /r:System.ComponentModel.Primitives.dll /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll ${testdir}/../../../resources/stubs/EntityFramework.cs ${testdir}/../../../resources/stubs/System.Data.cs ${testdir}/../../../resources/stubs/System.Windows.cs
// semmle-extractor-options: /r:System.ComponentModel.Primitives.dll /r:System.ComponentModel.TypeConverter.dll /r:System.Data.Common.dll ${testdir}/../../../resources/stubs/EntityFramework.cs ${testdir}/../../../resources/stubs/System.Data.cs ${testdir}/../../../resources/stubs/System.Windows.cs ${testdir}/../../../resources/stubs/Dapper.cs /r:System.Linq.Expressions.dll
using System;

View File

@@ -5,6 +5,13 @@ edges
| SqlInjection.cs:73:33:73:52 | access to property Text : String | SqlInjection.cs:74:56:74:61 | access to local variable query1 |
| SqlInjection.cs:73:33:73:52 | access to property Text : String | SqlInjection.cs:75:55:75:60 | access to local variable query1 |
| SqlInjection.cs:87:21:87:29 | access to property Text : String | SqlInjection.cs:88:50:88:55 | access to local variable query1 |
| SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | SqlInjectionDapper.cs:21:55:21:59 | access to local variable query |
| SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | SqlInjectionDapper.cs:30:66:30:70 | access to local variable query |
| SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | SqlInjectionDapper.cs:39:63:39:67 | access to local variable query |
| SqlInjectionDapper.cs:47:86:47:94 | access to property Text : String | SqlInjectionDapper.cs:49:47:49:51 | access to local variable query |
| SqlInjectionDapper.cs:57:86:57:94 | access to property Text : String | SqlInjectionDapper.cs:58:42:58:46 | access to local variable query |
| SqlInjectionDapper.cs:66:86:66:94 | access to property Text : String | SqlInjectionDapper.cs:67:42:67:46 | access to local variable query |
| SqlInjectionDapper.cs:75:86:75:94 | access to property Text : String | SqlInjectionDapper.cs:77:52:77:56 | access to local variable query |
nodes
| SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | semmle.label | access to field categoryTextBox : TextBox |
| SqlInjection.cs:38:21:38:40 | access to property Text : String | semmle.label | access to property Text : String |
@@ -15,8 +22,29 @@ nodes
| SqlInjection.cs:75:55:75:60 | access to local variable query1 | semmle.label | access to local variable query1 |
| SqlInjection.cs:87:21:87:29 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjection.cs:88:50:88:55 | access to local variable query1 | semmle.label | access to local variable query1 |
| SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:39:63:39:67 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:47:86:47:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:49:47:49:51 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:57:86:57:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:58:42:58:46 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:66:86:66:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:67:42:67:46 | access to local variable query | semmle.label | access to local variable query |
| SqlInjectionDapper.cs:75:86:75:94 | access to property Text : String | semmle.label | access to property Text : String |
| SqlInjectionDapper.cs:77:52:77:56 | access to local variable query | semmle.label | access to local variable query |
#select
| SqlInjection.cs:39:50:39:55 | access to local variable query1 | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | SqlInjection.cs:39:50:39:55 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:38:21:38:35 | access to field categoryTextBox : TextBox | this ASP.NET user input |
| SqlInjection.cs:74:56:74:61 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:74:56:74:61 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
| SqlInjection.cs:75:55:75:60 | access to local variable query1 | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | SqlInjection.cs:75:55:75:60 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:73:33:73:47 | access to field categoryTextBox : TextBox | this ASP.NET user input |
| SqlInjection.cs:88:50:88:55 | access to local variable query1 | SqlInjection.cs:87:21:87:29 | access to property Text : String | SqlInjection.cs:88:50:88:55 | access to local variable query1 | Query might include code from $@. | SqlInjection.cs:87:21:87:29 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | SqlInjectionDapper.cs:21:55:21:59 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:20:86:20:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | SqlInjectionDapper.cs:30:66:30:70 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:29:86:29:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:39:63:39:67 | access to local variable query | SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | SqlInjectionDapper.cs:39:63:39:67 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:38:86:38:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:49:47:49:51 | access to local variable query | SqlInjectionDapper.cs:47:86:47:94 | access to property Text : String | SqlInjectionDapper.cs:49:47:49:51 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:47:86:47:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:58:42:58:46 | access to local variable query | SqlInjectionDapper.cs:57:86:57:94 | access to property Text : String | SqlInjectionDapper.cs:58:42:58:46 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:57:86:57:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:67:42:67:46 | access to local variable query | SqlInjectionDapper.cs:66:86:66:94 | access to property Text : String | SqlInjectionDapper.cs:67:42:67:46 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:66:86:66:94 | access to property Text : String | this TextBox text |
| SqlInjectionDapper.cs:77:52:77:56 | access to local variable query | SqlInjectionDapper.cs:75:86:75:94 | access to property Text : String | SqlInjectionDapper.cs:77:52:77:56 | access to local variable query | Query might include code from $@. | SqlInjectionDapper.cs:75:86:75:94 | access to property Text : String | this TextBox text |

View File

@@ -0,0 +1,95 @@
using System;
namespace Test
{
using System.Data;
using System.Data.Entity;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
using System.Threading.Tasks;
using Dapper;
class SqlInjectionDapper
{
string connectionString;
public void Bad01()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
var result = connection.Query<object>(query);
}
}
public async Task Bad02()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
var result = await connection.QueryAsync<object>(query);
}
}
public async Task Bad03()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
var result = await connection.QueryFirstAsync(query);
}
}
public async Task Bad04()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
await connection.ExecuteAsync(query);
}
}
public void Bad05()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
connection.ExecuteScalar(query);
}
}
public void Bad06()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
connection.ExecuteReader(query);
}
}
public async Task Bad07()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
var comDef = new CommandDefinition(query);
var result = await connection.QueryFirstAsync(comDef);
}
}
public async Task Ok07()
{
using (var connection = new SqlConnection(connectionString))
{
var query = "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" + box1.Text + "' ORDER BY PRICE";
var comDef = new CommandDefinition(query);
// no call to any query method
}
}
System.Windows.Forms.TextBox box1;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
// This file contains auto-generated code.
// original-extractor-options: /r:Dapper.dll /r:System.Data.SqlClient.dll ...
namespace Dapper
{
// Generated from `Dapper.CommandDefinition` in `Dapper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null`
public struct CommandDefinition
{
public CommandDefinition(string commandText, object parameters = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null, Dapper.CommandFlags flags = CommandFlags.Buffered, System.Threading.CancellationToken cancellationToken = default) => throw null;
}
// Generated from `Dapper.CommandFlags` in `Dapper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null`
[System.Flags]
public enum CommandFlags
{
None = 0x0,
Buffered = 0x1,
Pipelined = 0x2,
NoCache = 0x4
}
// Generated from `Dapper.SqlMapper` in `Dapper, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null`
static public class SqlMapper
{
public static System.Collections.Generic.IEnumerable<T> Query<T>(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
public static System.Data.IDataReader ExecuteReader(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
public static System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<T>> QueryAsync<T>(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
public static System.Threading.Tasks.Task<dynamic> QueryFirstAsync(this System.Data.IDbConnection cnn, Dapper.CommandDefinition command) => throw null;
public static System.Threading.Tasks.Task<dynamic> QueryFirstAsync(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
public static System.Threading.Tasks.Task<int> ExecuteAsync(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
public static object ExecuteScalar(this System.Data.IDbConnection cnn, string sql, object param = null, System.Data.IDbTransaction transaction = null, int? commandTimeout = null, System.Data.CommandType? commandType = null) => throw null;
}
}

View File

@@ -75,7 +75,7 @@ The following properties are supported in ``qlpack.yml`` files.
* - ``name``
- ``org-queries``
- All packs
- The name of the QL pack defined using alphanumeric characters, hyphens, and periods. It must be unique as CodeQL cannot differentiate between QL packs with identical names. If you intend to distribute the pack, prefix the name with your (or your organization's) name followed by a hyphen. Use the pack name to specify queries to run using ``database analyze`` and to define dependencies between QL packs (see examples below).- '
- The name of the QL pack defined using alphanumeric characters, hyphens, and periods. It must be unique as CodeQL cannot differentiate between QL packs with identical names. If you intend to distribute the pack, prefix the name with your (or your organization's) name followed by a hyphen. Use the pack name to specify queries to run using ``database analyze`` and to define dependencies between QL packs (see examples below).
* - ``version``
- ``0.0.0``
- All packs

View File

@@ -21,11 +21,3 @@ Learn more about the files you can use when running CodeQL processes and the res
- :doc:`SARIF output <sarif-output>`: CodeQL supports SARIF as an output format for sharing static analysis results.
- :doc:`Exit codes <exit-codes>`: The CodeQL CLI reports the status of each command it runs as an exit code.
This exit code provides information for subsequent commands or for other tools that rely on the CodeQL CLI.
.. _cli-commands:
CodeQL CLI manual
-----------------
To view detailed information about each CodeQL CLI command,
including its usage and options, add the ``--help`` flag or visit the "`CodeQL CLI manual <../manual>`__."

View File

@@ -138,7 +138,7 @@ see ":doc:`About QL packs <about-ql-packs>`."
- For the queries used in a particular LGTM Enterprise release, check out the
branch tagged with the relevant release number. For example, the branch
tagged ``v1.23.0`` corresponds to LGTM Enterprise 1.23. You must use this
tagged ``v1.27.0`` corresponds to LGTM Enterprise 1.27. You must use this
version if you want to upload data to LGTM Enterprise. For further
information, see `Preparing CodeQL databases to upload to LGTM
<https://help.semmle.com/lgtm-enterprise/admin/help/prepare-database-upload.html>`__

View File

@@ -18,4 +18,4 @@ CodeQL CLI
using-the-codeql-cli
codeql-cli-reference
CodeQL CLI manual <https://codeql.github.com/docs/codeql-cli/manual>

View File

@@ -13,20 +13,6 @@ on the query and the expected results until the actual results and the expected
results exactly match. This topic shows you how to create test files and execute
tests on them using the ``test run`` subcommand.
.. container:: toggle
.. container:: name
**Information for LGTM Enterprise 1.23 users**
CodeQL tests are a new feature in CodeQL CLI version 2.0.2.
If you are an LGTM Enterprise 1.23 user, you should still use CodeQL CLI
version 2.0.1 to prepare databases to upload to your instance of LGTM. You
can use version 2.0.2 (or newer) to test your custom queries, but databases
created with versions newer than 2.0.1 are not compatible with LGTM
Enterprise 1.23. For more information, see ":ref:`Getting started with the CodeQL CLI <using-two-versions-of-the-codeql-cli>`."
Setting up a test QL pack for custom queries
--------------------------------------------

View File

@@ -58,6 +58,11 @@ Configuring settings for testing queries
To increase the number of threads used for testing queries, you can update the **Running Tests > Number Of Threads** setting.
Configuring settings for telemetry and data collection
--------------------------------------------------------
You can configure whether the CodeQL extension collects telemetry data. This is disabled by default. For more information, see ":doc:`About telemetry in CodeQL for Visual Studio Code <about-telemetry-in-codeql-for-visual-studio-code>`."
Further reading
----------------

View File

@@ -64,7 +64,7 @@ There are two ways to do this:
**Click to show information for LGTM Enterprise users**
Your local version of the CodeQL queries and libraries should match your version of LGTM Enterprise. For example, if you
use LGTM Enterprise 1.23, then you should clone the ``1.23.0`` branch of the `starter workspace <https://github.com/github/vscode-codeql-starter/>`__ (or the appropriate ``1.23.x`` branch, corresponding to each maintenance release).
use LGTM Enterprise 1.27, then you should clone the ``1.27.0`` branch of the `starter workspace <https://github.com/github/vscode-codeql-starter/>`__ (or the appropriate ``1.27.x`` branch, corresponding to each maintenance release).
This ensures that the queries and libraries you write in VS Code also work in the query console on LGTM Enterprise.

View File

@@ -130,7 +130,7 @@ System and Network
- `FileSystemWriteAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$FileSystemWriteAccess.html>`__ -- writing to the contents of a file
- `PersistentReadAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentReadAccess.html>`__ -- reading from persistent storage, like cookies
- `PersistentWriteAccess <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$PersistentWriteAccess.html>`__ -- writing to persistent storage
- `RemoteFlowSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$RemoteFlowSource.html>`__ -- source of untrusted user input
- `RemoteFlowSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$Cached$RemoteFlowSource.html>`__ -- source of untrusted user input
- `SystemCommandExecution <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/Concepts.qll/type.Concepts$SystemCommandExecution.html>`__ -- execution of a system command
Files

View File

@@ -12,7 +12,7 @@ You can model potential sources of untrusted user input in your code without mak
Specifying remote flow sources in external files is currently in beta and subject to change.
As mentioned in the :doc:`Data flow cheat sheet for JavaScript <data-flow-cheat-sheet-for-javascript>`, the CodeQL libraries for JavaScript
provide a class `RemoteFlowSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$RemoteFlowSource.html>`__ to represent sources of untrusted user input, sometimes also referred to as remote flow
provide a class `RemoteFlowSource <https://codeql.github.com/codeql-standard-libraries/javascript/semmle/javascript/security/dataflow/RemoteFlowSources.qll/type.RemoteFlowSources$Cached$RemoteFlowSource.html>`__ to represent sources of untrusted user input, sometimes also referred to as remote flow
sources.
To model a new source of untrusted input, such as a previously unmodelled library API, you can

View File

@@ -385,21 +385,23 @@ For more information, see ":ref:`monotonic-aggregates`."
Binding sets
============
**Available for**: |characteristic predicates|, |member predicates|, |non-member predicates|
**Available for**: |classes|, |characteristic predicates|, |member predicates|, |non-member predicates|
``bindingset[...]``
-------------------
You can use this annotation to explicitly state the binding sets for a predicate. A binding set
is a subset of the predicate's arguments such that, if those arguments are constrained to a
finite set of values, then the predicate itself is finite (that is, it evaluates to a finite
You can use this annotation to explicitly state the binding sets for a predicate or class. A binding set
is a subset of a predicate's or class body's arguments such that, if those arguments are constrained to a
finite set of values, then the predicate or class itself is finite (that is, it evaluates to a finite
set of tuples).
The ``bindingset`` annotation takes a comma-separated list of variables. Each variable must be
an argument of the predicate, possibly including ``this`` (for characteristic predicates and
member predicates) and ``result`` (for predicates that return a result).
The ``bindingset`` annotation takes a comma-separated list of variables.
For more information, see ":ref:`predicate-binding`."
- When you annotate a predicate, each variable must be an argument of the predicate, possibly including ``this``
(for characteristic predicates and member predicates) and ``result`` (for predicates that return a result).
For more information, see ":ref:`predicate-binding`."
- When you annotate a class, each variable must be ``this`` or a field in the class.
Binding sets for classes are supported from release 2.3.0 of the CodeQL CLI, and release 1.26 of LGTM Enterprise.
.. Links to use in substitutions

View File

@@ -14,7 +14,7 @@
C#,C# up to 8.0,"Microsoft Visual Studio up to 2019 with .NET up to 4.8,
.NET Core up to 3.1","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``"
Go (aka Golang), "Go up to 1.15", "Go 1.11 or more recent", ``.go``
Go (aka Golang), "Go up to 1.16", "Go 1.11 or more recent", ``.go``
Java,"Java 7 to 15 [3]_","javac (OpenJDK and Oracle JDK),
Eclipse compiler for Java (ECJ) [4]_",``.java``

View File

@@ -638,7 +638,21 @@ class BooleanLiteral extends Literal, @booleanliteral {
override string getAPrimaryQlClass() { result = "BooleanLiteral" }
}
/** An integer literal. For example, `23`. */
/**
* An integer literal. For example, `23`.
*
* An integer literal can never be negative except when:
* - It is written in binary, octal or hexadecimal notation
* - It is written in decimal notation, has the value `2147483648` and is preceded
* by a minus; in this case the value of the IntegerLiteral is -2147483648 and
* the preceding minus will *not* be modeled as `MinusExpr`.
*
* In all other cases the preceding minus, if any, will be modeled as a separate
* `MinusExpr`.
*
* The last exception is necessary because `2147483648` on its own would not be
* a valid integer literal (and could also not be parsed as CodeQL `int`).
*/
class IntegerLiteral extends Literal, @integerliteral {
/** Gets the int representation of this literal. */
int getIntValue() { result = getValue().toInt() }
@@ -646,12 +660,32 @@ class IntegerLiteral extends Literal, @integerliteral {
override string getAPrimaryQlClass() { result = "IntegerLiteral" }
}
/** A long literal. For example, `23l`. */
/**
* A long literal. For example, `23L`.
*
* A long literal can never be negative except when:
* - It is written in binary, octal or hexadecimal notation
* - It is written in decimal notation, has the value `9223372036854775808` and
* is preceded by a minus; in this case the value of the LongLiteral is
* -9223372036854775808 and the preceding minus will *not* be modeled as
* `MinusExpr`.
*
* In all other cases the preceding minus, if any, will be modeled as a separate
* `MinusExpr`.
*
* The last exception is necessary because `9223372036854775808` on its own
* would not be a valid long literal.
*/
class LongLiteral extends Literal, @longliteral {
override string getAPrimaryQlClass() { result = "LongLiteral" }
}
/** A floating point literal. For example, `4.2f`. */
/**
* A float literal. For example, `4.2f`.
*
* A float literal is never negative; a preceding minus, if any, will always
* be modeled as separate `MinusExpr`.
*/
class FloatingPointLiteral extends Literal, @floatingpointliteral {
/**
* Gets the value of this literal as CodeQL 64-bit `float`. The value will
@@ -662,7 +696,12 @@ class FloatingPointLiteral extends Literal, @floatingpointliteral {
override string getAPrimaryQlClass() { result = "FloatingPointLiteral" }
}
/** A double literal. For example, `4.2`. */
/**
* A double literal. For example, `4.2`.
*
* A double literal is never negative; a preceding minus, if any, will always
* be modeled as separate `MinusExpr`.
*/
class DoubleLiteral extends Literal, @doubleliteral {
/**
* Gets the value of this literal as CodeQL 64-bit `float`. The result will

View File

@@ -80,19 +80,15 @@ class Node extends TNode {
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType()
}
private Callable getEnclosingCallableImpl() {
/** Gets the callable in which this node occurs. */
Callable getEnclosingCallable() {
result = this.asExpr().getEnclosingCallable() or
result = this.asParameter().getCallable() or
result = this.(ImplicitVarargsArray).getCall().getEnclosingCallable() or
result = this.(InstanceParameterNode).getCallable() or
result = this.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result = this.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallableImpl()
}
/** Gets the callable in which this node occurs. */
Callable getEnclosingCallable() {
result = unique(DataFlowCallable c | c = this.getEnclosingCallableImpl() | c)
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getEnclosingCallable()
}
private Type getImprovedTypeBound() {

View File

@@ -0,0 +1,16 @@
class NumericLiterals {
void negativeLiterals() {
float f = -1f;
double d = -1d;
int i1 = -2147483647;
int i2 = -2147483648; // CodeQL models minus as part of literal
int i3 = -0b10000000000000000000000000000000; // binary
int i4 = -020000000000; // octal
int i5 = -0x80000000; // hex
long l1 = -9223372036854775807L;
long l2 = -9223372036854775808L; // CodeQL models minus as part of literal
long l3 = -0b1000000000000000000000000000000000000000000000000000000000000000L; // binary
long l4 = -01000000000000000000000L; // octal
long l5 = -0x8000000000000000L; // hex
}
}

View File

@@ -0,0 +1,12 @@
| NumericLiterals.java:3:14:3:15 | 1f | 1.0 | NumericLiterals.java:3:13:3:15 | -... |
| NumericLiterals.java:4:15:4:16 | 1d | 1.0 | NumericLiterals.java:4:14:4:16 | -... |
| NumericLiterals.java:5:13:5:22 | 2147483647 | 2147483647 | NumericLiterals.java:5:12:5:22 | -... |
| NumericLiterals.java:6:12:6:22 | -2147483648 | -2147483648 | NumericLiterals.java:6:7:6:22 | i2 |
| NumericLiterals.java:7:13:7:46 | 0b10000000000000000000000000000000 | -2147483648 | NumericLiterals.java:7:12:7:46 | -... |
| NumericLiterals.java:8:13:8:24 | 020000000000 | -2147483648 | NumericLiterals.java:8:12:8:24 | -... |
| NumericLiterals.java:9:13:9:22 | 0x80000000 | -2147483648 | NumericLiterals.java:9:12:9:22 | -... |
| NumericLiterals.java:10:14:10:33 | 9223372036854775807L | 9223372036854775807 | NumericLiterals.java:10:13:10:33 | -... |
| NumericLiterals.java:11:13:11:33 | -9223372036854775808L | -9223372036854775808 | NumericLiterals.java:11:8:11:33 | l2 |
| NumericLiterals.java:12:14:12:80 | 0b1000000000000000000000000000000000000000000000000000000000000000L | -9223372036854775808 | NumericLiterals.java:12:13:12:80 | -... |
| NumericLiterals.java:13:14:13:37 | 01000000000000000000000L | -9223372036854775808 | NumericLiterals.java:13:13:13:37 | -... |
| NumericLiterals.java:14:14:14:32 | 0x8000000000000000L | -9223372036854775808 | NumericLiterals.java:14:13:14:32 | -... |

View File

@@ -0,0 +1,9 @@
import java
from Literal l
where
l instanceof IntegerLiteral or
l instanceof LongLiteral or
l instanceof FloatingPointLiteral or
l instanceof DoubleLiteral
select l, l.getValue(), l.getParent()

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* The SQL library models for `mysql`, `mysql2`, `mssql`, `pg`, `sqlite3`, `sequelize`, and `@google-cloud/spanner` have improved,
leading to more SQL injection sinks.

View File

@@ -0,0 +1,5 @@
lgtm,codescanning
* Fixed a bug which caused some imports to be resolved incorrectly
for projects containing multiple `tsconfig.json` files.
* Fixed a bug which could cause some files in the `node_modules` folder
to be extracted even though they should be excluded.

View File

@@ -0,0 +1,3 @@
lgtm,codescanning
* Support for Redux has improved. The security queries can now track taint through reducer functions and state managed by Redux.
Affected packages are `redux`, `react-redux`, `@reduxjs/toolkit`, `redux-actions`, `redux-persist`, `reduce-reducers`, `redux-immutable`, and `immer`.

View File

@@ -21,7 +21,7 @@ public class ParsedProject {
/** Absolute paths to the files included in this project. */
public Set<File> getOwnFiles() {
return allFiles;
return ownFiles;
}
/** Absolute paths to the files included in or referenced by this project. */

View File

@@ -3,6 +3,7 @@
* @description Finds cases where the 'userId' field in a request to another service
* is an arbitrary user-controlled value, indicating lack of authentication.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/backend-idor
*/

View File

@@ -3,6 +3,7 @@
* @description Tracks the return value of 'escapeHtml' into 'decodeURI', indicating
* an ineffective sanitization attempt.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/decoding-after-sanitization
*/

View File

@@ -3,6 +3,7 @@
* @description Tracks the return value of an HTML sanitizer into an escape-sequence decoder,
* indicating an ineffective sanitization attempt.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/decoding-after-sanitization-generalized
*/

View File

@@ -3,6 +3,7 @@
* @description Tracks user-controlled values into 'eval' calls (special case of js/code-injection),
* and generates a visualizable path from the source to the sink.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/eval-taint-path
*/

View File

@@ -3,6 +3,7 @@
* @description Tracks values from an 'authKey' property into a postMessage call with unrestricted origin,
* indicating a leak of sensitive information.
* @kind path-problem
* @problem.severity warning
* @tags security
* @id js/examples/information-disclosure
*/

View File

@@ -2,6 +2,7 @@
* @name Extension of standard query: Stored XSS
* @description Extends the standard Stored XSS query with an additional source.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/stored-xss
*/

View File

@@ -3,6 +3,7 @@
* @description Extends the standard Stored XSS query with an additional source,
* using TrackedNode to track MySQL connections globally.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/stored-xss-trackednode
*/

View File

@@ -2,6 +2,7 @@
* @name Template injection
* @description Tracks user-controlled values to an unescaped lodash template placeholder.
* @kind path-problem
* @problem.severity error
* @tags security
* @id js/examples/template-injection
*/

View File

@@ -6,7 +6,6 @@
* @kind treemap
* @treemap.warnOn highValues
* @metricType externalDependency
* @precision medium
* @id js/external-dependencies
*/

View File

@@ -15,13 +15,8 @@ import javascript
import semmle.javascript.security.dataflow.DomBasedXss::DomBasedXss
import DataFlow::PathGraph
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where
(
cfg instanceof HtmlInjectionConfiguration or
cfg instanceof JQueryHtmlOrSelectorInjectionConfiguration
) and
cfg.hasFlowPath(source, sink)
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink,
sink.getNode().(Sink).getVulnerabilityKind() + " vulnerability due to $@.", source.getNode(),
"user-provided value"

View File

@@ -0,0 +1,11 @@
/**
* @id js/summary/lines-of-code
* @name Total lines of JavaScript and TypeScript code in the database
* @description The total number of lines of JavaScript or TypeScript code across all files checked into the repository, except in `node_modules`. This is a useful metric of the size of a database. For all files that were seen during extraction, this query counts the lines of code, excluding whitespace or comments.
* @kind metric
* @tags summary
*/
import javascript
select sum(File f | not f.getATopLevel().isExterns() | f.getNumberOfLinesOfCode())

View File

@@ -5,7 +5,7 @@
* user-controlled exit node of portal `p1` to an escaping entry node of portal `p2`,
* and have label `lbl2` at that point. Moreover, the path from `p1` to `p2` contains
* no sanitizers specified by configuration `cfg`.
* @kind flow-step-summary
* @kind table
* @id js/step-summary-extraction
*/

View File

@@ -3,7 +3,7 @@
* @description Extracts sink summaries, that is, tuples `(p, lbl, cfg)` representing the fact
* that data with flow label `lbl` may flow from a user-controlled exit node of portal
* `p` to a known sink for configuration `cfg`.
* @kind sink-summary
* @kind table
* @id js/sink-summary-extraction
*/

View File

@@ -3,7 +3,7 @@
* @description Extracts source summaries, that is, tuples `(p, lbl, cfg)` representing the fact
* that data may flow from a known source for configuration `cfg` to an escaping entry
* node of portal `p`, and have flow label `lbl` at that point.
* @kind source-summary
* @kind table
* @id js/source-summary-extraction
*/

View File

@@ -105,6 +105,7 @@ import semmle.javascript.frameworks.PropertyProjection
import semmle.javascript.frameworks.Puppeteer
import semmle.javascript.frameworks.React
import semmle.javascript.frameworks.ReactNative
import semmle.javascript.frameworks.Redux
import semmle.javascript.frameworks.Request
import semmle.javascript.frameworks.RxJS
import semmle.javascript.frameworks.ServerLess

View File

@@ -0,0 +1,15 @@
/**
* @name Import graph
* @description An edge in the import graph.
* @kind problem
* @problem.severity recommendation
* @id js/meta/alerts/import-graph
* @tags meta
* @precision very-low
*/
import javascript
from Import imprt, Module target
where target = imprt.getImportedModule()
select imprt, "Import targeting $@", target, target.getFile().getRelativePath()

View File

@@ -307,7 +307,7 @@ class ReachableBasicBlock extends BasicBlock {
/**
* Holds if this basic block strictly dominates `bb`.
*/
cached
pragma[inline]
predicate strictlyDominates(ReachableBasicBlock bb) { bbIDominates+(this, bb) }
/**
@@ -315,15 +315,13 @@ class ReachableBasicBlock extends BasicBlock {
*
* This predicate is reflexive: each reachable basic block dominates itself.
*/
predicate dominates(ReachableBasicBlock bb) {
bb = this or
strictlyDominates(bb)
}
pragma[inline]
predicate dominates(ReachableBasicBlock bb) { bbIDominates*(this, bb) }
/**
* Holds if this basic block strictly post-dominates `bb`.
*/
cached
pragma[inline]
predicate strictlyPostDominates(ReachableBasicBlock bb) { bbIPostDominates+(this, bb) }
/**
@@ -331,10 +329,8 @@ class ReachableBasicBlock extends BasicBlock {
*
* This predicate is reflexive: each reachable basic block post-dominates itself.
*/
predicate postDominates(ReachableBasicBlock bb) {
bb = this or
strictlyPostDominates(bb)
}
pragma[inline]
predicate postDominates(ReachableBasicBlock bb) { bbIPostDominates*(this, bb) }
}
/**

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