Skip to content

Commit 5d853e8

Browse files
committed
Merge branch 'main' into python-add-typetracker
2 parents 8b78b6b + 813d147 commit 5d853e8

File tree

135 files changed

+5421
-631
lines changed

Some content is hidden

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

135 files changed

+5421
-631
lines changed

change-notes/1.25/analysis-javascript.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
- [yargs](https://www.npmjs.com/package/yargs)
3131
- [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server)
3232

33-
* TypeScript 3.9 is now supported.
33+
* TypeScript 4.0 is now supported.
3434

3535
* TypeScript code embedded in HTML and Vue files is now extracted and analyzed.
3636

change-notes/1.25/analysis-python.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,3 @@ The following changes in version 1.25 affect Python analysis in all applications
2020
## Changes to libraries
2121

2222
* Importing `semmle.python.web.HttpRequest` will no longer import `UntrustedStringKind` transitively. `UntrustedStringKind` is the most commonly used non-abstract subclass of `ExternalStringKind`. If not imported (by one mean or another), taint-tracking queries that concern `ExternalStringKind` will not produce any results. Please ensure such queries contain an explicit import (`import semmle.python.security.strings.Untrusted`).
23-
* Added support for tainted f-strings.

change-notes/1.26/analysis-csharp.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ The following changes in version 1.26 affect C# analysis in all applications.
1919
## Changes to code extraction
2020

2121
* Partial method bodies are extracted. Previously, partial method bodies were skipped completely.
22+
* Inferring the lengths of implicitely sized arrays is fixed. Previously, multidimensional arrays were always extracted with the same length for
23+
each dimension. With the fix, the array sizes `2` and `1` are extracted for `new int[,]{{1},{2}}`. Previously `2` and `2` were extracted.
2224

2325
## Changes to libraries
2426

change-notes/1.26/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
| **Query** | **Expected impact** | **Change** |
2828
|--------------------------------|------------------------------|---------------------------------------------------------------------------|
2929
| Incomplete URL substring sanitization (`js/incomplete-url-substring-sanitization`) | More results | This query now recognizes additional URLs when the substring check is an inclusion check. |
30+
| Ambiguous HTML id attribute (`js/duplicate-html-id`) | Results no longer shown | Precision tag reduced to "low". The query is no longer run by default. |
3031

3132

3233
## Changes to libraries
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Improvements to Python analysis
2+
3+
The following changes in version 1.26 affect Python analysis in all applications.
4+
5+
## General improvements
6+
7+
8+
## New queries
9+
10+
| **Query** | **Tags** | **Purpose** |
11+
|-----------------------------|-----------|--------------------------------------------------------------------|
12+
13+
14+
## Changes to existing queries
15+
16+
| **Query** | **Expected impact** | **Change** |
17+
|----------------------------|------------------------|------------------------------------------------------------------|
18+
19+
20+
## Changes to libraries
21+
22+
* Added taint tracking support for string formatting through f-strings.

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,10 @@
325325
"csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingImports.qll",
326326
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingImports.qll"
327327
],
328+
"Inline Test Expectations": [
329+
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
330+
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
331+
],
328332
"XML": [
329333
"cpp/ql/src/semmle/code/cpp/XML.qll",
330334
"csharp/ql/src/semmle/code/csharp/XML.qll",
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
void test(char *arg1, int *arg2) {
2+
if (arg1[0] == 'A') {
3+
if (arg2 != NULL) { //maybe redundant
4+
*arg2 = 42;
5+
}
6+
}
7+
if (arg1[1] == 'B')
8+
{
9+
*arg2 = 54; //dereferenced without checking first
10+
}
11+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
6+
<overview>
7+
<p>This rule finds comparisons of a function parameter to null that occur when in another path the parameter is dereferenced without a guard check. It's
8+
likely either the check is not required and can be removed, or it should be added before the dereference
9+
so that a null pointer dereference does not occur.</p>
10+
</overview>
11+
12+
<recommendation>
13+
<p>A check should be added to before the dereference, in a way that prevents a null pointer value from
14+
being dereferenced. If it's clear that the pointer cannot be null, consider removing the check instead.</p>
15+
</recommendation>
16+
17+
<example>
18+
<sample src="RedundantNullCheckParam.cpp" />
19+
</example>
20+
21+
<references>
22+
<li>
23+
<a href="https://www.owasp.org/index.php/Null_Dereference">
24+
Null Dereference
25+
</a>
26+
</li>
27+
</references>
28+
29+
</qhelp>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/**
2+
* @name Redundant null check or missing null check of parameter
3+
* @description Checking a parameter for nullness in one path,
4+
* and not in another is likely to be a sign that either
5+
* the check can be removed, or added in the other case.
6+
* @kind problem
7+
* @id cpp/redundant-null-check-param
8+
* @problem.severity recommendation
9+
* @tags reliability
10+
* security
11+
* external/cwe/cwe-476
12+
*/
13+
14+
import cpp
15+
16+
predicate blockDominates(Block check, Block access) {
17+
check.getLocation().getStartLine() <= access.getLocation().getStartLine() and
18+
check.getLocation().getEndLine() >= access.getLocation().getEndLine()
19+
}
20+
21+
predicate isCheckedInstruction(VariableAccess unchecked, VariableAccess checked) {
22+
checked = any(VariableAccess va | va.getTarget() = unchecked.getTarget()) and
23+
//Simple test if the first access in this code path is dereferenced
24+
not dereferenced(checked) and
25+
blockDominates(checked.getEnclosingBlock(), unchecked.getEnclosingBlock())
26+
}
27+
28+
predicate candidateResultUnchecked(VariableAccess unchecked) {
29+
not isCheckedInstruction(unchecked, _)
30+
}
31+
32+
predicate candidateResultChecked(VariableAccess check, EqualityOperation eqop) {
33+
//not dereferenced to check against pointer, not its pointed value
34+
not dereferenced(check) and
35+
//assert macros are not taken into account
36+
not check.isInMacroExpansion() and
37+
// is part of a comparison against some constant NULL
38+
eqop.getAnOperand() = check and
39+
eqop.getAnOperand() instanceof NullValue
40+
}
41+
42+
from VariableAccess unchecked, VariableAccess check, EqualityOperation eqop, Parameter param
43+
where
44+
// a dereference
45+
dereferenced(unchecked) and
46+
// for a function parameter
47+
unchecked.getTarget() = param and
48+
// this function parameter is not overwritten
49+
count(param.getAnAssignment()) = 0 and
50+
check.getTarget() = param and
51+
// which is once checked
52+
candidateResultChecked(check, eqop) and
53+
// and which has not been checked before in this code path
54+
candidateResultUnchecked(unchecked)
55+
select check, "This null check is redundant or there is a missing null check before $@ ", unchecked,
56+
"where dereferencing happens"

cpp/ql/src/semmle/code/cpp/models/implementations/StdContainer.qll

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class StdSequenceContainerConstructor extends Constructor, TaintFunction {
2323
*/
2424
int getAValueTypeParameterIndex() {
2525
getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
26-
getDeclaringType().getTemplateArgument(0) // i.e. the `T` of this `std::vector<T>`
26+
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
2727
}
2828

2929
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -33,6 +33,24 @@ class StdSequenceContainerConstructor extends Constructor, TaintFunction {
3333
}
3434
}
3535

36+
/**
37+
* The standard container function `data`.
38+
*/
39+
class StdSequenceContainerData extends TaintFunction {
40+
StdSequenceContainerData() { this.hasQualifiedName("std", ["array", "vector"], "data") }
41+
42+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
43+
// flow from container itself (qualifier) to return value
44+
input.isQualifierObject() and
45+
output.isReturnValueDeref()
46+
or
47+
// reverse flow from returned reference to the qualifier (for writes to
48+
// `data`)
49+
input.isReturnValueDeref() and
50+
output.isQualifierObject()
51+
}
52+
}
53+
3654
/**
3755
* The standard container functions `push_back` and `push_front`.
3856
*/
@@ -70,6 +88,30 @@ class StdSequenceContainerFrontBack extends TaintFunction {
7088
}
7189
}
7290

91+
/**
92+
* The standard container function `assign`.
93+
*/
94+
class StdSequenceContainerAssign extends TaintFunction {
95+
StdSequenceContainerAssign() {
96+
this.hasQualifiedName("std", ["vector", "deque", "list", "forward_list"], "assign")
97+
}
98+
99+
/**
100+
* Gets the index of a parameter to this function that is a reference to the
101+
* value type of the container.
102+
*/
103+
int getAValueTypeParameterIndex() {
104+
getParameter(result).getUnspecifiedType().(ReferenceType).getBaseType() =
105+
getDeclaringType().getTemplateArgument(0).(Type).getUnspecifiedType() // i.e. the `T` of this `std::vector<T>`
106+
}
107+
108+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
109+
// flow from parameter to string itself (qualifier) and return value
110+
input.isParameterDeref(getAValueTypeParameterIndex()) and
111+
output.isQualifierObject()
112+
}
113+
}
114+
73115
/**
74116
* The standard container `swap` functions.
75117
*/

0 commit comments

Comments
 (0)