Skip to content

Commit d05a61c

Browse files
committed
Merge branch 'master' of https://github.com/github/codeql into pr/erik-krogh/3566
2 parents 3ae4e90 + fd05314 commit d05a61c

File tree

67 files changed

+1303
-256
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+1303
-256
lines changed

change-notes/1.25/analysis-javascript.md

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
## General improvements
44

55
* Support for the following frameworks and libraries has been improved:
6+
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
67
- [bluebird](http://bluebirdjs.com/)
78
- [express](https://www.npmjs.com/package/express)
9+
- [fastify](https://www.npmjs.com/package/fastify)
810
- [fstream](https://www.npmjs.com/package/fstream)
911
- [jGrowl](https://github.com/stanlemon/jGrowl)
1012
- [jQuery](https://jquery.com/)
@@ -13,12 +15,11 @@
1315
- [mssql](https://www.npmjs.com/package/mssql)
1416
- [mysql](https://www.npmjs.com/package/mysql)
1517
- [pg](https://www.npmjs.com/package/pg)
16-
- [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)
1718
- [sequelize](https://www.npmjs.com/package/sequelize)
1819
- [spanner](https://www.npmjs.com/package/spanner)
1920
- [sqlite](https://www.npmjs.com/package/sqlite)
20-
- [ssh2](https://www.npmjs.com/package/ssh2)
2121
- [ssh2-streams](https://www.npmjs.com/package/ssh2-streams)
22+
- [ssh2](https://www.npmjs.com/package/ssh2)
2223

2324
* TypeScript 3.9 is now supported.
2425

@@ -35,41 +36,42 @@
3536

3637
| **Query** | **Expected impact** | **Change** |
3738
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
38-
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
39-
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
40-
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
41-
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Less results | This query now recognizes additional safe patterns of doing URL redirects. |
42-
| Client-side cross-site scripting (`js/xss`) | Less results | This query now recognizes additional safe patterns of constructing HTML. |
39+
| Client-side URL redirect (`js/client-side-unvalidated-url-redirection`) | Fewer results | This query now recognizes additional safe patterns of doing URL redirects. |
40+
| Client-side cross-site scripting (`js/xss`) | Fewer results | This query now recognizes additional safe patterns of constructing HTML. |
41+
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
42+
| Expression has no effect (`js/useless-expression`) | Fewer results | This query no longer flags an expression when that expression is the only content of the containing file. |
4343
| Incomplete URL scheme check (`js/incomplete-url-scheme-check`) | More results | This query now recognizes additional url scheme checks. |
44+
| Misspelled variable name (`js/misspelled-variable-name`) | Message changed | The message for this query now correctly identifies the misspelled variable in additional cases. |
4445
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes additional utility functions as vulnerable to prototype polution. |
45-
| Expression has no effect (`js/useless-expression`) | Less results | This query no longer flags an expression when that expression is the only content of the containing file. |
46-
| Unknown directive (`js/unknown-directive`) | Less results | This query no longer flags directives generated by the Babel compiler. |
47-
| Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving NoSQL code operators are now recognized. |
46+
| Prototype pollution in utility function (`js/prototype-pollution-utility`) | More results | This query now recognizes more coding patterns that are vulnerable to prototype pollution. |
47+
| Uncontrolled command line (`js/command-line-injection`) | More results | This query now recognizes additional command execution calls. |
48+
| Uncontrolled data used in path expression (`js/path-injection`) | More results | This query now recognizes additional file system calls. |
49+
| Unknown directive (`js/unknown-directive`) | Fewer results | This query no longer flags directives generated by the Babel compiler. |
50+
| Unused property (`js/unused-property`) | Fewer results | This query no longer flags properties of objects that are operands of `yield` expressions. |
4851
| Zip Slip (`js/zipslip`) | More results | This query now recognizes additional vulnerabilities. |
49-
| Unused property (`js/unused-property`) | Less results | This query no longer flags properties of objects that are operands of `yield` expressions. |
5052

5153
The following low-precision queries are no longer run by default on LGTM (their results already were not displayed):
5254

5355
- `js/angular/dead-event-listener`
5456
- `js/angular/unused-dependency`
55-
- `js/conflicting-html-attribute`
56-
- `js/useless-assignment-to-global`
57-
- `js/too-many-parameters`
58-
- `js/unused-property`
5957
- `js/bitwise-sign-check`
6058
- `js/comparison-of-identical-expressions`
61-
- `js/misspelled-identifier`
59+
- `js/conflicting-html-attribute`
60+
- `js/ignored-setter-parameter`
6261
- `js/jsdoc/malformed-param-tag`
63-
- `js/jsdoc/unknown-parameter`
6462
- `js/jsdoc/missing-parameter`
65-
- `js/omitted-array-element`
66-
- `js/ignored-setter-parameter`
63+
- `js/jsdoc/unknown-parameter`
6764
- `js/json-in-javascript-file`
65+
- `js/misspelled-identifier`
66+
- `js/nested-loops-with-same-variable`
6867
- `js/node/cyclic-import`
6968
- `js/node/unused-npm-dependency`
70-
- `js/single-run-loop`
71-
- `js/nested-loops-with-same-variable`
69+
- `js/omitted-array-element`
7270
- `js/return-outside-function`
71+
- `js/single-run-loop`
72+
- `js/too-many-parameters`
73+
- `js/unused-property`
74+
- `js/useless-assignment-to-global`
7375

7476
## Changes to libraries
7577

@@ -79,3 +81,4 @@ The following low-precision queries are no longer run by default on LGTM (their
7981
- `Parameter.flow()` now gets the correct data flow node for a parameter. Previously this had a result, but the node was disconnected from the data flow graph.
8082
- `ParameterNode.asExpr()` and `.getAstNode()` now gets the parameter's AST node, whereas previously it had no result.
8183
- `Expr.flow()` now has a more meaningful result for destructuring patterns. Previously this node was disconnected from the data flow graph. Now it represents the values being destructured by the pattern.
84+
* The global data-flow and taint-tracking libraries now model indirect parameter accesses through the `arguments` object in some cases, which may lead to additional results from some of the security queries, particularly "Prototype pollution in utility function".

cpp/ql/src/external/DefectFilter.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,52 @@
1+
/** Provides a class for working with defect query results stored in dashboard databases. */
2+
13
import cpp
24

5+
/**
6+
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
7+
* such that `message` is the associated message and the location of the result spans
8+
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
9+
* in file `filepath`.
10+
*
11+
* For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
12+
*/
313
external predicate defectResults(
414
int id, string queryPath, string file, int startline, int startcol, int endline, int endcol,
515
string message
616
);
717

18+
/**
19+
* A defect query result stored in a dashboard database.
20+
*/
821
class DefectResult extends int {
922
DefectResult() { defectResults(this, _, _, _, _, _, _, _) }
1023

24+
/** Gets the path of the query that reported the result. */
1125
string getQueryPath() { defectResults(this, result, _, _, _, _, _, _) }
1226

27+
/** Gets the file in which this query result was reported. */
1328
File getFile() {
1429
exists(string path |
1530
defectResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
1631
)
1732
}
1833

34+
/** Gets the line on which the location of this query result starts. */
1935
int getStartLine() { defectResults(this, _, _, result, _, _, _, _) }
2036

37+
/** Gets the column on which the location of this query result starts. */
2138
int getStartColumn() { defectResults(this, _, _, _, result, _, _, _) }
2239

40+
/** Gets the line on which the location of this query result ends. */
2341
int getEndLine() { defectResults(this, _, _, _, _, result, _, _) }
2442

43+
/** Gets the column on which the location of this query result ends. */
2544
int getEndColumn() { defectResults(this, _, _, _, _, _, result, _) }
2645

46+
/** Gets the message associated with this query result. */
2747
string getMessage() { defectResults(this, _, _, _, _, _, _, result) }
2848

49+
/** Gets the URL corresponding to the location of this query result. */
2950
string getURL() {
3051
result =
3152
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +
Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
1+
/**
2+
* Provides classes for working with external data.
3+
*/
4+
15
import cpp
26

7+
/**
8+
* An external data item.
9+
*/
310
class ExternalData extends @externalDataElement {
11+
/** Gets the path of the file this data was loaded from. */
412
string getDataPath() { externalData(this, result, _, _) }
513

14+
/**
15+
* Gets the path of the file this data was loaded from, with its
16+
* extension replaced by `.ql`.
17+
*/
618
string getQueryPath() { result = getDataPath().regexpReplaceAll("\\.[^.]*$", ".ql") }
719

20+
/** Gets the number of fields in this data item. */
821
int getNumFields() { result = 1 + max(int i | externalData(this, _, i, _) | i) }
922

10-
string getField(int index) { externalData(this, _, index, result) }
23+
/** Gets the value of the `i`th field of this data item. */
24+
string getField(int i) { externalData(this, _, i, result) }
1125

12-
int getFieldAsInt(int index) { result = getField(index).toInt() }
26+
/** Gets the integer value of the `i`th field of this data item. */
27+
int getFieldAsInt(int i) { result = getField(i).toInt() }
1328

14-
float getFieldAsFloat(int index) { result = getField(index).toFloat() }
29+
/** Gets the floating-point value of the `i`th field of this data item. */
30+
float getFieldAsFloat(int i) { result = getField(i).toFloat() }
1531

16-
date getFieldAsDate(int index) { result = getField(index).toDate() }
32+
/** Gets the value of the `i`th field of this data item, interpreted as a date. */
33+
date getFieldAsDate(int i) { result = getField(i).toDate() }
1734

35+
/** Gets a textual representation of this data item. */
1836
string toString() { result = getQueryPath() + ": " + buildTupleString(0) }
1937

20-
private string buildTupleString(int start) {
21-
start = getNumFields() - 1 and result = getField(start)
38+
/** Gets a textual representation of this data item, starting with the `n`th field. */
39+
private string buildTupleString(int n) {
40+
n = getNumFields() - 1 and result = getField(n)
2241
or
23-
start < getNumFields() - 1 and result = getField(start) + "," + buildTupleString(start + 1)
42+
n < getNumFields() - 1 and result = getField(n) + "," + buildTupleString(n + 1)
2443
}
2544
}
2645

@@ -33,7 +52,9 @@ class DefectExternalData extends ExternalData {
3352
this.getNumFields() = 2
3453
}
3554

55+
/** Gets the URL associated with this data item. */
3656
string getURL() { result = getField(0) }
3757

58+
/** Gets the message associated with this data item. */
3859
string getMessage() { result = getField(1) }
3960
}

cpp/ql/src/external/MetricFilter.qll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,58 @@
1+
/** Provides a class for working with metric query results stored in dashboard databases. */
2+
13
import cpp
24

5+
/**
6+
* Holds if `id` in the opaque identifier of a result reported by query `queryPath`,
7+
* such that `value` is the reported metric value and the location of the result spans
8+
* column `startcolumn` of line `startline` to column `endcolumn` of line `endline`
9+
* in file `filepath`.
10+
*
11+
* For more information, see [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html).
12+
*/
313
external predicate metricResults(
414
int id, string queryPath, string file, int startline, int startcol, int endline, int endcol,
515
float value
616
);
717

18+
/**
19+
* A metric query result stored in a dashboard database.
20+
*/
821
class MetricResult extends int {
922
MetricResult() { metricResults(this, _, _, _, _, _, _, _) }
1023

24+
/** Gets the path of the query that reported the result. */
1125
string getQueryPath() { metricResults(this, result, _, _, _, _, _, _) }
1226

27+
/** Gets the file in which this query result was reported. */
1328
File getFile() {
1429
exists(string path |
1530
metricResults(this, _, path, _, _, _, _, _) and result.getAbsolutePath() = path
1631
)
1732
}
1833

34+
/** Gets the line on which the location of this query result starts. */
1935
int getStartLine() { metricResults(this, _, _, result, _, _, _, _) }
2036

37+
/** Gets the column on which the location of this query result starts. */
2138
int getStartColumn() { metricResults(this, _, _, _, result, _, _, _) }
2239

40+
/** Gets the line on which the location of this query result ends. */
2341
int getEndLine() { metricResults(this, _, _, _, _, result, _, _) }
2442

43+
/** Gets the column on which the location of this query result ends. */
2544
int getEndColumn() { metricResults(this, _, _, _, _, _, result, _) }
2645

46+
/**
47+
* Holds if there is a `Location` entity whose location is the same as
48+
* the location of this query result.
49+
*/
2750
predicate hasMatchingLocation() { exists(this.getMatchingLocation()) }
2851

52+
/**
53+
* Gets the `Location` entity whose location is the same as the location
54+
* of this query result.
55+
*/
2956
Location getMatchingLocation() {
3057
result.getFile() = this.getFile() and
3158
result.getStartLine() = this.getStartLine() and
@@ -34,8 +61,10 @@ class MetricResult extends int {
3461
result.getEndColumn() = this.getEndColumn()
3562
}
3663

64+
/** Gets the value associated with this query result. */
3765
float getValue() { metricResults(this, _, _, _, _, _, _, result) }
3866

67+
/** Gets the URL corresponding to the location of this query result. */
3968
string getURL() {
4069
result =
4170
"file://" + getFile().getAbsolutePath() + ":" + getStartLine() + ":" + getStartColumn() + ":" +

cpp/ql/src/semmle/code/cpp/Declaration.qll

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,12 @@ class Declaration extends Locatable, @declaration {
9898
this.hasQualifiedName(namespaceQualifier, "", baseName)
9999
}
100100

101-
override string toString() { result = this.getName() }
101+
/**
102+
* Gets a description of this `Declaration` for display purposes.
103+
*/
104+
string getDescription() { result = this.getName() }
105+
106+
final override string toString() { result = this.getDescription() }
102107

103108
/**
104109
* Gets the name of this declaration.

cpp/ql/src/semmle/code/cpp/Namespace.qll

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ class Namespace extends NameQualifyingElement, @namespace {
7979
/** Gets the metric namespace. */
8080
MetricNamespace getMetrics() { result = this }
8181

82-
override string toString() { result = this.getQualifiedName() }
82+
/** Gets a version of the `QualifiedName` that is more suitable for display purposes. */
83+
string getFriendlyName() { result = this.getQualifiedName() }
84+
85+
final override string toString() { result = getFriendlyName() }
8386

8487
/** Gets a declaration of (part of) this namespace. */
8588
NamespaceDeclarationEntry getADeclarationEntry() { result.getNamespace() = this }
@@ -104,7 +107,7 @@ class NamespaceDeclarationEntry extends Locatable, @namespace_decl {
104107
namespace_decls(underlyingElement(this), unresolveElement(result), _, _)
105108
}
106109

107-
override string toString() { result = this.getNamespace().toString() }
110+
override string toString() { result = this.getNamespace().getFriendlyName() }
108111

109112
/**
110113
* Gets the location of the token preceding the namespace declaration
@@ -150,7 +153,7 @@ class UsingDeclarationEntry extends UsingEntry {
150153
*/
151154
Declaration getDeclaration() { usings(underlyingElement(this), unresolveElement(result), _) }
152155

153-
override string toString() { result = "using " + this.getDeclaration().toString() }
156+
override string toString() { result = "using " + this.getDeclaration().getDescription() }
154157
}
155158

156159
/**
@@ -169,7 +172,7 @@ class UsingDirectiveEntry extends UsingEntry {
169172
*/
170173
Namespace getNamespace() { usings(underlyingElement(this), unresolveElement(result), _) }
171174

172-
override string toString() { result = "using namespace " + this.getNamespace().toString() }
175+
override string toString() { result = "using namespace " + this.getNamespace().getFriendlyName() }
173176
}
174177

175178
/**
@@ -204,7 +207,7 @@ class GlobalNamespace extends Namespace {
204207
*/
205208
deprecated string getFullName() { result = this.getName() }
206209

207-
override string toString() { result = "(global namespace)" }
210+
override string getFriendlyName() { result = "(global namespace)" }
208211
}
209212

210213
/**

cpp/ql/src/semmle/code/cpp/Variable.qll

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -260,24 +260,33 @@ class ParameterDeclarationEntry extends VariableDeclarationEntry {
260260
*/
261261
int getIndex() { param_decl_bind(underlyingElement(this), result, _) }
262262

263+
private string getAnonymousParameterDescription() {
264+
not exists(getName()) and
265+
exists(string idx |
266+
idx =
267+
((getIndex() + 1).toString() + "th")
268+
.replaceAll("1th", "1st")
269+
.replaceAll("2th", "2nd")
270+
.replaceAll("3th", "3rd")
271+
.replaceAll("11st", "11th")
272+
.replaceAll("12nd", "12th")
273+
.replaceAll("13rd", "13th") and
274+
if exists(getCanonicalName())
275+
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
276+
else result = "declaration of " + idx + " parameter"
277+
)
278+
}
279+
263280
override string toString() {
264-
if exists(getName())
265-
then result = super.toString()
266-
else
267-
exists(string idx |
268-
idx =
269-
((getIndex() + 1).toString() + "th")
270-
.replaceAll("1th", "1st")
271-
.replaceAll("2th", "2nd")
272-
.replaceAll("3th", "3rd")
273-
.replaceAll("11st", "11th")
274-
.replaceAll("12nd", "12th")
275-
.replaceAll("13rd", "13th")
276-
|
277-
if exists(getCanonicalName())
278-
then result = "declaration of " + getCanonicalName() + " as anonymous " + idx + " parameter"
279-
else result = "declaration of " + idx + " parameter"
280-
)
281+
isDefinition() and
282+
result = "definition of " + getName()
283+
or
284+
not isDefinition() and
285+
if getName() = getCanonicalName()
286+
then result = "declaration of " + getName()
287+
else result = "declaration of " + getCanonicalName() + " as " + getName()
288+
or
289+
result = getAnonymousParameterDescription()
281290
}
282291

283292
/**

0 commit comments

Comments
 (0)