Skip to content

Commit 9427428

Browse files
authored
Merge pull request #20127 from aschackmull/java/joinorder3
Java: Improve a couple of join-orders
2 parents c59d20a + 6c82752 commit 9427428

File tree

3 files changed

+53
-30
lines changed

3 files changed

+53
-30
lines changed

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,16 @@ predicate expectsContent(Node n, ContentSet c) {
348348
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
349349
}
350350

351+
pragma[nomagic]
352+
private predicate numericRepresentative(RefType t) {
353+
t.(BoxedType).getPrimitiveType().getName() = "double"
354+
}
355+
356+
pragma[nomagic]
357+
private predicate booleanRepresentative(RefType t) {
358+
t.(BoxedType).getPrimitiveType().getName() = "boolean"
359+
}
360+
351361
/**
352362
* Gets a representative (boxed) type for `t` for the purpose of pruning
353363
* possible flow. A single type is used for all numeric types to account for
@@ -356,10 +366,10 @@ predicate expectsContent(Node n, ContentSet c) {
356366
RefType getErasedRepr(Type t) {
357367
exists(Type e | e = t.getErasure() |
358368
if e instanceof NumericOrCharType
359-
then result.(BoxedType).getPrimitiveType().getName() = "double"
369+
then numericRepresentative(result)
360370
else
361371
if e instanceof BooleanType
362-
then result.(BoxedType).getPrimitiveType().getName() = "boolean"
372+
then booleanRepresentative(result)
363373
else result = e
364374
)
365375
or

java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -214,24 +214,35 @@ private predicate relevantNode(ObjNode n) {
214214
exists(ObjNode mid | relevantNode(mid) and objStep(mid, n) and relevantNodeBack(n))
215215
}
216216

217-
pragma[noinline]
218-
private predicate objStepPruned(ObjNode n1, ObjNode n2) {
219-
objStep(n1, n2) and relevantNode(n1) and relevantNode(n2)
217+
private newtype TObjFlowNode =
218+
TObjNode(ObjNode n) { relevantNode(n) } or
219+
TObjType(RefType t) { source(t, _) }
220+
221+
private predicate objStepPruned(TObjFlowNode node1, TObjFlowNode node2) {
222+
exists(ObjNode n1, ObjNode n2 |
223+
node1 = TObjNode(n1) and
224+
node2 = TObjNode(n2) and
225+
objStep(n1, n2)
226+
)
227+
or
228+
exists(RefType t, ObjNode n |
229+
node1 = TObjType(t) and
230+
node2 = TObjNode(n) and
231+
source(t, n)
232+
)
220233
}
221234

222-
private predicate stepPlus(Node n1, Node n2) = fastTC(objStepPruned/2)(n1, n2)
235+
private predicate flowSrc(TObjFlowNode src) { src instanceof TObjType }
236+
237+
private predicate flowSink(TObjFlowNode sink) { exists(ObjNode n | sink = TObjNode(n) and sink(n)) }
238+
239+
private predicate stepPlus(TObjFlowNode n1, TObjFlowNode n2) =
240+
doublyBoundedFastTC(objStepPruned/2, flowSrc/1, flowSink/1)(n1, n2)
223241

224242
/**
225243
* Holds if the qualifier `n` of an `Object.toString()` call might have type `t`.
226244
*/
227-
pragma[noopt]
228-
private predicate objType(ObjNode n, RefType t) {
229-
exists(ObjNode n2 |
230-
sink(n) and
231-
(stepPlus(n2, n) or n2 = n) and
232-
source(t, n2)
233-
)
234-
}
245+
private predicate objType(ObjNode n, RefType t) { stepPlus(TObjType(t), TObjNode(n)) }
235246

236247
private VirtualMethodCall objectToString(ObjNode n) {
237248
result.getQualifier() = n.asExpr() and sink(n)

java/ql/src/Likely Bugs/Resource Leaks/CloseType.qll

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -212,33 +212,35 @@ private LocalVariableDecl getCloseableVariable(CloseableInitExpr cie) {
212212
/**
213213
* A variable on which a "close" method is called, implicitly or explicitly, directly or indirectly.
214214
*/
215-
private predicate closeCalled(Variable v) {
215+
private predicate closeCalled(LocalScopeVariable v) {
216216
// `close()` is implicitly called on variables declared or referenced
217217
// in the resources clause of try-with-resource statements.
218218
exists(TryStmt try | try.getAResourceVariable() = v)
219219
or
220220
// Otherwise, there should be an explicit call to a method whose name contains "close".
221221
exists(MethodCall e |
222-
v = getCloseableVariable(_) or v instanceof Parameter or v instanceof LocalVariableDecl
223-
|
224222
e.getMethod().getName().toLowerCase().matches("%close%") and
225223
exists(VarAccess va | va = v.getAnAccess() |
226224
e.getQualifier() = va or
227225
e.getAnArgument() = va
228226
)
229-
or
230-
// The "close" call could happen indirectly inside a helper method of unknown name.
231-
exists(int i | e.getArgument(i) = v.getAnAccess() |
232-
exists(Parameter p, int j | p.getPosition() = j and p.getCallable() = e.getMethod() |
233-
closeCalled(p) and i = j
234-
or
235-
// The helper method could be iterating over a varargs parameter.
236-
exists(EnhancedForStmt for | for.getExpr() = p.getAnAccess() |
237-
closeCalled(for.getVariable().getVariable())
238-
) and
239-
p.isVarargs() and
240-
j <= i
241-
)
227+
)
228+
or
229+
// The "close" call could happen indirectly inside a helper method of unknown name.
230+
exists(Parameter p |
231+
closeCalled(p) and p.getAnArgument() = v.getAnAccess() and p.getCallable() instanceof Method
232+
)
233+
or
234+
exists(MethodCall e, int i | e.getArgument(i) = v.getAnAccess() |
235+
exists(Parameter p, int j |
236+
p.getPosition() = j and p.getCallable() = e.getMethod().getSourceDeclaration()
237+
|
238+
// The helper method could be iterating over a varargs parameter.
239+
exists(EnhancedForStmt for | for.getExpr() = p.getAnAccess() |
240+
closeCalled(for.getVariable().getVariable())
241+
) and
242+
p.isVarargs() and
243+
j <= i
242244
)
243245
)
244246
}

0 commit comments

Comments
 (0)