Skip to content

Commit 09036a3

Browse files
authored
Merge pull request #1760 from ian-semmle/mangling
C++: Use mangled names to resolve classes
2 parents 486707c + 99dd8d0 commit 09036a3

File tree

6 files changed

+4167
-206
lines changed

6 files changed

+4167
-206
lines changed

cpp/ql/src/semmle/code/cpp/internal/ResolveClass.qll

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,99 @@
11
import semmle.code.cpp.Type
22

3+
/** For upgraded databases without mangled name info. */
34
pragma[noinline]
45
private string getTopLevelClassName(@usertype c) {
6+
not mangled_name(_, _) and
57
isClass(c) and
68
usertypes(c, result, _) and
79
not namespacembrs(_, c) and // not in a namespace
810
not member(_, _, c) and // not in some structure
911
not class_instantiation(c, _) // not a template instantiation
1012
}
1113

12-
/** Holds if `d` is a unique complete class named `name`. */
14+
/**
15+
* For upgraded databases without mangled name info.
16+
* Holds if `d` is a unique complete class named `name`.
17+
*/
1318
pragma[noinline]
1419
private predicate existsCompleteWithName(string name, @usertype d) {
20+
not mangled_name(_, _) and
1521
is_complete(d) and
1622
name = getTopLevelClassName(d) and
1723
onlyOneCompleteClassExistsWithName(name)
1824
}
1925

26+
/** For upgraded databases without mangled name info. */
2027
pragma[noinline]
2128
private predicate onlyOneCompleteClassExistsWithName(string name) {
29+
not mangled_name(_, _) and
2230
strictcount(@usertype c | is_complete(c) and getTopLevelClassName(c) = name) = 1
2331
}
2432

25-
/** Holds if `c` is an incomplete class named `name`. */
33+
/**
34+
* For upgraded databases without mangled name info.
35+
* Holds if `c` is an incomplete class named `name`.
36+
*/
2637
pragma[noinline]
2738
private predicate existsIncompleteWithName(string name, @usertype c) {
39+
not mangled_name(_, _) and
2840
not is_complete(c) and
2941
name = getTopLevelClassName(c)
3042
}
3143

3244
/**
45+
* For upgraded databases without mangled name info.
3346
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
3447
* with the same name.
3548
*/
36-
private predicate hasCompleteTwin(@usertype c, @usertype d) {
49+
private predicate oldHasCompleteTwin(@usertype c, @usertype d) {
50+
not mangled_name(_, _) and
3751
exists(string name |
3852
existsIncompleteWithName(name, c) and
3953
existsCompleteWithName(name, d)
4054
)
4155
}
4256

57+
pragma[noinline]
58+
private @mangledname getTopLevelClassMangledName(@usertype c) {
59+
isClass(c) and
60+
mangled_name(c, result) and
61+
not namespacembrs(_, c) and // not in a namespace
62+
not member(_, _, c) and // not in some structure
63+
not class_instantiation(c, _) // not a template instantiation
64+
}
65+
66+
/** Holds if `d` is a unique complete class named `name`. */
67+
pragma[noinline]
68+
private predicate existsCompleteWithMangledName(@mangledname name, @usertype d) {
69+
is_complete(d) and
70+
name = getTopLevelClassMangledName(d) and
71+
onlyOneCompleteClassExistsWithMangledName(name)
72+
}
73+
74+
pragma[noinline]
75+
private predicate onlyOneCompleteClassExistsWithMangledName(@mangledname name) {
76+
strictcount(@usertype c | is_complete(c) and getTopLevelClassMangledName(c) = name) = 1
77+
}
78+
79+
/** Holds if `c` is an incomplete class named `name`. */
80+
pragma[noinline]
81+
private predicate existsIncompleteWithMangledName(@mangledname name, @usertype c) {
82+
not is_complete(c) and
83+
name = getTopLevelClassMangledName(c)
84+
}
85+
86+
/**
87+
* Holds if `c` is an incomplete class, and there exists a unique complete class `d`
88+
* with the same name.
89+
*/
90+
private predicate hasCompleteTwin(@usertype c, @usertype d) {
91+
exists(@mangledname name |
92+
existsIncompleteWithMangledName(name, c) and
93+
existsCompleteWithMangledName(name, d)
94+
)
95+
}
96+
4397
import Cached
4498
cached private module Cached {
4599
/**
@@ -49,7 +103,11 @@ cached private module Cached {
49103
cached @usertype resolveClass(@usertype c) {
50104
hasCompleteTwin(c, result)
51105
or
52-
(not hasCompleteTwin(c, _) and result = c)
106+
oldHasCompleteTwin(c, result)
107+
or
108+
(not hasCompleteTwin(c, _) and
109+
not oldHasCompleteTwin(c, _) and
110+
result = c)
53111
}
54112

55113
/**

cpp/ql/src/semmlecode.cpp.dbscheme

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,11 @@ usertype_uuid(
705705
unique string uuid: string ref
706706
);
707707

708+
mangled_name(
709+
unique int id: @declaration ref,
710+
int mangled_name : @mangledname
711+
);
712+
708713
is_pod_class(unique int id: @usertype ref);
709714
is_standard_layout_class(unique int id: @usertype ref);
710715

0 commit comments

Comments
 (0)