Skip to content

Commit 3ca2874

Browse files
committed
Merge branch 'main' into assignment
2 parents 8442146 + 9231119 commit 3ca2874

File tree

69 files changed

+3500
-386
lines changed

Some content is hidden

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

69 files changed

+3500
-386
lines changed

config/add-overlay-annotations.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ def insert_overlay_caller_annotations(lines):
177177
out_lines.append(line)
178178
return out_lines
179179

180+
explicitly_global = set([
181+
"java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll",
182+
"java/ql/lib/semmle/code/java/dispatch/DispatchFlow.qll",
183+
"java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll",
184+
"java/ql/lib/semmle/code/java/dispatch/internal/Unification.qll",
185+
])
180186

181187
def annotate_as_appropriate(filename, lines):
182188
'''
@@ -196,6 +202,9 @@ def annotate_as_appropriate(filename, lines):
196202
((filename.endswith("Query.qll") or filename.endswith("Config.qll")) and
197203
any("implements DataFlow::ConfigSig" in line for line in lines))):
198204
return None
205+
elif filename in explicitly_global:
206+
# These files are explicitly global and should not be annotated.
207+
return None
199208
elif not any(line for line in lines if line.strip()):
200209
return None
201210

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
---
22
category: feature
33
---
4-
* Added predicates `getTransitiveNumberOfVlaDimensionStmts`, `getTransitiveVlaDimensionStmt`, and `getParentVlaDecl` to `VlaDeclStmt` for handling `VlaDeclStmt`s whose base type defined in terms of an other `VlaDeclStmt` via a `typedef`.
4+
* Added predicates `getTransitiveNumberOfVlaDimensionStmts`, `getTransitiveVlaDimensionStmt`, and `getParentVlaDecl` to `VlaDeclStmt` for handling `VlaDeclStmt`s whose base type is defined in terms of another `VlaDeclStmt` via a `typedef`.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
struct S {
2+
int a;
3+
int b;
4+
int c;
5+
unsigned long *d;
6+
7+
union {
8+
struct {
9+
const char *e;
10+
int f;
11+
S *g;
12+
const char *h;
13+
int i;
14+
bool j;
15+
bool k;
16+
const char *l;
17+
char **m;
18+
} n;
19+
20+
struct {
21+
bool o;
22+
bool p;
23+
} q;
24+
} r;
25+
};
26+
27+
int too_many_constants_init(S *s);
28+
29+
char *too_many_constants(const char *h, bool k, int i) {
30+
const char *e = "";
31+
char l[64] = "";
32+
char *m;
33+
34+
S s[] = {
35+
{.a = 0, .c = 0, .d = nullptr, .r = {.n = {.e = e, .f = 1, .g = nullptr, .h = h, .i = i, .j = false, .k = k, .l = l, .m = &m}}},
36+
{.a = 0, .c = 0, .d = nullptr, .r = {.q = {.o = true, .p = true}}}
37+
};
38+
39+
too_many_constants_init(s);
40+
41+
return m; // GOOD - initialized by too_many_constants_init
42+
}

csharp/ql/src/Likely Bugs/LeapYear/UnsafeYearConstruction.qhelp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<example>
1313
<p>In this example, we are incrementing/decrementing the current date by one year when creating a new <code>System.DateTime</code> object. This may work most of the time, but on any given February 29th, the resulting value will be invalid.</p>
1414
<sample src="UnsafeYearConstructionBad.cs" />
15-
<p>To fix this bug, we add/substract years to the current date by calling <code>AddYears</code> method on it.</p>
15+
<p>To fix this bug, we add/subtract years to the current date by calling <code>AddYears</code> method on it.</p>
1616
<sample src="UnsafeYearConstructionGood.cs" />
1717
</example>
1818
<references>

go/ql/lib/CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ No user-facing changes.
44

55
## 4.3.2
66

7-
No user-facing changes.
7+
### Minor Analysis Improvements
8+
9+
* Go 1.25 is now supported.
810

911
## 4.3.1
1012

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
## 4.3.2
22

3-
No user-facing changes.
3+
### Minor Analysis Improvements
4+
5+
* Go 1.25 is now supported.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Improved support for various assertion libraries, in particular JUnit. This affects the control-flow graph slightly, and in turn affects several queries (mainly quality queries). Most queries should see improved precision (new true positives and fewer false positives), in particular `java/constant-comparison`, `java/index-out-of-bounds`, `java/dereferenced-value-may-be-null`, and `java/useless-null-check`. Some medium precision queries like `java/toctou-race-condition` and `java/unreleased-lock` may see mixed result changes (both slight improvements and slight regressions).

java/ql/lib/semmle/code/java/ControlFlowGraph.qll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,10 @@ private module ControlFlowGraphImpl {
365365
* Bind `t` to an unchecked exception that may occur in a precondition check or guard wrapper.
366366
*/
367367
private predicate uncheckedExceptionFromMethod(MethodCall ma, ThrowableType t) {
368-
conditionCheckArgument(ma, _, _) and
368+
(methodCallChecksArgument(ma) or methodCallUnconditionallyThrows(ma)) and
369369
(t instanceof TypeError or t instanceof TypeRuntimeException)
370370
or
371-
methodMayThrow(ma.getMethod(), t)
371+
methodMayThrow(ma.getMethod().getSourceDeclaration(), t)
372372
}
373373

374374
/**
@@ -586,6 +586,7 @@ private module ControlFlowGraphImpl {
586586
* Gets a `MethodCall` that always throws an exception or calls `exit`.
587587
*/
588588
private MethodCall nonReturningMethodCall() {
589+
methodCallUnconditionallyThrows(result) or
589590
result.getMethod().getSourceDeclaration() = nonReturningMethod() or
590591
result = likelyNonReturningMethod().getAnAccess()
591592
}

java/ql/lib/semmle/code/java/controlflow/Guards.qll

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -395,11 +395,13 @@ private module LogicInputCommon {
395395
predicate additionalImpliesStep(
396396
GuardsImpl::PreGuard g1, GuardValue v1, GuardsImpl::PreGuard g2, GuardValue v2
397397
) {
398-
exists(MethodCall check, int argIndex |
398+
exists(MethodCall check |
399399
g1 = check and
400-
v1.getDualValue().isThrowsException() and
401-
conditionCheckArgument(check, argIndex, v2.asBooleanValue()) and
402-
g2 = check.getArgument(argIndex)
400+
v1.getDualValue().isThrowsException()
401+
|
402+
methodCallChecksBoolean(check, g2, v2.asBooleanValue())
403+
or
404+
methodCallChecksNotNull(check, g2) and v2.isNonNullValue()
403405
)
404406
}
405407
}
Lines changed: 122 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Provides predicates for identifying precondition checks like
2+
* Provides predicates for identifying precondition and assertion checks like
33
* `com.google.common.base.Preconditions` and
44
* `org.apache.commons.lang3.Validate`.
55
*/
@@ -9,99 +9,150 @@ module;
99
import java
1010

1111
/**
12-
* Holds if `m` is a non-overridable method that checks that its zero-indexed `argument`
13-
* is equal to `checkTrue` and throws otherwise.
12+
* Holds if `m` is a method that checks that its argument at position `arg` is
13+
* equal to true and throws otherwise.
1414
*/
15-
predicate conditionCheckMethodArgument(Method m, int argument, boolean checkTrue) {
16-
condtionCheckMethodGooglePreconditions(m, checkTrue) and argument = 0
17-
or
18-
conditionCheckMethodApacheCommonsLang3Validate(m, checkTrue) and argument = 0
15+
private predicate methodCheckTrue(Method m, int arg) {
16+
arg = 0 and
17+
(
18+
m.hasQualifiedName("com.google.common.base", "Preconditions", ["checkArgument", "checkState"]) or
19+
m.hasQualifiedName("com.google.common.base", "Verify", "verify") or
20+
m.hasQualifiedName("org.apache.commons.lang3", "Validate", ["isTrue", "validState"]) or
21+
m.hasQualifiedName("org.junit.jupiter.api", "Assertions", "assertTrue") or
22+
m.hasQualifiedName("org.junit.jupiter.api", "Assumptions", "assumeTrue") or
23+
m.hasQualifiedName("org.testng", "Assert", "assertTrue")
24+
)
1925
or
20-
condtionCheckMethodTestingFramework(m, argument, checkTrue)
26+
m.getParameter(arg).getType() instanceof BooleanType and
27+
(
28+
m.hasQualifiedName("org.junit", "Assert", "assertTrue") or
29+
m.hasQualifiedName("org.junit", "Assume", "assumeTrue") or
30+
m.hasQualifiedName("junit.framework", _, "assertTrue")
31+
)
32+
}
33+
34+
/**
35+
* Holds if `m` is a method that checks that its argument at position `arg` is
36+
* equal to false and throws otherwise.
37+
*/
38+
private predicate methodCheckFalse(Method m, int arg) {
39+
arg = 0 and
40+
(
41+
m.hasQualifiedName("org.junit.jupiter.api", "Assertions", "assertFalse") or
42+
m.hasQualifiedName("org.junit.jupiter.api", "Assumptions", "assumeFalse") or
43+
m.hasQualifiedName("org.testng", "Assert", "assertFalse")
44+
)
2145
or
22-
exists(Parameter p, MethodCall ma, int argIndex, boolean ct, Expr arg |
23-
p = m.getParameter(argument) and
24-
not m.isOverridable() and
25-
m.getBody().getStmt(0).(ExprStmt).getExpr() = ma and
26-
conditionCheckArgument(ma, argIndex, ct) and
27-
ma.getArgument(argIndex) = arg and
28-
(
29-
arg.(LogNotExpr).getExpr().(VarAccess).getVariable() = p and
30-
checkTrue = ct.booleanNot()
31-
or
32-
arg.(VarAccess).getVariable() = p and checkTrue = ct
33-
)
46+
m.getParameter(arg).getType() instanceof BooleanType and
47+
(
48+
m.hasQualifiedName("org.junit", "Assert", "assertFalse") or
49+
m.hasQualifiedName("org.junit", "Assume", "assumeFalse") or
50+
m.hasQualifiedName("junit.framework", _, "assertFalse")
51+
)
52+
}
53+
54+
/**
55+
* Holds if `m` is a method that checks that its argument at position `arg` is
56+
* not null and throws otherwise.
57+
*/
58+
private predicate methodCheckNotNull(Method m, int arg) {
59+
arg = 0 and
60+
(
61+
m.hasQualifiedName("com.google.common.base", "Preconditions", "checkNotNull") or
62+
m.hasQualifiedName("com.google.common.base", "Verify", "verifyNotNull") or
63+
m.hasQualifiedName("org.apache.commons.lang3", "Validate", "notNull") or
64+
m.hasQualifiedName("java.util", "Objects", "requireNonNull") or
65+
m.hasQualifiedName("org.junit.jupiter.api", "Assertions", "assertNotNull") or
66+
m.hasQualifiedName("org.junit", "Assume", "assumeNotNull") or // vararg
67+
m.hasQualifiedName("org.testng", "Assert", "assertNotNull")
3468
)
3569
or
36-
exists(Parameter p, IfStmt ifstmt, Expr cond |
37-
p = m.getParameter(argument) and
38-
not m.isOverridable() and
39-
p.getType() instanceof BooleanType and
40-
m.getBody().getStmt(0) = ifstmt and
41-
ifstmt.getCondition() = cond and
42-
(
43-
cond.(LogNotExpr).getExpr().(VarAccess).getVariable() = p and checkTrue = true
44-
or
45-
cond.(VarAccess).getVariable() = p and checkTrue = false
46-
) and
47-
(
48-
ifstmt.getThen() instanceof ThrowStmt or
49-
ifstmt.getThen().(SingletonBlock).getStmt() instanceof ThrowStmt
50-
)
70+
arg = m.getNumberOfParameters() - 1 and
71+
(
72+
m.hasQualifiedName("org.junit", "Assert", "assertNotNull") or
73+
m.hasQualifiedName("junit.framework", _, "assertNotNull")
5174
)
5275
}
5376

54-
private predicate condtionCheckMethodGooglePreconditions(Method m, boolean checkTrue) {
55-
m.getDeclaringType().hasQualifiedName("com.google.common.base", "Preconditions") and
56-
checkTrue = true and
57-
(m.hasName("checkArgument") or m.hasName("checkState"))
77+
/**
78+
* Holds if `m` is a method that checks that its argument at position `arg`
79+
* satisfies a property specified by another argument and throws otherwise.
80+
*/
81+
private predicate methodCheckThat(Method m, int arg) {
82+
m.getParameter(arg).getType().getErasure() instanceof TypeObject and
83+
(
84+
m.hasQualifiedName("org.hamcrest", "MatcherAssert", "assertThat") or
85+
m.hasQualifiedName("org.junit", "Assert", "assertThat") or
86+
m.hasQualifiedName("org.junit", "Assume", "assumeThat")
87+
)
5888
}
5989

60-
private predicate conditionCheckMethodApacheCommonsLang3Validate(Method m, boolean checkTrue) {
61-
m.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "Validate") and
62-
checkTrue = true and
63-
(m.hasName("isTrue") or m.hasName("validState"))
90+
/** Holds if `m` is a method that unconditionally throws. */
91+
private predicate methodUnconditionallyThrows(Method m) {
92+
m.hasQualifiedName("org.junit.jupiter.api", "Assertions", "fail") or
93+
m.hasQualifiedName("org.junit", "Assert", "fail") or
94+
m.hasQualifiedName("junit.framework", _, "fail") or
95+
m.hasQualifiedName("org.testng", "Assert", "fail")
6496
}
6597

6698
/**
67-
* Holds if `m` is a non-overridable testing framework method that checks that its first argument
68-
* is equal to `checkTrue` and throws otherwise.
99+
* Holds if `mc` is a call to a method that checks that its argument `arg` is
100+
* equal to `checkTrue` and throws otherwise.
69101
*/
70-
private predicate condtionCheckMethodTestingFramework(Method m, int argument, boolean checkTrue) {
71-
argument = 0 and
72-
(
73-
m.getDeclaringType().hasQualifiedName("org.junit", "Assume") and
74-
checkTrue = true and
75-
m.hasName("assumeTrue")
102+
predicate methodCallChecksBoolean(MethodCall mc, Expr arg, boolean checkTrue) {
103+
exists(int pos | mc.getArgument(pos) = arg |
104+
methodCheckTrue(mc.getMethod().getSourceDeclaration(), pos) and checkTrue = true
76105
or
77-
m.getDeclaringType().hasQualifiedName("org.junit.jupiter.api", "Assertions") and
78-
(
79-
checkTrue = true and m.hasName("assertTrue")
80-
or
81-
checkTrue = false and m.hasName("assertFalse")
82-
)
83-
or
84-
m.getDeclaringType().hasQualifiedName("org.junit.jupiter.api", "Assumptions") and
85-
(
86-
checkTrue = true and m.hasName("assumeTrue")
87-
or
88-
checkTrue = false and m.hasName("assumeFalse")
89-
)
106+
methodCheckFalse(mc.getMethod().getSourceDeclaration(), pos) and checkTrue = false
90107
)
91-
or
92-
m.getDeclaringType().hasQualifiedName(["org.junit", "org.testng"], "Assert") and
93-
m.getParameter(argument).getType() instanceof BooleanType and
94-
(
95-
checkTrue = true and m.hasName("assertTrue")
108+
}
109+
110+
/**
111+
* Holds if `mc` is a call to a method that checks that its argument `arg` is
112+
* not null and throws otherwise.
113+
*/
114+
predicate methodCallChecksNotNull(MethodCall mc, Expr arg) {
115+
exists(int pos | mc.getArgument(pos) = arg |
116+
methodCheckNotNull(mc.getMethod().getSourceDeclaration(), pos)
96117
or
97-
checkTrue = false and m.hasName("assertFalse")
118+
methodCheckThat(mc.getMethod().getSourceDeclaration(), pos) and
119+
mc.getAnArgument().(MethodCall).getMethod().getName() = "notNullValue"
98120
)
99121
}
100122

101123
/**
124+
* Holds if `mc` is a call to a method that checks one of its arguments in some
125+
* way and possibly throws.
126+
*/
127+
predicate methodCallChecksArgument(MethodCall mc) {
128+
methodCallChecksBoolean(mc, _, _) or
129+
methodCallChecksNotNull(mc, _)
130+
}
131+
132+
/** Holds if `mc` is a call to a method that unconditionally throws. */
133+
predicate methodCallUnconditionallyThrows(MethodCall mc) {
134+
methodUnconditionallyThrows(mc.getMethod().getSourceDeclaration()) or
135+
exists(BooleanLiteral b | methodCallChecksBoolean(mc, b, b.getBooleanValue().booleanNot()))
136+
}
137+
138+
/**
139+
* DEPRECATED: Use `methodCallChecksBoolean` instead.
140+
*
141+
* Holds if `m` is a non-overridable method that checks that its zero-indexed `argument`
142+
* is equal to `checkTrue` and throws otherwise.
143+
*/
144+
deprecated predicate conditionCheckMethodArgument(Method m, int argument, boolean checkTrue) {
145+
methodCheckTrue(m, argument) and checkTrue = true
146+
or
147+
methodCheckFalse(m, argument) and checkTrue = false
148+
}
149+
150+
/**
151+
* DEPRECATED: Use `methodCallChecksBoolean` instead.
152+
*
102153
* Holds if `ma` is an access to a non-overridable method that checks that its
103154
* zero-indexed `argument` is equal to `checkTrue` and throws otherwise.
104155
*/
105-
predicate conditionCheckArgument(MethodCall ma, int argument, boolean checkTrue) {
156+
deprecated predicate conditionCheckArgument(MethodCall ma, int argument, boolean checkTrue) {
106157
conditionCheckMethodArgument(ma.getMethod().getSourceDeclaration(), argument, checkTrue)
107158
}

0 commit comments

Comments
 (0)