Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b896899

Browse files
committed
Merge master into next.
master as of dc3c5a6 Version numbers resolved in favour of `next`. C++ expected output file updated to accept test output.
2 parents bfb5731 + dc3c5a6 commit b896899

128 files changed

Lines changed: 2599 additions & 1071 deletions

File tree

Some content is hidden

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

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/csharp/ @Semmle/cs
22
/java/ @Semmle/java
33
/javascript/ @Semmle/js
4+
/cpp/ @Semmle/cpp-analysis

change-notes/1.19/analysis-cpp.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515

1616
| **Query** | **Expected impact** | **Change** |
1717
|----------------------------|------------------------|------------------------------------------------------------------|
18+
| Empty branch of conditional | Fewer false positive results | The query now recognizes commented blocks more reliably. |
1819
| Resource not released in destructor | Fewer false positive results | Placement new is now excluded from the query. Also fixed an issue where false positives could occur if the destructor body was not in the snapshot. |
1920
| Missing return statement (`cpp/missing-return`) | Visible by default | The precision of this query has been increased from 'medium' to 'high', which makes it visible by default in LGTM. It was 'medium' in release 1.17 and 1.18 because it had false positives due to an extractor bug that was fixed in 1.18. |
2021
| Missing return statement | Fewer false positive results | The query is now produces correct results when a function returns a template-dependent type. |
2122
| Call to memory access function may overflow buffer | More correct results | Array indexing with a negative index is now detected by this query. |
23+
| Suspicious call to memset | Fewer false positive results | Types involving decltype are now correctly compared. |
2224
| Suspicious add with sizeof | Fewer false positive results | Arithmetic with void pointers (where allowed) is now excluded from this query. |
2325
| Wrong type of arguments to formatting function | Fewer false positive results | False positive results involving typedefs have been removed. Expected argument types are determined more accurately, especially for wide string and pointer types. Custom (non-standard) formatting functions are also identified more accurately. |
2426

2527
## Changes to QL libraries
2628

2729
* Added a hash consing library for structural comparison of expressions.
30+
* `getBufferSize` now detects variable size structs more reliably.

change-notes/1.19/analysis-csharp.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
## General improvements
44

5-
* The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
6-
5+
* Control flow graph improvements:
6+
* The control flow graph construction now takes simple Boolean conditions on local scope variables into account. For example, in `if (b) x = 0; if (b) x = 1;`, the control flow graph will reflect that taking the `true` (resp. `false`) branch in the first condition implies taking the same branch in the second condition. In effect, the first assignment to `x` will now be identified as being dead.
7+
* Code that is only reachable from a constant failing assertion, such as `Debug.Assert(false)`, is considered to be unreachable.
8+
79
## New queries
810

911
| **Query** | **Tags** | **Purpose** |
@@ -13,7 +15,7 @@
1315
## Changes to existing queries
1416

1517
| Inconsistent lock sequence (`cs/inconsistent-lock-sequence`) | More results | This query now finds inconsistent lock sequences globally across calls. |
16-
18+
| Local scope variable shadows member (`cs/local-shadows-member`) | Fewer results | Results have been removed where a constructor parameter shadows a member, because the parameter is probably used to initialize the member. |
1719
| *@name of query (Query ID)*| *Impact on results* | *How/why the query has changed* |
1820

1921

change-notes/1.19/analysis-java.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,23 @@
66

77
| **Query** | **Tags** | **Purpose** |
88
|-----------------------------|-----------|--------------------------------------------------------------------|
9+
| Missing catch of NumberFormatException (`java/uncaught-number-format-exception`) | reliability, external/cwe/cwe-248 | Finds calls to `Integer.parseInt` and similar string-to-number conversions that might raise a `NumberFormatException` without a corresponding `catch`-clause. |
910

1011
## Changes to existing queries
1112

