mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
134 lines
3.5 KiB
Plaintext
134 lines
3.5 KiB
Plaintext
import semmle.code.cpp.Type
|
|
|
|
/** For upgraded databases without mangled name info. */
|
|
pragma[noinline]
|
|
private string getTopLevelClassName(@usertype c) {
|
|
not mangled_name(_, _) and
|
|
isClass(c) and
|
|
usertypes(c, result, _) and
|
|
not namespacembrs(_, c) and // not in a namespace
|
|
not member(_, _, c) and // not in some structure
|
|
not class_instantiation(c, _) // not a template instantiation
|
|
}
|
|
|
|
/**
|
|
* For upgraded databases without mangled name info.
|
|
* Holds if `d` is a unique complete class named `name`.
|
|
*/
|
|
pragma[noinline]
|
|
private predicate existsCompleteWithName(string name, @usertype d) {
|
|
not mangled_name(_, _) and
|
|
is_complete(d) and
|
|
name = getTopLevelClassName(d) and
|
|
onlyOneCompleteClassExistsWithName(name)
|
|
}
|
|
|
|
/** For upgraded databases without mangled name info. */
|
|
pragma[noinline]
|
|
private predicate onlyOneCompleteClassExistsWithName(string name) {
|
|
not mangled_name(_, _) and
|
|
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
|
|
}
|
|
|
|
/**
|
|
* For upgraded databases without mangled name info.
|
|
* Holds if `c` is an incomplete class named `name`.
|
|
*/
|
|
pragma[noinline]
|
|
private predicate existsIncompleteWithName(string name, @usertype c) {
|
|
not mangled_name(_, _) and
|
|
not is_complete(c) and
|
|
name = getTopLevelClassName(c)
|
|
}
|
|
|
|
/**
|
|
* For upgraded databases without mangled name info.
|
|
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
|
|
* with the same name.
|
|
*/
|
|
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
|
|
not mangled_name(_, _) and
|
|
exists(string name |
|
|
existsIncompleteWithName(name, c) and
|
|
existsCompleteWithName(name, d)
|
|
)
|
|
}
|
|
|
|
pragma[noinline]
|
|
private @mangledname getClassMangledName(@usertype c) {
|
|
isClass(c) and
|
|
mangled_name(c, result)
|
|
}
|
|
|
|
/** Holds if `d` is a unique complete class named `name`. */
|
|
pragma[noinline]
|
|
private predicate existsCompleteWithMangledName(@mangledname name, @usertype d) {
|
|
is_complete(d) and
|
|
name = getClassMangledName(d) and
|
|
onlyOneCompleteClassExistsWithMangledName(name)
|
|
}
|
|
|
|
pragma[noinline]
|
|
private predicate onlyOneCompleteClassExistsWithMangledName(@mangledname name) {
|
|
strictcount(@usertype c | is_complete(c) and getClassMangledName(c) = name) = 1
|
|
}
|
|
|
|
/** Holds if `c` is an incomplete class named `name`. */
|
|
pragma[noinline]
|
|
private predicate existsIncompleteWithMangledName(@mangledname name, @usertype c) {
|
|
not is_complete(c) and
|
|
name = getClassMangledName(c)
|
|
}
|
|
|
|
/**
|
|
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
|
|
* with the same name.
|
|
*/
|
|
private predicate hasCompleteTwin(@usertype c, @usertype d) {
|
|
exists(@mangledname name |
|
|
existsIncompleteWithMangledName(name, c) and
|
|
existsCompleteWithMangledName(name, d)
|
|
)
|
|
}
|
|
|
|
import Cached
|
|
|
|
cached
|
|
private module Cached {
|
|
/**
|
|
* If `c` is incomplete, and there exists a unique complete class with the same name,
|
|
* then the result is that complete class. Otherwise, the result is `c`.
|
|
*/
|
|
cached
|
|
@usertype resolveClass(@usertype c) {
|
|
hasCompleteTwin(c, result)
|
|
or
|
|
oldHasCompleteTwin(c, result)
|
|
or
|
|
not hasCompleteTwin(c, _) and
|
|
not oldHasCompleteTwin(c, _) and
|
|
result = c
|
|
}
|
|
|
|
/**
|
|
* Holds if `t` is a struct, class, union, or template.
|
|
*/
|
|
cached
|
|
predicate isClass(@usertype t) {
|
|
usertypes(t, _, 1) or
|
|
usertypes(t, _, 2) or
|
|
usertypes(t, _, 3) or
|
|
usertypes(t, _, 6) or
|
|
usertypes(t, _, 10) or
|
|
usertypes(t, _, 11) or
|
|
usertypes(t, _, 12)
|
|
}
|
|
|
|
cached
|
|
predicate isType(@type t) {
|
|
not isClass(t)
|
|
or
|
|
t = resolveClass(_)
|
|
}
|
|
}
|