Skip to content

Commit a42c845

Browse files
authored
Merge pull request github#15559 from MathiasVP/fix-constness-type
C++: Don't strip specifiers in `Node.getType`
2 parents 4c0d535 + dd3d701 commit a42c845

File tree

4 files changed

+60
-12
lines changed

4 files changed

+60
-12
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
709709
override DataFlowType getType() {
710710
exists(int indirectionIndex |
711711
indirectionIndex = globalUse.getIndirectionIndex() and
712-
result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1)
712+
result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex - 1)
713713
)
714714
}
715715

@@ -740,7 +740,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
740740

741741
override DataFlowType getType() {
742742
exists(DataFlowType type |
743-
type = globalDef.getUnspecifiedType() and
743+
type = globalDef.getUnderlyingType() and
744744
if this.isGLValue()
745745
then result = type
746746
else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1)
@@ -943,10 +943,13 @@ private Type getTypeImpl0(Type t, int indirectionIndex) {
943943
indirectionIndex > 0 and
944944
exists(Type stripped |
945945
stripped = stripPointer(t.stripTopLevelSpecifiers()) and
946-
// We need to avoid the case where `stripPointer(t) = t` (which can happen on
947-
// iterators that specify a `value_type` that is the iterator itself). Such a type
948-
// would create an infinite loop otherwise. For these cases we simply don't produce
949-
// a result for `getTypeImpl`.
946+
// We need to avoid the case where `stripPointer(t) = t` (which can happen
947+
// on iterators that specify a `value_type` that is the iterator itself).
948+
// Such a type would create an infinite loop otherwise. For these cases we
949+
// simply don't produce a result for `getTypeImpl`.
950+
// To be on the safe side, we check whether the _unspecified_ type has
951+
// changed since this also prevents an infinite loop when `stripped` and
952+
// `t` only differ by const'ness or volatile'ness.
950953
stripped.getUnspecifiedType() != t.getUnspecifiedType() and
951954
result = getTypeImpl0(stripped, indirectionIndex - 1)
952955
)
@@ -996,12 +999,14 @@ private module RawIndirectNodes {
996999

9971000
override Declaration getEnclosingCallable() { result = this.getFunction() }
9981001

1002+
override predicate isGLValue() { this.getOperand().isGLValue() }
1003+
9991004
override DataFlowType getType() {
10001005
exists(int sub, DataFlowType type, boolean isGLValue |
10011006
type = getOperandType(this.getOperand(), isGLValue) and
10021007
if isGLValue = true then sub = 1 else sub = 0
10031008
|
1004-
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
1009+
result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
10051010
)
10061011
}
10071012

@@ -1038,12 +1043,14 @@ private module RawIndirectNodes {
10381043

10391044
override Declaration getEnclosingCallable() { result = this.getFunction() }
10401045

1046+
override predicate isGLValue() { this.getInstruction().isGLValue() }
1047+
10411048
override DataFlowType getType() {
10421049
exists(int sub, DataFlowType type, boolean isGLValue |
10431050
type = getInstructionType(this.getInstruction(), isGLValue) and
10441051
if isGLValue = true then sub = 1 else sub = 0
10451052
|
1046-
result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub)
1053+
result = getTypeImpl(type.getUnderlyingType(), indirectionIndex - sub)
10471054
)
10481055
}
10491056

@@ -1136,7 +1143,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
11361143

11371144
override Declaration getEnclosingCallable() { result = this.getFunction() }
11381145

1139-
override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) }
1146+
override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
11401147

11411148
final override Location getLocationImpl() {
11421149
// Parameters can have multiple locations. When there's a unique location we use
@@ -1789,7 +1796,7 @@ class VariableNode extends Node, TVariableNode {
17891796
}
17901797

17911798
override DataFlowType getType() {
1792-
result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1)
1799+
result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1)
17931800
}
17941801

17951802
final override Location getLocationImpl() {

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,6 +548,11 @@ class GlobalUse extends UseImpl, TGlobalUse {
548548
*/
549549
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
550550

551+
/**
552+
* Gets the type of this use, after typedefs have been resolved.
553+
*/
554+
Type getUnderlyingType() { result = global.getUnderlyingType() }
555+
551556
override predicate isCertain() { any() }
552557

553558
override BaseSourceVariableInstruction getBase() { none() }
@@ -591,11 +596,16 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
591596
int getIndirection() { result = indirectionIndex }
592597

593598
/**
594-
* Gets the type of this use after specifiers have been deeply stripped
595-
* and typedefs have been resolved.
599+
* Gets the type of this definition after specifiers have been deeply
600+
* stripped and typedefs have been resolved.
596601
*/
597602
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
598603

604+
/**
605+
* Gets the type of this definition, after typedefs have been resolved.
606+
*/
607+
Type getUnderlyingType() { result = global.getUnderlyingType() }
608+
599609
override string toString() { result = "Def of " + this.getSourceVariable() }
600610

601611
override Location getLocation() { result = f.getLocation() }
@@ -1115,6 +1125,11 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
11151125
*/
11161126
DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() }
11171127

1128+
/**
1129+
* Gets the type of this definition, after typedefs have been resolved.
1130+
*/
1131+
DataFlowType getUnderlyingType() { result = global.getUnderlyingType() }
1132+
11181133
/** Gets the `IRFunction` whose body is evaluated after this definition. */
11191134
IRFunction getIRFunction() { result = global.getIRFunction() }
11201135

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
11
astTypeBugs
22
irTypeBugs
3+
incorrectBaseType
4+
| clang.cpp:22:8:22:20 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
5+
| clang.cpp:23:17:23:29 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
6+
| flowOut.cpp:50:14:50:15 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
7+
| flowOut.cpp:84:9:84:10 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
8+
| flowOut.cpp:101:13:101:14 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
9+
| self_parameter_flow.cpp:8:8:8:9 | *& ... | Expected 'Node.getType()' to be unsigned char, but it was unsigned char * |
10+
| test.cpp:67:28:67:37 | (reference dereference) | Expected 'Node.getType()' to be const int, but it was int * |
11+
| test.cpp:531:39:531:40 | *& ... | Expected 'Node.getType()' to be int, but it was const int * |
12+
| test.cpp:615:13:615:21 | *& ... | Expected 'Node.getType()' to be int, but it was void |
13+
| test.cpp:704:22:704:25 | *& ... | Expected 'Node.getType()' to be int, but it was int * |
14+
| test.cpp:715:24:715:25 | *& ... | Expected 'Node.getType()' to be unsigned char, but it was unsigned char * |
15+
| test.cpp:848:23:848:25 | (reference dereference) | Expected 'Node.getType()' to be int, but it was int * |
16+
| test.cpp:854:10:854:36 | * ... | Expected 'Node.getType()' to be const int, but it was int |
17+
| test.cpp:867:10:867:30 | * ... | Expected 'Node.getType()' to be const int, but it was int |
318
failures

cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ module IrTest {
2525
n != 1
2626
)
2727
}
28+
29+
query predicate incorrectBaseType(Node n, string msg) {
30+
exists(PointerType pointerType, Type nodeType, Type baseType |
31+
not n.isGLValue() and
32+
pointerType = n.asIndirectExpr(1).getActualType() and
33+
baseType = pointerType.getBaseType() and
34+
nodeType = n.getType() and
35+
nodeType != baseType and
36+
msg = "Expected 'Node.getType()' to be " + baseType + ", but it was " + nodeType
37+
)
38+
}
2839
}
2940

3041
import IrTest

0 commit comments

Comments
 (0)