From aabdf8430075c4d1bc930799f0c68f4d3792c5ca Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 2 Aug 2022 14:29:03 +0200 Subject: [PATCH] Java: Improve join-order for `not haveIntersection`. --- java/ql/lib/semmle/code/java/Type.qll | 23 +++++++++++++++++-- .../Collections/ContainsTypeMismatch.ql | 4 ++-- .../Collections/RemoveTypeMismatch.ql | 4 ++-- .../Comparison/IncomparableEquals.ql | 2 +- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index 2e83c31f26a..256df5d66f3 100755 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -1194,8 +1194,8 @@ private Type erase(Type t) { } /** - * Is there a common (reflexive, transitive) subtype of the erasures of - * types `t1` and `t2`? + * Holds if there is a common (reflexive, transitive) subtype of the erasures of + * types `t1` and `t2`. * * If there is no such common subtype, then the two types are disjoint. * However, the converse is not true; for example, the parameterized types @@ -1212,6 +1212,25 @@ predicate haveIntersection(RefType t1, RefType t2) { ) } +/** + * Holds if there is no common (reflexive, transitive) subtype of the erasures + * of types `t1` and `t2`. + * + * If there is no such common subtype, then the two types are disjoint. + * However, the converse is not true; for example, the parameterized types + * `List` and `Collection` are disjoint, + * but their erasures (`List` and `Collection`, respectively) + * do have common subtypes (such as `List` itself). + * + * For the definition of the notion of *erasure* see JLS v8, section 4.6 (Type Erasure). + */ +bindingset[t1, t2] +predicate notHaveIntersection(RefType t1, RefType t2) { + exists(RefType e1, RefType e2 | e1 = erase(t1) and e2 = erase(t2) | + not erasedHaveIntersection(e1, e2) + ) +} + /** * Holds if there is a common (reflexive, transitive) subtype of the erased * types `t1` and `t2`. diff --git a/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql b/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql index b34830c3537..52d790e0e71 100644 --- a/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql +++ b/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql @@ -118,7 +118,7 @@ class MismatchedContainerAccess extends MethodAccess { containerAccess(package, type, p, this.getCallee().getSignature(), i) | t = this.getCallee().getDeclaringType() and - t.getAnAncestor().getSourceDeclaration() = g and + t.getASourceSupertype*().getSourceDeclaration() = g and g.hasQualifiedName(package, type) and indirectlyInstantiates(t, g, p, result) ) @@ -139,7 +139,7 @@ from MismatchedContainerAccess ma, RefType typearg, RefType argtype, int idx where typearg = ma.getReceiverElementType(idx).getSourceDeclaration() and argtype = ma.getArgumentType(idx) and - not haveIntersection(typearg, argtype) + notHaveIntersection(typearg, argtype) select ma.getArgument(idx), "Actual argument type '" + argtype.getName() + "'" + " is incompatible with expected argument type '" + typearg.getName() + "'." diff --git a/java/ql/src/Likely Bugs/Collections/RemoveTypeMismatch.ql b/java/ql/src/Likely Bugs/Collections/RemoveTypeMismatch.ql index 8fa467c2d8a..076ccc12240 100644 --- a/java/ql/src/Likely Bugs/Collections/RemoveTypeMismatch.ql +++ b/java/ql/src/Likely Bugs/Collections/RemoveTypeMismatch.ql @@ -88,7 +88,7 @@ class MismatchedContainerModification extends MethodAccess { containerModification(package, type, p, this.getCallee().getSignature(), i) | t = this.getCallee().getDeclaringType() and - t.getAnAncestor().getSourceDeclaration() = g and + t.getASourceSupertype*().getSourceDeclaration() = g and g.hasQualifiedName(package, type) and indirectlyInstantiates(t, g, p, result) ) @@ -109,7 +109,7 @@ from MismatchedContainerModification ma, RefType elementtype, RefType argtype, i where elementtype = ma.getReceiverElementType(idx).getSourceDeclaration() and argtype = ma.getArgumentType(idx) and - not haveIntersection(elementtype, argtype) + notHaveIntersection(elementtype, argtype) select ma.getArgument(idx), "Actual argument type '" + argtype.getName() + "'" + " is incompatible with expected argument type '" + elementtype.getName() + "'." diff --git a/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql b/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql index c083c80c21d..d98fc77af38 100644 --- a/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql +++ b/java/ql/src/Likely Bugs/Comparison/IncomparableEquals.ql @@ -57,7 +57,7 @@ where else recvtp = ma.getMethod().getDeclaringType() ) and argtp = ma.getArgumentType() and - not haveIntersection(recvtp, argtp) + notHaveIntersection(recvtp, argtp) select ma, "Call to equals() comparing incomparable types " + recvtp.getName() + " and " + argtp.getName() + "."