Skip to content

Commit ba0429c

Browse files
committed
Merge branch 'master' into ir-flow-fields
2 parents 8c03423 + e974006 commit ba0429c

Some content is hidden

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

44 files changed

+1776
-11668
lines changed

change-notes/1.24/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ The following changes in version 1.24 affect C/C++ analysis in all applications.
2525
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | | This query is no longer run on LGTM. |
2626
| No space for zero terminator (`cpp/no-space-for-terminator`) | Fewer false positive results | This query has been modified to be more conservative when identifying which pointers point to null-terminated strings. This approach produces fewer, more accurate results. |
2727
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | Cases where the tainted allocation size is range checked are now more reliably excluded. |
28+
| Overflow in uncontrolled allocation size (`cpp/uncontrolled-allocation-size`) | Fewer false positive results | The query now produces fewer, more accurate results. |
2829
| Overloaded assignment does not return 'this' (`cpp/assignment-does-not-return-this`) | Fewer false positive results | This query no longer reports incorrect results in template classes. |
2930
| Unsafe array for days of the year (`cpp/leap-year/unsafe-array-for-days-of-the-year`) | | This query is no longer run on LGTM. |
3031
| Unsigned comparison to zero (`cpp/unsigned-comparison-zero`) | More correct results | This query now also looks for comparisons of the form `0 <= x`. |

cpp/ql/src/Critical/Negativity.qll

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
import cpp
22

3+
/**
4+
* Holds if `val` is an access to the variable `v`, or if `val`
5+
* is an assignment with an access to `v` on the left-hand side.
6+
*/
37
predicate valueOfVar(Variable v, Expr val) {
48
val = v.getAnAccess() or
59
val.(AssignExpr).getLValue() = v.getAnAccess()
610
}
711

12+
/**
13+
* Holds if either:
14+
* - `cond` is an (in)equality expression that compares the variable `v` to the value `-1`, or
15+
* - `cond` is a relational expression that compares the variable `v` to a constant.
16+
*/
817
predicate boundsCheckExpr(Variable v, Expr cond) {
918
exists(EQExpr eq |
1019
cond = eq and
@@ -43,6 +52,18 @@ predicate boundsCheckExpr(Variable v, Expr cond) {
4352
)
4453
}
4554

55+
/**
56+
* Holds if `node` is an expression in a conditional statement and `succ` is an
57+
* immediate successor of `node` that may be reached after evaluating `node`.
58+
* For example, given
59+
* ```
60+
* if (a < 10 && b) func1();
61+
* else func2();
62+
* ```
63+
* this predicate holds when either:
64+
* - `node` is `a < 10` and `succ` is `func2()` or `b`, or
65+
* - `node` is `b` and `succ` is `func1()` or `func2()`
66+
*/
4667
predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) {
4768
if node.isCondition()
4869
then succ = node.getATrueSuccessor() or succ = node.getAFalseSuccessor()
@@ -52,6 +73,12 @@ predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) {
5273
)
5374
}
5475

