Skip to content

Commit 1d0736e

Browse files
committed
PointerToAVirtualBaseClass: Support casts from parents of virtual
base classes.
1 parent 3ab9104 commit 1d0736e

File tree

4 files changed

+35
-12
lines changed

4 files changed

+35
-12
lines changed
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
- `M5-2-2` - `PointerToAVirtualBaseClassCastToAPointer.ql`:
22
- Report casts where the from or to types are typedefs to virtual base classes or derived classes.
3-
- Report casts to a reference type which is a derived type.
3+
- Report casts to a reference type which is a derived type.
4+
- Report casts where the base class is the parent of a virtual base class.
5+
- The alert message has been updated to refer to the virtual base class derivation.

cpp/common/src/codingstandards/cpp/rules/pointertoavirtualbaseclasscasttoapointer/PointerToAVirtualBaseClassCastToAPointer.qll

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,31 @@ abstract class PointerToAVirtualBaseClassCastToAPointerSharedQuery extends Query
1212

1313
Query getQuery() { result instanceof PointerToAVirtualBaseClassCastToAPointerSharedQuery }
1414

15-
query predicate problems(Cast cast, string message) {
16-
exists(VirtualBaseClass castFrom, Class castTo |
15+
query predicate problems(
16+
Cast cast, string message, VirtualClassDerivation derivation, string derivationDescription
17+
) {
18+
exists(Class castFrom, VirtualBaseClass virtualBaseClass, Class castTo, string type |
1719
not isExcluded(cast, getQuery()) and
1820
not cast instanceof DynamicCast and
19-
castTo = castFrom.getADerivedClass+() and
21+
castTo = virtualBaseClass.getADerivedClass+() and
22+
virtualBaseClass = castFrom.getADerivedClass*() and
23+
derivation = virtualBaseClass.getAVirtualDerivation() and
24+
derivation.getDerivedClass().getADerivedClass*() = castTo and
25+
derivationDescription = "derived through virtual base class " + virtualBaseClass.getName() and
2026
message =
21-
"A pointer to virtual base class " + castFrom.getName() +
22-
" is not cast to a pointer of derived class " + castTo.getName() + " using a dynamic_cast."
27+
"dynamic_cast not used for cast from " + type + " to base class " + castFrom.getName() +
28+
" to derived class " + castTo.getName() + " which is $@."
2329
|
2430
// Pointer cast
2531
castFrom = cast.getExpr().getType().stripTopLevelSpecifiers().(PointerType).getBaseType() and
26-
cast.getType().stripTopLevelSpecifiers().(PointerType).getBaseType() = castTo
32+
cast.getType().stripTopLevelSpecifiers().(PointerType).getBaseType() = castTo and
33+
type = "pointer"
2734
or
2835
// Reference type cast
2936
castFrom = cast.getExpr().getType().stripTopLevelSpecifiers() and
3037
// Not actually represented as a reference type in our model - instead as the
3138
// type itself
32-
cast.getType().stripTopLevelSpecifiers() = castTo
39+
cast.getType().stripTopLevelSpecifiers() = castTo and
40+
type = "reference"
3341
)
3442
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
| test.cpp:36:12:36:37 | reinterpret_cast<C2 *>... | A pointer to virtual base class C1 is not cast to a pointer of derived class C2 using a dynamic_cast. |
2-
| test.cpp:42:12:42:38 | reinterpret_cast<C2>... | A pointer to virtual base class C1 is not cast to a pointer of derived class C2 using a dynamic_cast. |
3-
| test.cpp:48:17:48:48 | reinterpret_cast<Derived>... | A pointer to virtual base class C1 is not cast to a pointer of derived class C2 using a dynamic_cast. |
1+
| test.cpp:41:12:41:37 | reinterpret_cast<C2 *>... | dynamic_cast not used for cast from pointer to base class C1 to derived class C2 which is $@. | test.cpp:11:12:11:28 | derivation | derived through virtual base class C1 |
2+
| test.cpp:47:12:47:38 | reinterpret_cast<C2>... | dynamic_cast not used for cast from reference to base class C1 to derived class C2 which is $@. | test.cpp:11:12:11:28 | derivation | derived through virtual base class C1 |
3+
| test.cpp:53:17:53:48 | reinterpret_cast<Derived>... | dynamic_cast not used for cast from reference to base class C1 to derived class C2 which is $@. | test.cpp:11:12:11:28 | derivation | derived through virtual base class C1 |
4+
| test.cpp:86:12:86:37 | reinterpret_cast<C2 *>... | dynamic_cast not used for cast from pointer to base class C0 to derived class C2 which is $@. | test.cpp:11:12:11:28 | derivation | derived through virtual base class C1 |

cpp/common/test/rules/pointertoavirtualbaseclasscasttoapointer/test.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
class C1 {
1+
class C0 {
2+
public:
3+
virtual ~C0() {}
4+
};
5+
6+
class C1 : public C0 {
27
public:
38
virtual ~C1() {}
49
};
@@ -72,4 +77,11 @@ void test_static_cast_reference_non_compliant() {
7277
C1 *p1 = &l1;
7378
// C2 &l2 = static_cast<C2 &>(*p1); // NON_COMPLIANT - prohibited by the
7479
// compiler
80+
}
81+
82+
void test_skipped_base_class() {
83+
C2 l1;
84+
C0 *p1 = &l1;
85+
C2 *l2 = dynamic_cast<C2 *>(p1); // COMPLIANT
86+
C2 *p2 = reinterpret_cast<C2 *>(p1); // NON_COMPLIANT
7587
}

0 commit comments

Comments
 (0)