1213
| **Query** | **Expected impact** | **Change** |
1314
|----------------------------|------------------------|------------------------------------------------------------------|
1415
| Array index out of bounds (`java/index-out-of-bounds`) | Fewer false positive results | False positives involving arrays with a length evenly divisible by 3 or some greater number and an index being increased with a similar stride length are no longer reported. |
16+
| Query built from user-controlled sources (`java/sql-injection`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. |
17+
| Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. |
1518
| Unreachable catch clause (`java/unreachable-catch-clause`) | Fewer false positive results | This rule now accounts for calls to generic methods that throw generic exceptions. |
1619
| Useless comparison test (`java/constant-comparison`) | Fewer false positive results | Constant comparisons guarding `java.util.ConcurrentModificationException` are no longer reported, as they are intended to always be false in the absence of API misuse. |
1720

1821
## Changes to QL libraries
1922

23+
* The default set of taint sources in the `FlowSources` library is extended to
24+
cover parameters annotated with Spring framework annotations indicating
25+
remote user input from servlets. This affects all security queries, which
26+
will yield additional results on projects using the Spring Web framework.
2027
* The `ParityAnalysis` library is replaced with the more general `ModulusAnalysis` library, which improves the range analysis.
2128

change-notes/1.19/analysis-javascript.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
| Unused variable, import, function or class | Fewer results | This rule now flags import statements with multiple unused imports once. |
3939
| User-controlled bypass of security check | Fewer results | This rule no longer flags conditions that guard early returns. The precision of this rule has been revised to "medium". Results are no longer shown on LGTM by default. |
4040
| Whitespace contradicts operator precedence | Fewer false-positive results | This rule no longer flags operators with asymmetric whitespace. |
41+
| Unused import | Fewer false-positive results | This rule no longer flags imports used by the `transform-react-jsx` Babel plugin. |
4142

4243
## Changes to QL libraries
4344

cpp/ql/src/Best Practices/Likely Errors/EmptyBlock.ql

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ class AffectedFile extends File {
2929
}
3030
}
3131