76+
/**
77+
* Holds if the current value of the variable `v` at control-flow
78+
* node `n` has been used either in:
79+
* - an (in)equality comparison with the value `-1`, or
80+
* - a relational comparison that compares `v` to a constant.
81+
*/
5582
predicate boundsChecked(Variable v, ControlFlowNode node) {
5683
exists(Expr test |
5784
boundsCheckExpr(v, test) and
@@ -63,6 +90,14 @@ predicate boundsChecked(Variable v, ControlFlowNode node) {
6390
)
6491
}
6592

93+
/**
94+
* Holds if `cond` compares `v` to some common error values. Specifically, this
95+
* predicate holds when:
96+
* - `cond` checks that `v` is equal to `-1`, or
97+
* - `cond` checks that `v` is less than `0`, or
98+
* - `cond` checks that `v` is less than or equal to `-1`, or
99+
* - `cond` checks that `v` is not some common success value (see `successCondition`).
100+
*/
66101
predicate errorCondition(Variable v, Expr cond) {
67102
exists(EQExpr eq |
68103
cond = eq and
@@ -88,6 +123,14 @@ predicate errorCondition(Variable v, Expr cond) {
88123
)
89124
}
90125

126+
/**
127+
* Holds if `cond` compares `v` to some common success values. Specifically, this
128+
* predicate holds when:
129+
* - `cond` checks that `v` is not equal to `-1`, or
130+
* - `cond` checks that `v` is greater than or equal than `0`, or
131+
* - `cond` checks that `v` is greater than `-1`, or
132+
* - `cond` checks that `v` is not some common error value (see `errorCondition`).
133+
*/
91134
predicate successCondition(Variable v, Expr cond) {
92135
exists(NEExpr ne |
93136
cond = ne and
@@ -113,6 +156,11 @@ predicate successCondition(Variable v, Expr cond) {
113156
)
114157
}
115158

159+
/**
160+
* Holds if there exists a comparison operation that checks whether `v`
161+
* represents some common *error* values, and `n` may be reached
162+
* immediately following the comparison operation.
163+
*/
116164
predicate errorSuccessor(Variable v, ControlFlowNode n) {
117165
exists(Expr cond |
118166
errorCondition(v, cond) and n = cond.getATrueSuccessor()
@@ -121,6 +169,11 @@ predicate errorSuccessor(Variable v, ControlFlowNode n) {
121169
)
122170
}
123171

172+
/**
173+
* Holds if there exists a comparison operation that checks whether `v`
174+
* represents some common *success* values, and `n` may be reached
175+
* immediately following the comparison operation.
176+
*/
124177
predicate successSuccessor(Variable v, ControlFlowNode n) {
125178
exists(Expr cond |
126179
successCondition(v, cond) and n = cond.getATrueSuccessor()
@@ -129,6 +182,10 @@ predicate successSuccessor(Variable v, ControlFlowNode n) {
129182
)
130183
}
131184

185+
/**
186+
* Holds if the current value of the variable `v` at control-flow node
187+
* `n` may have been checked against a common set of *error* values.
188+
*/
132189
predicate checkedError(Variable v, ControlFlowNode n) {
133190
errorSuccessor(v, n)
134191
or
@@ -139,6 +196,10 @@ predicate checkedError(Variable v, ControlFlowNode n) {
139196
)
140197
}
141198

199+
/**
200+
* Holds if the current value of the variable `v` at control-flow node
201+
* `n` may have been checked against a common set of *success* values.
202+
*/
142203
predicate checkedSuccess(Variable v, ControlFlowNode n) {
143204
successSuccessor(v, n)
144205
or

cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,31 @@ import cpp
1515
import semmle.code.cpp.security.TaintTracking
1616
import TaintedWithPath
1717

18-
predicate taintedChild(Expr e, Expr tainted) {
19-
(
20-
isAllocationExpr(e)
21-
or
22-
any(MulExpr me | me.getAChild() instanceof SizeofOperator) = e
23-
) and
24-
tainted = e.getAChild() and
18+
/**
19+
* Holds if `alloc` is an allocation, and `tainted` is a child of it that is a
20+
* taint sink.
21+
*/
22+
predicate allocSink(Expr alloc, Expr tainted) {
23+
isAllocationExpr(alloc) and
24+
tainted = alloc.getAChild() and
2525
tainted.getUnspecifiedType() instanceof IntegralType
2626
}
2727

2828
class TaintedAllocationSizeConfiguration extends TaintTrackingConfiguration {
29-
override predicate isSink(Element tainted) { taintedChild(_, tainted) }
29+
override predicate isSink(Element tainted) { allocSink(_, tainted) }
3030
}
3131

3232
predicate taintedAllocSize(
33-
Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause
33+
Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
3434
) {
3535
isUserInput(source, taintCause) and
3636
exists(Expr tainted |
37-
taintedChild(e, tainted) and
37+
allocSink(alloc, tainted) and
3838
taintedWithPath(source, tainted, sourceNode, sinkNode)
3939
)
4040
}
4141

42-
from Expr e, Expr source, PathNode sourceNode, PathNode sinkNode, string taintCause
43-
where taintedAllocSize(e, source, sourceNode, sinkNode, taintCause)
44-
select e, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow",
42+
from Expr source, Expr alloc, PathNode sourceNode, PathNode sinkNode, string taintCause
43+
where taintedAllocSize(source, alloc, sourceNode, sinkNode, taintCause)
44+
select alloc, sourceNode, sinkNode, "This allocation size is derived from $@ and might overflow",
4545
source, "user input (" + taintCause + ")"

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,15 @@ class Class extends UserType {
458458
exists(ClassDerivation d | d.getDerivedClass() = this and d = result)
459459
}
460460

461+
/**
462+
* Gets class derivation number `index` of this class/struct, for example the
463+
* `public B` is derivation 1 in the following code:
464+
* ```
465+
* class D : public A, public B, public C {
466+
* ...
467+
* };
468+
* ```
469+
*/
461470
ClassDerivation getDerivation(int index) {
462471
exists(ClassDerivation d | d.getDerivedClass() = this and d.getIndex() = index and d = result)
463472
}
@@ -900,6 +909,22 @@ class AbstractClass extends Class {
900909
class TemplateClass extends Class {
901910
TemplateClass() { usertypes(underlyingElement(this), _, 6) }
902911

912+
/**
913+
* Gets a class instantiated from this template.
914+
*
915+
* For example for `MyTemplateClass<T>` in the following code, the results are
916+
* `MyTemplateClass<int>` and `MyTemplateClass<long>`:
917+
* ```
918+
* template<class T>
919+
* class MyTemplateClass {
920+
* ...
921+
* };
922+
*
923+
* MyTemplateClass<int> instance;
924+
*
925+
* MyTemplateClass<long> instance;
926+
* ```
927+
*/
903928
Class getAnInstantiation() {
904929
result.isConstructedFrom(this) and
905930
exists(result.getATemplateArgument())

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,20 @@ class Comment extends Locatable, @comment {
1313

1414
override Location getLocation() { comments(underlyingElement(this), _, result) }
1515

16+
/**
17+
* Gets the text of this comment, including the opening `//` or `/*`, and the closing `*``/` if
18+
* present.
19+
*/
1620
string getContents() { comments(underlyingElement(this), result, _) }
1721

22+
/**
23+
* Gets the AST element this comment is associated with. For example, the comment in the
24+
* following code is associated with the declaration of `j`.
25+
* ```
26+
* int i;
27+
* int j; // Comment on j
28+
* ```
29+
*/
1830
Element getCommentedElement() {
1931
commentbinding(underlyingElement(this), unresolveElement(result))
2032
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class Compilation extends @compilation {
4040
/** Gets a file compiled during this invocation. */
4141
File getAFileCompiled() { result = getFileCompiled(_) }
4242

43+
/** Gets the `i`th file compiled during this invocation */
4344
File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) }
4445

4546
/**

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ class Diagnostic extends Locatable, @diagnostic {
1111
/** Gets the error code for this compiler message. */
1212
string getTag() { diagnostics(underlyingElement(this), _, result, _, _, _) }
1313

14+
/** Holds if `s` is the error code for this compiler message. */
1415
predicate hasTag(string s) { this.getTag() = s }
1516

1617
/**

0 commit comments

Comments
 (0)