diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index d6884627794b..f29904e14c56 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -23,3 +23,4 @@ dataExtensions: - ext/generated/*.model.yml - ext/experimental/*.model.yml warnOnImplicitThis: true +compileForOverlayEval: true diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index c30dd7012bfb..5f9fb1e95023 100644 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -424,6 +424,15 @@ class RefType extends Type, Annotatable, Modifiable, @reftype { */ RefType getAStrictAncestor() { result = this.getASupertype().getAnAncestor() } + /** + * Gets a direct or indirect supertype of this type. + * This does not include itself, unless this type is part of a cycle + * in the type hierarchy. + */ + overlay[caller?] + pragma[inline] + RefType getAStrictAncestorI() { result = this.getASupertype().getAnAncestor() } + /** * Gets the source declaration of a direct supertype of this type, excluding itself. * diff --git a/java/ql/lib/semmle/code/java/security/TempDirLocalInformationDisclosureQuery.qll b/java/ql/lib/semmle/code/java/security/TempDirLocalInformationDisclosureQuery.qll index 97ae75988b3b..1caadd3f8acd 100644 --- a/java/ql/lib/semmle/code/java/security/TempDirLocalInformationDisclosureQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TempDirLocalInformationDisclosureQuery.qll @@ -203,6 +203,7 @@ module TempDirSystemGetPropertyDirectlyToMkdir = /** * A `MethodCall` against a method that creates a temporary file or directory in a shared temporary directory. */ +overlay[local?] abstract class MethodCallInsecureFileCreation extends MethodCall { /** * Gets the type of entity created (e.g. `file`, `directory`, ...). @@ -218,6 +219,7 @@ abstract class MethodCallInsecureFileCreation extends MethodCall { /** * An insecure call to `java.io.File.createTempFile`. */ +overlay[local?] class MethodCallInsecureFileCreateTempFile extends MethodCallInsecureFileCreation { MethodCallInsecureFileCreateTempFile() { this.getMethod() instanceof MethodFileCreateTempFile and @@ -246,6 +248,7 @@ class MethodGuavaFilesCreateTempFile extends Method { /** * A call to the `com.google.common.io.Files.createTempDir` method. */ +overlay[local?] class MethodCallInsecureGuavaFilesCreateTempFile extends MethodCallInsecureFileCreation { MethodCallInsecureGuavaFilesCreateTempFile() { this.getMethod() instanceof MethodGuavaFilesCreateTempFile diff --git a/java/ql/src/Language Abuse/UselessTypeTest.ql b/java/ql/src/Language Abuse/UselessTypeTest.ql index dc727485bda5..a7a1f170fe38 100644 --- a/java/ql/src/Language Abuse/UselessTypeTest.ql +++ b/java/ql/src/Language Abuse/UselessTypeTest.ql @@ -18,7 +18,7 @@ from InstanceOfExpr ioe, RefType t, RefType ct where t = ioe.getExpr().getType() and ct = ioe.getCheckedType() and - ct = t.getAStrictAncestor() + ct = t.getAStrictAncestorI() select ioe, "There is no need to test whether an instance of $@ is also an instance of $@ - it always is.", t, t.getName(), ct, ct.getName() diff --git a/java/ql/src/Language Abuse/UselessUpcast.ql b/java/ql/src/Language Abuse/UselessUpcast.ql index ea7c12632ecd..d48e782b2e91 100644 --- a/java/ql/src/Language Abuse/UselessUpcast.ql +++ b/java/ql/src/Language Abuse/UselessUpcast.ql @@ -65,7 +65,7 @@ where src = cse.getExpr().getType() and dest = cse.getType() ) and - dest = src.getAStrictAncestor() and + dest = src.getAStrictAncestorI() and not usefulUpcast(e) select e, "There is no need to upcast from $@ to $@ - the conversion can be done implicitly.", src, src.getName(), dest, dest.getName() diff --git a/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.ql b/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.ql index 19bac66e0281..eeef82bcfae0 100644 --- a/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.ql +++ b/java/ql/src/Likely Bugs/Finalization/NullifiedSuperFinalize.ql @@ -17,7 +17,7 @@ from FinalizeMethod m, Class c, FinalizeMethod mSuper, Class cSuper where m.getDeclaringType() = c and mSuper.getDeclaringType() = cSuper and - c.getAStrictAncestor() = cSuper and + c.getAStrictAncestorI() = cSuper and not cSuper instanceof TypeObject and not exists(m.getBody().getAChild()) select m, "Finalize in " + c.getName() + " nullifies finalize in " + cSuper.getName() + "." diff --git a/java/ql/src/Likely Bugs/Inheritance/NoNonFinalInConstructor.ql b/java/ql/src/Likely Bugs/Inheritance/NoNonFinalInConstructor.ql index 606daac9c083..6b598a5a5c5f 100644 --- a/java/ql/src/Likely Bugs/Inheritance/NoNonFinalInConstructor.ql +++ b/java/ql/src/Likely Bugs/Inheritance/NoNonFinalInConstructor.ql @@ -47,13 +47,13 @@ where ma = unqualifiedCallToNonAbstractMethod(c, m) and // ... there exists an overriding method in a subtype, n.overrides+(m) and - n.getDeclaringType().getAStrictAncestor() = c.getDeclaringType() and + n.getDeclaringType().getAStrictAncestorI() = c.getDeclaringType() and // ... the method is in a supertype of c, m.getDeclaringType() = c.getDeclaringType().getAnAncestor() and // ... `n` reads a non-final field `f`, fa = nonFinalFieldRead(n, f) and // ... which is declared in a subtype of `c`, - f.getDeclaringType().getAStrictAncestor() = c.getDeclaringType() and + f.getDeclaringType().getAStrictAncestorI() = c.getDeclaringType() and // ... `f` is written only in the subtype constructor, and fw = fieldWriteOnlyIn(d, f) and // ... the subtype constructor calls (possibly indirectly) the offending super constructor. diff --git a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql index af86d90d690d..ca0b890e988d 100644 --- a/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql +++ b/java/ql/src/Likely Bugs/Serialization/IncorrectSerialVersionUID.ql @@ -21,5 +21,5 @@ where not f.isStatic() or not f.getType().hasName("long") ) and - f.getDeclaringType().getAStrictAncestor() instanceof TypeSerializable + f.getDeclaringType().getAStrictAncestorI() instanceof TypeSerializable select f, "'serialVersionUID' should be final, static, and of type long." diff --git a/java/ql/src/Likely Bugs/Serialization/NonSerializableField.ql b/java/ql/src/Likely Bugs/Serialization/NonSerializableField.ql index a39e29f6576f..d939777e6e1d 100644 --- a/java/ql/src/Likely Bugs/Serialization/NonSerializableField.ql +++ b/java/ql/src/Likely Bugs/Serialization/NonSerializableField.ql @@ -78,7 +78,7 @@ predicate exceptions(Class c, Field f) { f.isStatic() or // Classes that implement `Externalizable` completely take over control during serialization. - externalizable(c.getAStrictAncestor()) + externalizable(c.getAStrictAncestorI()) or // Stateless session beans are not normally serialized during their usual life-cycle // but are forced by their expected supertype to be serializable. @@ -93,7 +93,7 @@ predicate exceptions(Class c, Field f) { from Class c, Field f, string reason where c.fromSource() and - c.getAStrictAncestor() instanceof TypeSerializable and + c.getAStrictAncestorI() instanceof TypeSerializable and f.getDeclaringType() = c and not exceptions(c, f) and reason = nonSerialReason(f.getType()) diff --git a/java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.ql b/java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.ql index eb5c2d380c65..15278fcde643 100644 --- a/java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.ql +++ b/java/ql/src/Likely Bugs/Statements/PartiallyMaskedCatch.ql @@ -89,7 +89,7 @@ from TryStmt try, int first, int second, RefType masking, RefType masked, string where try.getFile().isJavaSourceFile() and masking = caughtType(try, first) and - masking.getAStrictAncestor() = masked and + masking.getAStrictAncestorI() = masked and masked = caughtType(try, second) and forall(RefType thrownType | thrownType = getAThrownExceptionType(try) and diff --git a/java/ql/src/Performance/InnerClassCouldBeStatic.ql b/java/ql/src/Performance/InnerClassCouldBeStatic.ql index dfc577282ca5..c215890f705f 100644 --- a/java/ql/src/Performance/InnerClassCouldBeStatic.ql +++ b/java/ql/src/Performance/InnerClassCouldBeStatic.ql @@ -22,7 +22,7 @@ pragma[nomagic] predicate inherits(Class c, Field f) { f = c.getAField() or - not f.isPrivate() and c.getAStrictAncestor().getAField() = f + not f.isPrivate() and c.getAStrictAncestorI().getAField() = f } /** diff --git a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql index fb7a40052f0b..f147e50ddb5c 100644 --- a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql @@ -12,6 +12,8 @@ * external/cwe/cwe-093 * external/cwe/cwe-113 */ +overlay[local?] +module; import java import semmle.code.java.dataflow.FlowSources diff --git a/java/ql/src/Security/CWE/CWE-833/LockOrderInconsistency.ql b/java/ql/src/Security/CWE/CWE-833/LockOrderInconsistency.ql index 899218838b9a..bfd2dc4be283 100644 --- a/java/ql/src/Security/CWE/CWE-833/LockOrderInconsistency.ql +++ b/java/ql/src/Security/CWE/CWE-833/LockOrderInconsistency.ql @@ -134,7 +134,7 @@ predicate inDifferentBranches(MethodCall ma1, MethodCall ma2) { /** The method access `ma` occurs in method `runnable`, which is an implementation of `Runnable.run()`. */ predicate inRunnable(MethodCall ma, Method runnable) { runnable.getName() = "run" and - runnable.getDeclaringType().getAStrictAncestor().hasQualifiedName("java.lang", "Runnable") and + runnable.getDeclaringType().getAStrictAncestorI().hasQualifiedName("java.lang", "Runnable") and ma.getEnclosingCallable() = runnable } diff --git a/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstantsString.ql b/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstantsString.ql index c50057c111e9..7c100202d5f4 100644 --- a/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstantsString.ql +++ b/java/ql/src/Violations of Best Practice/Magic Constants/MagicConstantsString.ql @@ -52,7 +52,7 @@ predicate trivialContext(Literal e) { or // Message in an exception. exists(ClassInstanceExpr constr | - constr.getType().(RefType).getAStrictAncestor().hasName("Exception") and + constr.getType().(RefType).getAStrictAncestorI().hasName("Exception") and e = constr.getArgument(0) ) } diff --git a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverridesNames.ql b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverridesNames.ql index 1ef2b8c614d3..52c932a8e768 100644 --- a/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverridesNames.ql +++ b/java/ql/src/Violations of Best Practice/Naming Conventions/ConfusingOverridesNames.ql @@ -65,7 +65,7 @@ where ) and not exists(Method mid | confusing(m1, mid) and - mid.getDeclaringType().getAStrictAncestor() = m2.getDeclaringType() + mid.getDeclaringType().getAStrictAncestorI() = m2.getDeclaringType() ) and not exists(Method notConfusing | notConfusing.getDeclaringType() = m1.getDeclaringType() and