C++: Resolve functions using complete mangled names

This commit is contained in:
Jeroen Ketema
2024-01-24 10:54:46 +01:00
parent 972d86c0a0
commit a79754b696
3 changed files with 64 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import semmle.code.cpp.Location
private import semmle.code.cpp.Enclosing
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveGlobalVariable
private import semmle.code.cpp.internal.ResolveFunction
/**
* Get the `Element` that represents this `@element`.
@@ -30,11 +31,14 @@ pragma[inline]
@element unresolveElement(Element e) {
not result instanceof @usertype and
not result instanceof @variable and
not result instanceof @function and
result = e
or
e = resolveClass(result)
or
e = resolveGlobalVariable(result)
or
e = resolveFunction(result)
}
/**

View File

@@ -9,6 +9,7 @@ import semmle.code.cpp.exprs.Call
import semmle.code.cpp.metrics.MetricFunction
import semmle.code.cpp.Linkage
private import semmle.code.cpp.internal.ResolveClass
private import semmle.code.cpp.internal.ResolveFunction
/**
* A C/C++ function [N4140 8.3.5]. Both member functions and non-member
@@ -25,6 +26,8 @@ private import semmle.code.cpp.internal.ResolveClass
* in more detail in `Declaration.qll`.
*/
class Function extends Declaration, ControlFlowNode, AccessHolder, @function {
Function() { isFunction(underlyingElement(this)) }
override string getName() { functions(underlyingElement(this), result, _) }
/**

View File

@@ -0,0 +1,57 @@
private predicate hasDefinition(@function f) {
exists(@fun_decl fd | fun_decls(fd, f, _, _, _) | fun_def(fd))
}
private predicate onlyOneCompleteFunctionExistsWithMangledName(@mangledname name) {
strictcount(@function f | hasDefinition(f) and mangled_name(f, name, true)) = 1
}
/** Holds if `f` is a unique function with a definition named `name`. */
private predicate isFunctionWithMangledNameAndWithDefinition(@mangledname name, @function f) {
hasDefinition(f) and
mangled_name(f, name, true) and
onlyOneCompleteFunctionExistsWithMangledName(name)
}
/** Holds if `f` is a function without a definition named `name`. */
private predicate isFunctionWithMangledNameAndWithoutDefinition(@mangledname name, @function f) {
not hasDefinition(f) and
mangled_name(f, name, true)
}
/**
* Holds if `incomplete` is a function without a definition, and there exists
* a unique function `complete` with the same name that does have a definition.
*/
private predicate hasTwinWithDefinition(@function incomplete, @function complete) {
not function_instantiation(incomplete, complete) and
(
not compgenerated(incomplete) or
not compgenerated(complete)
) and
exists(@mangledname name |
isFunctionWithMangledNameAndWithoutDefinition(name, incomplete) and
isFunctionWithMangledNameAndWithDefinition(name, complete)
)
}
import Cached
cached
private module Cached {
/**
* If `f` is a function without a definition, and there exists a unique
* function with the same name that does have a definition, then the
* result is that unique function. Otherwise, the result is `f`.
*/
cached
@function resolveFunction(@function f) {
hasTwinWithDefinition(f, result)
or
not hasTwinWithDefinition(f, _) and
result = f
}
cached
predicate isFunction(@function f) { f = resolveFunction(_) }
}