mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
C++: Use mangled_name in ResolveClass.qll
The old code is still around to handle upgraded databases.
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
import semmle.code.cpp.Type
|
import semmle.code.cpp.Type
|
||||||
|
|
||||||
|
/** For upgraded databases without mangled name info. */
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private string getTopLevelClassName(@usertype c) {
|
private string getTopLevelClassName(@usertype c) {
|
||||||
|
not mangled_name(_, _) and
|
||||||
isClass(c) and
|
isClass(c) and
|
||||||
usertypes(c, result, _) and
|
usertypes(c, result, _) and
|
||||||
not namespacembrs(_, c) and // not in a namespace
|
not namespacembrs(_, c) and // not in a namespace
|
||||||
@@ -9,24 +11,76 @@ private string getTopLevelClassName(@usertype c) {
|
|||||||
not class_instantiation(c, _) // not a template instantiation
|
not class_instantiation(c, _) // not a template instantiation
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Holds if `d` is a unique complete class named `name`. */
|
/**
|
||||||
|
* For upgraded databases without mangled name info.
|
||||||
|
* Holds if `d` is a unique complete class named `name`.
|
||||||
|
*/
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate existsCompleteWithName(string name, @usertype d) {
|
private predicate existsCompleteWithName(string name, @usertype d) {
|
||||||
|
not mangled_name(_, _) and
|
||||||
is_complete(d) and
|
is_complete(d) and
|
||||||
name = getTopLevelClassName(d) and
|
name = getTopLevelClassName(d) and
|
||||||
onlyOneCompleteClassExistsWithName(name)
|
onlyOneCompleteClassExistsWithName(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** For upgraded databases without mangled name info. */
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate onlyOneCompleteClassExistsWithName(string name) {
|
private predicate onlyOneCompleteClassExistsWithName(string name) {
|
||||||
|
not mangled_name(_, _) and
|
||||||
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
|
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 getTopLevelClassMangledName(@usertype c) {
|
||||||
|
isClass(c) and
|
||||||
|
mangled_name(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
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if `d` is a unique complete class named `name`. */
|
||||||
|
pragma[noinline]
|
||||||
|
private predicate existsCompleteWithMangledName(@mangledname name, @usertype d) {
|
||||||
|
is_complete(d) and
|
||||||
|
name = getTopLevelClassMangledName(d) and
|
||||||
|
onlyOneCompleteClassExistsWithMangledName(name)
|
||||||
|
}
|
||||||
|
|
||||||
|
pragma[noinline]
|
||||||
|
private predicate onlyOneCompleteClassExistsWithMangledName(@mangledname name) {
|
||||||
|
strictcount(@usertype c | is_complete(c) and getTopLevelClassMangledName(c) = name) = 1
|
||||||
|
}
|
||||||
|
|
||||||
/** Holds if `c` is an incomplete class named `name`. */
|
/** Holds if `c` is an incomplete class named `name`. */
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private predicate existsIncompleteWithName(string name, @usertype c) {
|
private predicate existsIncompleteWithMangledName(@mangledname name, @usertype c) {
|
||||||
not is_complete(c) and
|
not is_complete(c) and
|
||||||
name = getTopLevelClassName(c)
|
name = getTopLevelClassMangledName(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,9 +88,9 @@ private predicate existsIncompleteWithName(string name, @usertype c) {
|
|||||||
* with the same name.
|
* with the same name.
|
||||||
*/
|
*/
|
||||||
private predicate hasCompleteTwin(@usertype c, @usertype d) {
|
private predicate hasCompleteTwin(@usertype c, @usertype d) {
|
||||||
exists(string name |
|
exists(@mangledname name |
|
||||||
existsIncompleteWithName(name, c) and
|
existsIncompleteWithMangledName(name, c) and
|
||||||
existsCompleteWithName(name, d)
|
existsCompleteWithMangledName(name, d)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +103,11 @@ cached private module Cached {
|
|||||||
cached @usertype resolveClass(@usertype c) {
|
cached @usertype resolveClass(@usertype c) {
|
||||||
hasCompleteTwin(c, result)
|
hasCompleteTwin(c, result)
|
||||||
or
|
or
|
||||||
(not hasCompleteTwin(c, _) and result = c)
|
oldHasCompleteTwin(c, result)
|
||||||
|
or
|
||||||
|
(not hasCompleteTwin(c, _) and
|
||||||
|
not oldHasCompleteTwin(c, _) and
|
||||||
|
result = c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -705,6 +705,11 @@ usertype_uuid(
|
|||||||
unique string uuid: string ref
|
unique string uuid: string ref
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mangled_name(
|
||||||
|
unique int id: @declaration ref,
|
||||||
|
int mangled_name : @mangledname
|
||||||
|
);
|
||||||
|
|
||||||
is_pod_class(unique int id: @usertype ref);
|
is_pod_class(unique int id: @usertype ref);
|
||||||
is_standard_layout_class(unique int id: @usertype ref);
|
is_standard_layout_class(unique int id: @usertype ref);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user