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

Skip to content

Commit 47f87c2

Browse files
author
Robert Marsh
committed
Merge branch 'master' into rdmarsh/cpp/ir-constructor-side-effects
2 parents 64b34ad + 6c9f926 commit 47f87c2

127 files changed

Lines changed: 1910 additions & 1002 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.

change-notes/1.23/analysis-cpp.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
99
| **Query** | **Tags** | **Purpose** |
1010
|-----------------------------|-----------|--------------------------------------------------------------------|
1111
| Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). |
12+
| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. |
1213

1314
## Changes to existing queries
1415

@@ -23,6 +24,8 @@ The following changes in version 1.23 affect C/C++ analysis in all applications.
2324
| Too many arguments to formatting function (`cpp/too-many-format-arguments`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
2425
| Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. |
2526
| Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. |
27+
| Non-constant format string (`cpp/non-constant-format`) | Fewer false positive results | Fixed false positives resulting from mistmatching declarations of a formatting function. |
28+
| Wrong type of arguments to formatting function (`cpp/wrong-type-format-argument`) | More correct results and fewer false positive results | This query now understands explicitly specified argument numbers in format strings, such as the `1$` in `%1$s`. |
2629

2730
## Changes to libraries
2831

cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ where
1919
pointlessSelfComparison(cmp) and
2020
not nanTest(cmp) and
2121
not overflowTest(cmp) and
22+
not cmp.isFromTemplateInstantiation(_) and
2223
not exists(MacroInvocation mi |
2324
// cmp is in mi
2425
mi.getAnExpandedElement() = cmp and
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool foo(int n1, unsigned short delta) {
2+
return n1 + delta < n1; // BAD
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
bool bar(unsigned short n1, unsigned short delta) {
2+
// NB: Comparison is always false
3+
return n1 + delta < n1; // GOOD (but misleading)
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include <limits.h>
2+
bool foo(int n1, unsigned short delta) {
3+
return n1 > INT_MAX - delta; // GOOD
4+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bool bar(unsigned short n1, unsigned short delta) {
2+
return (unsigned short)(n1 + delta) < n1; // GOOD
3+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
When checking for integer overflow, you may often write tests like
8+
<code>a + b &lt; a</code>. This works fine if <code>a</code> or
9+
<code>b</code> are unsigned integers, since any overflow in the addition
10+
will cause the value to simply "wrap around." However, using
11+
<i>signed</i> integers is problematic because signed overflow has undefined
12+
behavior according to the C and C++ standards. If the addition overflows
13+
and has an undefined result, the comparison will likewise be undefined;
14+
it may produce an unintended result, or may be deleted entirely by an
15+
optimizing compiler.
16+
</p>
17+
</overview>
18+
<recommendation>
19+
<p>
20+
Solutions to this problem can be thought of as falling into one of two
21+
categories: (1) rewrite the signed expression so that overflow cannot occur
22+
but the signedness remains, or (2) rewrite (or cast) the signed expression
23+
into unsigned form.
24+
</p>
25+
26+
<p>
27+
Below we list examples of expressions where signed overflow may
28+
occur, along with proposed solutions. The list should not be
29+
considered exhaustive.
30+
</p>
31+
32+
<p>
33+
Given <code>unsigned short i, delta</code> and <code>i + delta &lt; i</code>,
34+
it is possible to rewrite it as <code>(unsigned short)(i + delta)&nbsp;&lt;&nbsp;i</code>.
35+
Note that <code>i + delta</code>does not actually overflow, due to <code>int</code> promotion
36+
</p>
37+
38+
<p>
39+
Given <code>unsigned short i, delta</code> and <code>i + delta &lt; i</code>,
40+
it is also possible to rewrite it as <code>USHORT_MAX - delta</code>. It must be true
41+
that <code>delta &gt; 0</code> and the <code>limits.h</code> or <code>climits</code>
42+
header has been included.
43+
</p>
44+
45+
<p>
46+
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
47+
it is possible to rewrite it as <code>INT_MAX - delta</code>. It must be true
48+
that <code>delta &gt; 0</code> and the <code>limits.h</code> or <code>climits</code>
49+
header has been included.
50+
</p>
51+
52+
<p>
53+
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
54+
it is also possible to rewrite it as <code>(unsigned)i + delta &lt; i</code>.
55+
Note that program semantics are affected by this change.
56+
</p>
57+
58+
<p>
59+
Given <code>int i, delta</code> and <code>i + delta &lt; i</code>,
60+
it is also possible to rewrite it as <code>unsigned int i, delta</code> and
61+
<code>i + delta &lt; i</code>. Note that program semantics are
62+
affected by this change.
63+
</p>
64+
</recommendation>
65+
66+
<example>
67+
<p>
68+
In the following example, even though <code>delta</code> has been declared
69+
<code>unsigned short</code>, C/C++ type promotion rules require that its
70+
type is promoted to the larger type used in the addition and comparison,
71+
namely a <code>signed int</code>. Addition is performed on
72+
signed integers, and may have undefined behavior if an overflow occurs.
73+
As a result, the entire (comparison) expression may also have an undefined
74+
result.
75+
</p>
76+
<sample src="SignedOverflowCheck-bad1.cpp" />
77+
<p>
78+
The following example builds upon the previous one. Instead of
79+
performing an addition (which could overflow), we have re-framed the
80+
solution so that a subtraction is used instead. Since <code>delta</code>
81+
is promoted to a <code>signed int</code> and <code>INT_MAX</code> denotes
82+
the largest possible positive value for an <code>signed int</code>,
83+
the expression <code>INT_MAX - delta</code> can never be less than zero
84+
or more than <code>INT_MAX</code>. Hence, any overflow and underflow
85+
are avoided.
86+
</p>
87+
<sample src="SignedOverflowCheck-good1.cpp" />
88+
<p>
89+
In the following example, even though both <code>n</code> and <code>delta</code>
90+
have been declared <code>unsigned short</code>, both are promoted to
91+
<code>signed int</code> prior to addition. Because we started out with the
92+
narrower <code>short</code> type, the addition is guaranteed not to overflow
93+
and is therefore defined. But the fact that <code>n1 + delta</code> never
94+
overflows means that the condition <code>n1 + delta &lt; n1</code> will never
95+
hold true, which likely is not what the programmer intended. (see also the
96+
<code>cpp/bad-addition-overflow-check</code> query).
97+
</p>
98+
<sample src="SignedOverflowCheck-bad2.cpp" />
99+
<p>
100+
The next example provides a solution to the previous one. Even though
101+
<code>i + delta</code> does not overflow, casting it to an
102+
<code>unsigned short</code> truncates the addition modulo 2^16,
103+
so that <code>unsigned short</code> "wrap around" may now be observed.
104+
Furthermore, since the left-hand side is now of type <code>unsigned short</code>,
105+
the right-hand side does not need to be promoted to a <code>signed int</code>.
106+
</p>
107+
108+
<sample src="SignedOverflowCheck-good2.cpp" />
109+
</example>
110+
<references>
111+
<li><a href="http://c-faq.com/expr/preservingrules.html">comp.lang.c FAQ list · Question 3.19 (Preserving rules)</a></li>
112+
<li><a href="https://wiki.sei.cmu.edu/confluence/display/c/INT31-C.+Ensure+that+integer+conversions+do+not+result+in+lost+or+misinterpreted+data">INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data</a></li>
113+
<li>W. Dietz, P. Li, J. Regehr, V. Adve. <a href="https://www.cs.utah.edu/~regehr/papers/overflow12.pdf">Understanding Integer Overflow in C/C++</a></li>
114+
</references>
115+
</qhelp>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* @name Undefined result of signed test for overflow
3+
* @description Testing for overflow by adding a value to a variable
4+
* to see if it "wraps around" works only for
5+
* unsigned integer values.
6+
* @kind problem
7+
* @problem.severity warning
8+
* @precision high
9+
* @id cpp/signed-overflow-check
10+
* @tags reliability
11+
* security
12+
*/
13+
14+
import cpp
15+
private import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
17+
18+
from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2
19+
where
20+
ro.getAnOperand() = add and
21+
add.getAnOperand() = expr1 and
22+
ro.getAnOperand() = expr2 and
23+
globalValueNumber(expr1) = globalValueNumber(expr2) and
24+
add.getUnspecifiedType().(IntegralType).isSigned() and
25+
not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and
26+
exprMightOverflowPositively(add) and
27+
exists(Compilation c | c.getAFileCompiled() = ro.getFile() |
28+
not c.getAnArgument() = "-fwrapv" and
29+
not c.getAnArgument() = "-fno-strict-overflow"
30+
)
31+
select ro, "Testing for signed overflow may produce undefined results."

cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql

Lines changed: 27 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,76 +13,52 @@ import semmle.code.cpp.security.boostorg.asio.protocols
1313
class ExistsAnyFlowConfig extends DataFlow::Configuration {
1414
ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" }
1515

16-
override predicate isSource(DataFlow::Node source) { any() }
16+
override predicate isSource(DataFlow::Node source) {
17+
exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr())
18+
}
1719

18-
override predicate isSink(DataFlow::Node sink) { any() }
20+
override predicate isSink(DataFlow::Node sink) {
21+
exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions |
22+
f.getACallToThisFunction() = fcSetOptions and
23+
fcSetOptions.getQualifier() = sink.asExpr()
24+
)
25+
}
1926
}
2027

2128
bindingset[flag]
2229
predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) {
23-
exists(
24-
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
25-
Expr optionsSink
26-
|
27-
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
28-
exists(VariableAccess contextSetOptions |
29-
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
30-
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
31-
contextSetOptions = fcSetOptions.getQualifier() and
32-
forall(
33-
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
34-
Expr optionArgumentSource
35-
|
36-
optionArgument = fcSetOptions.getArgument(0) and
37-
optionArgConfig
38-
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
39-
|
40-
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
41-
)
30+
exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions |
31+
anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
32+
exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions |
33+
contextSetOptions = fcSetOptions.getQualifier() and
34+
forall(
35+
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
36+
Expr optionArgumentSource
37+
|
38+
optionArgument = fcSetOptions.getArgument(0) and
39+
optionArgConfig
40+
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
41+
|
42+
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
4243
)
4344
)
4445
)
4546
}
4647

4748
bindingset[flag]
4849
predicate isOptionNotSet(ConstructorCall cc, int flag) {
49-
not exists(
50-
BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig,
51-
Expr optionsSink
52-
|
53-
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
54-
exists(VariableAccess contextSetOptions |
55-
testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and
56-
exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f |
57-
f.getACallToThisFunction() = fcSetOptions
58-
|
59-
contextSetOptions = fcSetOptions.getQualifier() and
60-
forall(
61-
Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig,
62-
Expr optionArgumentSource
63-
|
64-
optionArgument = fcSetOptions.getArgument(0) and
65-
optionArgConfig
66-
.hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument))
67-
|
68-
optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag
69-
)
70-
)
71-
)
72-
)
50+
not exists(FunctionCall fcSetOptions | isOptionSet(cc, flag, fcSetOptions))
7351
}
7452

7553
from
76-
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor,
77-
BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink,
78-
ConstructorCall cc, Expr e, string msg
54+
BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource,
55+
Expr protocolSink, ConstructorCall cc, Expr e, string msg
7956
where
8057
configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and
8158
cc.getArgument(0) = protocolSink and
8259
(
8360
BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
84-
not exists(Expr optionsSink |
85-
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
61+
not (
8662
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and
8763
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
8864
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
@@ -91,8 +67,7 @@ where
9167
or
9268
BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and
9369
not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and
94-
not exists(Expr optionsSink |
95-
config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and
70+
not (
9671
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and
9772
isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and
9873
isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2())

cpp/ql/src/Microsoft/SAL.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ class SALParameter extends Parameter {
126126
}
127127

128128
/**
129-
* A SAL element, i.e. a SAL annotation or a declaration entry
129+
* A SAL element, that is, a SAL annotation or a declaration entry
130130
* that may have SAL annotations.
131131
*/
132132
library class SALElement extends Element {

0 commit comments

Comments
 (0)