32+
/**
33+
* A block, or an element we might find textually within a block that is
34+
* not a child of it in the AST.
35+
*/
3236
class BlockOrNonChild extends Element {
3337
BlockOrNonChild() {
3438
( this instanceof Block
@@ -68,6 +72,9 @@ class BlockOrNonChild extends Element {
6872
}
6973
}
7074

75+
/**
76+
* A block that contains a non-child element.
77+
*/
7178
predicate emptyBlockContainsNonchild(Block b) {
7279
emptyBlock(_, b) and
7380
exists(BlockOrNonChild c, AffectedFile file |
@@ -78,7 +85,27 @@ predicate emptyBlockContainsNonchild(Block b) {
7885
)
7986
}
8087

88+
/**
89+
* A block that is entirely on one line, which also contains a comment. Chances
90+
* are the comment is intended to refer to the block.
91+
*/
92+
predicate lineComment(Block b) {
93+
emptyBlock(_, b) and
94+
exists(Location bLocation, File f, int line |
95+
bLocation = b.getLocation() and
96+
f = bLocation.getFile() and
97+
line = bLocation.getStartLine() and
98+
line = bLocation.getEndLine() and
99+
exists(Comment c, Location cLocation |
100+
cLocation = c.getLocation() and
101+
cLocation.getFile() = f and
102+
cLocation.getStartLine() = line
103+
)
104+
)
105+
}
106+
81107
from ControlStructure s, Block eb
82108
where emptyBlock(s, eb)
83109
and not emptyBlockContainsNonchild(eb)
110+
and not lineComment(eb)
84111
select eb, "Empty block without comment"

cpp/ql/src/Security/CWE/CWE-253/HResultBooleanConversion.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ where exists
4848
ctls.getControllingExpr() = e1
4949
and e1.getType().(TypedefType).hasName("HRESULT")
5050
and not isHresultBooleanConverted(e1)
51+
and not ctls instanceof SwitchStmt // not controlled by a boolean condition
5152
and msg = "Direct usage of a type " + e1.getType().toString() + " as a conditional expression"
5253
)
5354
or

cpp/ql/src/jsf/4.10 Classes/AV Rule 82.ql

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ predicate pointerThis(Expr e) {
2525
// `f(...)`
2626
// (includes `this = ...`, where `=` is overloaded so a `FunctionCall`)
2727
exists(FunctionCall fc | fc = e and callOnThis(fc) |
28-
exists(fc.getTarget().getBlock()) implies returnsPointerThis(fc.getTarget())
28+
returnsPointerThis(fc.getTarget())
2929
) or
3030

3131
// `this = ...` (where `=` is not overloaded, so an `AssignExpr`)
@@ -38,22 +38,33 @@ predicate dereferenceThis(Expr e) {
3838
// `f(...)`
3939
// (includes `*this = ...`, where `=` is overloaded so a `FunctionCall`)
4040
exists(FunctionCall fc | fc = e and callOnThis(fc) |
41-
exists(fc.getTarget().getBlock()) implies returnsDereferenceThis(fc.getTarget())
41+
returnsDereferenceThis(fc.getTarget())
4242
) or
4343

4444
// `*this = ...` (where `=` is not overloaded, so an `AssignExpr`)
4545
dereferenceThis(e.(AssignExpr).getLValue())
4646
}
4747

48+
/**
49+
* Holds if all `return` statements in `f` return `this`, possibly indirectly.
50+
* This includes functions whose body is not in the database.
51+
*/
4852
predicate returnsPointerThis(Function f) {
49-
forex(ReturnStmt s | s.getEnclosingFunction() = f |
53+
f.getType().getUnspecifiedType() instanceof PointerType and
54+
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
5055
// `return this`
5156
pointerThis(s.getExpr())
5257
)
5358
}
5459

60+
/**
61+
* Holds if all `return` statements in `f` return a reference to `*this`,
62+
* possibly indirectly. This includes functions whose body is not in the
63+
* database.
64+
*/
5565
predicate returnsDereferenceThis(Function f) {
56-
forex(ReturnStmt s | s.getEnclosingFunction() = f |
66+
f.getType().getUnspecifiedType() instanceof ReferenceType and
67+
forall(ReturnStmt s | s.getEnclosingFunction() = f and reachable(s) |
5768
// `return *this`
5869
dereferenceThis(s.getExpr())
5970
)
@@ -72,7 +83,6 @@ predicate assignOperatorWithWrongType(Operator op, string msg) {
7283
predicate assignOperatorWithWrongResult(Operator op, string msg) {
7384
op.hasName("operator=")
7485
and not returnsDereferenceThis(op)
75-
and exists(op.getBlock())
7686
and not op.getType() instanceof VoidType
7787
and not assignOperatorWithWrongType(op, _)
7888
and msg = "Assignment operator in class " + op.getDeclaringType().getName() + " does not return a reference to *this."

cpp/ql/src/semmle/code/cpp/commons/Buffer.qll

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,6 @@
11
import cpp
22
import semmle.code.cpp.dataflow.DataFlow
33

4-
/**
5-
* Holds if `sizeof(s)` occurs as part of the parameter of a dynamic
6-
* memory allocation (`malloc`, `realloc`, etc.), except if `sizeof(s)`
7-
* only ever occurs as the immediate parameter to allocations.
8-
*
9-
* For example, holds for `s` if it occurs as
10-
* ```
11-
* malloc(sizeof(s) + 100 * sizeof(char))
12-
* ```
13-
* but not if it only ever occurs as
14-
* ```
15-
* malloc(sizeof(s))
16-
* ```
17-
*/
18-
private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
19-
exists(SizeofTypeOperator sof |
20-
sof.getTypeOperand().getUnspecifiedType() = s |
21-
// Check all ancestor nodes except the immediate parent for
22-
// allocations.
23-
isStdLibAllocationExpr(sof.getParent().(Expr).getParent+())
24-
)
25-
}
26-
274
/**
285
* Holds if `v` is a member variable of `c` that looks like it might be variable sized in practice. For
296
* example:
@@ -34,15 +11,40 @@ private predicate isDynamicallyAllocatedWithDifferentSize(Class s) {
3411
* };
3512
* ```
3613
* This requires that `v` is an array of size 0 or 1, and `v` is the last member of `c`. In addition,
37-
* there must be at least one instance where a `c` pointer is allocated with additional space.
14+
* there must be at least one instance where a `c` pointer is allocated with additional space. For
15+
* example, holds for `c` if it occurs as
16+
* ```
17+
* malloc(sizeof(c) + 100 * sizeof(char))
18+
* ```
19+
* but not if it only ever occurs as
20+
* ```
21+
* malloc(sizeof(c))
22+
* ```
3823
*/
3924
predicate memberMayBeVarSize(Class c, MemberVariable v) {
4025
exists(int i |
26+
// `v` is the last field in `c`
4127
i = max(int j | c.getCanonicalMember(j) instanceof Field | j) and
4228
v = c.getCanonicalMember(i) and
43-
v.getType().getUnspecifiedType().(ArrayType).getSize() <= 1
44-
) and
45-
isDynamicallyAllocatedWithDifferentSize(c)
29+
30+
// v is an array of size at most 1
31+
v.getType().getUnspecifiedType().(ArrayType).getArraySize() <= 1
32+
) and (
33+
exists(SizeofOperator so |
34+
// `sizeof(c)` is taken
35+
so.(SizeofTypeOperator).getTypeOperand().getUnspecifiedType() = c or
36+
so.(SizeofExprOperator).getExprOperand().getType().getUnspecifiedType() = c |
37+
38+
// arithmetic is performed on the result
39+
so.getParent*() instanceof AddExpr
40+
) or exists(AddressOfExpr aoe |
41+
// `&(c.v)` is taken
42+
aoe.getAddressable() = v
43+
) or exists(BuiltInOperationOffsetOf oo |
44+
// `offsetof(c, v)` using a builtin
45+
oo.getAChild().(VariableAccess).getTarget() = v
46+
)
47+
)
4648
}
4749

4850
/**
@@ -81,19 +83,21 @@ int getBufferSize(Expr bufferExpr, Element why) {
8183
// buffer is a fixed size dynamic allocation
8284
isFixedSizeAllocationExpr(bufferExpr, result) and
8385
why = bufferExpr
84-
) or (
86+
) or exists(DataFlow::ExprNode bufferExprNode |
8587
// dataflow (all sources must be the same size)
88+
bufferExprNode = DataFlow::exprNode(bufferExpr) and
89+
8690
result = min(Expr def |
87-
DataFlow::localFlowStep(DataFlow::exprNode(def), DataFlow::exprNode(bufferExpr)) |
91+
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) |
8892
getBufferSize(def, _)
8993
) and result = max(Expr def |
90-
DataFlow::localFlowStep(DataFlow::exprNode(def), DataFlow::exprNode(bufferExpr)) |
94+
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) |
9195
getBufferSize(def, _)
9296
) and
9397

9498
// find reason
9599
exists(Expr def |
96-
DataFlow::localFlowStep(DataFlow::exprNode(def), DataFlow::exprNode(bufferExpr)) |
100+
DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) |
97101
why = def or
98102
exists(getBufferSize(def, why))
99103
)

cpp/ql/src/semmle/code/cpp/controlflow/SSAUtils.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,17 @@ cached library class SSAHelper extends int {
124124
* Modern Compiler Implementation by Andrew Appel.
125125
*/
126126
private predicate frontier_phi_node(LocalScopeVariable v, BasicBlock b) {
127-
exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn(v, _, x, _))
127+
exists(BasicBlock x | dominanceFrontier(x, b) and ssa_defn_rec(v, x))
128128
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
129129
and live_at_start_of_bb(v, b)
130130
}
131131

132+
private predicate ssa_defn_rec(LocalScopeVariable v, BasicBlock b) {
133+
phi_node(v, b)
134+
or
135+
variableUpdate(v, _, b, _)
136+
}
137+
132138
/**
133139
* Holds if `v` is defined, for the purpose of SSA, at `node`, which is at
134140
* position `index` in block `b`. This includes definitions from phi nodes.

0 commit comments

Comments
 (0)