Skip to content

Commit 0e4865c

Browse files
committed
Merge branch 'main' into javascript/ssrf
2 parents f3c0bf7 + 55256d4 commit 0e4865c

File tree

302 files changed

+17604
-2415
lines changed

Some content is hidden

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

302 files changed

+17604
-2415
lines changed

config/identical-files.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll",
77
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll",
88
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl6.qll",
9+
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll",
910
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
1011
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll",
1112
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll",
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm
2+
* Improvements made to the (`cpp/uncontrolled-arithmetic`) query, reducing the frequency of false positive results.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Virtual function specifiers are now accessible via the new predicates on `Function` (`.isDeclaredVirtual`, `.isOverride`, and `.isFinal`).

cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,19 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR
2929
override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
3030
node = declWithNoInit(v)
3131
or
32-
exists(Call c, VariableAccess va |
32+
exists(Call c, int bufferArg, int sizeArg |
3333
c = node and
34-
c.getTarget().hasName("readlink") and
35-
c.getArgument(1) = va and
36-
va.getTarget() = v
34+
(
35+
c.getTarget().hasName("readlink") and bufferArg = 1 and sizeArg = 2
36+
or
37+
c.getTarget().hasName("readlinkat") and bufferArg = 2 and sizeArg = 3
38+
) and
39+
c.getArgument(bufferArg).(VariableAccess).getTarget() = v and
40+
(
41+
// buffer size parameter likely matches the full buffer size
42+
c.getArgument(sizeArg) instanceof SizeofOperator or
43+
c.getArgument(sizeArg).getValue().toInt() = v.getType().getSize()
44+
)
3745
)
3846
}
3947

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,15 @@ private class RandS extends RandomFunction {
7474

7575
predicate missingGuard(VariableAccess va, string effect) {
7676
exists(Operation op | op.getAnOperand() = va |
77-
missingGuardAgainstUnderflow(op, va) and effect = "underflow"
77+
// underflow - random numbers are usually non-negative, so underflow is
78+
// only likely if the type is unsigned. Multiplication is also unlikely to
79+
// cause underflow of a non-negative number.
80+
missingGuardAgainstUnderflow(op, va) and
81+
effect = "underflow" and
82+
op.getUnspecifiedType().(IntegralType).isUnsigned() and
83+
not op instanceof MulExpr
7884
or
85+
// overflow
7986
missingGuardAgainstOverflow(op, va) and effect = "overflow"
8087
)
8188
}
@@ -108,6 +115,9 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration {
108115
op instanceof BitwiseAndExpr or
109116
op instanceof ComplementExpr
110117
).getAnOperand*()
118+
or
119+
// block unintended flow to pointers
120+
node.asExpr().getUnspecifiedType() instanceof PointerType
111121
}
112122
}
113123

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
...
2+
int i1;
3+
char c1;
4+
...
5+
if((c1<50)&&(c>10))
6+
switch(c1){
7+
case 300: // BAD: the code will not be executed
8+
...
9+
if((i1<5)&&(i1>0))
10+
switch(i1){ // BAD
11+
case 21: // BAD: the code will not be executed
12+
...
13+
switch(c1){
14+
...
15+
dafault: // BAD: maybe it will be right `default`
16+
...
17+
}
18+
19+
...
20+
switch(c1){
21+
i1=c1*2; // BAD: the code will not be executed
22+
case 12:
23+
...
24+
switch(c1){ // GOOD
25+
case 12:
26+
break;
27+
case 10:
28+
break;
29+
case 9:
30+
break;
31+
default:
32+
break;
33+
}
34+
...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>A mismatch between conditionals and <code>switch</code> cases can lead to control-flow violations (CWE-691) where the developer either does not handle all combinations of conditions or unintentionally created dead code (CWE-561).</p>
7+
8+
9+
</overview>
10+
11+
<example>
12+
<p>The following example demonstrates fallacious and fixed ways of using a <code>switch</code> statement.</p>
13+
<sample src="FindIncorrectlyUsedSwitch.c" />
14+
15+
</example>
16+
<references>
17+
18+
<li>
19+
CERT C Coding Standard:
20+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MSC12-C.+Detect+and+remove+code+that+has+no+effect+or+is+never+executed">MSC12-C. Detect and remove code that has no effect or is never executed</a>.
21+
</li>
22+
23+
</references>
24+
</qhelp>
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/**
2+
* @name Incorrect switch statement
3+
* @description --Finding places the dangerous use of a switch.
4+
* --For example, when the range of values for a condition does not cover all of the selection values..
5+
* @kind problem
6+
* @id cpp/operator-find-incorrectly-used-switch
7+
* @problem.severity warning
8+
* @precision medium
9+
* @tags correctness
10+
* security
11+
* external/cwe/cwe-561
12+
* external/cwe/cwe-691
13+
* external/cwe/cwe-478
14+
*/
15+
16+
import cpp
17+
import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
18+
19+
/** Holds if the range contains no boundary values. */
20+
predicate isRealRange(Expr exp) {
21+
upperBound(exp).toString() != "18446744073709551616" and
22+
upperBound(exp).toString() != "9223372036854775807" and
23+
upperBound(exp).toString() != "4294967295" and
24+
upperBound(exp).toString() != "Infinity" and
25+
upperBound(exp).toString() != "NaN" and
26+
lowerBound(exp).toString() != "-9223372036854775808" and
27+
lowerBound(exp).toString() != "-4294967296" and
28+
lowerBound(exp).toString() != "-Infinity" and
29+
lowerBound(exp).toString() != "NaN" and
30+
upperBound(exp) != 2147483647 and
31+
upperBound(exp) != 268435455 and
32+
upperBound(exp) != 33554431 and
33+
upperBound(exp) != 8388607 and
34+
upperBound(exp) != 65535 and
35+
upperBound(exp) != 32767 and
36+
upperBound(exp) != 255 and
37+
upperBound(exp) != 127 and
38+
upperBound(exp) != 63 and
39+
upperBound(exp) != 31 and
40+
upperBound(exp) != 15 and
41+
upperBound(exp) != 7 and
42+
lowerBound(exp) != -2147483648 and
43+
lowerBound(exp) != -268435456 and
44+
lowerBound(exp) != -33554432 and
45+
lowerBound(exp) != -8388608 and
46+
lowerBound(exp) != -65536 and
47+
lowerBound(exp) != -32768 and
48+
lowerBound(exp) != -128
49+
}
50+
51+
/** Holds if the range of values for the condition is less than the choices. */
52+
predicate isNotAllSelected(SwitchStmt swtmp) {
53+
not swtmp.getExpr().isConstant() and
54+
exists(int i |
55+
i != 0 and
56+
(
57+
i = lowerBound(swtmp.getASwitchCase().getExpr()) and
58+
upperBound(swtmp.getExpr()) < i
59+
or
60+
(
61+
i = upperBound(swtmp.getASwitchCase().getExpr()) or
62+
i = upperBound(swtmp.getASwitchCase().getEndExpr())
63+
) and
64+
lowerBound(swtmp.getExpr()) > i
65+
)
66+
)
67+
}
68+
69+
/** Holds if the range of values for the condition is greater than the selection. */
70+
predicate isConditionBig(SwitchStmt swtmp) {
71+
not swtmp.hasDefaultCase() and
72+
not exists(int iu, int il |
73+
(
74+
iu = upperBound(swtmp.getASwitchCase().getExpr()) or
75+
iu = upperBound(swtmp.getASwitchCase().getEndExpr())
76+
) and
77+
upperBound(swtmp.getExpr()) = iu and
78+
(
79+
il = lowerBound(swtmp.getASwitchCase().getExpr()) or
80+
il = lowerBound(swtmp.getASwitchCase().getEndExpr())
81+
) and
82+
lowerBound(swtmp.getExpr()) = il
83+
)
84+
}
85+
86+
/** Holds if there are labels inside the block with names similar to `default` or `case`. */
87+
predicate isWrongLableName(SwitchStmt swtmp) {
88+
not swtmp.hasDefaultCase() and
89+
exists(LabelStmt lb |
90+
(
91+
(
92+
lb.getName().charAt(0) = "d" or
93+
lb.getName().charAt(0) = "c"
94+
) and
95+
(
96+
lb.getName().charAt(1) = "e" or
97+
lb.getName().charAt(1) = "a"
98+
) and
99+
(
100+
lb.getName().charAt(2) = "f" or
101+
lb.getName().charAt(2) = "s"
102+
)
103+
) and
104+
lb.getEnclosingStmt().getParentStmt*() = swtmp.getStmt() and
105+
not exists(GotoStmt gs | gs.getName() = lb.getName())
106+
)
107+
}
108+
109+
/** Holds if the block contains code before the first `case`. */
110+
predicate isCodeBeforeCase(SwitchStmt swtmp) {
111+
exists(Expr exp |
112+
exp.getEnclosingStmt().getParentStmt*() = swtmp.getStmt() and
113+
not exists(Loop lp |
114+
exp.getEnclosingStmt().getParentStmt*() = lp and
115+
lp.getEnclosingStmt().getParentStmt*() = swtmp.getStmt()
116+
) and
117+
not exists(Stmt sttmp, SwitchCase sctmp |
118+
sttmp = swtmp.getASwitchCase().getAStmt() and
119+
sctmp = swtmp.getASwitchCase() and
120+
(
121+
exp.getEnclosingStmt().getParentStmt*() = sttmp or
122+
exp.getEnclosingStmt() = sctmp
123+
)
124+
)
125+
)
126+
}
127+
128+
from SwitchStmt sw, string msg
129+
where
130+
isRealRange(sw.getExpr()) and
131+
lowerBound(sw.getExpr()) != upperBound(sw.getExpr()) and
132+
lowerBound(sw.getExpr()) != 0 and
133+
not exists(Expr cexp |
134+
cexp = sw.getASwitchCase().getExpr() and not isRealRange(cexp)
135+
or
136+
cexp = sw.getASwitchCase().getEndExpr() and not isRealRange(cexp)
137+
) and
138+
not exists(Expr exptmp |
139+
exptmp = sw.getExpr().getAChild*() and
140+
not exptmp.isConstant() and
141+
not isRealRange(exptmp)
142+
) and
143+
(sw.getASwitchCase().terminatesInBreakStmt() or sw.getASwitchCase().terminatesInReturnStmt()) and
144+
(
145+
isNotAllSelected(sw) and msg = "The range of condition values is less than the selection."
146+
or
147+
isConditionBig(sw) and msg = "The range of condition values is wider than the choices."
148+
)
149+
or
150+
isWrongLableName(sw) and msg = "Possibly erroneous label name."
151+
or
152+
isCodeBeforeCase(sw) and msg = "Code before case will not be executed."
153+
select sw, msg
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
...
2+
throw ("my exception!",546); // BAD
3+
...
4+
throw errorFunc("my exception!",546); // GOOD
5+
...
6+
std::runtime_error("msg error"); // BAD
7+
...
8+
throw std::runtime_error("msg error"); // GOOD
9+
...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Finding places for the dangerous use of exceptions.</p>
7+
8+
</overview>
9+
10+
<example>
11+
<p>The following example demonstrates erroneous and fixed methods for using exceptions.</p>
12+
<sample src="FindIncorrectlyUsedExceptions.cpp" />
13+
14+
</example>
15+
<references>
16+
17+
<li>
18+
CERT CPP Coding Standard:
19+
<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL57-CPP.+Do+not+let+exceptions+escape+from+destructors+or+deallocation+functions">DCL57-CPP. Do not let exceptions escape from destructors or deallocation functions</a>.
20+
</li>
21+
22+
</references>
23+
</qhelp>

0 commit comments

Comments
 (0)