diff --git a/java/ql/lib/semmle/code/java/Member.qll b/java/ql/lib/semmle/code/java/Member.qll index 565da1b6d97..b871451f408 100644 --- a/java/ql/lib/semmle/code/java/Member.qll +++ b/java/ql/lib/semmle/code/java/Member.qll @@ -33,6 +33,7 @@ class Member extends Element, Annotatable, Modifiable, @member { * Holds if this member has the specified name and is declared in the * specified package and type. */ + pragma[nomagic] predicate hasQualifiedName(string package, string type, string name) { this.getDeclaringType().hasQualifiedName(package, type) and this.hasName(name) } diff --git a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll index b7ef1410bfa..2b20e2e1320 100644 --- a/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/ExternalFlow.qll @@ -345,6 +345,29 @@ private predicate elementSpec( neutralModel(package, type, name, signature, _, _) and ext = "" and subtypes = false } +private string getNestedName(Type t) { + not t instanceof RefType and result = t.toString() + or + not t.(Array).getElementType() instanceof NestedType and result = t.(RefType).nestedName() + or + result = + t.(Array).getElementType().(NestedType).getEnclosingType().nestedName() + "$" + t.getName() +} + +private string getQualifiedName(Type t) { + not t instanceof RefType and result = t.toString() + or + result = t.(RefType).getQualifiedName() + or + exists(Array a, Type c | a = t and c = a.getElementType() | + not c instanceof RefType and result = t.toString() + or + exists(string pkgName | pkgName = c.(RefType).getPackage().getName() | + if pkgName = "" then result = getNestedName(a) else result = pkgName + "." + getNestedName(a) + ) + ) +} + /** * Gets a parenthesized string containing all parameter types of this callable, separated by a comma. * @@ -353,32 +376,86 @@ private predicate elementSpec( */ cached string paramsString(Callable c) { + result = + "(" + concat(int i | | getNestedName(c.getParameterType(i).getErasure()), "," order by i) + ")" +} + +pragma[nomagic] +private string paramsString_old(Callable c) { result = "(" + concat(int i | | c.getParameterType(i).getErasure().toString(), "," order by i) + ")" } -private Element interpretElement0( +private string paramsStringQualified(Callable c) { + result = + "(" + concat(int i | | getQualifiedName(c.getParameterType(i).getErasure()), "," order by i) + + ")" +} + +predicate failMatch( + string package, string type, boolean subtypes, string name, string signature, string sig2, + string sigf +) { + elementSpec(package, type, subtypes, name, signature, _) and + not exists(interpretElement0(package, type, subtypes, name, signature)) and + exists(Callable c | + c = interpretElement0_old(package, type, subtypes, name, signature) and + sig2 = paramsString(c) and + sigf = paramsStringQualified(c) + ) +} + +private Element interpretElement0_old( string package, string type, boolean subtypes, string name, string signature ) { elementSpec(package, type, subtypes, name, signature, _) and - exists(RefType t | t.hasQualifiedName(package, type) | + ( exists(Member m | ( result = m or subtypes = true and result.(SrcMethod).overridesOrInstantiates+(m) ) and - m.getDeclaringType() = t and - m.hasName(name) + m.hasQualifiedName(package, type, name) | signature = "" or m.(Callable).getSignature() = any(string nameprefix) + signature or + paramsString_old(m) = signature + ) + or + exists(RefType t | + t.hasQualifiedName(package, type) and + (if subtypes = true then result.(SrcRefType).getASourceSupertype*() = t else result = t) and + name = "" and + signature = "" + ) + ) +} + +private Element interpretElement0( + string package, string type, boolean subtypes, string name, string signature +) { + elementSpec(package, type, subtypes, name, signature, _) and + ( + exists(Member m | + ( + result = m + or + subtypes = true and result.(SrcMethod).overridesOrInstantiates+(m) + ) and + m.hasQualifiedName(package, type, name) + | + signature = "" or + paramsStringQualified(m) = signature or paramsString(m) = signature ) or - (if subtypes = true then result.(SrcRefType).getASourceSupertype*() = t else result = t) and - name = "" and - signature = "" + exists(RefType t | + t.hasQualifiedName(package, type) and + (if subtypes = true then result.(SrcRefType).getASourceSupertype*() = t else result = t) and + name = "" and + signature = "" + ) ) }